当前位置: 首页 > news >正文

嵌入式:Linux软件编程:线程

一、线程:进程内的轻量级执行单元

1. 基本概念

进程是资源分配的基本单位,而线程是CPU 调度的基本单位。一个进程可以包含多个线程,线程共享进程的内存空间(文本段、数据段、堆区等),但拥有独立的栈区和寄存器。

  • 线程是一个轻量级的进程
    • 线程本质就是一个进程
    • 线程和进程不完全一致,轻量指空间,进程空间和线程空间管理方法不同

2. 线程与进程的核心区别

维度进程线程
资源分配独立地址空间,资源独占共享进程资源
切换开销大(需切换地址空间)小(仅切换栈和寄存器)
通信方式需 IPC(如管道、信号量)直接访问共享内存
独立性高(一个崩溃不影响其他)低(共享资源,相互影响)
进程和线程区别
  1. 线程本质是进程,线程是任务创建、调度、回收的过程
  2. 进程空间:文本段 + 数据段 + 系统数据段
  3. 线程空间:
    • 线程必须位于进程空间内部,没有进程,线程无法独立存在
    • 一个进程中的所有线程共享 文本段 + 数据段 + 堆区,独享 栈区
    • 线程独享的栈区默认认为 8M
    • 一个进程中的多个线程切换调度任务时,资源开销比较小
  4. 进程和线程核心区别:

    • 线程是 CPU 任务调度的最小单元
    • 进程是 操作系统资源分配的最小单元

    3. 多进程和多线程的优缺点

    场景多进程多线程对比
    效率切换需重新映射物理地址,资源开销大同一进程内切换,资源开销小多线程 > 多进程
    通信无共享空间,需进程间通信(IPC)有共享空间,定义共享变量即可交换数据多线程 > 多进程
    资源竞争无共享空间,不存在资源竞争共享空间通信,需保证互斥性(防资源竞争)多进程 > 多线程
    安全空间独立,一个进程崩溃不影响其他进程共用进程空间,一线程崩溃可能导致进程退出(其余线程失效)多进程 > 多线程


4. 线程的调度

  • 与进程调度规则一致
  • 宏观并行(多线程同时执行的表象),微观串行(CPU 实际分时切换执行)

5. 线程的消亡

  • 线程结束后需回收线程空间,否则产生 僵尸线程(资源泄漏)

6. 线程的创建与终止

  • 创建线程:通过pthread_create()函数,需指定线程执行的函数、参数等。
  • 终止线程pthread_exit()主动结束线程,pthread_cancel()可取消其他线程。
  • 等待线程pthread_join()阻塞等待线程结束并回收资源,类似进程的wait()

7. 线程的函数接口

(1)进程接口 vs 线程接口对比
进程接口线程接口功能
forkpthread_create创建进程 / 线程
exitpthread_exit结束进程 / 线程
waitpthread_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 多任务程序的基础。

http://www.dtcms.com/a/333695.html

相关文章:

  • 深入浅出的 RocketMQ-面试题解析
  • AI架构师生存手册:图解避坑MCP工具链/智能体RAG/推理蒸馏实战
  • TF 上架协作实战,跨部门配合下的内测发布节奏管理
  • Cursor CLI 技术解析:免费调用 GPT-5 的命令行方案
  • 工控机的用途与介绍:工业自动化的重要引擎
  • [激光原理与应用-287]:理论 - 波动光学 - 电磁波既能承载能量,又能承载信息?
  • Systemd Service 文件详解
  • 反射和类加载机制
  • Leetcode 最小生成树系列(2)
  • 深入解析 Monkey OCR:本地化、多语言文本识别的利器与实践指南
  • 德州扑克游戏术语
  • 什么是Redis的哨兵模式
  • 针对前面2篇文章的一个细节的修订(UAC ADC/DAC录音播放,以及UAC ADC/PWM录音播放)
  • const修饰指针用法详解
  • libdrm 和 libgbm
  • 零基础从头教学Linux(Day 13)
  • 13_集合框架
  • ScanNet项目介绍
  • Linux网络配置:聚合链路与网桥实战
  • 开疆智能ModbusTCP转Ethernet网关连接FBOX串口服务器配置案例
  • MySQL多表查询案例
  • 360 集团20周年会:战略升级ALL IN Agent,抢占智能体时代先机
  • OSCP - Proving Grounds - CVE-2024-25180
  • 基于WSL搭建Ubuntu 22.04.x LTS开发环境
  • LLM - 使用 SGLang 部署 Qwen3-32B 与 Qwen2.5-VL-32B-Instruct
  • 《GUI-Actor: Coordinate-Free Visual Grounding for GUI Agents》论文精读笔记
  • 今日分享:C++模板(全详解)
  • 大数据系列之:设置CMS垃圾收集器
  • std::set_symmetric_difference
  • 第七十三章:AI的“黑箱”迷局:推理链路中的断点与Tensor调试——让模型“交代一切”!