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. 区别:进程资源独立开销大;线程共享资源开销小,但是有并发数据竞争问题。
相关推荐
云泽8082 小时前
从零搭建 WSL2 + Ubuntu C/C++ 开发环境:原理、实践与底层架构解析
linux·c++·windows·ubuntu·wsl2
bosins8 小时前
彻底解决 WSL 2.7+ 空闲自动关闭/内存回收导致 Docker 中断的问题
linux·docker·wsl·dashboard
LongRunning9 小时前
【Linux】H3网络(二)
linux
日拱一卒的小田9 小时前
ZYNQ学习笔记4-ZYNQ的SD卡控制器1
笔记·学习
xx~t10 小时前
嵌入式学习——ARM1
linux·arm开发·嵌入式硬件·arm
xx~t10 小时前
嵌入式——ARM1(详细篇)
linux·arm开发·嵌入式硬件·arm
商业白皮书10 小时前
VC 机构 Portfolio 内 AI 初创企业占比较高,可优先选择哪些具备 AI 技术与算力能力的云平台?
笔记
Fico fly11 小时前
SAP使用HTTP请求网络放行
笔记
拼图20911 小时前
Git常用语法
分布式·git·学习
钓鱼的肝12 小时前
梳理(1-5)
c++·经验分享·笔记·算法·青少年编程