第三章 Linux进程线程:线程进程总结

线程和进程区别

对比维度进程(Process)线程(Thread)
定义最小的资源分配单元。独立运行的程序实例,拥有自己的内存空间和系统资源最小的执行单元。进程中的执行单元多个线程共享同一进程的资源
资源管理独立地址空间、独立文件描述符、独立堆和栈共享进程的地址空间、文件描述符和堆,但有独立的栈
创建与切换fork() 创建进程,开销较大;进程切换涉及完整上下文切换,速度较慢pthread_create() 创建线程,开销小线程切换仅涉及线程上下文,速度较快
通信方式进程间通信(IPC):管道、消息队列、共享内存、套接字等,通信开销较大共享进程内存,可直接访问全局变量,通信开销小,但需要同步控制
并发性进程独立运行,一个进程崩溃不会影响其他进程,适用于多核并行计算线程共享资源,一个线程崩溃可能导致整个进程崩溃,适用于 I/O 密集型任务
切换开销高,涉及进程上下文切换低,线程切换只需保存和恢复少量寄存
适用场景适用于独立运行的程序,如数据库、后台服务、分布式计算适用于需要频繁数据交互的任务,如 Web 服务器、多线程计算

进程间通信(IPC)方式对比表

通信方式优点缺点适用场景 示例 API
无名管道(Pipe)- 简单易用,适用于父子进程通信 - 速度较快,基于内存传输- 仅支持 单向通信 - 只能用于 具有亲缘关系(父子进程) - 数据是 字节流,需要解析进程间的简单数据传输int pipe(int pipefd[2])
命名管道(FIFO)- 允许 无亲缘关系进程 通信 - 仍然基于内存,通信速度较快- 半双工通信(单向传输) - 需要 文件路径 来命名管道 - 读取数据后数据被清除不同进程间的数据传输,通过文件系统传输mkfifo(const char pathname, mode_t mode);读写 open("fifo", O_WRONLY);
消息队列(Message Queue)- 多对多 进程通信,支持 消息结构化存储 - 不会像管道一样丢失数据(数据持久化) - 可设置优先级,提高消息处理顺序控制- 消息长度有限(受系统限制,如 msgmax) - 读取时需遍历队列,效率可能受影响 - 需要 显式创建和管理 消息队列任务调度、事件通知,如多进程日志系统msgget(), msgsnd(), msgrcv()(Linux)
共享内存(Shared Memory)- 最快的 IPC 方式(进程直接访问内存,无需内核干预) - 适合大数据共享(如图像处理) - 多个进程可直接读写共享数据- 需要 同步机制(如信号量或互斥锁) 防止数据竞争 - 进程 意外退出 可能导致数据不一致需要 高效数据交换 的场景,如视频流处理、数据库缓存shmget(), shmat(), shmdt()(Linux)
信号量(Semaphore)- 适用于 进程同步,可控制资源访问 - 支持进程间和线程间 资源共享控制- 仅用于 同步,不能传输数据 - 使用复杂,需手动维护信号量状态进程同步、控制 临界区资源访问,如数据库连接管理semget(), semop(), semctl()(Linux)
信号(Signal)- 适用于 异步事件通知 - 轻量级,不需要额外的资源 - 进程可自定义信号处理函数- 只能传递简单信息(信号编号) - 可能会被 忽略或屏蔽 - 信号的处理顺序 不确定进程控制,如终止、暂停、恢复进程(kill 命令)kill(), signal(), sigaction()
  1. 管道(Pipe)/命名管道(FIFO) 适用于简单的进程间数据流传输(如 Shell 命令)。
  2. 消息队列(Message Queue) 适用于 事件驱动 的任务调度,但数据量受限。
  3. 共享内存(Shared Memory) 是 最快 的进程通信方式,适用于 大数据传输,但需要同步机制防止冲突。
  4. 信号量(Semaphore) 用于 同步进程信号(Signal) 用于 事件通知

僵尸进程(Zombie Process)和孤儿进程(Orphan Process)的预防与处理

1. 僵尸进程(Zombie Process)
  • 子进程执行完毕,但 父进程没有调用 wait() 或 waitpid() 处理它的退出状态,导致子进程的 PCB(进程控制块) 仍然保留在系统进程表中,成为“僵尸”状态。
  • 僵尸进程不会占用 CPU 或内存,但会占用进程表项(PID),如果大量僵尸进程堆积,可能导致 系统无法创建新进程
预防和处理僵尸进程**
方法具体操作优缺点
1. wait()waitpid()父进程在适当的时间调用 wait() 回收子进程资源优点:简单直接,避免产生僵尸进程- 缺点:如果父进程没有及时调用,仍可能短时间出现僵尸进程
2. 设置信号处理函数(SIGCHLD在父进程中捕获 SIGCHLD 信号,并在信号处理函数中调用 waitpid(-1, NULL, WNOHANG); 回收任意子进程优点:适用于多个子进程,避免 wait() 阻塞父进程- 缺点:信号处理函数可能受到其他信号干扰,导致某些子进程未被正确回收
3. 让子进程自己 exit() 退出不建议使用,因为子进程自己退出不会清除其 PCB,必须由父进程 wait()- 缺点:不能真正解决僵尸进程问题
4.pthread_detach(tid);让线程自动释放资源,不需要 pthread_join()优点: - 避免僵尸线程,无需手动回收 - 适用于短时任务或守护线程 缺点: - 线程结束后无法获取返回值 - 不能回收已变成僵尸的线程
5.pthread_join(tid, NULL);等待线程结束,回收线程资源优点: - 确保线程正常结束并释放资源 - 可获取线程返回值 缺点: - 需要手动调用,否则可能导致资源泄漏 - 若线程未结束,pthread_join() 会阻塞主线程
2. 孤儿进程(Orphan Process)

定义父进程先于子进程退出,子进程成为 孤儿进程,此时 init 进程(PID=1)会接管它,并回收其资源
孤儿进程的影响

  • 通常不会造成严重问题,因为 init 进程会自动 wait() 清理它们。
  • 但在某些情况下,如子进程仍然占用关键资源或进行 I/O 操作,可能导致 资源泄露 或 输出错误
如何预防和处理孤儿进程
方法具体操作优缺点
1. 让父进程 wait() 回收子进程在父进程退出前,等待所有子进程执行完毕- 优点:保证子进程完成后再退出- 缺点:如果子进程运行时间较长,父进程会一直等待
2. 让子进程以守护进程(Daemon)方式运行子进程 调用 setsid() 让自己成为新的会话组长,独立运行- 优点:适用于长期运行的后台任务,如 Web 服务器、日志收集等- 缺点:不适用于短生命周期进程
3. 使用 prctl(PR_SET_CHILD_SUBREAPER, 1);(Linux)某个进程(如守护进程)接管孤儿进程,而不是 init 进程- 优点:适用于复杂的多进程管理- 缺点:仅适用于 Linux
4. 父进程提前通知子进程在退出前,通知子进程先退出,如发送 SIGTERM 信号- 优点:保证父进程退出时不留下孤儿进程- 缺点:子进程必须支持信号处理
代码示例:让子进程成为守护进程,避免孤儿进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>

void daemonize() {
    pid_t pid = fork();
    if (pid > 0) {
        exit(0);  // 让父进程退出,子进程成为孤儿进程
    } else if (pid < 0) {
        perror("fork failed");
        exit(1);
    }

    // 创建新会话
    setsid();

    // 更改工作目录
    chdir("/");

    // 关闭标准输入、输出和错误流
    fclose(stdin);
    fclose(stdout);
    fclose(stderr);
}

int main() {
    daemonize();  // 让进程成为守护进程

    while (1) {
        sleep(5);
        printf("守护进程运行中...\n");  // 由于标准输出关闭,实际不会打印
    }

    return 0;
}

总结
问题定义影响预防与处理
僵尸进程子进程退出但父进程未 wait(),导致进程表项未释放占用 PID 资源,可能导致新进程无法创建- wait()waitpid() 处理子进程 - 绑定 SIGCHLD 信号处理函数 - prctl(PR_SET_CHILD_SUBREAPER, 1)(Linux)
孤儿进程父进程先于子进程退出,子进程由 init 进程接管影响较小,但可能导致 资源泄露- 让父进程 wait() 子进程 - 让子进程调用 setsid() 变为守护进程 - 让父进程提前通知子进程退出

通常,孤儿进程不需要特别处理,因为 init 进程会自动回收,而 僵尸进程需要特别关注,防止系统资源耗尽。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值