一.进程
1.进程控制块(PCB)
进程运行时,内核为进程每个进程分配一个PCB,维护进程相关的信息,linux内核的进程控制块为task_struct结构体
2.进程的状态转换图
查看进程状态命令:ps aux
以树状显示进程:pstree
- 浅度睡眠(可中断等待状态):在阻塞时等待某些条件达成,当达成条件时,会被内核设置为运行,其也可以因为接收到信号而被提前唤醒
- 深度睡眠(不可中断等待状态):只能待资源满足时被唤醒,不能通过信号或中断唤醒,由于其不接受外来的任何信号,因此无法用kill杀掉
- 僵死(僵尸态):表示进程已经结束,但还没有用释放其空间
3.进程号
查看进程号的命令:ps -ajx
0号进程为内核进程,用于管理其他所有进程
- 进程号(PID)
- 父进程号(PPID)
- 进程组号(PGID):当一个进程没有与其他进程进行组队时,其一个进程也有自己的进程组号
获取进程号的函数:
//获取本进程号
#include <sys/types.h>
#include <unistd.h>
pid_t getpid();
//获取父进程号
pid_t getppid();
//使用pid进程号,来获取其进程所在的进程组号,当参数为0时返回的是当前进程的进程组号
pid_t getpgid(pid_t pid);
4.创建进程
使用fork创建进程得到的子进程是父进程的一个复制品,它从父进程中继承了整个进程的地址空间(包括进程上下文、堆栈等),其子进程独有的为进程号和计时器等,因此用fork创建进程代价很大
//用于从一个已存在的进程中创建一个新进程,其为子进程
//成功创建时在子进程中返回0,在父进程中返回子进程的ID
//创建失败返回-1,其原因有二:一为当前进程数已经达到系统规定的上限;二为系统内存不足
#include <sys/types.h>
#include <unistd.h>
pid_t fork();
返回两个值的原因:
由于fork创建的子进程会复制父进程的上下文,所以在执行父进程中的fork函数后,其返回的值为子进程ID,在执行子进程中的fork函数后,返回的值为0。
父子进程在宏观上是同时进行的
5.特殊进程
(1)孤儿进程
父进程先结束,子进程还在执行,子进程就是孤儿进程,其会被1号进程负责给子进程回收资源
(2.)僵尸进程
子进程结束,父进程没有回收子进程资源
(3)守护进程
是脱离终端的孤儿进程,其在后台运行,为某种特殊服务存在,其一般用于服务器
6.wait函数
当每个进程退出时,内核都会释放该进程所有资源,但仍然会保留一定信息,只要为进程控制块(PCB)
父进程可以通过调用wait或者waitpid得到它的退出状态同时彻底清除掉该进程,其一次只能清理一个
wait函数和waitpid函数区别:
- wait函数会阻塞
- waitpid函数可以设置阻塞,还可以指定等待那个子进程结束
#include <sys/types.h>
#include <sys/wait.h>
//参数为进程的退出时的状态信息(可以为NULL,即当子进程结束,即调用),成功返回结束子进程的进程号,失败返回-1
pid_t wait(int *status);