Linux 线程与pthread库

Linux线程与pthread库

  • 1. 线程和pthread库
  • 2. 线程的终止与退出
  • 3. 为什么需要线程库?
  • 4. 虚拟地址空间与线程库

在Linux系统中,线程控制是多任务编程的核心,而POSIX线程库(pthread库)则是应用层的原生线程库,为开发者提供了丰富的线程控制功能。

1. 线程和pthread库

1.1 线程创建
在Linux系统中,通过pthread库提供的pthread_create函数可以创建新的线程。该函数的原型如下:

在这里插入图片描述

参数:
thread:参数是一个输出型参数,用于获取创建成功的线程ID。
attr:参数用于设置线程的属性,传入NULL表示使用默认属性。
start_routine:参数是一个函数地址,表示线程启动后要执行的函数。
arg:参数是传给线程例程的参数。

1.2 线程ID获取

每个线程都有一个唯一的线程ID,通过 pthread_self 函数可以获取当前线程的ID。线程ID是一个无符号长整型数。
在这里插入图片描述

1.3. 线程等待

线程的等待是为了确保资源得到释放,避免系统泄漏。使用 pthread_join 函数可以等待线程的结束。
在这里插入图片描述

参数:
thread:参数是被等待线程的ID。
retval:存储线程的返回值(退出状态信息)的位置。
返回值:线程等待成功返回0,失败返回错误码。

下面的示例演示了线程的创建和等待过程:

在编译时,需要链接pthread库。在使用gcc编译时,可以通过在命令行中添加"-pthread"选项来链接pthread库。例如:

gcc -o my_program my_program.c -pthread
#include <pthread.h>
#include <stdio.h>  // 添加了这个头文件以使用printf
#include <unistd.h>
#include <sys/types.h>// 线程执行的工作
void* thread_routine(void* arg) {char* msg = (char*)arg;int n = 10;pthread_t tid = pthread_self();pid_t pid = getpid();pid_t ppid = getppid();// 在循环中输出线程信息while (n--) {// 修正了输出格式符printf("线程消息:%s pid: %d, ppid:%d, tid: %lu\n", msg, pid, ppid, tid);sleep(1);}// 返回线程的退出值return ((void*)42);
}int main() {pthread_t tid;  // 存放新线程的IDconst char* message = "你好,线程";  // 线程的消息void* exit_code;  // 用于存放线程的退出值// 创建线程if (pthread_create(&tid, NULL, thread_routine, (void*)message) != 0) {printf("创建线程失败\n");return 1;}// 输出主线程信息printf("主线程消息:%s pid: %d, ppid:%d, tid: %lu\n", message, getpid(), getppid(), pthread_self());// pthread_join 会阻塞等待子线程结束if (pthread_join(tid, &exit_code) == 0) {// 修正了输出格式符printf("线程返回值:%ld\n", (long)exit_code);} else {printf("等待线程失败\n");}return 0;  // 返回主函数的退出值
}

输出:在这里插入图片描述

运行时使用 ps -aL 显示当前系统中所有线程的信息

在这里插入图片描述

线程ID(TID) 是在进程内唯一的,它用于在同一进程内区分不同的线程
进程ID(PID) 用于在整个系统中唯一标识一个进程
如果PIDLWP相同,表示这个标识是主线程的标识;
如果它们不同,那么通常PID表示整个进程,而LWP表示不同的线程

2. 线程的终止与退出

线程的终止与退出有三种方式:

  1. 使用 return 语句:在线程函数中使用 return 语句可以使线程提前结束,但主线程使用 return 并不会终止整个进程。

示例:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void* thread_routine(void* arg) {// 线程执行的工作return (void*)42; // 返回退出码 42
}
int main() {pthread_t tid;if (pthread_create(&tid, NULL, thread_routine, NULL) != 0) {printf("创建线程失败\n");return 1;}// 等待线程退出,并获取退出码void* exit_code;pthread_join(tid, &exit_code);printf("线程退出码:%ld\n", (long)exit_code);return 0;
}
  1. 使用 pthread_exit 函数:允许线程独立终止,而不影响其他线程或整个进程

在这里插入图片描述

参数
retval:线程退出时的退出码信息。

功能
pthread_exit 函数允许线程独立终止,而不影响其他线程或整个进程。线程可以通过调用 pthread_exit 提前结束自己的执行,并传递一个退出码。

示例:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void* thread_routine(void* arg) {// 线程执行的工作pthread_exit((void*)42);  // 线程退出,返回退出码 42
}
int main() {pthread_t tid;if (pthread_create(&tid, NULL, thread_routine, NULL) != 0) {printf("创建线程失败\n");return 1;}// 等待线程退出,并获取退出码void* exit_code;pthread_join(tid, &exit_code);printf("线程退出码:%ld\n", (long)exit_code);return 0;
}
  1. 使用 pthread_cancel 函数:用于取消指定线程,被取消的线程可以在任何地方被取消,不仅限于线程函数的返回点。
    在这里插入图片描述

参数:
thread:要取消的线程的线程ID。
功能:
pthread_cancel 函数用于请求取消指定线程。该函数向指定线程发送取消请求,被取消的线程可以在任何地方被取消,不仅限于线程函数的返回点。

示例:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>// 线程函数
void* thread_routine(void* arg) {// 线程执行的工作while(1) {printf("Thread ID: %lu\n", pthread_self());sleep(1);}
}
int main() {pthread_t tid;// 创建线程if (pthread_create(&tid, NULL, thread_routine, NULL) != 0) {// 处理线程创建失败return 1;}sleep(3);// 取消线程pthread_cancel(tid);// 等待线程退出pthread_join(tid, NULL);return 0;
}

3. 为什么需要线程库?

在Linux内核中,线程的管理并不是直接由内核进行的,而是通过引入轻量级进程(Lightweight Process,LWP)的概念来实现。这种设计的核心思想是让内核专注于进程的管理,而将线程的管理交给用户空间的线程库。

  1. 轻量级进程(LWP): 在Linux内核中,每个进程都被分配一个LWP,它实际上是内核对进程的抽象,具有独立的PID,但共享相同的资源。LWP拥有独立的执行流,但线程的管理由用户空间的线程库负责。

  2. 线程概念在用户空间: Linux中没有专门的系统调用用于线程管理,而是通过用户空间的线程库(如pthread库)提供的接口实现。线程库中的函数用于创建、销毁和管理线程,这些线程在内核中对应LWP。

  3. 内核分工与线程库作用: 内核不直接管理线程,而是将管理任务委托给用户空间的线程库。线程库负责调度、切换和同步线程,提供高层次的线程抽象,使开发者能更轻松地进行多线程编程。

  4. 用户空间线程库的作用: 线程库在实现线程管理时可能使用内核提供的机制,但它们是用户空间的实体。线程库简化了开发者对多线程的操作,让他们不必深入了解内核的底层细节。

4. 虚拟地址空间与线程库

在这里插入图片描述

  1. 线程库在虚拟地址空间中位于共享区域。具体来说,用户空间的线程库,例如pthread库,通常会被加载到共享区域,这使得它对于同一进程内的所有线程都是可见的。在这个共享区域内,每个新线程都有一个对应的线程控制块(Thread Control Block,TCB),用于存储关于线程的各种信息,确保线程的独立性。

  2. 每个新线程在共享区域都有一个对应的线程控制块(Thread Control Block,TCB)。线程控制块存储了关于线程的各种信息,确保了线程的独立性。在pthread库中,线程ID(tid)指向了对应线程控制块的起始地址。通过这种方式,用户空间的线程库可以有效地管理和操作线程,而不必依赖内核级别的线程管理。线程控制块的存在使得线程库能够追踪线程的状态、优先级、寄存器值等信息,从而更好地协调和调度线程的执行。这种设计使得用户空间的线程库能够更加灵活地处理线程的创建、调度和撤销等操作,降低了对内核的依赖性。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Zookeeper】what is Zookeeper?

官网地址&#xff1a;https://zookeeper.apache.org/https://zookeeper.apache.org/ 以下来自官网的介绍 ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. A…

FCIS 2023:洞悉网络安全新态势,引领创新防护未来

随着网络技术的飞速发展&#xff0c;网络安全问题日益凸显&#xff0c;成为全球共同关注的焦点。在这样的背景下&#xff0c;FCIS 2023网络安全创新大会应运而生&#xff0c;旨在汇聚业界精英&#xff0c;共同探讨网络安全领域的最新动态、创新技术和解决方案。 本文将从大会的…

全球HBM研发进展解析

HBM&#xff08;高带宽内存&#xff09;的整体发展趋势和各大厂商的研究进度&#xff1a; 整体发展趋势&#xff1a; 市场需求增长显著&#xff1a;随着AI、机器学习以及高性能计算应用的迅速发展&#xff0c;尤其是生成式AI技术对更高性能计算能力的需求&#xff0c;市场对HB…

Android学习之路(26) ARouter APT技术详解

APT前置知识 注解基础&#xff1a; 1.元注解 1.Target&#xff1a;目标&#xff0c;表示注解修饰的目标 ElementType.ANNOTIONS_TYPE: 目标是注解&#xff0c;给注解设置的注解ElementType.CONSTRUCTOR: 构造方法ElementType.FIELD: 属性注解ElementType.METHOD: 方法注解Ele…

使用mmrotate对自定义数据集进行检测

这里写自定义目录标题 安装虚拟环境创建与准备安装mmrotate 自定义数据集标注数据与格式转换数据集划分与大图像切片 训练与测试修改配置文件执行训练进行测试鸣谢 安装 mmrotate是一个自带工作目录的python工具箱&#xff0c;个人觉得&#xff0c;在不熟悉的情况下&#xff0…

虚拟机配置了静态ip地址后,通过ssh连接到虚拟机比较慢

配置了静态ip地址后&#xff0c;通过ssh连接到虚拟机比较慢 [rootlocalhost ~]# vim /etc/ssh/sshd_config#快速方式找到UsePAM&#xff0c;输入“/UsePAM”而后回车&#xff0c;直接跳到UsePAM位置&#xff0c;将yes修改成no #键盘输入" i "开始编译 #"Esc&qu…

2024 年你应该使用 Bun、Node.js 还是 Deno?

导读&#xff1a;在 2024 年&#xff0c;JavaScript 开发者面临着 Node.js、Deno 和 Bun 这三个主要运行环境的选择。Node.js 以其成熟的生态系统和高性能著称&#xff0c;但可能面临性能限制。Deno 强调安全性&#xff0c;提供改进的开发者体验&#xff0c;但生态系统尚不成熟…

你的歌声婉转入云霄

可爱的一朵玫瑰花 - 吕继宏 可爱的一朵玫瑰花塞地玛丽亚 可爱的一朵玫瑰花塞地玛丽亚 那天我在山上打猎骑着马&#xff08;人善被人欺马善被人骑&#xff09; 正当你在山下歌唱婉转入云霄 歌声使我迷了路 我从山坡滚下 哎呀呀 你的歌声婉转入云霄 强壮的青年哈萨克伊万杜达尔 …

安卓Termux+Hexo博客框架快速搭建本地网站并实现公网访问

文章目录 前言 1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并结合…

浙大恩特客户资源管理系统 crmbasicaction 接口任意文件上传

该文章由掌控安全学院——1782814368投稿 【产品介绍】 浙大恩特客户资源管理系统是一款针对企业客户资源管理的软件产品。该系统旨在帮助企业高效地管理和利用客户资源&#xff0c;提升销售和市场营销的效果。 【漏洞介绍】 浙大恩特客户资源管理系统 crmbasicaction 任意…

Python学习路线 - Python高阶技巧 - 拓展

Python学习路线 - Python高阶技巧 - 拓展 闭包闭包注意事项 装饰器装饰器的一般写法(闭包写法)装饰器的语法糖写法 设计模式单例模式工厂模式 多线程进程、线程并行执行多线程编程threading模块 网络编程Socket客户端和服务端Socket服务端编程实现服务端并结合客户端进行测试 S…

陶哲轩如何用 GPT-4 辅助数学研究

关于陶哲轩&#xff08;Terence Tao&#xff09;用 GPT-4 进行数学研究的话题始于陶本人在 微软 Unlocked 上发表的 Embracing Change and Resetting Expectations 一文。文中提到&#xff1a; …… I could feed GPT-4 the first few PDF pages of a recent math preprint and…