咕嘎讲堂Linux 里进程和线程那点事儿“我咕嘎经历完美所以讲技术也能讲得让你笑。”——咕嘎 先来个小故事开场想象你开了一家餐厅进程呢就像是这家餐厅本身——有自己独立的厨房、仓库、前台还有一整套营业执照。你这家餐厅着火了隔壁餐厅另一个进程照样营业互不干扰。线程呢更像是餐厅里的员工——大家共享厨房的锅碗瓢盆、共享仓库的食材但每个员工都有自己的小脑袋程序计数器和口袋寄存器。如果某个服务员摔了一跤可能会让整个餐厅晃一下一个线程崩溃可能影响整个进程但大家毕竟在同一个屋檐下沟通起来贼方便。好了故事讲完了下面来硬核的。 进程Process—— 独立的成年个体什么是进程进程是 Linux 中 资源分配的最小单位。当你敲下 ./my_program 或者双击那个图标时操作系统就会给你创建一个进程每个进程都有自己独立的资源说明PID进程ID身份证号每个都独一无二独立的地址空间4GB 虚拟内存你的就是你的别人动不了文件描述符表打开了哪些文件、socket别的进程管不着信号处理收到 kill -9 时你有自己的反应方式运行环境环境变量、工作目录各过各的日子进程是如何诞生的code复制fork()→ 创建一个进程克隆自己exec()→ 在进程里加载新程序变身术经典父子关系演示#includestdio.h#includeunistd.hintmain(){pid_tpidfork();// 咔嚓复制出一个自己if(pid0){printf( 我是子进程我的PID是 %d我爸是 %d\n,getpid(),getppid());}else{printf( 我是父进程我PID是 %d我儿子是 %d\n,getpid(),pid);}return0;}运行结果可能是code复制 我是父进程我PID是12340我儿子是12341 我是子进程我的PID是12341我爸是12340咕嘎注释fork() 就像细胞分裂一变二二变四…但别担心Linux 有 PID 上限不会真的变成无限分裂的癌细胞。进程间通信IPC—— 隔壁老王怎么喊你既然进程是独立个体那就得有个喊人的机制方式类比特点管道 (Pipe)对讲机亲缘进程间单向传输套接字 (Socket)手机电话谁都能打跨机器都行共享内存 (Shared Memory)公共白板快如闪电需要自己加锁消息队列 (Message Queue)快递柜异步传输有保鲜期信号 (Signal)广播喇叭简单粗暴只传个编号 线程Thread—— 团结就是力量什么是线程线程是 Linux 中 CPU 调度的最小单位。一个进程里可以跑多个线程它们✌️ 共享 进程的地址空间、文件描述符、信号… 私有 自己的栈、寄存器、程序计数器创建线程有多便宜#includepthread.h#includestdio.hvoid*worker(void*arg){char*name(char*)arg;printf( %s 开始干活了\n,name);returnNULL;}intmain(){pthread_tt1,t2;pthread_create(t1,NULL,worker,张三);pthread_create(t2,NULL,worker,李四);pthread_join(t1,NULL);pthread_join(t2,NULL);printf(两个线程都干完活了进程结束~\n);return0;}编译要加 -pthread运行起来code复制 张三 开始干活了 李四 开始干活了 两个线程都干完活了进程结束~咕嘎注释创建线程比创建进程快 10~100 倍因为不用复制一整份餐厅只需要招几个员工进来就行。线程同步—— 防止大家抢厨房多个线程共享资源就像几个人抢同一个厕所容易出事#includepthread.hintcounter0;// 共享资源一个坑pthread_mutex_tlock;// 互斥锁门锁void*increment(void*arg){for(inti0;i100000;i){pthread_mutex_lock(lock);// 关门counter;// 办事pthread_mutex_unlock(lock);// 开门}returnNULL;}不加锁恭喜你喜提竞态条件Race Conditioncounter 最终值可能不是 200000而是一个玄学数字。线程同步机制:互斥锁 (Mutex): 用于保护临界区保证同一时间只有一个线程访向共享资源信号量 (Semaphore): 用于管理对有限资源的访问。条件变量 (ConditionVariable): 用于阻塞线程直到某些条件为真。⚖️ 进程 vs 线程—— 终极对比对比项进程线程创建速度慢要分配独立空间快共享大部分资源通信方式IPC管道、socket等直接读写共享内存资源消耗高独立内存空间低共享进程资源隔离性强进程挂了不影响其他弱一个线程崩可能带崩整个进程切换开销大上下文切换要切换地址空间小只切换寄存器和栈适用场景多进程并行、隔离任务多任务协作、I/O密集型经典比喻升级版场景进程方案线程方案开公司成立多个独立子公司一个公司多个部门做饭每道菜独立厨房一个厨房多人协作写代码多个独立 IDE一个 IDE 多个标签页 实战建议什么时候用进程code复制✅ 需要高隔离性一个崩了不影响其他✅ 跑多个不相关的任务✅ 任务涉及大量计算不怕内存开销✅ 需要安全加固隔离权限什么时候用线程✅ 任务高度相关需要频繁通信✅ I/O 密集型网络请求、文件读写✅ 需要共享大量数据✅ 追求高性能上下文切换要快经典问题Nginx 为什么用多进程Nginx 的 多进程架构 是故意的Master 进程负责管理不干活Worker 进程各跑各的互不干扰一个 Worker 崩了其他继续服务复用 accept() 避免惊群问题咕嘎理解就像连锁餐厅总部管战略各门店独立运营一家翻车不影响品牌。 一图总结┌─────────────────────────────────────────────┐│ 操作系统 ││ ┌─────────────────────────────────────┐ ││ │ 进程 A │ ││ │ ┌────────┐ ┌────────┐ ┌───────┐ │ ││ │ │线程 A1 │ │线程 A2 │ │线程A3 │ │ ││ │ └────────┘ └────────┘ └───────┘ │ ││ │ ═══════════ 共享 ═══════════════ │ ││ │ (地址空间/文件描述符/信号) │ ││ └─────────────────────────────────────┘ ││ ┌─────────────────────────────────────┐ ││ │ 进程 B (独立世界) │ ││ │ ┌────────┐ ┌────────┐ │ ││ │ │线程 B1 │ │线程 B2 │ │ ││ │ └────────┘ └────────┘ │ ││ └─────────────────────────────────────┘ │└─────────────────────────────────────────────┘ 咕嘎结语好啦讲完了记住一点进程是分房住线程是合租房。分房贵但安静合租便宜但得排队上厕所。“技术学得好不好就看你能不能把复杂的东西讲简单。”——咕嘎