关于fork以及子shell继承环境变量的疑问

在shell里,有这样的说法“在我目前这个shell的情况下,去启用另一个新的shell,新的那个shell 就是子程序啦!在一般的状态下,父程序的自定义变量是无法在子程序内使用的。但是透过export将变量变成环境变量后,就能够在子程序底下应用了”。

但是在C里,父进程调用fork()创建子进程,子进程成为父进程的副本,复制父进程的所有进程内存到其内存地址空间中。父、子进程的“数据段”,“堆栈段”和“代码段”完全相同,即子进程中的每一个字节都和父进程一样。fork之后,从 fork 处开始父子进程并行执行,公有变量的值也在 fork 处被复制(当时的值),只不过父子进程分别使用各自的复本(而非共享)。

     我对上面的两段话就有点不理不啦,觉得有点矛盾,应该子shell自动继承父shell的变量啊。直到今天意识到忽略了一点。在开启子shell的时候,是fork+exec的模式,系统调用exec是以新的进程去代替原来的进程,原进程的代码段,数据段,堆栈段被新的进程所代替,所以父进程的变量是不会再存在于子进程了。而且exec可以接受一个指向环境字符串指针数组的指针,意思是把新的环境变量指定到新的进程中去,若不提供该指针则将原来的环境变量(即父进程的)默认为新进程的环境变量。

       这样,子shell只能继承父shell的环境变量,并且子shell对环境变量的修改不会影响到父shell就可以理解了。

这里讲解一下fork and exec 过程调用流程

      进程都会通过父进程以复制(fork)的方式产生一个一莫一样的子进程,然后被复制出来的子进程再以exec的方式执行实际要进行的进程,最终就成为一个子进程的存在。整个流程就像下面这张图所示:

      系统先以fork方式复制一个与子进程相同的暂存进程,这个进程与父进程唯一的区别就是PID不同!但是这个暂存进程还会多一个PPID的参数,PPID就是父进程的进程标识符。然后暂存进程开始以exec的方式加载实际要执行的程序,如上图,进的进程的名称为qqq,最终子进程的程序代码就变成qqq了。

在shell中,就是先fork子进程,然后进行程序的替换。上面的问题也就很好的理解

有次写程序也遇要了这样的疑问,想了好半天,最后在网上找到这篇博客,详见下面的地址。

来源:http://m.blog.chinaunix.net/uid-26234482-id-3686073.html

猜你喜欢

转载自blog.csdn.net/smile_zhangw/article/details/81811745