当前位置:  技术问答>linux和unix

vfork深度解析!!!

    来源: 互联网  发布时间:2016-05-12

    本文导语:  我们已经知道,fork会将调用进程的所有内容原封不动的拷贝到新产生的子进程中去,这些拷贝的动作很消耗时间,而如果fork完之后我们马上就调用exec,这些辛辛苦苦拷贝来的东西又会被立刻抹掉,这看起来非常不划...

我们已经知道,fork会将调用进程的所有内容原封不动的拷贝到新产生的子进程中去,这些拷贝的动作很消耗时间,而如果fork完之后我们马上就调用exec,这些辛辛苦苦拷贝来的东西又会被立刻抹掉,这看起来非常不划算,于是人们设计了一种"写时拷贝(copy-on-write)"技术,使得fork结束后并不立刻复制父进程的内容,而是到了真正实用的时候才复制,这样如果下一条语句是exec,它就不会白白作无用功了,也就提高了效率


上面这段话高手能不能解释一下,特别是“这些辛辛苦苦拷贝来的东西又会被立刻抹掉”为什么会这样,原因是什么?
“进程的所有内容”是PCB里的内容吗?
我们平时在linux下开发用fork还是vfork?

|
呵呵
其实上面一段话的意思是LINUX内核用的是一种写时拷贝copy-on-write技术,也就是说fork的时候子进程是完全复制父进程的页面(这里的复制,指子进程未分配独立的页面,共享父进程的页面,只不过复制了父进程的mm_struct页面结构而已,这样好处就是,开销小
但有一个问题?子进程要写的时候怎么办,此时才会真正分配页面,那这个是怎么实现的呢,原来子进程在创建时将父子进程的页面表项改成了写保护,只要父/子进程一方要写此空间时就会触发一次页面异常,由内核来为子进程重新分配页面,修改页面表项目标志
这样的好处是什么呢,让LINUX在创建进程的时候大大降低了开销,能够快速地复制进程就是源于此
vfork一般是系统来调用的,大家都知道LINUX的线程创建就是通过内核调用vfork来实现的.

vfork会复制父进程的copy_files,copy_fs,copy_sighand,而不拷贝mm_struct只是通过指针共享父进程的mm_struct并没有自己的复本,这就是跟fork的区别

|
应用编程里的共享内存机制明白吗? 在各自的进程的空存空间里的地址是不一样的,但都是对应同一块物理内存。fork的行为也有点类似,fork后的父子进程的对应的物理内存其实是完全一样的,并没有实际进行任何的物理内存拷贝。只是当你父子任何一个进程要改变内存里的内容是,就会发生6楼所说的写时复制。但6楼说线程的创建是用vfork应该是不对的。

|


父进程中的数据空间和堆、栈可能会产生副本,具体情况要看你使用的是vfork还是fork.fork会产生副本,而vfork则共享这部分内存。


下面是“Unix环境高级编程”里面摘录的一段。更多的内容可能需要你自己去仔细研读了   
    
  用f   o   r   k函数创建子进程后,子进程往往要调用一种e   x   e   c函数以执行另一个程序。   
  当进程调用一种e   x   e   c函数时,该进程完全由新程序代换,而新程序则从其m   a   i   n函数开始执行。   
  因为调用e   x   e   c并不创建新进程,所以前后的进程I   D并未改变。e   x   e   c只是用另一个新程序替换了   
  当前进程的正文、数据、堆和栈段。   
  前面曾提及在执行e   x   e   c后,进程I   D没有改变。除此之外,执行新程序的进程还保持了原进   
  程的下列特征:   
  ?   进程I   D和父进程I   D。   
  ?   实际用户I   D和实际组I   D。   
  ?   添加组I   D。   
  ?   进程组I   D。   
  ?   对话期I   D。   
  ?   控制终端。   
  ?   闹钟尚余留的时间。   
  ?   当前工作目录。   
  ?   根目录。   
  ?   文件方式创建屏蔽字。   
  ?   文件锁。   
  ?   进程信号屏蔽。   
  ?   未决信号。   
  ?   资源限制。   
  ?   tms_utime,   tms_stime,   tms_cutime以及t   m   s   _   u   s   t   i   m   e值。   
  对打开文件的处理与每个描述符的e   x   e   c关闭标志值有关。见图3   -   1以及3   .   1   3   节中对   
  F   D   _   C   L   O   E   X   E   C的说明,进程中每个打开描述符都有一个e   x   e   c关闭标志。若此标志设置,则在   
  执行e   x   e   c时关闭该描述符,否则该描述符仍打开。除非特地用f   c   n   t   l设置了该标志,否则系统的   
  默认操作是在e   x   e   c后仍保持这种描述符打开。

|
用f  o  r  k函数创建子进程后,子进程往往要调用一种e  x  e  c函数以执行另一个程序。

问题是,子进程其实都还没有运行的呀?
而且子进程是
“在什么时候”
“什么地方”
“通过什么方式”
来调用exec中的一个函数的呢?


因为从 exec函数的实现来看,确实是当前进程的可执行文件被我们要执行的那个文件给替换掉了。
以下代码摘至,linux 0.11 内核中exec.c文件中的do_execve()函数:
  if (current->executable)
    iput (current->executable);  // 放回当前进程的原执行文件的inode
  current->executable = inode;   // 用待执行文件的inode替换原来的执行文件

所以,这么看来,确实是“当前进程(即子进程)”调用exec函数,才能这么做“替换”工作的。

然后就出现了前面的问题了。

现在被这样的东西给搞晕头了。


|
其实也没什么 啦
关键就是这一句

因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。

你能理解这个 就差不多了

|
看看exec的作用是什么

|
帮顶

|
呵呵,,,我再来看看,有没进展

|
嗨嗨,那句辛辛苦苦拷贝来的东西太绝了。
为什么要理解它,只要记住就OK了。

|
exec执行后是去执行别的东西了,而不是当前进程,exec会再产生进程的,所以当前进程就没有了


看看exec就知道了

|
fork时拷贝是通过映射的是同一块物理内存实现的,并没有实际进行数据拷贝. exec的时候还会真正替换里面的内容. 这里需要理解虚拟地址空间跟物理地址空间的区别

|
楼主呢?怎么样 了?

|
因為fork很耗費資源,但是exec又是完全替換,所以當然是"浪費辛辛苦苦的工作", 關於vfork,6樓說到關鍵了!

    
 
 

您可能感兴趣的文章:

 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 我想和vfork出来的子进程通信(见者加分)
  • <unix环境变量高级编程第8章> vfork例题的疑问
  • 我想让vfork后就execl一进程,同时让execl出来的进程之间能相互通信,求助
  • 请问下面一个关于vfork的c程序的运行结果为什么会出现Segmentation fault ?哪位高手帮我解释下,谢谢。
  • 急!同一个c文件里vfork();pthread_create();两个函数,Makefile该怎么写?谢谢
  • vfork函数
  • 关于vfork()函数对父进程空间的处理
  • 使用vfork(),后用return 出现段错误问题
  • 一个简单的vfork pid 问题?
  • what's the difference between fork()&vfork()?
  • 关于vfork()问题,为什么其对父进程共享的变量的操作结果不是预期的?请高手指点,多谢了
  • vfork中多进程间共享描述符的问题


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3