循环创建N个子进程

概述

fork函数对于并发编程来说还是比较重要的,记录下利用fork函数循环创建N个子进程.

例子代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// a file named fork-child.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

#define childNum 10

int main(void)
{
pid_t pid;
int x;

printf("Let's begin!\n\n");

for(x = 0; x < childNum; x++){
pid = fork();
if(pid == -1){
perror("fork error");
exit(1);
}else if(pid == 0){
break;
}
}
if(x < childNum){
sleep(x);
printf("I'm %2dth child, pid = %d\n",x+1,getpid());
}else{
sleep(x);
printf("I'm a parent\n");
}

return 0;
}

编译并运行,输出如下所示:

haha@hello:~/.../test-code$ gcc -g -o fork-child fork-child.c
haha@hello:~/.../test-code$ ./fork-child
Let's begin!

I'm  1th child, pid = 26810
I'm  2th child, pid = 26812
I'm  3th child, pid = 26813
I'm  4th child, pid = 26814
I'm  5th child, pid = 26815
I'm  6th child, pid = 26816
I'm  7th child, pid = 26817
I'm  8th child, pid = 26818
I'm  9th child, pid = 26819
I'm 10th child, pid = 26820
I'm a parent
haha@hello:~/.../test-code$

总结

父子进程之间在fork后,有哪些相同,哪些异同之处?

刚fork后:

父子相同处: 相同变量, .data, .text, 栈,堆,环境变量, 用户ID, 宿主目录, 进程工作目录, 信号处理方式……
父子不同处: 进程ID, fork返回值, 父进程, 进程运行时间, 闹钟(定时器), 未决信号集

似乎, 子进程复制了父进程0-3G用户空间内容,以及父进程的PCB,但pid不同,真的每fork一个子进程都要将父进程的0-3G地址空间完全
拷贝一份,然后映射至物理内存吗?

当然不是!父子进程间遵循读时共享写时复制的原则.这样设计,无论子进程执行父进程的逻辑还是执行自己的逻辑都能节省内存开销.

重点!!!!! 父子进程不共享全局变量.父子进程共享的是文件描述符号(打开文件的结构体)和mmap建立的映射区.

特别的,fork之后父进程先执行还是子进程先执行不确定.取决于内核所使用的调度算法.父进程和子进程争夺使用CPU资源,谁先争夺到,
谁先执行.没有固定的先后执行顺序.