给出如下C程序,在linux下使用gcc编译:
#include "stdio.h"
#include "sys/types.h"
#include "unistd.h"
int main()
{
pid_t pid1;
pid_t pid2;
pid1 = fork();
pid2 = fork();
printf("pid1:%d, pid2:%d\n", pid1, pid2);
}
要求如下:
已知从这个程序执行到这个程序的所有进程结束这个时间段内,没有其它新进程执行。
1、请说出执行这个程序后,将一共运行几个进程。
2、如果其中一个进程的输出结果是“pid1:1001, pid2:1002”,写出其他进程的输出结果(不考虑进程执行顺序)。
解答: P0 ----------> fork pid1=1001 -----------> fork pid2=1002 (1001,1002)
| P1 |P2
| | ------> pid2=0 (1001,0)
| -->pid1=0 ------------> fork pid2=1003 (0,1003)
| ------>pid2=0 (0,0)
fork以后子进城继承父进程的所有变量、环境变量、程序计数器的当前值。
vfork 和 fork 被调用时都返回两次。两次返回的唯一区别是子进程返回0,而父进程的返回子进程的进程ID。
两者的区别是:
1、fork()创建的子进程是父进程的副本,即子进程有父进程数据空间,堆和栈的副本(不是共享)。而vfork()创建的进程并不将父进程的地址空间完全复制到子进程中,相反,在子进程调用exec或exit之前,它在父进程的空间进行。
2、vfork()保证子进程先运行,在调用exec或exit之前共享父进程数据,在它调用exec或exit之后父进程才可能被调度运行。
3、vfork的子进程在调用exec或exit之前若依赖于父进程的进一步动作,则会导致死锁。
vfork引进的缘由: 以前的fork比较傻,要创建新地址空间,并拷贝父进程的资源,而往往子进程会调用exec,这样前面的工作就白费了。于是vfork暂时共享父进程的地址空间,所以不能进行写操作。
新内核中的fork都采用了写时复制技术(对地址空间,mm和页表还是要复制的),大大提高了性能(但是肯定比vfork开销大,vfork不用复制),vfork也就没多少意义了。
进程fork后,如果设置CLONE_FILES标识(进程间共享文件),则增加current task_struct -> files -> count (此时,所有进程共享打开的文件,相互之间互相影响); 反之,则调用dup_fd 增加file->f_count(). 问题: 如果父进程不是共享方式打开的话,是不是应该打开失败? 比如设备文件?