Linux 进程与线程学习笔记

一、进程回收 waitpid

c 复制代码
pid_t waitpid(pid_t pid, int *wstatus, int options);

功能:回收指定子进程的空间

参数

  1. pid:要回收的子进程 PID
  2. wstatus:保存子进程结束状态空间的首地址
  3. options
    • 0:阻塞回收
    • WNOHANG:非阻塞回收

返回值

  • 成功:返回回收子进程 ID
  • 失败:返回 -1
  • 设置 WNOHANG 非阻塞,如果子进程没有结束返回 0

💡 对比:wait 只能阻塞随机回收子进程;waitpid 可以指定进程,支持非阻塞,实际开发用的更多。

二、exec 函数族

c 复制代码
extern char **environ;
int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *path, const char *arg, ..., (char *) NULL, char * const envp[] );
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *file, char *const argv[], char *const envp[]);

功能 :利用进程空间执行另一段代码,调用成功之后,原代码后面全部不会执行

后缀记忆口诀:

  • l:参数以列表形式传递,逐个写参数,以 NULL 结尾
  • v:参数以指针数组形式传递,传字符串数组
  • p:在系统环境变量 PATH 下查找文件名,可以不用写完整路径
  • e:执行新代码时更新进程环境变量,传入自定义环境变量表

返回值

  • 成功:没有返回,直接运行新程序
  • 失败:返回 -1

⚠️ exec 只是替换进程地址空间,PID 不变,不会创建新进程,一般搭配 fork 使用。

三、环境变量

进程在执行代码过程中临时存放信息的变量,称为环境变量,全局所有子进程都可以继承。

setenv

c 复制代码
int setenv(const char *name, const char *value, int overwrite);

功能:设置环境变量的值

  • name:环境变量名称
  • value:设置环境变量的值
  • overwrite:非 0 覆盖旧值;0 不覆盖旧值

返回:成功返回 0,失败返回 -1


四、线程

1. 什么是线程

线程是一个轻量级的进程,一个任务创建、调度、消亡的过程。

进程和线程核心区别

  1. 进程:操作系统资源分配最小单元
    • 进程独占 0-4G 虚拟内存空间:文本段、数据段、堆段、系统数据段。每个进程完全独立。
  2. 线程:操作系统任务调度最小单元
    • 线程存在于进程空间内部;只有自己独立栈空间,其余堆、全局、文本段全部和进程内其他线程共享

✅ 内存共享总结

  • 独享:线程栈空间(默认 8M),局部变量
  • 共享:全局变量、静态变量、字符串常量、堆区

线程调度

宏观并行,微观串行;CPU 时间片轮转调度。

线程消亡

线程结束必须回收线程空间,否则产生僵尸线程

进程 vs 线程接口对照表

进程 线程
fork pthread_create
exit pthread_exit
wait pthread_join

2. 线程核心 API

① pthread_create 创建线程
c 复制代码
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);
  • thread:存放线程 ID(TID) 空间首地址
  • attr:线程属性,栈大小、优先级等,填 NULL 使用默认属性
  • start_routine:线程函数指针,线程要执行的函数
  • arg:传给线程函数的参数

返回:成功返回 0;失败返回错误码。

② pthread_exit 结束线程
c 复制代码
void pthread_exit(void *retval);
  • retval:线程结束传出的状态,可被 pthread_join 接收。

💡 注意:线程函数里面不要直接 return,优先用 pthread_exit;main 函数 return 会直接结束整个进程,杀死所有子线程。

③ pthread_join 回收线程
c 复制代码
int pthread_join(pthread_t thread, void **retval);
  • thread:待回收线程 TID
  • retval:接收线程退出状态的二级指针,可以传 NULL 不接收

返回:成功返回 0;失败返回错误码。

特性:阻塞等待线程结束,线程没跑完函数就卡在 join 这里。

3. 开发练习思路

  1. 创建 N 个线程,每个线程打印自己 TID,模拟多任务并发
  2. 多线程任务:采集、存储、显示、日志四个任务,各自 sleep 不同时间模拟业务耗时
  3. 主线程监听终端输入,控制子线程启停

⚠️ 高频踩坑点

  1. 共享全局变量多线程同时读写,会出现数据竞争,需要后续加锁。
  2. 传给线程函数的参数不要传局部变量,线程调度晚,局部变量已经销毁,会野指针。
  3. 忘记 pthread_join,产生僵尸线程,内存泄漏。
  4. main 函数直接 return,所有子线程直接被杀死,没有机会执行完。

补充学习思维导图总结

  1. 进程:fork/waitpid + exec 替换程序 + 环境变量
  2. 线程:轻量级,共享地址空间,私有栈;pthread_create / pthread_exit / pthread_join
  3. 区别:进程资源独立开销大;线程共享资源开销小,但是有并发数据竞争问题。
相关推荐
手握风云-1 小时前
一条消息的旅程:RabbitMQ 学习与实践(四)
学习
渡我白衣1 小时前
深入理解 Transformer:Transformer 究竟是什么?
java·linux·开发语言·c++·人工智能·深度学习·transformer
光电的一只菜鸡8 小时前
ubuntu之坑(二十)——VMware虚拟机系统无法正常进入如何处理
linux·运维·ubuntu
GlueNa2SiO39 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
Capricorn198810 小时前
解决全网抄 Karpathy 导致的 LLM Wiki 污染?基于知芽 Notebook Skill 的 raw/ 笔记法排障指南
大数据·论文阅读·人工智能·笔记·论文笔记
你住过的屋檐10 小时前
【Nginx】linux上安装nginx
linux·运维·nginx
壹玖玖肆11 小时前
openGauss使用笔记
笔记
宵时待雨11 小时前
linux笔记归纳17:传输层协议UDP
linux·笔记·udp
SCandL15212 小时前
k8s service
linux·容器·kubernetes