class Process
fd = open("/dev/tty", 1);
write(fd, "hello\n", 6);
pid = fork();
execl("/bin/echo", "echo", "hello", 0);
fd = open(); ...; fork();
)
while (1) { printf ("$"); 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"); } }
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"))
$ ls > tmp1just before exec insert:
close(1); fd = creat("tmp1", 0666); // fd will be 1
The kernel will return the first free file descriptor, 1 in this case.
$ sh < script > tmp1If for example the file
script
contains
echo one echo twoIs that equivalent to:
$ echo one > tmp1 $ echo two > tmp1
$ sort file.txt | uniq | wcor
$ sort file.txt > tmp1 $ uniq tmp1 > tmp2 $ wc tmp2 $ rm tmp1 tmp2
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 &