Linux中使用C语言的fork()函数创建子进程的实例教程
一、fork入门知识 #include <unistd.h> #include <stdio.h> int main () { pid_t fpid; //fpid表示fork函数返回的值 int count=0; 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()); printf("我是爹的儿子/n");//对某些人来说中文看着更直白。 count++; } else { printf("i am the parent process,getpid()); printf("我是孩子他爹/n"); count++; } printf("统计结果是: %d/n",count); return 0; } 运行结果是: i am the child process,my process id is 5574 我是爹的儿子 统计结果是: 1 i am the parent process,my process id is 5573 我是孩子他爹 统计结果是: 1 在语句fpid=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的几乎完全相同,将要执行的下一条语句都是if(fpid<0)…… 有人说两个进程的内容完全一样啊,怎么打印的结果不一样啊,那是因为判断条件的原因,上面列举的只是进程的代码和指令,还有变量啊。 #include <unistd.h> #include <stdio.h> int main(void) { int i=0; printf("i son/pa ppid pid fpid/n"); //ppid指当前进程的父进程pid //pid指当前进程的pid,//fpid指fork返回给当前进程的值 for(i=0;i<2;i++){ pid_t fpid=fork(); if(fpid==0) printf("%d child %4d %4d %4d/n",i,getppid(),getpid(),fpid); else printf("%d parent %4d %4d %4d/n",fpid); } return 0; } 运行结果是: i son/pa ppid pid fpid 0 parent 2043 3224 3225 0 child 3224 3225 0 1 parent 2043 3224 3226 1 parent 3224 3225 3227 1 child 1 3227 0 1 child 1 3226 0 这份代码比较有意思,我们来认真分析一下: p2043->p3224->p3225 第一次fork后,p3224(父进程)的变量为i=0,fpid=3225(fork函数在父进程中返向子进程id),代码内容为: for(i=0;i<2;i++){ pid_t fpid=fork();//执行完毕,i=0,fpid=0 if(fpid==0) printf("%d child %4d %4d %4d/n",fpid); else printf("%d parent %4d %4d %4d/n",fpid); } return 0; 所以打印出结果: 0 parent 2043 3224 3225 0 child 3224 3225 0 第二步:假设父进程p3224先执行,当进入下一个循环时,i=1,接着执行fork,系统中又新增一个进程p3226,对于此时的父进程,p2043->p3224(当前进程)->p3226(被创建的子进程)。 1 parent 2043 3224 3226 1 parent 3224 3225 3227 第三步:第二步创建了两个进程p3226,p3227,这两个进程执行完printf函数后就结束了,因为这两个进程无法进入第三次循环,无法fork,该执行return 0;了,其他进程也是如此。 1 child 1 3227 0 1 child 1 3226 0 细心的读者可能注意到p3226,p3227的父进程难道不该是p3224和p3225吗,怎么会是1呢?这里得讲到进程的创建和死亡的过程,在p3224和p3225执行完第二个循环后,main函数就该退出了,也即进程该死亡了,因为它已经做完所有事情了。p3224和p3225死亡后,p3226,p3227就没有父进程了,这在操作系统是不被允许的,所以p3226,p3227的父进程就被置为p1了,p1是永远不会死亡的,至于为什么,这里先不介绍,留到“三、fork高阶知识”讲。 这个程序最终产生了3个子进程,执行过6次printf()函数。 #include <unistd.h> #include <stdio.h> int main(void) { int i=0; for(i=0;i<3;i++){ pid_t fpid=fork(); if(fpid==0) printf("son/n"); else printf("father/n"); } return 0; } 它的执行结果是: father son father father father father son son father son son son father son 这里就不做详细解释了,只做一个大概的分析。 for i=0 1 2 father father father son son father son son father father son son father son 其中每一行分别代表一个进程的运行打印结果。 老规矩,大家看一下下面的代码: #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,getpid()); else printf("I am the parent process,getpid()); return 0; }执行结果如下: fork! I am the parent process,my process id is 3361 I am the child process,my process id is 3362 则新的程序的执行结果是: fork!I am the parent process,my process id is 3298 fork!I am the child process,my process id is 3299 这就跟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次!!!! 所以说printf("+");不能正确地反应进程的数量。 大家看了这么多可能有点疲倦吧,不过我还得贴最后一份代码来进一步分析fork函数。 #include <stdio.h> #include <unistd.h> int main(int argc,char* argv[]) { fork(); fork() && fork() || fork(); fork(); return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ruby-on-rails – 自定义Rails I18n Locale Plur
- ruby-on-rails – 在Rails 4中创建API – 未初始
- 关于React Native中FlatList的onEndReached属性频
- 我应该使用XML在我的C#.Net应用程序中存储配置设
- c# – 在哪里可以找到有关.NET中多维System.Arra
- React Navigation 入门(四) - 屏幕导航 Naviga
- 65条最常用正则表达式,你要的都在这里了
- 打开Flex4.6时出现了Failed to create the Java
- c – OpenMP原子内存顺序
- 使用Playground快速练习Swift语法(汇总)