进程控制编程之僵尸进程、守护进程创建、进程等待
来源:互联网 发布:办公软件考试系统 编辑:程序博客网 时间:2024/06/08 16:07
一 僵尸进程:那些虽然已经终止的进程,但进程描述符仍然保留在内存中(进程描述符占有极少的内存空间),等待其父进程为其收尸。
1,僵尸进程是子进程比父进程先终止:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){pid_t pid = fork();if(pid == -1){perror("fork ");return -1;}if(pid > 0){printf("父进程 ID :%d\n",getpid());while(1);}else{printf("子进程 ID : %d\n",getpid());exit(0);}return 0;}设置一个死循环让父进程一直运行,子进程先结束,使用ps -ef | grep a.out 查看进程:
产生一个<defunct>,死了的进程即僵尸进程,若要处理僵尸进程,kill子进程是不可行的,只有kill其父进程。后面也会讲到用wait和waitpid处理
[root@promote 21-进程]# ps -ef | grep a.out root 771 5570 97 23:41 pts/1 00:00:44 ./a.outroot 772 771 0 23:41 pts/1 00:00:00 [a.out] <defunct>root 811 775 0 23:42 pts/0 00:00:00 grep a.out[root@promote 21-进程]# kill 772[root@promote 21-进程]# ps -ef | grep a.out root 771 5570 98 23:41 pts/1 00:04:00 ./a.outroot 772 771 0 23:41 pts/1 00:00:00 [a.out] <defunct>root 852 775 0 23:45 pts/0 00:00:00 grep a.out[root@promote 21-进程]# kill 771[root@promote 21-进程]# ps -ef | grep a.out root 854 775 0 23:45 pts/0 00:00:00 grep a.out2,父进程比子进程先结束,子进程会由其祖先进程init所领养
[root@promote 21-进程]# ./a.out 子进程 ID : 892父进程 ID :891[root@promote 21-进程]# ps -ef | grep a.out root 892 1 93 23:50 pts/0 00:00:05 ./a.outroot 894 775 0 23:50 pts/0 00:00:00 grep a.out[root@promote 21-进程]# pstreeinit─┬─/usr/bin/sealer ├─VGAuthService ├─a.out二 守护进程创建:Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int mon(){pid_t pid = fork();if(pid < 0){perror("fork ");return -1;}if(pid > 0)//父进程终止{exit(0);}//创建新会话 setsid() //#include <unistd.h> //pid_t setsid(void);if(setsid() < 0){return -1;//On error, -1 is returned, and errno is set.}//重设文件掩码 umask()//#include <sys/types.h> //#include <sys/stat.h> //mode_t umask(mode_t mask);umask(0);//改变文件工作目录 chdir()//#include <unistd.h> //int chdir(const char *path);if(chdir("/") < 0){return -1;//On success,zero is returned.On error, -1 is returned}//关闭文件描述符(关闭标准输入,标准输出,标准错误)close(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);//重定向标准输入、标准输出、标准错误open("/dev/NULL",O_RDWR); //fd 0open("/dev/NULL",O_RDWR); //fd 1open("/dev/NULL",O_RDWR); //fd 2//因为守护进程没有控制终端,标准输出等也被重定向到了 /dev/null//进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。return 0;}int main(){mon();while(1);return 0;}
[root@promote 21-进程]# ./a.out [root@promote 21-进程]# ps -ef |grep a.out root 1182 1 96 00:19 ? 00:00:08 ./a.outroot 1184 775 0 00:19 pts/0 00:00:00 grep a.out进程在后台运行并未形成僵尸进程
当然系统提供的函数daemon() 可以直接创建守护进程,上述做法为了更好的了解守护进程
三 进程等待:wait waitid
父进程创建子进程后,要知道子进程什么时候被终止,是被正常终止还是不正常终止
1,wait : 如果一个子进程已经终止,并且是一个僵死进程,wait立即返回并取得该子进程的状态,否则wait使其调用者阻塞直到一个子进程终止。如果调用者阻塞并且它有多个子进程,则在其一个子进程终止时,wait就立即返回。因为wait返回终止子进程的ID,所以总能了解到是哪一个子进程终止了。
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <stdlib.h>#include <sys/wait.h>int main(){pid_t pid = fork();if(pid == -1){perror("fork ");return -1;}if(pid > 0){printf("父进程ID :%d\n",getpid());sleep(5);//等待子进程结束int status;pid_t childpid = wait(&status);printf("成功处理一个子进程,该子进程ID :%d\n",childpid);if(WIFEXITED(status))//若子进程正常死亡,返回一个非零值{printf("子进程正常死亡\n");}else{printf("非正常死亡\n");}}else{printf("子进程ID :%d\n",getpid());exit(0);}return 0;}
当子进程先结束,父进程睡眠5秒之后执行wait函数,讲子进程正常处理
[root@promote 21-进程]# ./a.out 子进程ID :1326父进程ID :1325成功处理一个子进程,该子进程ID :1326子进程正常死亡
在父进程睡眠时,查看进程会发现子进程成为僵尸进程,在5秒后wait才把该进程处理掉
[root@localhost 21-进程]# ps -ef |grep a.outroot 1325 775 0 00:38 pts/0 00:00:00 ./a.outroot 1326 1325 0 00:38 pts/0 00:00:00 [a.out] <defunct>root 1328 5570 0 00:38 pts/1 00:00:00 grep a.out[root@localhost 21-进程]# ps -ef |grep a.outroot 1330 5570 0 00:38 pts/1 00:00:00 grep a.out
若是子进程还在运行中,中途kill子进程:子进程非正常死亡
[root@localhost 21-进程]# ps -ef |grep a.outroot 1465 775 0 00:53 pts/0 00:00:00 ./a.outroot 1466 1465 99 00:53 pts/0 00:00:06 ./a.outroot 1468 5570 0 00:53 pts/1 00:00:00 grep a.out[root@localhost 21-进程]# kill 1466[root@promote 21-进程]# ./a.out 子进程ID :1466父进程ID :1465成功处理一个子进程,该子进程ID :1466非正常死亡
2,waitpid:
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
参数:如果不在意结束状态值,则参数status可以设成NULL。
参数pid为欲等待的子进程识别码:
pid<-1 等待进程组识别码为pid绝对值的任何子进程。
pid=-1 等待任何子进程,相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid的子进程。
参数option可以为0 或下面的OR 组合
WNOHANG: 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED :如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <stdlib.h>#include <sys/wait.h>int main(){pid_t pid = fork();if(pid == -1){perror("fork ");return -1;}if(pid == 0){printf("子进程ID :%d \n",getpid());exit(0);}else if(pid > 0){printf("父进程ID :%d\n",getpid());sleep(10);int status;pid_t childpid = waitpid (-1,&status,WNOHANG);//pid == -1 :等待任何一个子进程退出,此时和wait相同printf("成功处理子进程,该子进程是 :%d,%d\n",childpid,status);}return 0;}
当pid = -1时,处理结果和wait相同
[root@promote 21-进程]# ./a.out 子进程ID :1507 父进程ID :1506成功处理子进程,该子进程是 :1507,0
- 进程控制编程之僵尸进程、守护进程创建、进程等待
- 进程控制-------僵尸进程、守护进程
- 守护进程、僵尸进程
- Linux进程控制编程之守护进程
- 守护进程与僵尸进程
- 守护进程与僵尸进程
- 僵尸进程和守护进程
- 守护进程和僵尸进程
- 守护进程与僵尸进程
- 守护进程与僵尸进程
- 守护进程与僵尸进程
- 守护进程和僵尸进程
- 区别之守护进程 孤儿进程 僵尸进程
- 区别之守护进程 孤儿进程 僵尸进程
- 面试总结之守护进程,僵尸进程和孤儿进程
- C语言之进程控制(僵尸进程和守护进程)
- 进程控制(上):进程创建,进程等待,进程终止
- 孤儿进程、僵尸进程、守护进程
- 九的余数
- 2017年8月11日 星期五
- Codeforces Round #401 (Div. 2) (solve 4 of 5)
- java中构造方法
- Docker下用.NET Core写C#程序
- 进程控制编程之僵尸进程、守护进程创建、进程等待
- ubuntu1604环境下安装caffe及cuda80等相关组件实际操作流程
- Windows 7 Boot Updater 如何使用
- hpu 多校联萌(三) 1415
- 二叉树问题---统计所有可能的二叉树结构的种数
- Trie总结
- 解决mac osx下pip安装ipython权限的问题
- java中的锁优化
- Microsoft Corporation 去掉 windows 修改 启动加载 版权