fork系统调用
#include <unistd.h> #include <stdio.h> int main() { pid_t pid; int count =0; pid = fork(); if(pid < 0) { printf("error!"); } else if(pid == 0) { printf("i am child %d ",getpid()); count++; } else { printf("i am father %d ",getpid()); count++; }
//两次输出的都是1 printf("count:%d ",count); return 0; }
fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;
fork出错可能有两种原因:
1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。
2)系统内存不足,这时errno的值被设置为ENOMEM。
fork把进程当前的情况拷贝一份,不是从代码开始处拷贝的。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。
#include <unistd.h> #include <stdio.h> int main() { int i = 0; for(i = 0;i < 2;++i) { pid_t pid = fork(); if(pid == 0) { printf("i = %d child %d %d ",i,getpid(),getppid()); } else { printf("i = %d father %d childid = %d %d ",i,getpid(),pid,getppid()); } } return 0; }
输出:
i = 0 father 3020 childid = 3021 2650 i = 1 father 3020 childid = 3022 2650 i = 1 child 3022 1662 i = 0 child 3021 1662 i = 1 father 3021 childid = 3023 1662 i = 1 child 3023 1662
注意,上述进程如果跑完循环,就死亡了,这样子进程就没有父进程了,这在操作系统中是不被允许的 ,所以置为1662
对于这种N次循环的情况,执行printf函数的次数为2*(1+2+4+……+2N-1)次,创建的子进程数为1+2+4+……+2N-1个
#include <unistd.h> #include <stdio.h> int main() { pid_t fpid;//fpid表示fork函数返回的值 //printf("fork!"); printf("fork!/n"); fpid = fork(); if (fpid < 0) printf("error in fork!"); else if (fpid == 0) printf("I am the child process, my process id is %d/n", getpid()); else printf("I am the parent process, my process id is %d/n", getpid()); return 0; }
执行结果如下:
fork!
I am the parent process, my process id is 3361
I am the child process, my process id is 3362
如果把语句printf("fork!/n");注释掉,执行printf("fork!");
则新的程序的执行结果是:
fork!I am the parent process, my process id is 3298
fork!I am the child process, my process id is 3299
程序的唯一的区别就在于一个/n回车符号,为什么结果会相差这么大呢?
这就跟printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有实际的写到屏幕上。但是,只要看到有/n 则会立即刷新stdout,因此就马上能够打印了。
运行了printf("fork!")后,“fork!”仅仅被放到了缓冲里,程序运行到fork时缓冲里面的“fork!” 被子进程复制过去了。因此在子进程度stdout缓冲里面就也有了fork! 。所以,你最终看到的会是fork! 被printf了2次!!!!
而运行printf("fork! /n")后,“fork!”被立即打印到了屏幕上,之后fork到的子进程里的stdout缓冲里不会有fork! 内容。因此你看到的结果会是fork! 被printf了1次!!!!
#include <stdio.h> #include <unistd.h> int main() { fork(); fork()&&fork()||fork(); fork(); printf("+ "); return 0; }
总共20个进程,除去main进程,还有19个进程
第一个fork和最后一个fork肯定是会执行的。
主要在中间3个fork上,可以画一个图进行描述。
这里就需要注意&&和||运算符。
A&&B,如果A=0,就没有必要继续执行&&B了;A非0,就需要继续执行&&B。
A||B,如果A非0,就没有必要继续执行||B了,A=0,就需要继续执行||B。
fork()对于父进程和子进程的返回值是不同的,按照上面的A&&B和A||B的分支进行画图,可以得出5个分支。
http://blog.csdn.net/jason314/article/details/5640969