进程篇:循环创建N个子进程
标签:fork();N个子进程
从前面的进程篇——fork()可以了解到fork函数会创建父进程和子进程,并且他们在执行的时候,怎么来控制说是先创建父进程,还是先创建子进程呢?其实根据计算机原理来说,父子进程抢占cpu,谁先得到就谁先执行,其实也有一种说法,是父进程先执行的可能性比较大,但是没有理论依据。好了,费话不多说,我们来看代码。
首先,我们先看这样的一段代码:
1 #include<stdio.h>2 #include<unistd.h>3 int main()4 {5 int i;6 pid_t pid;7 // for(i=0;i<5;i++)8 // {9 pid = fork();10 if(pid==-1)11 perror("error\n");12 else if(pid==0)13 printf("child,pid=%u,ppid=%u\n",getpid(),getppid());14 else{15 // sleep(1); 16 printf("father,pid=%u,ppid=%u\n",getpid(),getppid());17 }18 // }19 return 0;20 21 }
这段代码其实很简单,但是大家看一下结果,就会有问题了:
从这个结果,我们可以看出的是,结果输出为什么会出现在命令行中,而不是像平时代码一样,执行完后出现命令行,但是这个确出现在了命令行。我们用命令查看一下,输入命令:
ps aux | grep 2669
得到的结果是:
wz 2669 0.0 0.3 8512 3468 pts/0 Ss 10:21 0:00 bash
wz 6391 0.0 0.0 6124 824 pts/0 S+ 20:41 0:00 grep --color=auto 2669
看到这个2669这个进程是bash进程的进程号: 所以产生上面的现象的原因是:
在产生这么多的子进程的时候,bash是不知道这么多的子进程和孙子进程的,在开始的shell命令行中,我们使用./fork的命令,然后shell进程把自己切入到后台,前台是给了fork程序来使用的,shell进程收回前台的命令是在它执行完之后,也就是儿子进程执行完之后,shell会收回前台,在父进程return之后,shell进程就把前台收回了,然后再进入命令行模式中,等待用户输入命令,所以会出现这样的情况,所以解决办法就是保证shell的子进程在最后结束。
好了,解决完上面的问题,我们来看循环子进程的问题。对于循环子进程来说,我们很容易就知道,我们需要fork()函数执行N次,我们用3次来模拟,代码如下:
1 #include<stdio.h>2 #include<unistd.h>3 int main()4 {5 int i;6 pid_t pid;7 for(i=0;i<3;i++)8 {9 pid = fork();10 if(pid==-1)11 perror("error\n");12 else if(pid==0)13 printf("i am %dth child,pid=%u,ppid=%u\n",i+1,getpid(),getppid() ); 14 else{15 sleep(1);16 printf("i am %dth father,pid=%u,ppid=%u\n",i+1,getpid(),getppid( ));17 }18 }19 return 0;20 21 }
得到的结果为:
i am 1th child,pid=7222,ppid=7221
i am 2th child,pid=7223,ppid=7222
i am 3th child,pid=7224,ppid=7223
i am 1th father,pid=7221,ppid=2669
i am 2th father,pid=7222,ppid=7221
i am 3th father,pid=7223,ppid=7222
i am 2th child,pid=7225,ppid=7221
i am 3th child,pid=7226,ppid=7222
i am 3th child,pid=7227,ppid=7225
i am 2th father,pid=7221,ppid=2669
i am 3th father,pid=7222,ppid=7221
i am 3th father,pid=7225,ppid=7221
i am 3th child,pid=7228,ppid=7221
i am 3th father,pid=7221,ppid=2669
看起来比较凌乱。但是为什么会出现这么多,我们通过一张图来看一下:
从这图很容易看出来子进程产生的过程。
上面的程序我们修改一下,就可以很准确的看到有几个子进程被创建:
1 #include<stdio.h>2 #include<unistd.h>3 int main()4 {5 int i;6 pid_t pid;7 for(i=0;i<5;i++)8 {9 pid = fork();10 if(pid==-1)11 perror("error\n");12 else if(pid==0)13 {14 break;15 }16 if(i<5) 17 {18 sleep(i);19 printf("i am %dth child\n",i+1);20 }21 else22 {23 sleep(i);24 printf("i am parent\n");25 }26 }27 return 0;28 29 }
结果为:
i am 1th child
i am 2th child
i am 3th child
i am 4th child
i am 5th child
这就看起来比较明显了。