Linux - fork

给出如下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().  问题: 如果父进程不是共享方式打开的话,是不是应该打开失败? 比如设备文件?

你可能感兴趣的:(c,linux,工作,struct,gcc)