进程认识
基本概念
- 进程是Linux任务的执行单位,也是Linux系统资源的分配单元;
- 每个Linux应用程序运行后由一个或多个进程构成;
- 每个Linux进程可以执行一个或多个程序;
- Linux进程有多种状态。
生命周期
- 就绪/运行状态(R):TASK_RUNNING
- 阻塞状态:
– 可中断(S):TASK_INTERRUPTIBLE
– 不可中断(S):TASK_UNINTERRUPTIBLE - 停止状态(T):TASK_STOPPED
- 退出状态: TASK_DEAD
– 僵尸(X):EXIT_ZOMBIE
– 死亡(Z):EXIT_DEAD
必知
- 每个进程都有一个唯一的标识(即进程标识符,PID)
- 每个进程都是由另一个进程创建而来(即:父进程)
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
进程树
- 整个Linux系统的所有进程构成一个树状结构;
- 树根由内核自动创建,即:IDLE(PID:0)
- 系统中的第一个进程是init/systemd(PID:1)
– 0号进程创建1号进程,1号进程负责完成内核部分初始化工作;
– 1号进程加载执行初始化程序,演变为用户态1号进程;
进程创建
- pid_t fork(void);
– 通过当前进程创建新的进程,当前进程为父进程,新进程为子进程; - int execve(const char* pathname, char* const argv[], char *const envp[]);
– 在当前进程中执行pathname指定的程序代码;
fork()的工作方式
- 为子进程申请内存空间,并将父进程数据完全复制到子进程空间中;
- 两个进程中的程序执行位置完全一致(fork()函数调用位置);
- 不同之处:
通过fork()返回值来判断父子进程,从而执行不同代码
– 父进程:fork()返回子进程PID
– 子进程:fork()返回0;
execve()的工作方式
- 根据参数路径加载可执行程序;
- 通过可执行程序信息构建进程数据,并写入当前进程空间;
- 将程序执行位置重置到入口地址处(即,main());
execve(...)将重置当前进程空间(代码 & 数据)而不会创建新的进程
;