孤儿进程与僵尸进程

孤儿进程:

如果父进程先退出,子进程还没退出那么子进程的父进程将变为init进程。(注:任何一个进程都必须有父进程)

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <unistd.h>
  5. int main()
  6. {
  7. pid_t pid;
  8. //创建一个进程
  9. pid = fork();
  10. //创建失败
  11. if (pid < 0)
  12. {
  13. perror("fork error:");
  14. exit(1);
  15. }
  16. //子进程
  17. if (pid == 0)
  18. {
  19. printf("I am the child process.\n");
  20. //输出进程ID和父进程ID
  21. printf("pid: %d\tppid:%d\n",getpid(),getppid());
  22. printf("I will sleep five seconds.\n");
  23. //睡眠5s,保证父进程先退出
  24. sleep(5);
  25. printf("pid: %d\tppid:%d\n",getpid(),getppid());
  26. printf("child process is exited.\n");
  27. }
  28. //父进程
  29. else
  30. {
  31. printf("I am father process.\n");
  32. //父进程睡眠1s,保证子进程输出进程id
  33. sleep(1);
  34. printf("father process is  exited.\n");
  35. }
  36. return 0;
  37. }

僵尸进程:

如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵尸进程。

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. int main()
  6. {
  7. pid_t pid;
  8. pid = fork();
  9. if (pid < 0)
  10. {
  11. perror("fork error:");
  12. exit(1);
  13. }
  14. else if (pid == 0)
  15. {
  16. printf("I am child process.I am exiting.\n");
  17. exit(0);
  18. }
  19. printf("I am father process.I will sleep two seconds\n");
  20. //等待子进程先退出
  21. sleep(2);
  22. //输出进程信息
  23. system("ps -o pid,ppid,state,tty,command");
  24. printf("father process is exiting.\n");
  25. return 0;
  26. }

<defunct>僵尸进程

孤儿进程由init处理,并不会有什么危害。但是僵尸进程的大量存在会占用PID等资源,可能会导致系统无法产生新的进程。任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个
子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。  如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理

避免僵尸进程

通过信号机制

 子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程。测试程序如下所示:

  1. //示例: 避免僵尸进程
  2. int main(int argc, char *argv[])
  3. {
  4. signal(SIGCHLD, SIG_IGN);
  5. pid_t pid = fork();
  6. if (pid < 0)
  7. err_exit("fork error");
  8. else if (pid == 0)
  9. exit(0);
  10. else
  11. {
  12. sleep(50);
  13. }
  14. exit(0);
  15. }

文件共享

父进程的所有文件描述符都被复制到子进程中, 就好像调用了dup函数, 父进程和子进程每个相同的打开文件描述符共享一个文件表项(因此, 父子进程共享同一个文件偏移量);

  1. //根据上图: 理解下面这段程序和下图的演示
  2. int main(int argc, char *argv[])
  3. {
  4. signal(SIGCHLD, SIG_IGN);
  5. int fd = open("test.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);
  6. if (fd == -1)
  7. err_exit("file open error");
  8. cout << "We Don`t flash memory\n";
  9. char buf[BUFSIZ];
  10. bzero(buf, sizeof(buf));
  11. pid_t pid = fork();
  12. if (pid < 0)
  13. err_exit("fork error");
  14. else if (pid > 0)
  15. {
  16. strcpy(buf, "Parent...");
  17. write(fd, buf, strlen(buf));
  18. close(fd);
  19. cout << "fd = " << fd << endl;
  20. exit(0);
  21. }
  22. else if (pid == 0)
  23. {
  24. strcpy(buf, "Child...");
  25. write(fd, buf, strlen(buf));
  26. close(fd);
  27. cout << "fd = " << fd << endl;
  28. exit(0);
  29. }
  30. }

结果是fd(文件描述符)的值相等。这说明父子进程共享同一个文件描述符,当然文件偏移量等信息也是共享的。

fork与vfork的区别

1. fork子进程拷贝父进程的数据段(但是现在提供了写时复制技术,只有当子进程真正需要写内存时,才复制出该内存的一段副本),因此,在父进程/子进程中对全局变量所做的修改并不会影响子进程/父进程的数据内容.

vfork子进程与父进程共享数据段,因此父子进程对数据的更新是同步的;

2. fork父、子进程的执行次序是未知的,取决于操作系统的调度算法

vfork:子进程先运行,父进程后运行;

3. 如果创建子进程是为了调用exec执行一个新的程序的时候,就应该使用vfork,但是你在vfork后执行其它语句却是非常危险的,因为很容易和父进程产生冲突。

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main(void)
  4. {
  5. pid_t pid;
  6. int count = 0;
  7. pid=vfork();
  8. count++;
  9. printf("count=%d\n",count);
  10. return 0;
  11. }

在学习linux进程编程的时候遇到一个问题,就是使用vfork()函数以后本以为下面会打印出1和2,但是结果却出人意料。

打印出的结果是:

count=1

count=1

Segmentation fault

出现了段错误,经过查证得知,vfork()创建子进程成功后是严禁使用return的,只能调用exit()或者exec族的函数,否则后果不可预料,在main函数里return和exit()效果一样是有前提的:没有调用vfork。

(如果return处什么都没有也会出现段错误,结果如下

count=1

count=9

Segmentation fault

)

Linux进程理解与实践(二)僵尸&孤儿进程 和文件共享的更多相关文章

  1. Linux进程理解与实践(三)进程终止函数和exec函数族的使用

    进程的几种终止方式(Termination) (1)正常退出 从main函数返回[return] 调用exit 调用_exit或者_Exit 最后一个线程从其启动处返回 从最后一个线程调用pthrea ...

  2. Linux进程理解与实践(四)wait函数处理僵尸进程

    Wait的背景 当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) 子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程 ...

  3. Linux进程理解与实践(五)细谈守护进程

    一. 守护进程及其特性      守护进程最重要的特性是后台运行.在这一点上DOS下的常驻内存程序TSR与之相似.其次,守护进程必须与其运行前的环境隔离开来.这些环境包括未关闭的文件描述符,控制终端, ...

  4. Linux进程理解与实践(一)基本概念和编程概述(fork,vfork,cow)

    进程 and 程序 什么是程序? 程序是完成特定任务的一系列指令集合. 什么是进程? [1]从用户的角度来看:进程是程序的一次执行过程 [2]从操作系统的核心来看:进程是操作系统分配的内存.CPU时间 ...

  5. !!!!Linux系统开发 系列 4 进程资源 环境 fork()子进程 wait() waitpid()僵尸 孤儿进程

    http://990487026.blog.51cto.com/10133282/1834893

  6. OWIN的理解和实践(二) – Host和Server的开发

    对于开发人员来说,代码就是最好的文档,如上一篇博文所说,下面我们就会基于Kanata项目的一些具体调用代码,来进一步深入理解OWIN的实现和作用. 今天我们先针对Host和Server来实现一个简单的 ...

  7. 进程与线程(二) java进程的内存模型

    从我出生那天起,我就知道我有个兄弟,他桀骜不驯,但实力强悍 ,人家都叫它C+++            ----java 上回说到了,C进程的内存分配,那么一个java运行过程也是一个进程,java内 ...

  8. 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程

    23.1 进程链和进程扇 23.1.1 概念 进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程.... 这种就为进程链 进程扇:一个父进程构建出多个子进程,子进程都 ...

  9. 【Linux 进程】孤儿进程、僵尸进程和守护进程

    1.孤儿进程: 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程.孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作.孤儿进程是 ...

随机推荐

  1. Java实验项目二——猜数游戏

    1 /* 2 * Description:定义比较类,实现两个数的比较 3 * 4 * */ 5 6 7 package compare; 8 9 import dao.Operate; 10 11 ...

  2. 小哈学python----一行代码输出特定字符"Love"拼成的心形

    print('\n'.join([''.join([('Love'[(x-y) % len('Love')] if ((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2* ...

  3. java001-泛型

    泛型出现的意义: 为编码阶段的不确定性和转化做视觉设计 将运行期遇到的问题转移到编译期,省去了强转的麻烦 package com.xiaolin.basic; /** * 泛型:将运行期遇到的问题转移 ...

  4. 管理员的基本防范措施 Linux系统安全及应用

    系统安全及应用一.账号安全基本措施① 系统账号清理② 密码安全控制③ 命令历史限制④ 终端自动注销二.SU命令切换用户① 用途及用法② 验证密码③ 限制使用su命令的用户④ 查看su操作记录补充三.L ...

  5. [刘阳Java]_BeanNameViewResolver视图解析器_第8讲

    BeanNameViewResolver:这个视图解析器跟XmlViewResolver有点类似,也是通过把返回的逻辑视图名称去匹配定义好的视图bean对象.它要求视图bean对象都定义在Spring ...

  6. IDEA 生成类注释和方法注释

    目录 一.生成类注释-01 1.1.生成类注解模板 1.2.把模板设置到IDEA中 1.3.效果图 二.生成类注释-02 2.1.生成类注释模板 2.2.把模板设置到IDEA中 2.3.效果图 2.4 ...

  7. 《手把手教你》系列技巧篇(九)-java+ selenium自动化测试-元素定位大法之By name(详细教程)

    1.简介 上一篇宏哥已经介绍了通过id来定位元素,今天继续介绍其他剩下的七种定位方法中的通过name来定位元素.本文来介绍Webdriver中元素定位方法之By name,顾名思义,就是我们想要定位的 ...

  8. CocoaPods 私有化

    一.创建所需要的代码仓库 创建 Spec 私有索引库(ZFSpec),用来存放本地spec 创建模块私有库(ZFPodProject),用来存放项目工程文件 二.私有索引库添加到本地 CocoaPod ...

  9. 软件开发(js+java开发)的启发

    发现了个很重要的意义 1,一个对象,既包含被监听的参数,也包括监听处理本身 2,基于1的开发模式 3,在函数中定义监听器 4,1)高内聚: 统一面向对象,一个功能一个对象 不同对象不互相调用,不互相引 ...

  10. Android系统编程入门系列之界面Activity响应丝滑的传统动画

    上篇文章介绍了应用程序内对用户操作响应的相关方法位置,简单的响应逻辑可以是从一个界面Activity跳转到另一个界面Activity,也可以是某些视图View的相对变化.然而不管是启动一个界面执行新界 ...