fd = open("/dev/foo", 1);
write(fd, "hello\n", 6);
pid = fork();
fd = open(); ...; fork();
while (1) {
write (1, "$ ", 2);
readcommand (command, args); // parse user input
if ((pid = fork ()) == 0) { // child?
exec (command, args, 0);
} else if (pid > 0) { // parent?
wait (0); // wait for child to terminate
} else {
perror ("Failed to fork\n");
}
}
errno,
perror prints out a descriptive error
message based on errno.
The split of process creation into fork and exec turns out to have been an inspired choice, though that might not have been clear at the time; see the assigned paper for today.
$ ls
read (0, buf, bufsize)
write (1, "hello\n", strlen("hello\n"))
fcntl(fd, F_SETFD, FD_CLOEXEC)
$ ls > tmp1
just before exec insert:
close(1);
creat("tmp1", 0666); // fd will be 1
The kernel always uses the first free file descriptor, 1 in this case.
Could use dup2() to clone a file descriptor to a new number.
$ sh < script > tmp1
If for example the file script contains
echo one
echo two
FD inheritance makes this work well.
$ ls f1 f2 nonexistant-f3 > tmp1 2> tmp1
after creat, insert:
close(2);
creat("tmp1", 0666); // fd will be 2
why is this bad? illustrate what's going on with file descriptors. better:
close(2); dup(1); // fd will be 2or in bourne shell syntax,
$ ls f1 f2 nonexistant-f3 > tmp1 2>&1
$ sort < file.txt > tmp1 $ uniq tmp1 > tmp2 $ wc tmp2 $ rm tmp1 tmp2can be more concisely done as:
$ sort < file.txt | uniq | wc
int fdarray[2];
char buf[512];
int n;
pipe(fdarray);
write(fdarray[1], "hello", 5);
n = read(fdarray[0], buf, sizeof(buf));
// buf[] now contains 'h', 'e', 'l', 'l', 'o'
fork(), so this also works:
int fdarray[2];
char buf[512];
int n, pid;
pipe(fdarray);
pid = fork();
if(pid > 0){
write(fdarray[1], "hello", 5);
} else {
n = read(fdarray[0], buf, sizeof(buf));
}
fork() we already have,
to set up a pipe:
int fdarray[2];
if (pipe(fdarray) < 0) panic ("error");
if ((pid = fork ()) == 0) { child (left end of pipe)
close (1);
tmp = dup (fdarray[1]); // fdarray[1] is the write end, tmp will be 1
close (fdarray[0]); // close read end
close (fdarray[1]); // close fdarray[1]
exec (command1, args1, 0);
} else if (pid > 0) { // parent (right end of pipe)
close (0);
tmp = dup (fdarray[0]); // fdarray[0] is the read end, tmp will be 0
close (fdarray[0]);
close (fdarray[1]); // close write end
exec (command2, args2, 0);
} else {
printf ("Unable to fork\n");
}
$ compute &