【Linux C | 多线程编程】线程的基础知识

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍线程的基础知识 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
⏰发布时间⏰:2024-03-16 13:03:47

本文未经允许,不得转发!!!

目录

  • 🎄一、什么是线程
  • 🎄二、多线程的优缺点
    • ✨2.1 多线程的优点
    • ✨2.2 多线程的缺点
  • 🎄三、线程ID
    • ✨3.1 gettid
    • ✨3.2 syscall
    • ✨3.3 查看线程ID
  • 🎄四、/proc/PID/task/ 目录
  • 🎄五、总结


在这里插入图片描述

🎄一、什么是线程

在了解线程之前,先看看程序和进程是什么?

程序:程序或可执行文件是静态的静态的实体,只是一组指令的集合,没有执行的意义。

进程:是运行之后的程序,是一个动态的实体, 有自己的生命周期。

线程:线程是一个进程内部的一个控制序列,是操作系统进程调度器可以调度的最小执行单元。一个进程运行之后,就至少会有一个线程。只有一个线程的进程叫单线程进程

一个进程可能包含多个线程, 传统意义上的进程, 不过是多线程的一种特例, 即该进程只包含一个线程。在Linux系统开发中,也经常会使用到多线程编程,把进程设计成在同一时刻能够做多件事,每个线程处理各自独立的任务。

在这里插入图片描述


在这里插入图片描述

🎄二、多线程的优缺点

✨2.1 多线程的优点

  1. 同一个进程的线程会共享内存地址空间。同一个进程的多个线程共享一份全局内存区域, 包括初始化数据段、 未初始化数据段和动态分配的堆内存段。这使得创建或终止线程的时间要少于进程,共享数据比进程简单。
  2. 发挥多核优势, 充分利用CPU资源。如果存在多个相同的任务, 彼此之间并行不悖, 互不依赖(或者依赖性很小) , 那么启动多个线程并发处理, 是一个不错的选择。通过为每种事件类型的处理分配单独的线程,能够简化处理异步时间的代码。
  3. 有些问题可以通过将其分解从而改善整个程序的吞吐量。
  4. 交互的程序可以通过使用多线程实现相应时间的改善,多线程可以把程序中处理用户输入输出的部分与其它部分分开。

✨2.2 多线程的缺点

  1. 多线程的进程, 因地址空间的共享让该进程变得更加脆弱。多个线程之中, 只要有一个线程不够健壮存在bug,就可能导致整个进程崩溃。
  2. 线程模型作为一种并发的编程模型, 效率并没有想象的那么高, 会出现复杂度高、 易出错、 难以测试和定位的问题。
    多线程编程很难将全部任务均等地分给每个进程;
    多线程之间可能存在依赖关系,一个线程未完成某些操作之前,其他线程不应该运行。
  3. 多线程编程存在四个陷进:死锁(Dead Lock)、饿死(Starvation)、活锁(Live Lock)、竞态条件(Race Condition)

在这里插入图片描述

🎄三、线程ID

在Linux中, 目前的线程实现是Native POSIX Thread Library,简称NPTL。在这种实现下,线程又被称为轻量级进程(Light Weighted Process),每一个用户态的线程,在内核之中都对应一个调度实体,也拥有自己的进程描述符(task_struct结构体) 。

对于单线程进程来说,一个进程对应内核里的一个进程描述符, 对应一个进程ID。
多线程的进程, 又被称为线程组, 线程组内的每一个线程在内核之中都存在一个进程描述符(task_struct) 与之对应。

struct task_struct {...pid_t pid;pid_t tgid;...struct task_struct *group_leader;...struct list_head thread_group;...
}

内核的 struct task_struct 结构体中的两个ID字段:
pid:pthread ID,表示线程ID;
tgid:意思是 Thread Group ID,表示线程组ID,对应的是进程ID。

✨3.1 gettid

Linux中提供系统调用 gettid 来获取调用者的线程ID。但是,这个系统调用没有glibc封装,使用glibc的编译器时只能使用 syscall 函数来调用 gettid 系统调用;

gettid函数原型

#include <sys/types.h>
pid_t gettid(void);
Note: There is no glibc wrapper for this system call; see NOTES.

函数描述:gettid() 返回调用方的线程ID(TID)。在单线程进程中,线程ID等于进程ID(PID,由getpid()返回)。在多线程进程中,所有线程都有相同的PID,但每个线程都有一个唯一的TID。


✨3.2 syscall

因为在 glibc 的编译器没有gettid 函数,所以只能使用 syscall 函数来获取线程ID,syscall函数原型如下:

#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include <unistd.h>
#include <sys/syscall.h>   /* For SYS_xxx definitions */
int syscall(int number, ...);

函数描述:syscall()是一个小型库函数,用于系统调用,该系统调用的汇编语言接口具有指定的数字和指定的参数。例如,当调用C库中没有包装函数的系统调用时,使用syscall()非常有用。

下面是一个例子,创建4个线程,分别获取自己的线程ID,例子中用到一些陌生的函数如:pthread_create,会在后面介绍线程的文章讲解。这个例子可以使用命令gcc gettid.c -lpthread 进行编译,-lpthread表示要链接线程库。

// gettid.c
#include <stdio.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h>void *func(void *arg)
{int *pI = arg;pid_t tid = /*getpid()*/syscall(SYS_gettid);printf("this thread is num %d , tid=%d\n", *pI, tid);while(1); // 避免线程退出return NULL;
}
int main()
{int i=0;int args[4] = {0,};for(i=0; i<4; i++){pthread_t threadId;args[i] = i;pthread_create(&threadId, NULL, func, &args[i]);}while(1); // 避免线程退出return 0;
}

运行结果:
在这里插入图片描述


✨3.3 查看线程ID

在Linux下,使用ps命令中的-L选项,会显示出线程的如下信息。

  • LWP: 线程ID, 即gettid() 系统调用的返回值。
  • NLWP: 线程组内线程的个数

使用ps命令查看上面程序的线程,因为ps命令输出太多了,这里使用grep过滤一下,使用命令ps -eLf | grep -e "PID" -e "a.out",只显示带有PIDa.out关键字的行,结果如下:
可以看到a.out有5个线程,主线程是PID和LWP列一样的线程,即113178那一行。
在这里插入图片描述
ps命令还可以使用-T选项来显示SPID列,表示线程ID。如果想知道更多的ps命令,可以使用ps --help查看。


在这里插入图片描述

🎄四、/proc/PID/task/ 目录

procfs在task下会给进程的每个线程建立一个子目录, 目录名为线程ID。

已知某进程的进程ID,我们就可以通过/proc/PID/task/目录下的子目录来查看该进程的线程个数和线程ID。

以上个小节进程ID为113178的进程举例,也是可以看到对应目录下有5个由线程ID命令的子目录:
在这里插入图片描述


在这里插入图片描述

🎄五、总结

👉本文介绍线程的基础知识,包括线程优缺点、线程ID、/proc/PID/task/ 目录等。

需要强调的一点是,线程和进程不一样, 进程有父进程的概念, 但在线程组里面, 所有的线程都是对等的关系。

  • 并不是只有主线程才能创建线程, 被创建出来的线程同样可以创建线程。
  • 不存在类似于fork函数那样的父子关系, 大家都归属于同一个线程组, 进程ID都相等, group_leader都指向主线程, 而且各有各的线程ID。
  • 并非只有主线程才能调用pthread_join连接其他线程, 同一线程组内的任意线程都可以对某线程执行pthread_join函数。
  • 并非只有主线程才能调用pthread_detach函数, 其实任意线程都可以对同一线程组内的线程执行分离操作

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

参考资料:
《Linux环境编程:从应用到内核》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2870086.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux系列】计算机系统中的架构与发行版:理解与区分

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

软件测试 自动化测试selenium 基础篇

文章目录 1. 什么是自动化测试&#xff1f;1.1 自动化分类 2. 什么是 Selenium &#xff1f;3. 为什么使用 Selenium &#xff1f;4. Selenium 工作原理5. Selenium 环境搭建 1. 什么是自动化测试&#xff1f; 将人工要做的测试工作进行转换&#xff0c;让代码去执行测试工作 …

使用PWM实现呼吸灯功能

CC表示的意思位捕获比较&#xff0c;CCR表示的是捕获比较寄存器 占空比等效于PWM模拟出来的电压的多少&#xff0c;占空比越大等效出的模拟电压越趋近于高电平&#xff0c;占空比越小等效出来的模拟电压越趋近于低电平&#xff0c;分辨率表示的是占空比变化的精细程度&#xf…

ChatGPT GPT4科研应用、数据分析与机器学习、论文高效写作、AI绘图技术

原文链接&#xff1a;ChatGPT GPT4科研应用、数据分析与机器学习、论文高效写作、AI绘图技术https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247596849&idx3&sn111d68286f9752008bca95a5ec575bb3&chksmfa823ad6cdf5b3c0c446eceb5cf29cccc3161d746bdd9f2…

【C++】类和对象终章

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、初始化列表1.1 初始化列表的形式1.2 初始化列表的注意事项 二、explicit关键…

Halcon识别文字案例

识别文字并显示到页面上 read_image (Image, needle1.png) * 打开窗口 dev_open_window (0, 0, 512, 512, black, WindowHandle) dev_display (Image)* 画矩形 gen_rectangle1 (ROI_0, 52.4648, 99.0391, 256.758, 354.063) * 裁剪 reduce_domain (Image, ROI_0, ImageReduced)…

Unity Live Capture 中实现面部捕捉同步模型动画

Unity Face Capture 是一个强大的工具&#xff0c;可以帮助你快速轻松地将真实人脸表情捕捉到数字模型中。在本文中&#xff0c;我们将介绍如何在 Unity Face Capture 中实现面部捕捉同步模型动画。 安装 |实时捕获 |4.0.0 (unity3d.com) 安装软件插件 安装 Live Capture 软件…

合并多棵二叉搜索树

1932. 合并多棵二叉搜索树 困难 相关标签 相关企业 提示 给你 n 个 二叉搜索树的根节点 &#xff0c;存储在数组 trees 中&#xff08;下标从 0 开始&#xff09;&#xff0c;对应 n 棵不同的二叉搜索树。trees 中的每棵二叉搜索树 最多有 3 个节点 &#xff0c;且不存在值…

【论文阅读】Diffused Heads: Diffusion Models Beat GANs on Talking-Face Generation

Diffused Heads: 扩散模型在说话人脸生成方面击败GANs paper&#xff1a;[2301.03396] Diffused Heads: Diffusion Models Beat GANs on Talking-Face Generation (arxiv.org) code&#xff1a;MStypulkowski/diffused-heads: Official repository for Diffused Heads: Diffu…

Vue3+TypeScript 学习回顾,温故而知新

文章简介&#xff1a; &#xff08;1&#xff09;简介&#xff1a; 在 Vue3 中编码规范如下&#xff1a; 编码语言: JavaScript代码风格: 组合式API选项式、API简写形式: setup语法糖 &#xff08;2&#xff09;复习内容&#xff1a; 1.核心: ref、reactive、computed、w…

【道路交通管理与控制】第九章——城市智能交通管理与控制概论

文章目录 一、概述二、路线导行系统三、交通信息服务系统&#xff08;ATIS&#xff09;四、先进的城市公共交通系统&#xff08;APTS&#xff09;五、交通拥挤收费系统六、停车诱导系统&#xff08;PGIS&#xff09;七、地理信息和车辆定位系统&#xff08;AVL&#xff09;的应…

尼伽OLED透明屏闪耀第24届中国零售业博览会,引领零售行业革新

2024 CHINA SHOP 第二十四届中国零售业博览会 3.13-15 上海 3.13-15日&#xff0c;第24届中国零售业博览会盛大开幕&#xff0c;起立科技&#xff08;旗下品牌&#xff1a;起鸿、尼伽&#xff09;携其自主研发的30寸OLED透明屏和移动AI透明屏机器人惊艳亮相&#xff0c;成为展…

【AI】用iOS的ML(机器学习)创建自己的AI App

用iOS的ML(机器学习)创建自己的AI App 目录 用iOS的ML(机器学习)创建自己的AI App机器学习如同迭代过程CoreML 的使用方法?软件要求硬件开始吧!!构建管道:设计和训练网络Keras 转 CoreML将模型集成到 Xcode 中结论推荐超级课程: Docker快速入门到精通Kubernetes入门到…

​​SQLiteC/C++接口详细介绍之sqlite3类(十)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;九&#xff09; 下一篇&#xff1a;​​SQLiteC/C接口详细介绍之sqlite3类&#xff08;十一&#xff09; 30.sqlite3_enable_load_extension&#x…

USB打印机改网络打印机

解决传统SMB缺陷可跨平台设备使用。 1、安装deepin 如何安装 – 深度科技社区 2、配置IP地址 vi /etc/network/interfaces && systemctl restart networking 3、安装程序上传到服务器并解压。运行0Dinstalld目录下文件 sh 0Dinstalld/0installdd.sh http://XX.XX.XX…

蓝桥杯刷题(九)

1.三国游戏 代码 #输入数据 nint(input()) Xlilist(map(int,input().split())) Ylilist(map(int,input().split())) Zlilist(map(int,input().split())) #分别计算X-Y-Z/Y-Z-X/Z-X-Y并排序 newXli sorted([Xli[i] - Yli[i] - Zli[i] for i in range(n)],reverseTrue) newYli …

MLC-LLM框架的安卓应用部署实战

这几天根据官网教程把MLC-LLM在安卓端部署了一下&#xff0c;中间遇到了不少问题&#xff0c;也搜集了不少解决方案&#xff0c;同时也结合了别人的实践经历&#xff0c;现分享总结如下。 感谢博主tao_spyker的文章基于MLC LLM将Llama2-7B模型部署至Android手机运行&#xff0c…

HTML5:七天学会基础动画网页13

看完前面很多人可能还不是很明白0%-100%那到底是怎么回事&#xff0c;到底该怎么用&#xff0c;这里我们做一个普遍的练习——心跳动画 想让心❤跳起来&#xff0c;我们先分析一波&#xff0c;这个心怎么写&#xff0c;我们先写一个正方形&#xff0c;再令一个圆形前移: 再来一…

【数据可视化】使用Python + Gephi,构建中医方剂关系网络图!

代码和示例数据下载 前言 在这篇文章中&#xff0c;我们将会可视化 《七版方剂学》 的药材的关系&#xff0c;我们将使用Python制作节点和边的数据&#xff0c;然后在Gephi中绘制出方剂的网络图。 Gephi是一个专门用于构建网络图的工具&#xff0c;只要你能提供节点和边的数…

RTC的Google拥塞控制算法 rmcat-gcc-02

摘要 本文档描述了使用时的两种拥塞控制方法万维网&#xff08;RTCWEB&#xff09;上的实时通信&#xff1b;一种算法是基于延迟策略&#xff0c;一种算法是基于丢包策略。 1.简介 拥塞控制是所有共享网络的应用程序的要求互联网资源 [RFC2914]。 实时媒体的拥塞控制对于许…