嵌入式:Linux软件编程:线程
一、线程:进程内的轻量级执行单元
1. 基本概念
进程是资源分配的基本单位,而线程是CPU 调度的基本单位。一个进程可以包含多个线程,线程共享进程的内存空间(文本段、数据段、堆区等),但拥有独立的栈区和寄存器。
- 线程是一个轻量级的进程
- 线程本质就是一个进程
- 线程和进程不完全一致,轻量指空间,进程空间和线程空间管理方法不同
2. 线程与进程的核心区别
维度 | 进程 | 线程 |
---|---|---|
资源分配 | 独立地址空间,资源独占 | 共享进程资源 |
切换开销 | 大(需切换地址空间) | 小(仅切换栈和寄存器) |
通信方式 | 需 IPC(如管道、信号量) | 直接访问共享内存 |
独立性 | 高(一个崩溃不影响其他) | 低(共享资源,相互影响) |
进程和线程区别
- 线程本质是进程,线程是任务创建、调度、回收的过程
- 进程空间:文本段 + 数据段 + 系统数据段
- 线程空间:
- 线程必须位于进程空间内部,没有进程,线程无法独立存在
- 一个进程中的所有线程共享 文本段 + 数据段 + 堆区,独享 栈区
- 线程独享的栈区默认认为 8M
- 一个进程中的多个线程切换调度任务时,资源开销比较小
- 进程和线程核心区别:
- 线程是 CPU 任务调度的最小单元
- 进程是 操作系统资源分配的最小单元
3. 多进程和多线程的优缺点
场景 多进程 多线程 对比 效率 切换需重新映射物理地址,资源开销大 同一进程内切换,资源开销小 多线程 > 多进程 通信 无共享空间,需进程间通信(IPC) 有共享空间,定义共享变量即可交换数据 多线程 > 多进程 资源竞争 无共享空间,不存在资源竞争 共享空间通信,需保证互斥性(防资源竞争) 多进程 > 多线程 安全 空间独立,一个进程崩溃不影响其他进程 共用进程空间,一线程崩溃可能导致进程退出(其余线程失效) 多进程 > 多线程
4. 线程的调度
- 与进程调度规则一致
- 宏观并行(多线程同时执行的表象),微观串行(CPU 实际分时切换执行)
5. 线程的消亡
- 线程结束后需回收线程空间,否则产生 僵尸线程(资源泄漏)
6. 线程的创建与终止
- 创建线程:通过
pthread_create()
函数,需指定线程执行的函数、参数等。 - 终止线程:
pthread_exit()
主动结束线程,pthread_cancel()
可取消其他线程。 - 等待线程:
pthread_join()
阻塞等待线程结束并回收资源,类似进程的wait()
。
7. 线程的函数接口
(1)进程接口 vs 线程接口对比
进程接口 | 线程接口 | 功能 |
---|---|---|
fork | pthread_create | 创建进程 / 线程 |
exit | pthread_exit | 结束进程 / 线程 |
wait | pthread_join | 回收进程 / 线程资源 |
(2)pthread_create
int pthread_create(pthread_t *thread, // 存放线程ID的地址const pthread_attr_t *attr,// 线程属性(默认传NULL)void *(*start_routine)(void *), // 线程函数入口void *arg // 传给线程的参数
);
- 功能:在进程内创建新线程
- 返回值:成功返回
0
,失败返回错误码
(3)pthread_self
pthread_t pthread_self(void);
- 功能:获取当前线程的 ID
(4)pthread_exit
void pthread_exit(void *retval);
- 功能:主动结束当前线程
- 参数:
retval
为线程退出时的返回值(可被pthread_join
捕获)
(5)pthread_join
int pthread_join(pthread_t thread, // 要回收的线程IDvoid **retval // 存放线程退出值的地址(可选,传NULL则忽略)
);
- 功能:
- 阻塞等待目标线程结束,回收其资源;
- 同步功能(等待线程执行完毕)。
- 返回值:成功返回
0
,失败返回错误码。
注意:
- 若目标线程未退出,
pthread_join
会一直阻塞; - 通过
retval
可获取线程通过pthread_exit
设置的退出值。 - pthread_join具备同步功能
#include "../head.h"// 线程函数:符合pthread库要求的函数签名(返回值void*,参数void*)
void *thread1(void *arg)
{ //可以合并为一个,只不过运行的代码一样而已printf("线程(TID:%#lx)开始运行\n",pthread_self());return NULL;
}
// void *thread2(void *arg)
// {
// printf("线程(TID:%#lx)开始运行\n",pthread_self());// return NULL;
// }
// void *thread3(void *arg)
// {
// printf("线程(TID:%#lx)开始运行\n",pthread_self());// return NULL;
// }int main (void)
{int ret1 = 0;int ret2 = 0;int ret3 = 0;pthread_t tid1;pthread_t tid2;pthread_t tid3;//thread:存放线程ID空间的 首地址// attr:线程的属性,默认属性NULL// start_routine:线程函数的入口// arg:线程传入的参数ret1 = pthread_create(&tid1,NULL,thread1,NULL);if(ret1 != 0){perror("fail to pthread_create\n");return -1;}ret2 = pthread_create(&tid2,NULL,thread1,NULL);if(ret2 != 0){perror("fail to pthread_create\n");return -1;}ret3 = pthread_create(&tid3,NULL,thread1,NULL);if(ret3 != 0){perror("fail to pthread_create\n");return -1;}// printf("线程(TID:%#lx)创建成功\n",tid);while(1){//线程执行的同时进程也在执行//防止进程先结束}return 0;
}
#include "../head.h"void *thread1(void *arg)
{printf("线程1(ITD:%#lx)开始执行\n", pthread_self());pthread_exit("线程1退出");return NULL;
}void *thread2(void *arg)
{printf("线程2(ITD:%#lx)开始执行\n", pthread_self());pthread_exit("线程2退出");return NULL;
}void *thread3(void *arg)
{printf("线程3(ITD:%#lx)开始执行\n", pthread_self());pthread_exit("线程3退出");return NULL;
}int main(void)
{pthread_t tid[3];int i = 0;// 函数指针数组// 是一个数组 数组里是指向函数的指针void *(*p[3])(void *) = {thread1, thread2, thread3};void *pret = NULL;//循环创建for (i = 0; i < 3; i++){pthread_create(&tid[i], NULL, p[i], NULL);}//循环退出for(i = 0;i < 3; i++){ // 具有阻塞的功能 回收线程pthread_join(tid[i],&pret);printf("线程退出状态:%s\n",(char *)pret);//pret本来是void * }#if 0pthread_t tid1;pthread_t tid2;pthread_t tid3;pthread_create(&tid1, NULL, thread1, NULL);pthread_create(&tid2, NULL, thread2, NULL);pthread_create(&tid3, NULL, thread3, NULL);
#endifwhile (1){}return 0;
}
8. 线程同步机制
由于线程共享资源,需通过同步机制避免数据竞争:
- 互斥锁(
pthread_mutex_t
):确保同一时间只有一个线程访问临界资源(如全局变量)。 - 条件变量(
pthread_cond_t
):让线程等待特定条件满足后再执行(如 "队列非空" 时消费数据)。 - 信号量:控制同时访问资源的线程数量(如限制 5 个线程同时读写文件)。
三、总结
进程是操作系统资源分配的基本单位,拥有独立的内存空间和完整的生命周期;线程是轻量级的执行单元,共享进程资源,适合高并发场景。理解进程的内存布局、调度机制和状态流转,掌握线程的同步方法,是编写高效 Linux 多任务程序的基础。