Uni-app App 端自定义导航栏完整实现指南
2025/12/30 14:26:34
正常进程 → 父进程死亡 → 变成孤儿 → 被init收养 → 正常结束 (父母死了) (无父) (政府收养) (正常生活)早期Linux是由init进程直接管理它,Ubuntu并不是由 init进程 接管的
而是由一个systemd接管的
init实际执行的就是systemd,因此被systemd的进程收养的孤儿进程,相当于被 init收养了
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/types.h>intmain(){pid_tpid=fork();if(pid==0){// 子进程printf("子进程 PID=%d 启动\n",getpid());printf("子进程的父进程 PID=%d\n",getppid());// 子进程睡眠5秒,等父进程先死sleep(5);printf("5秒后...\n");printf("子进程 PID=%d 还在运行\n",getpid());printf("现在的父进程 PID=%d (应该是1)\n",getppid());sleep(5);// 再运行一段时间printf("子进程结束\n");}else{// 父进程printf("父进程 PID=%d 创建了子进程 %d\n",getpid(),pid);printf("父进程立即结束\n");// 父进程立即退出,子进程变成孤儿exit(0);}return0;}# 运行以上的程序,然后用另一个终端查看 $ ps aux | grep -E "PID|孤儿进程的程序名" # 可以看到子进程的PPID(父进程ID)变成了1| 僵尸进程 | 先于父进程结束 | 便于父进程读取进程退出的状态 |
|---|---|---|
| 孤儿进程 | 后于父进程结束 | 常用于创建守护进程 |
// 如果没有孤儿进程收养机制:// 父进程死亡 → 子进程变成"野进程" → 无法被管理 → 资源泄漏// 有了收养机制:// 父进程死亡 → init收养 → 正常管理 → 资源正确释放# init进程(PID=1)是系统所有进程的祖先进程 # 它的责任包括: # 1. 收养所有孤儿进程 # 2. 等待孤儿进程结束 # 3. 回收孤儿进程资源# 方法1:使用ps查看PPID=1的进程ps-eo pid,ppid,pgid,sid,cmd|awk'$2 == 1 && $1 != 1'# 方法2:查找被init收养的进程ps-ef|awk'$3 == 1 && $2 != 0'# 方法3:使用pstree查看进程树pstree -p|grep-A5-B5"init"#!/bin/bash# monitor_orphans.sh - 监控孤儿进程whiletrue;doecho"=== 检查孤儿进程$(date)==="# 查找孤儿进程orphan_count=$(ps-eo pid,ppid,cmd|awk'$2 == 1 && $1 != 1'|wc-l)if[$orphan_count-gt0];thenecho"发现$orphan_count个孤儿进程:"ps-eo pid,ppid,user,cmd,start_time --sort=-start_time|awk'$2 == 1 && $1 != 1'echo"详细信息:"forpidin$(ps-eo pid,ppid|awk'$2 == 1 && $1 != 1 {print $1}');doecho"进程$pid:"echo" 运行时间:"$(ps-oetime=-p $pid)echo" 内存使用:"$(ps-orss=-p $pid)"KB"echo" CPU使用:"$(ps-o %cpu=-p $pid)"%"# 检查是否正常ifkill-0$pid2>/dev/null;thenecho" 状态:运行正常"elseecho" 状态:已结束"fiecho"---"doneelseecho"没有发现孤儿进程"fiecho""sleep60# 每分钟检查一次done#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>intmain(){// 方法1:优雅地终止孤儿进程pid_torphan_pid=1234;// 假设的孤儿进程PID// 先尝试友好终止if(kill(orphan_pid,SIGTERM)==0){printf("已发送SIGTERM给进程 %d\n",orphan_pid);// 等待一段时间sleep(5);// 检查是否还在运行if(kill(orphan_pid,0)==0){printf("进程 %d 还在运行,发送SIGKILL\n",orphan_pid);kill(orphan_pid,SIGKILL);}else{printf("进程 %d 已终止\n",orphan_pid);}}else{printf("进程 %d 不存在或无法终止\n",orphan_pid);}return0;}if(fork()>0)exit(0);//进程组首进程不能成为会话首进程,所以这一步很关键setsid();//成立一个会话close(0);close(1);close(2);或者
close(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);#include<sys/types.h>#include<sys/stat.h>mode_tumask(mode_tmask);对umask()的调用总会成功,并返回进程的前一umask
#include<stdio.h>#include<sys/stat.h>#include<sys/types.h>intmain(intargc,constchar*argv[]){umask(0222);//设置本进程的umask//由于后面不再做任何事所以这里省略了错误判断mkdir("/home/linux/process/tmp_mkdir",0777);perror("mkdir");//提示目录文件是否创建成功return0;}if(-1==chdir("/")){perror("chdir");exit(EXIT_FAILURE);}| 特性 | 孤儿进程 | 僵尸进程 | 守护进程 |
|---|---|---|---|
| 父进程状态 | 已终止 | 未调用wait() | 已终止(故意) |
| 进程状态 | 运行中 | 已终止 | 运行中 |
| 占用资源 | 正常占用 | 占用PID,不占内存 | 正常占用 |
| 能否被杀死 | 可以 | 不可以 | 可以 |
| 回收者 | init进程 | 父进程 | init进程 |
| 产生方式 | 父进程先死 | 父进程不wait | 故意fork两次 |
| 是否正常 | 正常现象 | 程序bug | 设计如此 |