NAME fork - create a process SYNOPSIS int fork(); DESCRIPTION Fork() creates a new process as a duplicate of the calling process. The new process (the "child") contains an exact copy of the address space, registers and open file table of the calling process (the "parent"). As such, both processes return from the fork() system call. The only way that the two processes differ is that: - The child has a different process id. - The child's parent process id is set to the process id of the parent. - The return values of the fork() call -- see below. All open files in the parent will also be open, with the same file descriptors, in the child, as if dup() or dup2() were called. RETURN VALUES - Fork returns 0 in the child. - Fork returns the process id of the child in the parent. - Fork returns -1 if there is an error; no child process is created. |
#include <pthread.h> #include "socketfun.h" #include <stdio.h> #include <stdlib.h> /* This thread reads from the socket, and writes to standard output. */ void *thread(void *arg) { char buf[1000]; FILE *fin; fin = (FILE *) arg; while (fgets(buf, 1000, fin) != NULL) { fputs(buf, stdout); fflush(stdout); } exit(0); return NULL; } /* This thread reads from standard input, and writes to the socket. */ int main(int argc, char **argv) { int fd; FILE *fin, *fout; char buf[1000]; pthread_t tid; if (argc != 3) { fprintf(stderr, "usage: telnet host port\n"); exit(1); } fd = request_connection(argv[1], atoi(argv[2])); fin = fdopen(fd, "r"); fout = fdopen(fd, "w"); if (pthread_create(&tid, NULL, thread, (void *) fin) != 0) exit(1); while (fgets(buf, 1000, stdin) != NULL) { fputs(buf, fout); fflush(fout); } return 0; } |
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> void a(jmp_buf env) { int i; i = 3; setjmp(env); printf("%d\n", i); } int main() { jmp_buf env; a(env); longjmp(env, 1); return 1; } |
The jmp_buf stores the stack and frame pointers of a() at the time that a() is called, but when a() returns, those locations on the stack will be overwritten by any subsequent procedure call. When the longjmp() happens, you'll be running in a()'s old stack frame, whose values will have been overwritten, and are therefore corrupt. This includes the variables of a() and the information that a() uses to return to its caller. In the case of the example above, the longjmp() call itself is what will corrupt the values of a(). When I run it on my Macbook, I get the following:
UNIX> a.out 3 1 Segmentation fault UNIX>
#include "socketfun.h" #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> int main() { int p[2]; int fd; int dummy; if (pipe(p) == -1) exit(1); if (fork() != 0) { if (fork() != 0) { /* This is the parent, a.out process. */ close(p[0]); /* Simply close the pipe and wait for the children to exit. */ close(p[1]); wait(&dummy); wait(&dummy); exit(0); } fd = open("f1.txt", O_RDONLY); /* This is the bin/x child. First redirect stdin */ if (fd < 0) exit(1); dup2(fd, 0); close(fd); dup2(p[1], 1); /* Then stdout, exec and exit if there was an error. */ close(p[0]); close(p[1]); execlp("/bin/x", "x", "4.5", NULL); exit(1); } fd = request_connection("eecs.utk.edu", 6000); /* And the bin/y child - do stdout. */ dup2(fd, 1); close(fd); dup2(p[0], 0); /* Then stdin, exec and exit. */ close(p[0]); close(p[1]); execlp("/bin/y", "y", "fred", "5", NULL); exit(1); } |
UNIX> sh q5-ss.sh P P P A B C A C B B A C B C A C A B UNIX>The answers are: g, j, q, v, A, E.
UNIX> sh q5-ss.sh PP PP A A B B B B A A UNIX>The answers are: c, t.
UNIX> sh q5-ss.sh SPA XP A B Yes, it takes 100 seconds.... UNIX>The answer is: d.
UNIX> sh q5-ss.sh XP YP SPBSPA C B C A UNIX>The answer is: G.
UNIX> sh q5-ss.sh PE PE PE A B C UNIX>The answer is: a, m, y.
UNIX> sh q5-ss.sh XP YP SPAB C A B C B A UNIX>The answer is: A, E.
UNIX> sh q5-ss.sh SPAA XP XP A B C A C B UNIX>The answer is: g, j
UNIX> q5 XP AP B A UNIX> q5 XP AP BThe answer is: m, n
#1: Three threads -- A and B simply block on cv1 and cv2 respectively, and C wakes each up at the appropriate time:
UNIX> a.out PXPXP YPYPYP SBSASBSASB A B A B A B UNIX>You'll note that the following won't work, because some of the time, thread three will signal A before it blocks:
UNIX> a.out XPXPXP YPYPYP ASBSASBSASB A B A B A B UNIX> a.out XPXPXP YPYPYP ASBSASBSASB B A B A B UNIX>#2: Two threads -- A does all the sleeping, and at the end of each second, it either prints or wakes up B. B simply prints and blocks.
UNIX> a.out PSASPSASPSA XPXPXP A B A B A B UNIX>#3: Two threads -- A will block on cv1 and B will block on cv2, and they alternate waking each other up.
UNIX> q5 PXSPBXSPB SPAYSPAYSP A B A B A B UNIX>
Q5A: 4 - PAYSPAYSPAY-XSPBXSPBXP A----------- A-B-A-B-AB------- |
This means that when I ran my grading program with the arguments "PAYSPAYSPAY XSPBXSPBXP", it had two different outputs. The first was an "A", and then nothing. The second was "A", "B", "A", "B", "AB", each separated by a second. The answer was worth four points out of six.