码迷,mamicode.com
首页 > 其他好文 > 详细

APUE学习笔记——8.3~8.4创建新进程fork()、vfork()

时间:2014-08-29 14:44:18      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:子进程   fork   vfork   

  1. #include <unistd.h>
  2. pid_t fork(void);
  3. Returns: 0 in child, process ID of child in parent,?1 on error
    Unix可以使用系统函数fork()创建一个新进程。
    fork()执行一次返回两次。
    返回值:
        0:            表示子进程
        子进程id: 表示父进程
     子进程可以通过getppid()来获取父进程id,所以只需要返回0,表示创建成功即可.而对于父进程来说,他无从得知子进程的id,因此在创建的时候就应该吧子进程的Id号返回给他。

    我们知道,每个进程都会涉及到进程控制块、正文段、数据段,三部分内容。
    进程控制块是每个进程独有的,这就不用多说。 
    正文段里面是程序的指令,都是只读的,因此父进程和子进程可以共享这部分内容 。share
    数据段:  子进程会拷贝一份父进程的数据段(数据空间、堆、栈)。注意:这里是copy而不是share

    由于我们知道,一般创建子进程后,进阶着就是使用exec替换子进程为一个新的程序了,这是父进程的数据段内容就没什么用了。因此,现代系统在实现的时候,采用了写时复制copy-on-write(COW)。该方法就是内核将数据段设置为共享share,但它是只读的,当父进程或者子进程下需要对数据进行修改时,就自己copy一个副本。

    Example
  1. #include "apue.h"
  2. #include "myerr.h"
  3. int globvar=6;/*external variable in initialized data */
  4. char buf[] = "a write to stdout\n";
  5. int
  6. main(void)
  7. {
  8. int var; /* automatic variable on the stack */
  9. pid_t pid;
  10. var = 88;
  11. if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
  12. err_sys("write error");
  13. printf("before fork\n"); /* we don’t flush stdout */
  14. if ((pid = fork()) < 0) {
  15. err_sys("fork error");
  16. }else if (pid == 0) { /* child */
  17. globvar++; /* modify variables */
  18. var++;
  19. }else {
  20. sleep(2); /* parent */
  21. }
  22. printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
  23. exit(0);
  24. }
执行结果:
    
  1. windeal@ubuntu:~/Windeal/apue$ ./exe
  2. a write to stdout
  3. before fork
  4. pid = 4523, glob = 7, var = 89
  5. pid = 4522, glob = 6, var = 88
  6. windeal@ubuntu:~/Windeal/apue$
在这个例子中,我们在子进程中对globvar和var都进行自加,然后又在父进程中sleep(2),使得子进程先执行。
最终结果,父进程的数据都没变,子进程globvar和var都变成了新的值。
    从例子中可以看出,正文段是共享的,都使用了printf语句(你要说是copy,我就不跟你辩了。。。)
vfork()
    功能与fork()基本相似。
    不同点:
        vfork保证子进程先执行,也就是子进程执行了exec程序或者exit后才执行fork()。如果子进程中有依赖父进程的下一步动作才能执行的部分,可能会导致死锁。
        vfork创建的子进程会共享父进程的数据段。也就是说它会改变父进程的数据。
  1. #include "apue.h"
  2. #include "myerr.h"
  3. int globvar=6;/*external variable in initialized data */
  4. int
  5. main(void)
  6. {
  7. int var; /* automatic variable on the stack */
  8. pid_t pid;
  9. var = 88;
  10. printf("before vfork\n"); /* we don’t flush stdio */
  11. if ((pid = vfork()) < 0) {
  12. err_sys("vfork error");
  13. }else if (pid == 0) { /* child */
  14. globvar++; /* modify parent’s variables */
  15. var++;
  16. _exit(0); /* child terminates */
  17. }
  18. /* parent continues here */
  19. printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
  20. exit(0);
  21. }
  22. ~
执行结果:
  1. windeal@ubuntu:~/Windeal/apue$ ./exe
  2. before vfork
  3. pid = 6298, glob = 7, var = 89
  4. windeal@ubuntu:~/Windeal/apue$
可以看到父进程globvar和var被子进程改变了。

        vfork()被一些版本视为过时的接口,一般不使用。所以不必过多研究,多用fork()来创建新进程即可。


APUE学习笔记——8.3~8.4创建新进程fork()、vfork()

标签:子进程   fork   vfork   

原文地址:http://blog.csdn.net/windeal3203/article/details/38924869

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!