广州网站建设网站定制,wordpress 询价按钮,erp生产管理系统,知名网站建设公司好吗Orphan Process孤儿进程
父进程先于子进程退出#xff0c;子进程失去托管#xff0c;这种子进程统称为孤儿进程 失效进程#xff08;孤儿进程#xff09;#xff1a;导致内存泄漏#xff0c;影响新进程的创建孤儿进程的危害不可预测#xff0c;如果一个孤儿进程持续的申…Orphan Process孤儿进程
父进程先于子进程退出子进程失去托管这种子进程统称为孤儿进程 失效进程孤儿进程导致内存泄漏影响新进程的创建孤儿进程的危害不可预测如果一个孤儿进程持续的申请系统资源这导致影响系统稳定性
编写一个孤儿进程检测处理模型
getpid();
getppid();ps aux #查看进程详细信息
ps ajx #查看进程关系#include sys/mman.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include stdio.h
#include stdlib.h
#include string.hint main()
{pid_t pid;pid fork();if (pid 0){sleep(30);exit(0);}else if (pid 0){printf(child pid %d ,ppid %d, getpid(), getppid());sleep(32);printf(child pid %d ,ppid %d, getpid(), getppid());while(1){sleep(1);}}else{}return 0;
}孤儿进程检查 创建一个独立的check进程。父进程通过管道将自己的pid传给check进程。
process.c
#include stdio.h
#include unistd.h
#include stdlib.h
#include string.h
#include sys/types.h
#include sys/stat.h
#include sys/fcntl.h
#include pthread.h
#include signal.h
#include sys/wait.hint main()
{// 创建五个子进程pid_t pid;int i 0;for (i; i 5; i){pid fork();if (pid 0)break;}// 父进程if (pid 0){int wfd;char str_pid[10];bzero(str_pid, 10);if ((wfd open(fifo, O_RDWR)) -1)//两端都是RDWR权限否则会check端会因为process端结束而发现管道关闭出现异常。{perror(open failed);exit(0);}sprintf(str_pid, %d, getpid());write(wfd, str_pid, strlen(str_pid));sleep(20);exit(0);wait(NULL);}else if (pid 0){printf(child pid %d running..\n, getpid());while (1){sleep(1);}}else{perror(fork call failed);exit(0);}return 0;
}
check.c
#include stdio.h
#include unistd.h
#include stdlib.h
#include string.h
#include sys/types.h
#include sys/stat.h
#include sys/fcntl.h
#include signal.h
#include errno.hint main()
{int rfd;if ((rfd open(fifo, O_RDWR)) -1)//使用RDWR权限防止写端关闭管道权限不够而关闭{perror(打开管道失败);exit(0);}printf(open成功\n);char buf[10];bzero(buf, sizeof(buf));read(rfd, buf, sizeof(buf));pid_t pid atoi(buf);printf(check process pid: %d ,get Parent pid: %d..\n, getpid(), pid);// 非阻塞读取管道// 1、获取文件属性int flag;fcntl(rfd, F_GETFL, flag);flag | O_NONBLOCK; // 设置文件属性为非阻塞fcntl(rfd, F_SETFL, flag);int len;int esrch;char str_pid[10];bzero(str_pid, 10);while ((len read(rfd, buf, sizeof(buf))) -1){// EAGAIN:这意味着“现在没有可用的数据以后再试一次” 。//非阻塞返回if (errno EAGAIN){kill(pid, 0); // 尝试杀一下这个进程if (errno ESRCH){// 要杀的进程已经不存在了printf(check parent %d its dead\n, pid);pid - pid * 2;// sprintf(str_pid,%d,pid);printf(group id %d\n, pid);// 杀死孤儿进程kill(pid, 9);//函数kill比重载kill命令更合理exit(0);}printf(check parent alive\n);}else{perror(read call failed);exit(0);}sleep(1);}if (len 0){printf(parent exit , check_process Done\n);exit(0);}return 0;
}
注意要点
双端访问权限都要是RDWR“通过尝试kill父进程来判断父进程是否存在”不要放在判断语句里。判断errno的值kill子进程组是要使用函数而不是重载命令
进程间三种关系
亲缘关系 process Group进程组关系 为了方便管理系统中大量进程设计了进程组结构属于一种管理概念 进程组是由一个组长进程和多个组员进程构成、PIDProcess ID、PPIDParent Process ID和PGIDProcess Group ID 每个终端进程都是组长进程 组长进程标志pid pgid此进程为组长进程 进程组的生命周期较长与某个特定的进程无关直到组中最后一个进程终止或转移进程组为空时系统释放进程组 根据就近原则组长进程创建的子进程这些子进程会归纳到父进程同组变为组员进程 进程组关系与亲缘关系没有必然联系因为组成员可以转移的 创建进程组只有组员进程可以完成组长无法成功 getpgrp(); //返回当前进程的pgid(组id)setpgid(pid_tpid,pid t gpid); //此函数可以创建组或转移组中进程
setpgid(getpid(),getpid()); //申请组id,创建组只有组员进程可以成功
setpgid(getpid(0,1000); //转移进程到目标组中去转移进程要保证对目标组有足够的访问权限其次目标组要存在
process Session会话关系 会话关系便于终端或系统管理终端进程和终端子进程 会话由一个会话发起者和多个会话参与者构成 会话发起者退出以进程组为单位杀死参与者 只杀死终端进程为首的一组进程 会话发起者的标志 pid pgid sid会话id 后续开发app时要进行脱离控制终端避免会话发起者bash接收杀死应用进程 脱离终端让组员进程创建新组避免杀死 创建新会话脱离原有会话 getsid(getpid());//获取当前进程的会话id
setsid();//当前进程创建新会话,创建新会话只有组员进程能完成因为此函数中会进行进程组创建如果是组长此步骤不会成功终端进程无法脱离终端必然受终端控制因为它无法创建组也无法成立新会话
另一种孤儿进程——守护进程Daemon Process
孤儿进程多进程模型中父进程异常关闭导致子进程失去托管这类进程为孤儿进程。 开发者关闭其父进程让子进程脱离终端控制此进程工作于后台周期执行这类进程称为守护进程也是孤儿
守护进程也叫精灵进程和普通进程的差异性 守护进程的生命周期比普通进程长守护进程的生命周期随操作系统持续开机自动启动关机则关闭 守护进程为主程序提供服务和支持保证主程序的稳定性 守护进程不允许参与前台任务也不允许将数据打印到前台 低效模式运行不允许占用大量系统资源
守护进程执行的三种模式
间隔执行定时执行条件触发
shell脚本实现开机启动
守护进程的开发流程 重定向STD_FILENO 造孤儿——父进程创建子进程、父进程退出 子进程脱离控制终端创建新会话 关闭前台描述符STDIN_FILENO,STDOUT_FILENO STD_FILENO默认是perror(“xxx call faild”) 标准错误是占用标准输出的会将异常信息显示在终端上前台为了避免错误信息抛出到前台可以采用重定向的方式将错误信息抛出到文件中 修改进程的工作目录为根目录 默认情况下进程的工作目录是程序所在位置进程访问文件访问磁盘信息都是以工作目录为基准 修改进程的Umask掩码为0002 执行守护进程任务 守护进程的退出处理
demo,编写一个守护进程后台执行开机启动每间隔3s向time.log中写入系统时间