目录

一、基本概念

二、进程创建

1. 进程空间分布

2. 虚拟地址与物理地址

3. 多进程存储与调度

三、进程相关命令

1. top

2. ps -ef

3. ps -aux

4. 后台执行进程任务

5. jobs

6. fg

7. nice/renice

8. kill/killall

四、进程状态

五、进程相关函数接口

1.fork:创建子进程

2.getpid/getppid

3.exit与_exit

4.进程回收

1.wait

2.waitpid

六、进程消亡

1.孤儿进程

2.僵尸进程:

3.如何避免产生僵尸进程?

一、基本概念

  • 进程:程序动态执行的过程,包含创建、调度、消亡等阶段
  • 程序:存放在外存中的一段数据集合(静态)

二、进程创建

1. 进程空间分布

操作系统为每个运行的进程开辟 0-4G 虚拟内存空间,分为:

  • 内核空间:不允许用户访问
  • 用户空间
    • 文本段:存放代码和指令
    • 数据段:包含字符串常量、已初始化 / 未初始化的全局变量 / 静态变量(编译时开辟空间,程序结束回收,未初始化值为 0)
数据区存放数据特点:
  • 未经初始化值为0
  • 编译时开辟空间
  • 程序结束时回收空间
  • 系统数据段
  • 堆区:通过malloc申请、free释放(需避免内存泄露)
堆区存放数据特点:
  • malloc申请堆区空间
  • free释放堆区空间
  • 注意:避免产生内存泄露
  • 栈区:存放局部变量、函数运行数据(未初始化值为随机值,超出作用域自动回收)
栈区存放数据特点:
  • 未经初始化值为随机值
  • 执行到变量定义开辟内存空间
  • 超过变量作用域回收变量空间

2. 虚拟地址与物理地址

  • 虚拟地址:用户可见的地址,代表用户可寻址范围
  • 物理地址:内存存放数据的实际硬件地址
  • MMU(内存映射单元):负责虚拟地址与物理地址的映射

3. 多进程存储与调度

  • 存储特点:多个进程物理地址独立(空间独立),但共享虚拟内存空间
  • 调度算法
  1. 先来先执行
  2. 高优先级调度
  3. 时间片轮转调度
  • 调度本质:宏观并行(看似同时执行),微观串行(CPU 在多个任务间高速切换)
  • 宏观分析:一个 CPU 同时执行多个进程任务
    微观分析:一个 CPU 在多个任务中高速切换保障多任务执行

三、进程相关命令

命令功能关键信息
top动态查看进程信息(按 CPU、内存占用率)显示 PID(进程 ID)、USER(创建者)、PR/NI(优先级)、% CPU、% MEM 等,q退出
ps -ef查看某一时刻所有进程信息显示 UID(创建用户)、PID、PPID(父进程 ID)、CMD(进程命令);`ps -efgrep 进程名 ` 可查找特定进程
ps -aux查看某一时刻所有进程信息显示 USER、PID、% CPU、% MEM、STAT(状态)等
./a.out &后台执行进程进程在后台运行
jobs查看终端后台进程任务显示后台进程编号
fg 编号将后台进程放到前台执行需通过jobs获取进程编号
nice/renice改变进程优先级优先级范围 - 20~20(数字越小优先级越高);nice -n 优先级 进程名/renice -n 优先级 进程PID
kill/killall杀死进程kill -编号 进程PID/killall -编号 进程名kill -9 PID强制终止

1. top

示例: top
功能:根据 CPU 占用率和内存占用率查看当前所有进程的信息
PID :唯一区分进程的 ID
USER :创建者
PR NI :优先级
VIRT
RES
SHR :资源占用
S :状态
%CPU:CPU 占用率
%MEM: 内存占用率
TIME+ :运行的时长
COMMAND :进程命令
q 退出

2. ps -ef

示例: ps -ef
功能:查看该时刻的所有进程信息
UID :创建进程的用户
PID :进程的 ID
PPID :父进程的 ID
C
STIME
TTY :进程依赖的终端
TIME
CMD
ps -ef | grep 进程名
查找与进程名对应的进程信息

3. ps -aux

示例: ps -aux
功能:查看该时刻的所有进程信息
USER
PID
%CPU
%MEM
VSZ
RSS
TTY
STAT :进程的状态
START TIME
COMMAND

4. 后台执行进程任务

示例: ./a.out &
功能:后台执行 a.out 进程

5. jobs

示例: jobs
功能:查看终端下所有的后台进程任务

6. fg

示例: fg 编号(通过 jobs 查看)
功能:后台执行的任务放到前台执行

7. nice/renice

示例: nice -n 优先级编号 进程名
renice -n 优先级编号 进程 PID
功能:改变进程的优先级
优先级范围: -20 - 20
数字越小优先级越高

8. kill/killall

示例: kill - 编号 进程 PID
killall - 编号 进程名
功能:杀死进程任务
kill -9 PID

四、进程状态

状态标识进程状态及含义
R就绪态 / 运行态(位于 CPU 调度队列中)
S可唤醒等待态(等待资源,可被打断,资源到来后加入调度队列)
D不可唤醒等待态(等待资源,不可被打断,资源到来后加入调度队列)
T停止态(用户人为暂停)
Z僵尸态(进程结束,空间未回收)
X结束态(进程结束,空间已回收)

五、进程相关函数接口

1.fork:创建子进程

  • 功能:父进程调用后生成子进程,子进程拷贝父进程的文本段、数据段、系统数据段
  • 返回值:父进程返回子进程 PID,子进程返回 0,出错返回 - 1
  • 特点:父子进程空间独立,变量 / 数据互不影响,PID 不同
注意:
  • 子进程拷贝父进程文本段、数据段、系统数据段
  • 父进程与子进程空间独立,同一份代码中的变量和数据都会在父子进程中各有一份,父子进程
  • 修改自己空间的数据不会影响对方的空间
  • 进程的PID不一样
  • fork的返回值不一样,父进程中返回子进程的PID,子进程中返回0
  • PID:一定是 > 0

2.getpid/getppid

  • getpid()原型:pid_t getpid(void);        获取当前进程 PID
  • getppid()原型:pid_t getppid(void);         获取当前进程的父进程 PID

3.exit_exit

  • 原型:void exit(int status);
  • 功能: 结束进程任务并返回进程结束状态
  • 参数: status:进程结束状态的值
  • 原型:void _exit(int status);
  • 功能: 结束进程任务并返回进程结束状态
  • 参数: status:进程结束状态的值
注意:
  1. 在主函数中调用exitreturn功能保持一致
  2. return在函数内部将结束该函数
  3. exit在函数内部会将进程结束
  4. exit会在结束前刷新缓存区
  5. _exit不会刷新缓存区

4.进程回收

1.wait
  • 原型: pid_t wait(int *wstatus);
    功能: 回收子进程空间
    参数: wstatus:存放子进程结束状态空间的首地址
    返回值: 成功返回回收到的子进程的PID ;失败返回-1
  • WIFEXITED(wstatus) :测试进程是否正常结束
    WEXITSTATUS(wstatus) :获得进程退出的值
    WIFSIGNALED(wstatus) :测试进程是否被杀死
    WTERMSIG(wstatus) :获得杀死该进程的信号编号
注意:
  • wait具有阻塞等待功能,等到有子进程结束才会回收子进程继续向下执行
  • wait可以实现父子进程任务的同步
2.waitpid
  • 可指定回收特定子进程(功能更灵活)
  • 原型: pid_t waitpid(pid_t pid, int *wstatus, int options);
    功能:回收指定的子进程空间
    参数:pid:要回收的进程的 PID -1 表示回收任意子进程)
               wstatus: 存放子进程结束状态空间首地址
               options:
                          0                       阻塞回收
                          WNOHANG      非阻塞回收
    返回值:
                 成功返回回收到的子进程 PID
                 失败返回 -1
                 指定的子进程空间没结束,返回 0
    waitpid(-1, NULL, 0) 等价于 wait(NULL)
    注意:
    • waitpid可以非阻塞回收子进程空间
    • waitpid可以回收指定子进程空间

六、进程消亡

1.孤儿进程

  • 产生:父进程先结束,子进程成为孤儿进程
  • 处理:被init进程收养

2.僵尸进程

  • 是每个进程结束必然会经历的阶段
  • 产生原因:子进程结束后,父进程未回收其空间,导致空间被占用

3.如何避免产生僵尸进程?

  •  父进程先结束,子进程会成为孤儿进程,孤儿进程被 init 进程收养,子进程再结束, init进程回收进程空间
  • 子进程结束,父进程回收子进程空间,避免产生僵尸进程 

七、exec函数族

1. exec函数族

  • 利用进程空间执行另一份代码
  • exec常搭配fork使用,fork负责创建新的子进程,exec负责让子进程执行自己的代码
extern char **environ;
int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp [] */);
int execv(const char *path, char *const argv [] );
int execvp(const char *file, char *const argv [] );
int execvpe(const char *file, char *const argv [] ,char *const envp [] );
l: 参数以列表的形式传递
p: 在系统变量 PATH 对应的目录下查找文件
v: 参数以指针数组的形式传递
e: 执行新代码是更新环境变量

2. 主函数传参

1. 主函数形式
void main(void);
int main(void);
int main(int argc, const char *argv [] );
int main(int argc, const char **argv);
argc: 传入参数的个数
argv: 存放每一个传入参数指针的数组名
argv [ 0 ] = "./a.out"
argv [ 1 ] = "hello"
argv [ 2 ] = "world"
argv [ 3 ] = "how"
argv [ ... ] = ...
argv [ argc ] = ...

3. system函数

原型:  int system(const char *command);
功能: 运行command 命令
参数: command:shell命令字符串首地址
返回值:  成功返回0
                失败返回 -1
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐