在做某个公司的笔试题的时候遇到了这么一个问题,描述如下:
如下代码会输出多少个"-"字符?
#include<stdio.h> #include<sys/types.h> #include<unistd.h> int main() { int i; for(i=0;i<2;i++) { fork(); printf("-\n"); } return 0; }
在这里只做一个引子,下面稍微介绍一下fork()然后再解决这个问题。
fork()函数
#include<unistd.h> /*返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1*/ pid_t fork(void);由fork创建的新进程被称为子进程(child process)。fork函数被调用一次,但返回两次。子进程的返回值是0,而父进程的返回值则是新进程的进程ID。 将子进程ID返回给父进程的理由是:因为一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程ID。 fork使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用getpid以获得其父进程的进程ID。
使fork失败的两个主要原因是:系统中已经有了太多的进程,或者该实际用户ID的进程总数超过了系统限制。
fork有下面两种用法:
(1)一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的--父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求到达。
(2)一个进程要执行一个不同的程序。这对shell是常见的情况。子进程从fork返回后立即调用exec。
归结起来说就是是实现多线程。C语言多线程实现需要自己控制来实现,这个比Java要复杂。
注意:fork确实创建了一个子进程并完全复制父进程,但是子进程是从fork后面那个指令开始执行的。对于原因也很合乎逻辑,如果子进程也从main开头到尾执行所有指令,那么它执行到fork指令时也必定会创建一个子子进程,子子孙孙无穷尽也,如此下去,这个小小的程序就可以创建无数多个进程可以把你的电脑搞瘫痪,所以fork作者肯定不会这么做。
在此,我们还是举一个最经典的fork的代码示例:
#include<stdio.h> #include<sys/types.h> #include<unistd.h> int main() { pid_t pid = fork();//程序从这里开始分岔,父子进程都从这一句开始执行一次 if(pid > 0) { sleep(2); printf( "this is parent process:process id is %d\n",getpid() ); } else if(pid==0) { printf( "this is child process:process id is %d\n",getpid() ); } else { printf("error!\n"); } return 0; }
结果:
现在回到开头的程序上,到底输出多少个"-"?原来的代码将循环解析一下成为如下格式:
int main() { fork(); printf("-\n"); fork(); printf("-\n"); return 0; }
分析:首先父进程A执行第一个fork()函数,然后生成了一个子进程B,此时A和B同时也就是并发执行,都执行printf("-");先输出了两个"-",然后进程A和进程B由都执行fork()函数,因此A又创建了子进程C,B创建了子进程D,现在一共有四个进程ABCD,然后同时执行下面的printf("-");,打印四次,输出四个"-",一共输出6个"-"。
如下图:
可见,一共执行了6次printf("-")。
OK,我们知道了这个之后再来看一道有意思的问题:
#include<stdio.h> int main() { fork(); fork()&&fork()||fork(); fork(); }请问有多少个进程?
分析:解决这个问题主要注意三点:1.子进程是从fork后面那个指令开始执行的;2.fork父子进程的不同返回值;3对于"a&&b"如果a为0,那么不会再执行b。
用语言来描述实在是太复杂,上一张,希望读者能够看懂:
参考资料:
《UNIX高级环境编程》
转载请注明出处:http://blog.csdn.net/lavorange/article/details/38961247