首页 > 技术文章 > Linux进程

xkDiogt 2020-08-23 15:54 原文

Linux进程

进程是程序的动态表现, 是分配资源(内存、时间片)的基本单位

 

Linux下进程结构:抢亲缘关系(父子进程) 

 

PCB控制块

进程pid、进程状态、进程启动时长等

 PCB中记录了操作系统所需的,用于描述进程的当前情况以及控制进程运行的全部信息。

进程创建过程

0~3G:用户空间

3G~4G:PCB

1. 父进程调用fork, 内核创建子进程_CREAT

2. 内核用父进程的PCB控制块进行子进程PCB的初始化(除了pid等进程唯一信息)

3. 内核将父进程的用户空间拷贝给子进程(读时共享, 写时复制)

4. 子进程从fork之后开始执行

 

fork

系统内置未经过包裹的API

fork();

返回值

父进程中返回子进程的pid

在子进程中返回0

-1表示失败

 

pid连续的进程具有亲缘关系(层级关系)

 

vfork:创建不继承父进程用户空间的子进程, 需要配合exec使用

 

区分父子进程的工作

通过fork的返回值区分父子进程

if (fork() > 0)
{
    // 父进程工作
}
else if (fork() == 0)
{
    // 子进程工作
}
else
{
    // fork出错
}

 

获取进程ID

pid_t getpid(void); // 获取当前进程id
pid_t getppid(void); // 获取当前进程父进程id

 

EXEC族

完成进程功能重载

将其他进程的用户空间拷贝到当前进程, 如果还有其他工作, 需要在fork和exec之间完成

execl("/bin/ls", "-l", NULL);

 还有其他exec族函数

 

僵尸进程(Zombie)

子进程先于父进程终止

内核不会释放所有子进程的资源, PCB不会被回收(为了让父进程了解子进程终止的信息)

系统PCB的数量是有限的, 如果没有回收干净, 可能无法创建新的进程

父进程回收子进程PCB资源

wait:

pid_t wait(int *status); // 参数:子进程终止原因

wait函数是阻塞函数, 回收成功返回子进程的pid

如果没有子进程, 调用失败, 返回-1, errno被置为ECHILD。

WIFEXITED(int status); // 判断是否是正常终止
WEXITSTATUS(int status); // 如果正常终止, 获取return返回值
WIFSIGNALED(int status); // 判断进程是否是被信号杀死
STERMSIG(int statux); // 获取杀死进程的信号编号

...

waitpid:

pid_t waitpid(pid_t pid, int *status, int option);

参数

pid < -1:回收指定组中的所有子进程(组号)

pid == -1:回收所有子进程

pid == 0:回收同组的所有子进程

pid > 0:回收指定的一个子进程(进程ID)

status:进程终止信息

option:WNOHANG和WUNTRACED

WNOHANG:不会一直等待子进程结束, 立即返回

WUNTRACED:

返回值

成功返回回收的子进程pid

子进程不需要回收:0

没有子进程:-1

孤儿进程

父进程先于子进程结束

孤儿进程出现后会被托管进程托管, 仅负责回收, 不管理, 孤儿进程工作不会停止

 

进程组

进程:进程ID  父进程ID  进程组ID  会话ID

getpid();
getppid();
getpgrp(); // 获取组id
getsid(); // 获取会话id

1. 进程组由一个组长进程和若干个组员进程构成

2. 进程组PGID = 组长ID

3. 默认父进程为组长, 子进程为组员, 亲缘关系和组关系没有必然联系

4. 如果进程组中最后一个进程结束或转移,进程组将会被销毁释放

5. 进程组中的进程是可以转移的

 

创建新的进程组

只有组员可以创建进程组

setgpid(); // 可以创建组, 也可以转移到其他组

pid = pgid:创建新的进程组

pid != pgid:转移到其他的进程组

 

会话组

pid = pgid = sid

只有组长可以称为会话组组长

终端就是一个会话发起者, 在终端下运行的进程都是组员

会话组组长结束, 所有参与会话的组员都会被结束

创建新会话

setsid(); // 先创建进程组, 通过进程组创建新的会话, 进程组组长和会话发起者不能调用

 

守护进程

1. 守护进程生命周期长, 开机启动, 关机结束

2. 为操作系统提供服务和支持, 在后台运行

 

1. 开机启动

2. 脱离控制终端(脱离现有会话id)

3. 周期性提供服务和支持

4. 退出处理

 

过程

1. 创建子进程, 父进程终止

2. 子进程创建新会话

3. 改变进程工作目录:/(根目录)

4. 修改nmask权限掩码:0

5. 关闭无用的文件描述符

6. 核心工作

7. 退出处理

 

推荐阅读