进程参数和环境参数的意义
— 一般情况下,子进程的创建是为了解决某个子问题
— 子进程解决问题需要父进程的"数据输入" (进程参数 & 环境变量)
设置原则:
-
子进程启动时必然用到的参数使用进程参数传递
-
子进程解决问题可能用到的参数使用环境变量传递
编程示例:
可以看到需要返回值是19 注意echo $?是打印最近一个进程的执行结果!!!
深入理解父子进程
— 子进程的创建是为了并行的解决子问题(问题分解)
— 父进程需要通过子进程的结果最终解决问题(并获取结果)
进程等待系统接口
pid_t wait(int* status) 标准
- 等待一个子进程完成,并返回子进程标识和状态信息
- 当有多个子进程完成,随机挑选一个子进程返回
pid_t waitpid(pid_t pid, int* status, int options); maxpro
- 可等待特定的子进程或一组子进程
- 在子进程还未终止时,可通过options设置不必等待(直接返回)
进行退出系统接口
-
头文件:#include <unistd.h>
-
void _exit(int status); //系统调用,终止当前进程
-
头文件:#include <stdlib.h>
-
void exit(int status); //库函数,先做资清理,再通过系统调用终止进程
-
void abort(void); //异常终止当前进程(通过产生SIGABRT信号终止)
僵尸进程
-
理论上,进程 退出/终止 后应立即释放所有系统资源
-
然而,为了给父进程提供一些重要信息,子进程 退出/终止 所占的部分资源会暂留
-
当父进程收集这部分信息后(wait/waitpid),子进程所有资源被释放
-
父进程调用 wait(),为子进程"收尸"处理并释放暂留资源
-
若父进程退出,init/systemd 为子进程"收尸"处理并释放暂留资源
-
僵尸进程的危害
- 僵尸进程保留进程的 终止状态 和 资源的使用信息
- 进程为何退出,进程消耗CPU时间,进程最大内存驻留值,等
- 如果僵尸进程得不到回收,那么可能影响正常进程的创建
- 进程创建最重要的资源是内存和进程标识
- 僵尸进程的存在可看作一种类型的内存泄漏
- 当系统僵尸进程过多,可能导致进程标识不足,无法创建新进程
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
static void worker(pid_t pid)
{
printf("grand-child: %d\n", pid);
sleep(150);
}
int main(int argc, char* argv[])
{
pid_t pid = 0;
int status = 0;
printf("parent = %d\n", getpid());
pid = fork();
if( pid < 0 )
{
printf("fork error\n");
}
else if( pid == 0 )
{
int i = 0;
for(i=0; i<5; i++)
{
if( (pid = fork()) == 0 )
{
worker(getpid());
break;
}
}
sleep(60);
printf("child(%d) is over...\n", getpid());
}
else
{
printf("wait child = %d\n", pid);
sleep(120);
while( waitpid(pid, &status, 0) == pid )
{
printf("Parent is over - child: %d, status = %x\n", pid, status);
}
}
return 0;
}
可能用到命令
gcc test.c
./a.out &
ps ax |grep pts