APUE_notes项目解析:深入理解进程关系与作业控制
【免费下载链接】APUE_notes 项目地址: https://gitcode.com/gh_mirrors/ap/APUE_notes
引言
在Unix/Linux系统中,进程关系是一个核心概念,它决定了进程如何组织、如何交互以及如何受终端控制。本文将基于APUE_notes项目中的内容,深入剖析进程关系、会话、进程组以及作业控制等关键概念,帮助读者全面理解Unix/Linux系统的进程管理机制。
终端登录过程解析
BSD系统登录流程
-
init进程:系统启动时,内核创建PID为1的init进程,这是所有用户进程的始祖。
-
终端初始化:
- init读取/etc/ttys文件
- 为每个允许登录的终端设备fork子进程
- 子进程exec执行getty程序
-
getty工作:
- 打开终端设备(文件描述符0、1、2)
- 显示"login:"提示
- 获取用户名后调用login程序
-
login验证:
- 获取用户密码并验证
- 验证成功后设置用户环境:
- 更改工作目录到用户主目录
- 设置终端所有权和权限
- 初始化环境变量(HOME, SHELL等)
- 最后启动用户shell
不同系统的差异
- Mac OS X:使用launchd代替init,默认提供图形终端
- Linux:使用/etc/inittab代替/etc/ttys
进程组详解
基本概念
进程组是一个或多个进程的集合,具有以下特点:
- 同一进程组内的进程接收来自同一终端的信号
- 每个进程组有唯一的进程组ID
- 进程组组长是创建该组的进程,其PID等于组ID
- 进程组生命周期独立于组长进程
关键函数
-
获取进程组ID:
pid_t getpgrp(void); // 获取调用进程的组ID pid_t getpgid(pid_t pid); // 获取指定进程的组ID -
设置进程组ID:
int setpgid(pid_t pid, pid_t pgid);使用规则:
- pid=pgid:指定进程成为新组长
- pid=0:使用调用者PID
- pgid=0:使用pid作为新组ID
重要限制:进程只能为自己或子进程设置组ID,且必须在子进程exec前设置。
会话机制深入
会话概念
会话是一个或多个进程组的集合,特点包括:
- 每个会话有唯一会话ID(等于首进程的PID)
- 一个会话最多有一个控制终端
- 会话首进程是与终端建立连接的进程
会话管理函数
- 创建新会话:
pid_t setsid(void);成功时:
- 调用进程成为新会话首进程
- 创建新进程组(调用进程为组长)
- 断开原有控制终端
关键点:调用进程不能是进程组组长,通常先fork让子进程调用。
- 获取会话ID:
pid_t getsid(pid_t pid);
作业控制全解析
基本概念
作业控制允许用户在单个终端上管理多个任务:
- 一个作业对应一个进程组
- 分为前台作业和后台作业
- 通过特殊控制字符管理:
- Ctrl+C (SIGINT)
- Ctrl+\ (SIGQUIT)
- Ctrl+Z (SIGTSTP)
终端控制函数
-
获取/设置前台进程组:
pid_t tcgetpgrp(int fd); int tcsetpgrp(int fd, pid_t pgrpid); -
获取会话ID:
pid_t tcgetsid(int fd);
作业控制行为
-
后台作业限制:
- 尝试读取终端 → 收到SIGTTIN信号
- 尝试写入终端 → 可能收到SIGTTOU信号
-
孤儿进程组处理:
- 定义:组中所有进程的父进程都不在同一会话的其他组中
- 处理:向包含停止进程的孤儿进程组发送SIGHUP和SIGCONT信号
实际应用示例
进程组操作示例
void demo_process_group() {
pid_t pid = fork();
if (pid == 0) { // 子进程
setpgid(0, 0); // 创建新进程组
printf("Child: PID=%d, PGID=%d\n", getpid(), getpgrp());
} else { // 父进程
printf("Parent: PID=%d, PGID=%d\n", getpid(), getpgrp());
wait(NULL);
}
}
会话创建示例
void demo_session() {
pid_t pid = fork();
if (pid == 0) {
setsid(); // 子进程创建新会话
printf("New session ID: %d\n", getsid(0));
} else {
wait(NULL);
}
}
总结
理解进程关系是掌握Unix/Linux系统编程的关键。通过本文的讲解,我们了解到:
- 进程通过进程组组织,通过会话管理终端连接
- 作业控制机制允许灵活管理前后台任务
- 孤儿进程组有特殊处理逻辑
- 相关系统调用提供了精细的控制能力
这些概念构成了Unix多任务环境的基础,对于开发可靠的系统程序至关重要。
【免费下载链接】APUE_notes 项目地址: https://gitcode.com/gh_mirrors/ap/APUE_notes
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



