对apue书中fork的解释!
首先看一下apue一书的187页的例子:
1 #include "apue.h" 2 3 int glob = 6; 4 char buf[] = "a write to stdout\n"; 5 int main(void) 6 { 7 int var; 8 pid_t pid; 9 var = 88; 10 if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) 11 err_sys("write error"); 12 printf("before fork\n"); 13 14 if((pid = fork()) < 0) 15 { 16 err_sys("fork error"); 17 } 18 else if(pid == 0) 19 { 20 glob++; 21 var++; 22 } 23 else 24 { 25 sleep(2); 26 } 27 printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var); 28 exit(0); 29 }
运行./a.out后得到结果:
a write to stdout
before fork
pid = 4848, glob = 7, var = 89
pid = 4847, glob = 6, var = 88
但是如果将输出重定向到一个文件后其结果就不一样了!
$ ./a.out > temp.out
$ cat temp.out
a write to stdout
before fork
pid = 4858, glob = 7, var = 89
before fork
pid = 4857, glob = 6, var = 88
通过这个例子主要是分析一下为什么重定向到文件以后会多打印出一个“before fork”了?
首先: fork的特殊作用是调用一次返回两次,返回值==0的代表子进程,>0 的代表父进程。
子进程和父进程要共享代码段,同时子进程将继承父进程的缓冲区,文件描述符等!
而在本例中: printf("before fork!\n"),在打印的时候就是将缓冲区中的数据打印出来!
第一种情况:(./a.out 输出到标准输出上!)
一开始父进程执行printf("before fork\n")打印,所以出现了before fork 语句,由于这是标准输出,是行缓冲机制,所以在用\n进行换行时系统就会把缓冲区中的数据冲洗掉,所以子进程继承得到的缓冲区将为空,然后程序执行fork,子进程先执行,指向++操作后,利用printf打印操作数的值也就是:
pid = 4848, glob = 7, var = 89
然后子进程执行exit函数退出程序,在退出程序的时候会清理缓冲区,所以会检查子进程中缓冲区的内容,如果存在则写会输出上,但是子进程继承来的缓冲区已经被冲洗掉了,不存在数据,所以exit退出时子进程将不会打印:
before fork !
最后父进程执行打印操作数的语句:
pid = 4847, glob = 6, var = 88
第二次将其打印到文件中:
由于打印到文件中,文件不会去识别\n就去冲洗掉内存缓冲区 ,,所以在子进程调用exit函数退出程序时,就会把缓冲区中的数据再次打印到文件中,然后退出。
然后父进程打印退出!
最后总结一下:
1. 要熟悉fork一个子进程后,子进程是会共享代码段的,拷贝了数据段。
2. 要知道标准输出会通过换行符\n, 冲洗掉缓冲区的内容
3. exit函数在退出的时候会清理缓冲区,将缓冲区数据写回文件,关闭文件描述符等!
浙公网安备 33010602011771号