Linux 多线程 / 多进程编程、同步互斥、信号机制完整梳理

📅 2026/7/18 17:26:45
Linux 多线程 / 多进程编程、同步互斥、信号机制完整梳理
一、多进程编程进程独立地址空间资源隔离1. 创建进程核心 APIfork()调用一次返回两次父进程返回子进程 PID子进程返回 0失败返回 - 1。写时复制 COW初期父子共享页表修改内存才拷贝开销大。示例逻辑pid_t pid fork(); if(pid 0) { perror(fork); } else if(pid 0) { /* 子进程 */ } else { /* 父进程pid是子进程号 */ }vfork()不拷贝地址空间子进程直接复用父进程内存必须立刻exec/_exit现已基本废弃。exec 系列替换进程镜像execl/execlp/execle/execv/execvp/execvefork 后调用执行新程序。进程回收 wait /waitpidwait()阻塞等待任意子进程退出获取退出状态处理僵尸进程。waitpid(pid, status, WNOHANG)非阻塞可指定等待某一子进程。僵尸进程子进程先退出、父进程未回收PCB 残留孤儿进程父进程先退出子进程由init/systemd收养。2. 进程间通信 IPC多进程数据交换管道 pipe单向仅父子进程通信命名管道 FIFO无亲缘进程可用共享内存 shmget/shmat/shmdt/shmctl最快 IPC需手动同步消息队列 msgget/msgsnd/msgrcv带类型消息缓冲信号量 semget/semop/semctl专门用于进程同步互斥Socket本地域 socket跨进程 / 跨机器通用二、多线程编程线程进程内执行流共享地址空间1. pthread 核心 API创建pthread_create(tid, attr, start_routine, arg)等待回收pthread_join(tid, retval)阻塞回收分离线程pthread_detach(tid)线程退出自动释放资源无需 join线程退出pthread_exit(void *ret)主线程exit()会杀死所有子线程pthread_exit()仅结束主线程、子线程继续运行获取自身 tidpthread_self()2. 线程独有 / 共享资源共享全局变量、堆、文件描述符、信号处理函数、代码段独有栈、寄存器、errno、线程私有数据 TSD、调度优先级三、同步与互斥解决竞态条件多执行流并发修改共享资源一互斥同一时刻仅一个执行流访问临界区1. 互斥锁 pthread_mutex_t线程专用pthread_mutex_t mtx PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(mtx); // 加锁阻塞 pthread_mutex_unlock(mtx); // 解锁 pthread_mutex_trylock(mtx);// 非阻塞加锁失败返回EBUSY类型普通锁、递归锁同一线程可多次 lock、错误检测锁。2. 进程间互斥信号量 semaphoreSystem V 信号量semget/semop/semctl支持多计数器常用于多进程互斥同步POSIX 无名信号量存于共享内存多进程 / 线程可用POSIX 有名信号量sem_open磁盘持久化无亲缘进程通信二同步控制执行流先后顺序条件变量 pthread_cond_t配合互斥锁使用pthread_cond_wait(cond, mtx)释放锁并阻塞被唤醒后重新加锁pthread_cond_signal唤醒一个等待线程pthread_cond_broadcast唤醒全部等待线程典型场景生产者消费者模型。读写锁 pthread_rwlock_t读共享、写独占大量读少量写场景提升并发rdlock多线程同时持有wrlock独占。自旋锁 pthread_spinlock_t忙等循环不切换上下文适合临界区极短、CPU 充足场景。三进程同步补充文件锁 fcntl文件级互斥简单轻量共享内存 信号量高性能多进程并发读写四、Linux 信号处理机制1. 信号基础信号是内核 / 进程发给另一进程的异步通知中断程序正常执行常见信号SIGINT (2) CtrlCSIGKILL (9) 强制杀死不可捕获SIGSEGV (11) 段错误SIGCHLD 子进程退出SIGALRM 定时器信号信号状态递达、未决、阻塞信号屏蔽字 mask2. 信号注册 APIsignal(int sig, void (*handler)(int))简易接口跨平台兼容性差sigaction(int sig, struct sigaction *act, oldact)推荐精细控制sa_handler普通信号处理函数sa_sigaction带附加信息的处理函数支持 siginfo_tsa_mask执行 handler 时临时屏蔽的信号集sa_flagsSA_RESTART系统调用自动重启、SA_NOCLDWAITSIGCHLD 不产生僵尸3. 信号集操作屏蔽 / 解除屏蔽信号sigset_t set; sigemptyset(set); // 清空集合 sigaddset(set, SIGINT); // 添加信号 sigprocmask(SIG_BLOCK, set, NULL); // 阻塞指定信号 sigprocmask(SIG_UNBLOCK, set, NULL); // 解除阻塞4. 信号等待pause()阻塞直到收到任意信号sigsuspend(mask)临时替换屏蔽字并阻塞原子操作避免竞态5. 多进程 / 多线程信号特性进程信号SIGCHLD 用于父进程异步回收子进程避免轮询 waitpid线程信号规则信号屏蔽字是线程私有每个线程可独立屏蔽不同信号同步信号SIGSEGV/SIGFPE发送到触发线程异步信号随机发给任意未屏蔽该信号的线程多线程程序推荐单独创建一个专用线程统一处理所有异步信号其余线程全部屏蔽信号简化逻辑6. 信号处理限制信号 handler 内只能调用异步安全函数write、sigaddset 等禁止 malloc、printf、pthread 系列等非安全函数易死锁 / 内存损坏。五、面试高频总结可直接用于简历 / 口述进程与线程区别进程资源隔离、切换开销大线程共享地址空间、切换轻量线程依赖进程存在。互斥 vs 同步互斥保证同一时间唯一访问临界区同步控制执行先后顺序条件变量 互斥锁是标准组合。锁选择短临界区用自旋锁普通线程互斥用 mutex多读少写用读写锁多进程同步用信号量。信号关键点SIGKILL 无法捕获线程独立屏蔽字handler 仅可调用异步安全函数SIGCHLD 解决僵尸进程。生产者消费者经典模型实现线程版 (mutexcond)、进程版 (共享内存 信号量)。