if (fork() == 0) {
/* set up file descriptors 1 and 2 in the child
process */
close(1);
close(2);
if (open(“/home/bc/Output”, O_WRONLY) == -1) {
exit(1); }
if (open(“/home/bc/Output”, O_WRONLY) == -1) {
exit(1);
}
execl(“/home/bc/bin/program”, “program”, 0);
exit(1);
}
/* parent continues here */
stdout and stderr both go into the same file would it cause any problem?
321 0
Operating Systems – CSCI 402
Redirecting Output … Twice
Every call to open() creates a new entry in the system file table
3
Copyright ý . Output
File-descriptor table (per process)
Operating Systems – CSCI 402
Child¡¯s address space
Copyright ý . address space
…
close(1);
close(2);
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
}
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
} execl(…)
4
321 0
Operating Systems – CSCI 402
Redirected Output
ref mode loc inode
1
WRONLY
0
inode pointer
File-descriptor table (per process)
File descriptor 1
Child¡¯s address space
Copyright ý . address space
…
close(1);
close(2);
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
}
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
} execl(…)
5
321 0
Operating Systems – CSCI 402
Redirected Output
ref mode loc inode
1
WRONLY
0
inode pointer
File-descriptor table (per process)
File descriptor 1
File descriptor 2
Child¡¯s address space
1
WRONLY
0
inode pointer
Copyright ý . address space
…
close(1);
close(2);
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
}
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
} execl(…)
6
321 0
Operating Systems – CSCI 402
Redirected Output
1
WRONLY
0
inode pointer
File-descriptor table (per process)
ref mode loc inode
1
WRONLY
0
inode pointer
Kernel address space
File descriptor 1
File descriptor 2
Child¡¯s new address space
remember, extended address space survives execs
let¡¯s say we write 100 bytes to stdout Copyright ý . Cheng
321 0
7
Redirected Output After Writing 100 Bytes
Operating Systems – CSCI 402
1
WRONLY
100
inode pointer
File-descriptor table (per process)
ref mode loc inode
1
WRONLY
0
inode pointer
Kernel address space
File descriptor 1
File descriptor 2
Child¡¯s new address space
write() to fd=2 will wipe out data in the first 100 bytes that may not be the intent
321 0
8
Copyright ý . Systems – CSCI 402
Sharing Context Information
if (fork() == 0) {
/* set up file descriptors 1 and 2 in the child
process */
close(1);
close(2);
if (open(“/home/bc/Output”, O_WRONLY) == -1) {
exit(1); }
dup(1);
execl(“/home/bc/bin/program”, “program”, 0);
exit(1);
}
/* parent continues here */
use the dup() system call to share context information if that¡¯s what you want
9
321 0
Copyright ý . Systems – CSCI 402
Redirected Output After Dup
File-descriptor table (per process)
Child¡¯s address space
Copyright ý . address space
} dup(1); …
…
close(1);
close(2);
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
10
321 0
Operating Systems – CSCI 402
Redirected Output After Dup File-descriptor
File descriptor 1
Child¡¯s address space
table (per process)
ref mode
loc inode
1
WRONLY
0
inode pointer
Copyright ý . address space
} dup(1); …
…
close(1);
close(2);
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
11
321 0
Operating Systems – CSCI 402
Redirected Output After Dup File-descriptor
File descriptor 1
File descriptor 2
Child¡¯s address space
table (per process)
ref mode
loc inode
2
WRONLY
0
inode pointer
Kernel address space
} dup(1); …
…
close(1);
close(2);
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
12
321 0
Copyright ý . Systems – CSCI 402
Redirected Output After Dup File-descriptor
File descriptor 1
File descriptor 2
Child¡¯s address space
table (per process)
ref mode
loc inode
2
WRONLY
0
inode pointer
Kernel address space
There is also a dup2() system call Copyright ý . Cheng
…
close(1);
if (open(
“/home/bc/Output”,
O_WRONLY) == -1) {
exit(1);
}
dup2(1, 2);
…
321 0
13
write(logfile, LogEntry, strlen(LogEntry));
…
exit(0);
}
/* parent process computes something, then does: */
write(logfile, LogEntry, strlen(LogEntry));
…
remember, extended address space survives execs
also fork() Copyright ý . Cheng
321 0
14
Operating Systems – CSCI 402
Fork and File Descriptors
It would be useful to be able to share file context information with a child process
when fork() is called, the child process gets a copy of the parent¡¯s file descriptor table
int logfile = open(“log”, O_WRONLY);
if (fork() == 0) {
/* child process computes something, then does: */
Operating Systems – CSCI 402
File Descriptors After Fork
Parent¡¯s address space
Kernel address space
int logfile = open(“log”,
O_WRONLY);
if (fork() == 0) {
write(logfile, LogEntry,
strlen(LogEntry));
…
exit(0); }
write(logfile, LogEntry,
strlen(LogEntry));
parent and child processes get separate file descriptor
table but share extended address space Copyright ý . Cheng
321 0
15
Operating Systems – CSCI 402
File Descriptors After Fork
logfile
Parent¡¯s address space
ref mode loc inode
1
WRONLY
0
inode pointer
Kernel address space
int logfile = open(“log”,
O_WRONLY);
if (fork() == 0) {
write(logfile, LogEntry,
strlen(LogEntry));
…
exit(0); }
write(logfile, LogEntry,
strlen(LogEntry));
parent and child processes get separate file descriptor
table but share extended address space Copyright ý . Cheng
321 0
16
File Descriptors After Fork
Operating Systems – CSCI 402
logfile
Parent¡¯s address space
ref mode loc inode
2
WRONLY
0
inode pointer
logfile
Child¡¯s address space
Kernel address space
int logfile = open(“log”,
O_WRONLY);
if (fork() == 0) {
write(logfile, LogEntry,
strlen(LogEntry));
…
exit(0); }
write(logfile, LogEntry,
strlen(LogEntry));
parent and child processes get separate file descriptor
table but share extended address space indirectly Copyright ý . Cheng
321 0
17
File Descriptors After Fork
Operating Systems – CSCI 402
logfile
Parent¡¯s address space
ref mode loc inode
2
WRONLY
0
inode pointer
logfile
Child¡¯s address space
Kernel address space
int logfile = open(“log”,
O_WRONLY);
if (fork() == 0) {
write(logfile, LogEntry,
strlen(LogEntry));
…
exit(0); }
write(logfile, LogEntry,
strlen(LogEntry));
parent and child processes can communicate using such a
shared file descriptor, although difficult to synchronize Copyright ý . Cheng
321 0
18
Operating Systems – CSCI 402
Pipes
A pipe is a means for one process to send data to another directly, as if it were writing to a file
sender process
receiver process
the sending process behaves as if it has a file descriptor to a file that has been opened for writing
the receiving process behaves as if it has a file descriptor to a file that has been opened for reading
The pipe() system call creates a pipe object in the kernel and returns (via an output parameter) the two file descriptors that refer to the pipe
one, set for write-only, refers to the input side
the other, set for read-only, refers to the output side
a pipe has no name, cannot be passed to another process
321 0
19
Copyright ý . Systems – CSCI 402
Pipes
int p[2]; // array to hold pipe¡¯s file descriptors
pipe(p); // creates a pipe, assume no errors
// p[0] refers to the read/output end of the pipe
// p[1] refers to the write/input end of the pipe
if (fork() == 0) {
char buf[80];
close(p[1]); // not needed by the child
while (read(p[0], buf, 80) > 0) {
// use data obtained from parent
… }
exit(0); // child done
} else {
char buf[80];
close(p[0]); // not needed by the parent
for (;;) {
// prepare data for child
…
write(p[1], buf, 80);
}
}
321 0
20
Copyright ý . Systems – CSCI 402
Pipes
Parent¡¯s address space
Kernel address space
parent creates a pipe object in the kernel
int p[2];
pipe(p);
if (fork() == 0) {
close(p[1]);
while (read(p[0],
buf, 80) > 0) {
…
}
exit(0);
} else {
close(p[0]);
for (;;) {
…
write(p[1], buf, 80);
}
Copyright ý . Cheng
}
21
321 0
Pipes
Operating Systems – CSCI 402
(read)
(write)
p[0]
p[1]
Parent¡¯s address space
Kernel address space
parent creates a pipe object in the kernel
int p[2];
pipe(p);
if (fork() == 0) {
close(p[1]);
while (read(p[0],
buf, 80) > 0) {
…
}
exit(0);
} else {
close(p[0]);
for (;;) {
…
write(p[1], buf, 80);
}
Copyright ý . Cheng
}
22
321 0
Pipes
Operating Systems – CSCI 402
p[0] p[1]
Parent¡¯s address space
(read)
(write)
(read)
(write)
p[0] p[1]
Child¡¯s address space
Kernel address space
int p[2];
pipe(p);
if (fork() == 0) {
close(p[1]);
while (read(p[0],
buf, 80) > 0) {
…
}
exit(0);
} else {
close(p[0]);
for (;;) {
…
write(p[1], buf, 80);
}
parent and child processes get separate file descriptor
tables but share extended address space Copyright ý . Cheng
321 0
23
}
Operating Systems – CSCI 402
Pipes
p[0] p[1]
Parent¡¯s address space
(read)
(write)
(read)
(write)
p[0] p[1]
Child¡¯s address space
Kernel address space
child closes the write-end of the pipe
int p[2];
pipe(p);
if (fork() == 0) {
close(p[1]);
while (read(p[0],
buf, 80) > 0) {
…
}
exit(0);
} else {
close(p[0]);
for (;;) {
…
write(p[1], buf, 80);
}
}
24
321 0
Copyright ý . Systems – CSCI 402
Pipes
p[0] p[1]
Parent¡¯s address space
(read)
(write)
(read)
(write)
p[0] p[1]
Child¡¯s address space
Kernel address space
child closes the write-end of the pipe
parent closes the read-end of the pipe
int p[2];
pipe(p);
if (fork() == 0) {
close(p[1]);
while (read(p[0],
buf, 80) > 0) {
…
}
exit(0);
} else {
close(p[0]);
for (;;) {
…
write(p[1], buf, 80);
}
}
25
321 0
Copyright ý .
Operating Systems – CSCI 402
p[0] p[1]
Parent¡¯s address space
(read)
(write)
(read)
(write)
p[0] p[1]
Child¡¯s address space
Kernel address space
child closes the write-end of the pipe
parent closes the read-end of the pipe
int p[2];
pipe(p);
if (fork() == 0) {
close(p[1]);
while (read(p[0],
buf, 80) > 0) {
…
}
exit(0);
} else {
close(p[0]);
for (;;) {
…
write(p[1], buf, 80);
}
}
26
321 0
Copyright ý . Systems – CSCI 402
Command Shell
Now you know enough to write a command shell
execute a command
redirect I/O
pipe the output of one program to another
cat f0 | ./warmup1 sort
the shell needs to create a pipe create two child processes
in the first child
have stdout go to the write-end of the pipe close the read-end of the pipe
exec “cat f0”
in the 2nd child
have stdin come from the read-end of the pipe close the write-end of the pipe
exec “./warmup1 sort”
run a program in the background
primes 1000000 > primes.out &
321 0
27
Copyright ý . Cheng
“man lseek” gives
off_t lseek(int fd, off_t offset, int whence); whence can be SEEK_SET, SEEK_CUR, SEEK_END
if succeeds, returns cursor position (always measured from
the beginning of the file)
otherwise, returns (-1)
errno is set to indicate the error
read(fd,buf,1) advances the cursor position by 1, so we need to move the cursor position back 2 positions
321 0
28
Operating Systems – CSCI 402
Random Access In Sequential I/O
fd = open(“textfile”, O_RDONLY);
// go to last char in file
fptr = lseek(fd, (off_t)(-1), SEEK_END);
while (fptr != -1) {
read(fd, buf, 1);
write(1, buf, 1);
fptr = lseek(fd, (off_t)(-2), SEEK_CUR);
}
Copyright ý . Cheng