Input/Output CS 351: Systems Programming Michael Saelee - - PowerPoint PPT Presentation

input output
SMART_READER_LITE
LIVE PREVIEW

Input/Output CS 351: Systems Programming Michael Saelee - - PowerPoint PPT Presentation

Input/Output CS 351: Systems Programming Michael Saelee <lee@iit.edu> Computer Science Science CPU Memory I/O shared network disk terminal printer memory Computer Science Science shared network disk terminal


slide-1
SLIDE 1

Input/Output

CS 351: Systems Programming Michael Saelee <lee@iit.edu>

slide-2
SLIDE 2

Computer Science Science

I/O Memory CPU

disk terminal shared memory printer network …

slide-3
SLIDE 3

Computer Science Science

disk terminal shared memory printer network …

  • vast number of different mechanisms
  • but overlapping requirements:
  • read/write operations
  • metadata (e.g., name, position)
  • robustness, thread-safety
slide-4
SLIDE 4

Computer Science Science

programming concerns:

  • how are I/O endpoints represented?
  • how to perform I/O?
  • how to perform I/O efficiently?
slide-5
SLIDE 5

Computer Science Science

focus on Unix system-level I/O

slide-6
SLIDE 6

Computer Science Science

§Unix I/O & Filesystem Architecture Brief

slide-7
SLIDE 7

Computer Science Science

2 general classes of I/O devices:

  • block: accessed in fixed-size chunks;

support for seeking & random access

  • character: char-by-char streaming

access; no seeking / random access

slide-8
SLIDE 8

Computer Science Science

block device

… …

char device

slide-9
SLIDE 9

Computer Science Science

2 general classes of I/O devices:

  • block: e.g., disk, memory
  • character: e.g., network, mouse
slide-10
SLIDE 10

Computer Science Science

the filesystem acts as a namespace for data residing on different devices

slide-11
SLIDE 11

Computer Science Science

regular files consist of ASCII or binary data, stored on a block device

slide-12
SLIDE 12

Computer Science Science

special files may represent directories, in- memory structures, sockets, or raw devices

slide-13
SLIDE 13

Computer Science Science

i.e., “files” are a general OS abstraction for arbitrary data objects!

slide-14
SLIDE 14

Computer Science Science

each file has a unique inode data structure in the filesystem, tracking:

  • ownership & permissions
  • size, type, and location
  • number of links
slide-15
SLIDE 15

Computer Science Science

a given i-node can be referenced using

  • ne or more fully qualified path(s), e.g.,
  • /home/lee/.emacs
  • /proc/sys/kernel/version
  • /dev/tty
slide-16
SLIDE 16

Computer Science Science

inode table

OS’s filesystem module “/home/lee/.emacs”

slide-17
SLIDE 17

Computer Science Science

“/home/lee/.emacs”

inode table

OS’s filesystem module

locate & load inode structure * filename → inode association = link

slide-18
SLIDE 18

Computer Science Science

every currently open file has a single in-memory inode, aka. “vnode”

vnode

  • ownership
  • permissions
  • size & location
slide-19
SLIDE 19

Computer Science Science

each open file is also tracked by the kernel using an open file description structure

vnode

  • ownership
  • permissions
  • size & location
  • pen file desc
  • position
  • access mode
slide-20
SLIDE 20

Computer Science Science

can have multiple open file descriptions referencing a single vnode (e.g., to track separate read/write positions)

vnode

  • ownership
  • permissions
  • size & location
  • pen file desc
  • position
  • access mode
  • pen file desc
  • position
  • access mode
slide-21
SLIDE 21

Computer Science Science

for each process, the kernel maintains a table

  • f pointers to its open file structures

... OFD OFD OFD OFD vnode vnode vnode

slide-22
SLIDE 22

Computer Science Science

all these structures reside in kernel memory (off-limits to user processes)!

... OFD vnode OFD OFD vnode OFD vnode

protected memory

slide-23
SLIDE 23

Computer Science Science

to let a process reference an open file, the kernel returns an index into the table protected memory

1 2 3 ... OFD vnode OFD OFD vnode OFD vnode

slide-24
SLIDE 24

Computer Science Science

3 kernel user call this a file descriptor (FD)

1 2 3 ... OFD vnode OFD OFD vnode OFD vnode

slide-25
SLIDE 25

Computer Science Science

by convention, processes …

  • read from FD 0 for standard input
  • write to FD 1 for standard output
  • write to FD 2 for standard error
slide-26
SLIDE 26

Computer Science Science

after opening a file, all fi le operations are performed using file descriptors!

slide-27
SLIDE 27

Computer Science Science

1 2 1 2 1 2

kernel space

per process system-wide

OFD OFD OFD OFD vnode vnode vnode

network terminal

disk

slide-28
SLIDE 28

Computer Science Science

FDs obscure kernel I/O & FS implementation details from the user, and enable an elegant, abstract I/O API

slide-29
SLIDE 29

Computer Science Science

§System-level I/O API

slide-30
SLIDE 30

Computer Science Science

int open ( const char *path, int oflag, ... ); int fstat ( int fd, struct stat *buf ); int dup ( int fd ); int dup2 ( int fd1, int fd2 ); int close ( int fd );

  • ff_t lseek ( int fd, off_t offset, int whence );

ssize_t read ( int fd, void *buf, size_t nbytes ); ssize_t write ( int fd, const void *buf, size_t nbytes );

slide-31
SLIDE 31

Computer Science Science

  • loads vnode for file at path (if not

already loaded)

  • creates & inits a new OFD
  • returns a FD referring to the new OFD

int open(const char *path, int oflag, ...);

slide-32
SLIDE 32

Computer Science Science

  • oflag is an or-ing of O_RDONLY, O_WRONLY,

O_RDWR, O_CREAT, O_TRUNC, etc.

  • if O_CREAT, must specify access

permissions of new file (“rwx” flags)

int open(const char *path, int oflag, ...);

slide-33
SLIDE 33

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); 1 2 3 4 vnode empty file OFD

(first unused FD is used/returned)

slide-34
SLIDE 34

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); 1 2 3 4 OFD vnode empty file

$ ls -l foo.txt

  • rw-r--r-- 1 lee staff 5 Feb 15 18:23 foo.txt

rwx flags from (octal) 0644

slide-35
SLIDE 35

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); int fd2 = open("foo.txt", O_RDONLY); 1 2 3 4 OFD vnode empty file

OFD

slide-36
SLIDE 36

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); struct stat stat; /* query file metadata */ fstat(fd1, &stat); printf("Inode # : %lu\n", stat.st_ino); printf("Size : %lu\n", stat.st_size); printf("Links : %lu\n", stat.st_nlink); Inode # : 19603149 Size : 0 Links : 1

slide-37
SLIDE 37

Computer Science Science

† a process inherits its parent’s open files across a fork, and retains them post-exec!

slide-38
SLIDE 38

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); fork(); 3 4 OFD vnode empty file

per-process cross-system parent

3 4

child

i.e., parent and child share position and file access mode

slide-39
SLIDE 39

Computer Science Science

sharing an OFD can be very handy — e.g., for coordinating output to terminal

slide-40
SLIDE 40

Computer Science Science

can also explicitly “share” position from separate FDs using dup syscalls

slide-41
SLIDE 41

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); int fd2 = dup(fd1); 1 2 3 4 OFD vnode empty file

… i.e., reading/writing FD 4 is equivalent to doing so with FD 3

slide-42
SLIDE 42

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); dup2(fd1, 2); /* second arg is "destination" fd */ 1 2 3 4 OFD vnode empty file

… i.e., reading/writing FD 2 (stderr) is equivalent to doing so with FD 3

(original FD is automatically closed)

slide-43
SLIDE 43

Computer Science Science

  • delete OFD pointer in file table for fd
  • if the OFD has no referring FDs (in

any process), deallocate it

int close(int fd);

slide-44
SLIDE 44

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); int fd2 = open("foo.txt", O_RDONLY); 1 2 3 4 OFD vnode empty file

OFD

slide-45
SLIDE 45

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); int fd2 = open("foo.txt", O_RDONLY); close(fd1); 1 2 3 4 vnode empty file OFD

OFD

slide-46
SLIDE 46

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); int fd2 = open("foo.txt", O_RDONLY); close(fd1); close(fd2); 1 2 3 4 empty file vnode

OFD

slide-47
SLIDE 47

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); int fd2 = dup(fd1); 1 2 3 4 OFD vnode empty file

slide-48
SLIDE 48

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); int fd2 = dup(fd1); close(fd1); 1 2 3 4 OFD vnode empty file

slide-49
SLIDE 49

Computer Science Science

int fd1 = open("foo.txt", O_CREAT | O_TRUNC | O_RDWR, 0644); int fd2 = dup(fd1); close(fd1); close(fd2); 1 2 3 4 empty file OFD vnode

slide-50
SLIDE 50

Computer Science Science

application: input/output redirection

  • leverage FD usage conventions
  • 0 = stdin, 1 = stdout, 2 = stderr
  • recall: FD says nothing about the

actual file/device it refers to!

slide-51
SLIDE 51

Computer Science Science

Demo: Shell I/O redirection

slide-52
SLIDE 52

Computer Science Science

int main(int argc, char *argv[]) { int fd = open("foo.txt", O_CREAT|O_TRUNC|O_RDWR, 0644); dup2(fd, 1); printf("Arg: %s\n", argv[1]); } $ ./a.out hello! $

  • rw-r--r-- 1 lee staff 12 Feb 19 20:36 foo.txt

$ cat foo.txt Arg: hello! ls -l foo.txt

slide-53
SLIDE 53

Computer Science Science

1 2 3 4 OFD vnode empty file

(by default: terminal) ⎫ ⎬ ⎭

int main(int argc, char *argv[]) { int fd = open("foo.txt", O_CREAT|O_TRUNC|O_RDWR, 0644); dup2(fd, 1); printf("Arg: %s\n", argv[1]); /* printf prints to stdout */ }

slide-54
SLIDE 54

Computer Science Science

1 2 3 4 OFD vnode empty file

(output)

int main(int argc, char *argv[]) { int fd = open("foo.txt", O_CREAT|O_TRUNC|O_RDWR, 0644); dup2(fd, 1); printf("Arg: %s\n", argv[1]); /* printf prints to stdout */ }

slide-55
SLIDE 55

Computer Science Science

$ ./a.out $ hello! int main() { int fd = open("foo.txt", O_CREAT|O_TRUNC|O_RDWR, 0644); if (fork() == 0) { dup2(fd, 1); execlp("echo", "echo", "hello!", NULL); } close(fd); } cat foo.txt

slide-56
SLIDE 56

Computer Science Science

illustrates a powerful technique that requires separating fork & exec

  • original program sets up new process

environment before exec-ing

int main() { int fd = open("foo.txt", O_CREAT|O_TRUNC|O_RDWR, 0644); if (fork() == 0) { dup2(fd, 1); execlp("echo", "echo", "hello!", NULL); } close(fd); }

slide-57
SLIDE 57

Computer Science Science

  • reads up to nbytes bytes from open file

at fd into buf

  • by default, block for at least 1 byte
  • returns # bytes read (or -1 for error)

ssize_t read(int fd, void *buf, size_t nbytes);

slide-58
SLIDE 58

Computer Science Science

  • writes

into open file at fd from buf

  • by default, block for at least 1 byte
  • returns # bytes written (or -1 for error)

ssize_t write(int fd, const void *buf, size_t nbytes);

up to nbytes bytes

slide-59
SLIDE 59

Computer Science Science

i.e., short counts can occur — process asks OS to write k bytes, but

  • nly l < k bytes are actually written

up to nbytes bytes “ ”

slide-60
SLIDE 60

Computer Science Science

why?

slide-61
SLIDE 61

Computer Science Science

reads:

  • EOF, unreadable FD, “slow” file,

interrupt, etc. writes:

  • out of space, unwritable FD, “slow”

file, interrupt, etc.

slide-62
SLIDE 62

Computer Science Science

read/write are the lowest level I/O calls

— kernel objective is to support maximum performance & minimum latency

slide-63
SLIDE 63

Computer Science Science

e.g., if reading from slow network, return to process asap and allow it to decide to read again or do something else

slide-64
SLIDE 64

Computer Science Science

(but usually, short counts are a royal pain)

slide-65
SLIDE 65

Computer Science Science

ssize_t robust_read(int fd, void *buf, size_t n) { size_t nleft = n; ssize_t nread; char *p = buf; while (nleft > 0) { if ((nread = read(fd, p, nleft)) < 0) return -1; /* error in read */ else if (nread == 0) break; /* read returns 0 on EOF */ nleft -= nread; p += nread; } return (n - nleft); }

slide-66
SLIDE 66

Computer Science Science

(yuck) good news: short counts only occur on EOF for reads on regular files

slide-67
SLIDE 67

Computer Science Science

but there’s another concern…

slide-68
SLIDE 68

Computer Science Science

char buf[10]; int fd, x, y, z; fd = open("data.txt", O_RDONLY); read(fd, buf, 2); buf[2] = 0; x = atoi(buf); read(fd, buf, 2); buf[2] = 0; y = atoi(buf); read(fd, buf, 2); buf[2] = 0; z = atoi(buf); printf("%d %d %d", x, y, z);

data.txt

102030 10 20 30

slide-69
SLIDE 69

Computer Science Science

  • ne syscall per integer read = inefficient!!!

char buf[10]; int fd, x, y, z; fd = open("data.txt", O_RDONLY); read(fd, buf, 2); buf[2] = 0; x = atoi(buf); read(fd, buf, 2); buf[2] = 0; y = atoi(buf); read(fd, buf, 2); buf[2] = 0; z = atoi(buf); printf("%d %d %d", x, y, z);

data.txt

102030

slide-70
SLIDE 70

Computer Science Science

fd = open("data.txt", O_RDONLY); read(fd, buf, 2); buf[2] = 0; x = atoi(buf); read(fd, buf, 2); buf[2] = 0; y = atoi(buf); read(fd, buf, 2); buf[2] = 0; z = atoi(buf); printf("%d %d %d", x, y, z);

data.txt

102030

$ strace ./a.out execve("./a.out", ["./a.out"], [/* 67 vars */]) = 0 ...

  • pen("data.txt", O_RDONLY) = 3

read(3, "10", 2) = 2 read(3, "20", 2) = 2 read(3, "30", 2) = 2 write(1, "10 20 30", 8) = 8 ...

slide-71
SLIDE 71

Computer Science Science

solution: buffering

slide-72
SLIDE 72

Computer Science Science

step 1: read more bytes than we need into a separate backing buffer

user kernel

slide-73
SLIDE 73

Computer Science Science

step 1: read more bytes than we need into a separate backing buffer

user kernel read

slide-74
SLIDE 74

Computer Science Science

char buf[10], bbuf[80]; int fd, x, y, z; fd = open("data.txt", O_RDONLY); read(fd, bbuf, sizeof(bbuf));

data.txt

102030

slide-75
SLIDE 75

Computer Science Science

step 2: avoid syscalls and process future “reads” from that buffer

user kernel

copy

slide-76
SLIDE 76

Computer Science Science

step 2: avoid syscalls and process future “reads” from that buffer

user kernel

copy copy

slide-77
SLIDE 77

Computer Science Science

step 2: avoid syscalls and process future “reads” from that buffer

user kernel

copy copy copy

slide-78
SLIDE 78

Computer Science Science

char buf[10], bbuf[80]; int fd, x, y, z; fd = open("data.txt", O_RDONLY); read(fd, bbuf, sizeof(bbuf)); buf[2] = 0; memcpy(buf, bbuf, 2); x = atoi(buf);

data.txt

102030

slide-79
SLIDE 79

Computer Science Science

char buf[10], bbuf[80]; int fd, x, y, z; fd = open("data.txt", O_RDONLY); read(fd, bbuf, sizeof(bbuf)); buf[2] = 0; memcpy(buf, bbuf, 2); x = atoi(buf); memcpy(buf, bbuf+2, 2); y = atoi(buf);

data.txt

102030

slide-80
SLIDE 80

Computer Science Science

char buf[10], bbuf[80]; int fd, x, y, z; fd = open("data.txt", O_RDONLY); read(fd, bbuf, sizeof(bbuf)); buf[2] = 0; memcpy(buf, bbuf, 2); x = atoi(buf); memcpy(buf, bbuf+2, 2); y = atoi(buf); memcpy(buf, bbuf+4, 2); z = atoi(buf);

data.txt

102030

slide-81
SLIDE 81

Computer Science Science

fd = open("data.txt", O_RDONLY); read(fd, bbuf, sizeof(bbuf)); buf[2] = 0; memcpy(buf, bbuf, 2); x = atoi(buf); memcpy(buf, bbuf+2, 2); y = atoi(buf); memcpy(buf, bbuf+4, 2); z = atoi(buf);

data.txt

102030

$ strace ./a.out execve("./a.out", ["./a.out"], [/* 67 vars */]) = 0 ...

  • pen("data.txt", O_RDONLY) = 3

read(3, "102030\n", 80) = 7 write(1, "10 20 30", 8) = 8 ...

slide-82
SLIDE 82

Computer Science Science

to generalize, bundle together: (1) FD (2) backing buffer (3) num unused bytes (4) pointer to next byte

slide-83
SLIDE 83

Computer Science Science

typedef struct { int fd; /* (1) wrapped FD */ char buf[100]; /* (2) backing buffer */ int count; /* (3) num unused bytes */ char *nextp; /* (4) pointer to next byte */ } bufio_t; void bufio_init(bufio_t *bp, int fd) { bp->fd = fd; bp->count = 0; bp->nextp = bp->buf; }

slide-84
SLIDE 84

Computer Science Science

ssize_t bufio_read(bufio_t *bp, char *buf, size_t n) { int ncpy; /* fill backing buffer if empty */ if (bp->count <= 0) { bp->count = read(bp->fd, bp->buf, sizeof(bp->buf)); if (bp->count <= 0) return bp->count; /* EOF or read error */ else bp->nextp = bp->buf; /* re-init buf position */ } /* copy from backing buffer to user buffer */ ncpy = (bp->count < n)? bp->count : n; memcpy(buf, bp->nextp, ncpy); bp->nextp += ncpy; bp->count -= ncpy; return ncpy; }

slide-85
SLIDE 85

Computer Science Science

char buf[10]; int fd, x, y, z; bufio_t bbuf; fd = open("data.txt", O_RDONLY); bufio_init(&bbuf, fd); buf[2] = 0; bufio_read(&bbuf, buf, 2); x = atoi(buf); bufio_read(&bbuf, buf, 2); y = atoi(buf); bufio_read(&bbuf, buf, 2); z = atoi(buf);

data.txt

102030

slide-86
SLIDE 86

Computer Science Science

  • pen is now a distraction… we never use

the FD directly (except to initialize buffer)

slide-87
SLIDE 87

Computer Science Science

next step: hide syscalls from user — wrap

  • pen together with buffer initialization
slide-88
SLIDE 88

Computer Science Science

bufio_t *buf_open(const char *path) { bufio_t *buf = malloc(sizeof(bufio_t)); int fd = open(path, O_RDWR); bufio_init(buf, fd); return buf; } int main() { bufio_t *bbuf = buf_open("data.txt"); char buf[10]; int x, y, z; bufio_read(bbuf, buf, 2); ... }

slide-89
SLIDE 89

Computer Science Science

Stop!

<stdio.h> does all this for us!

slide-90
SLIDE 90

Computer Science Science

fclose fdopen feof ferror fflush fgetc fgetln fgetpos fgets fopen fprintf fputc fputs fread freopen fscanf fseek fsetpos fwrite getc mktemp perror printf putc putchar puts remove rewind scanf sprintf sscanf strerror tmpfile ungetc vfprintf vprintf vscanf ...

slide-91
SLIDE 91

Computer Science Science

… all use buffered I/O

slide-92
SLIDE 92

Computer Science Science

stdio functions operate on stream objects i.e., buffered wrappers on FDs

slide-93
SLIDE 93

Computer Science Science

FILE* fopen ( const char *filename, const char *mode ); FILE* fdopen ( int fd, const char *mode ); int fclose ( FILE *stream ); int fseek ( FILE *stream, long offset, int whence ); size_t fread ( void *ptr, size_t size, size_t nitems, FILE *stream ); size_t fwrite ( void *ptr, size_t size, size_t nitems, FILE *stream ); int fprintf ( FILE *stream, const char *format, ... ); int fscanf ( FILE *stream, const char *format, ... ); char* fgets ( char *str, int size, FILE *stream );

slide-94
SLIDE 94

Computer Science Science

int x, y, z; FILE *infile = fopen("data.txt", "r"); fscanf(infile, "%2d", &x); fscanf(infile, "%2d", &y); fscanf(infile, "%2d", &z); printf("%d %d %d", x, y, z); fclose(infile); /* or memory leak! */ $ strace ./a.out execve("./a.out", ["./a.out"], [/* 67 vars */]) = 0 ...

  • pen("data.txt", O_RDONLY) = 3

read(3, "102030\n", 4096) = 7 write(1, "10 20 30", 8) = 8 close(3) = 0 ...

slide-95
SLIDE 95

Computer Science Science

printf("h"); printf("e"); printf("l"); printf("l"); printf("o"); $ strace ./a.out ... write(1, "hello", 5) = 5 ...

(writes are buffered too!)

slide-96
SLIDE 96

Computer Science Science

stream buffer can absorb multiple writes before being flushed to underlying file

slide-97
SLIDE 97

Computer Science Science

flush happens on:

  • buffer being filled
  • (normal) process termination
  • newline, in a line-buffered stream
  • explicitly, with fflush
slide-98
SLIDE 98

Computer Science Science

$ ./a.out hellohello

@#$%^&*!!!

int main() { printf("h"); printf("e"); printf("l"); printf("l"); printf("o"); fork(); }

slide-99
SLIDE 99

Computer Science Science

int n, fd = open("fox.txt", O_RDONLY); char buf[10]; n = read(fd, buf, sizeof(buf)); write(1, buf, n); if (fork() == 0) { n = read(fd, buf, sizeof(buf)); write(1, buf, n); exit(0); } wait(NULL); n = read(fd, buf, sizeof(buf)); write(1, buf, n); $ ./a.out The quick brown fox jumps over

fox.txt

the quick brown fox jumps over the lazy dog

slide-100
SLIDE 100

Computer Science Science

int n; FILE *stream = fopen("fox.txt", "r"); char buf[10]; n = fread(buf, 1, sizeof(buf), stream); write(1, buf, n); if (fork() == 0) { n = fread(buf, 1, sizeof(buf), stream); write(1, buf, n); exit(0); } wait(NULL); n = fread(buf, 1, sizeof(buf), stream); write(1, buf, n); $ ./a.out The quick brown fox brown fox

fox.txt

the quick brown fox jumps over the lazy dog

@#$%^&*!!!

slide-101
SLIDE 101

Computer Science Science

things gets even more confusing when we perform both input & output

slide-102
SLIDE 102

Computer Science Science

int fd = open("fox.txt", O_RDWR); char buf[10]; /* output followed by input */ write(fd, "a playful ", 10); read(fd, buf, sizeof(buf)); write(1, buf, sizeof(buf)); $ ./a.out brown fox

fox.txt

the quick brown fox jumps over the lazy dog a playful brown fox jumps over the lazy dog

slide-103
SLIDE 103

Computer Science Science

int fd = open("fox.txt", O_RDWR); FILE *stream = fdopen(fd, "r+"); char buf[10]; /* output followed by input */ fwrite("a playful ", 1, 10, stream); read(fd, buf, sizeof(buf)); write(1, buf, sizeof(buf)); $ ./a.out the quick

fox.txt

the quick brown fox jumps over the lazy dog

@#$%^&*!!!

the quick a playful jumps

  • ver the lazy

dog

slide-104
SLIDE 104

Computer Science Science

int fd = open("fox.txt", O_RDWR); char buf[10]; /* input followed by output */ read(fd, buf, sizeof(buf)); write(fd, "green cat ", 10); write(1, buf, sizeof(buf)); $ ./a.out the quick

fox.txt

the quick brown fox jumps over the lazy dog the quick green cat jumps over the lazy dog

slide-105
SLIDE 105

Computer Science Science

FILE *stream = fopen("fox.txt", "r+"); char buf[10]; /* input followed by output */ fread(buf, 1, sizeof(buf), stream); fwrite("green cat ", 1, 10, stream); write(1, buf, sizeof(buf)); $ ./a.out the quick

fox.txt

the quick brown fox jumps over the lazy dog

@#$%^&*!!!

the quick brown fox jumps over the lazy dog green cat

slide-106
SLIDE 106

Computer Science Science

ISO C99 standard, 7.19.5.3 (par 6)

When a file is opened with update mode ..., both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function ..., and , unless the input operation encounters end- of-file. input shall not be directly followed by output without an intervening call to a file positioning function

slide-107
SLIDE 107

Computer Science Science

input shall not be directly followed by output without an intervening call to a file positioning function

but not all files support “file positioning functions”! (e.g., no seeks on character devices)

slide-108
SLIDE 108

Computer Science Science

lessons:

  • buffered stdio functions help minimize

system overhead & simplify I/O

  • use whenever possible!
slide-109
SLIDE 109

Computer Science Science

lessons:

  • but need to beware of glitches
  • don’t mix buffered & unbuffered I/O
  • and not appropriate for some devices

(e.g., network)

  • use low-level, robust I/O for these