6.进程的使用方式
-
-
- [**1. 父子进程的关系**](#1. 父子进程的关系)
- [**2. 进程的终止**](#2. 进程的终止)
- [**3. 僵尸进程和孤儿进程**](#3. 僵尸进程和孤儿进程)
- [**4. 进程资源回收**](#4. 进程资源回收)
- [**5. exec 函数族**](#5. exec 函数族)
- [**6. system 函数**](#6. system 函数)
- [**7. 练习与作业**](#7. 练习与作业)
- [**8. 进程的退出状态**](#8. 进程的退出状态)
- [**9. 进程的清理函数**](#9. 进程的清理函数)
- [**10. 总结**](#10. 总结)
-
1. 父子进程的关系
- 子进程是父进程的副本 :
- 子进程复制父进程的数据段、堆、栈,共享正文段(代码段)。
- 子进程从
fork
之后开始执行,父子进程的执行顺序不确定。
- 区别 :
fork
的返回值不同:- 父进程中返回子进程的PID。
- 子进程中返回0。
- PID不同:子进程拥有独立的进程ID。
2. 进程的终止
- 正常终止 :
main
函数中return
。exit()
:C库函数,刷新缓冲区,关闭所有流,执行清理函数(如atexit
注册的函数)。_exit()
/_Exit()
:系统调用,直接终止进程,不刷新缓冲区,不执行清理函数。
- 异常终止 :
4. 主线程退出。
5. 主线程调用pthread_exit
。
6.abort()
:触发SIGABRT
信号终止进程。
7. 收到信号(如kill
命令发送的信号)。
8. 最后一个线程被pthread_cancel
取消。
3. 僵尸进程和孤儿进程
- 僵尸进程 :
- 进程已终止,但其资源未被父进程回收。
- 父进程可以通过
wait
或waitpid
回收子进程资源。
- 孤儿进程 :
- 父进程先于子进程终止,子进程被
init
进程(PID=1)接管。 - 孤儿进程不会成为僵尸进程。
- 父进程先于子进程终止,子进程被
4. 进程资源回收
- wait :
- 函数原型:
pid_t wait(int *status);
- 功能:阻塞等待任意子进程退出,并回收其资源。
- 参数:
status
用于存储子进程的退出状态。 - 返回值:成功返回子进程PID,失败返回-1。
- 函数原型:
- waitpid :
- 函数原型:
pid_t waitpid(pid_t pid, int *status, int options);
- 功能:回收指定子进程的资源。
- 参数:
pid
:指定要回收的子进程PID。status
:存储子进程的退出状态。options
:选项(如WNOHANG
表示非阻塞模式)。
- 返回值:成功返回子进程PID,失败返回-1。
- 函数原型:
5. exec 函数族
- 功能:用新程序替换当前进程的地址空间,从新程序的启动例程开始执行。
- 常见函数 :
execl
:以参数列表形式传递参数。execv
:以参数数组形式传递参数。execlp
:在PATH
环境变量中查找可执行文件。execvp
:在PATH
环境变量中查找可执行文件,并以参数数组形式传递参数。execle
:传递环境变量。execve
:系统调用,传递参数数组和环境变量。
- 特点 :
- 调用成功时不返回,调用失败时返回-1。
- 不创建新进程,进程ID不变。
6. system 函数
- 函数原型:
int system(const char *command);
- 功能:在代码中执行Shell命令。
- 返回值:成功返回0,失败返回-1。
- 实现原理 :
fork
+exec
。
7. 练习与作业
- 练习1:设计一个多进程程序,父子进程分别向同一个文件写入数据,并标明进程ID和时间。
- 练习2 :使用
waitpid
函数回收指定子进程资源,并打印其退出状态。 - 练习3 :使用
execlp
或execvp
启动ps
命令,并带参数执行。 - 作业1 :设计一个多进程程序,父进程获取用户输入并写入文件,子进程读取文件并打印输出。输入
quit
时双方退出,确保不产生僵尸进程和孤儿进程。 - 作业2:设计一个多进程程序,将一个大文件分割为多个子文件,并确保子文件可以合并为原始文件。
8. 进程的退出状态
- 正常退出 :通过
exit
或return
传递退出状态。 - 异常退出:通过信号传递终止原因。
- 状态回收 :
WIFEXITED(status)
:判断进程是否正常退出。WEXITSTATUS(status)
:获取正常退出时的状态码。WIFSIGNALED(status)
:判断进程是否因信号终止。WTERMSIG(status)
:获取导致进程终止的信号编号。
9. 进程的清理函数
- atexit :
- 函数原型:
int atexit(void (*function)(void));
- 功能:注册进程退出时执行的函数。
- 返回值:成功返回0,失败返回非0。
- 函数原型:
- 执行顺序 :
atexit
注册的函数按注册顺序的逆序执行。
10. 总结
- 父子进程通过
fork
创建,子进程是父进程的副本。 - 进程可以通过
exit
、_exit
、信号等方式终止。 - 僵尸进程和孤儿进程是进程管理中的常见问题,需要通过
wait
或waitpid
回收资源。 exec
函数族用于替换进程的地址空间,执行新程序。system
函数可以方便地在代码中执行Shell命令。