Linux 详谈线程概念与控制(二)

VASP+Multiwfn+VMD静电势计算与可视化全流程解析 静电势是表征分子与材料表面电荷分布的关键物理量,它通过求解泊松方程,将电子密度与原子核电荷在空间中的贡献结合起来,直观揭示体系的电子富集与缺失区域。这一性质在理解化学反应活性、分子间相互作用(如氢键、卤键)以及材料表面性质方面具有重要价值。在计算材料科学与量子化学领域,基于第一性原理计算获得高精度电子结构数据后,如何将其转化为可直观分析的静电势图,是连接理论计算与物理解释的关键技术环节。本文聚焦于构建一条高效、可控的端到端工作流,详细解析如何利用VASP进行高精度电子密度计算,通过专业波函数分析软件Mult 阅读详情

1. Linux进程VS线程

进程和线程

进程是资源分配的基本单位

线程是调度的基本单位

线程共享进程数据,但也拥有⾃⼰的⼀部分数据:

线程ID

⼀组寄存器

栈

errno

信号屏蔽字

调度优先级

进程的多个线程共享

同⼀地址空间,因此Text Segment、Data Segment都是共享的,如果定义⼀个函数,在各线程中都可以调⽤,如果定义⼀个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:

⽂件描述符表

每种信号的处理⽅式(SIG_ IGN、SIG_ DFL或者⾃定义的信号处理函数)

当前⼯作⽬录

⽤⼾id和组id

进程和线程的关系如下图

关于进程线程的问题

 如何看待之前学习的单进程?具有⼀个线程执⾏流的进程

2. Linux线程控制

POSIX线程库

与线程有关的函数构成了⼀个完整的系列,绝⼤多数函数的名字都是以“pthread_”打头的

要使⽤这些函数库,要通过引⼊头⽂ <pthread.h>

链接这些线程函数库时要使⽤编译器命令的“-lpthread”选项

创建线程

功能:创建⼀个新的线程
原型:
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void(*start_routine)(void*), void *arg);
参数:
    thread:返回线程ID
    attr:设置线程的属性,attr为NULL表⽰使⽤默认属性
    start_routine:是个函数地址,线程启动后要执⾏的函数
    arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码

错误检查:

传统的⼀些函数是,成功返回0,失败返回-1,并且对全局变量errno赋值以指⽰错误。

pthreads函数出错时不会设置全局变量errno(⽽⼤部分其他POSIX函数会这样做)。⽽是将错误代码通过返回值返回

pthreads同样也提供了线程内的errno变量,以⽀持其它使⽤errno的代码。对于pthreads函数的错误,建议通过返回值业判定,因为读取返回值要⽐读取线程内的errno变量的开销更⼩

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
void* rout(void* arg) {
	int i;
	for (; ; ) {
		printf("I'am thread 1\n");
		sleep(1);
	}
}
int main(void)
{
	pthread_t tid;
	int ret;
	if ((ret = pthread_create(&tid, NULL, rout, NULL)) != 0) {
		fprintf(stderr, "pthread_create : %s\n", strerror(ret));
		exit(EXIT_FAILURE);
	}
	int i;
	for (; ; ) {
		printf("I'am main thread\n");
		sleep(1);
	}
}
#include <pthread.h>
// 获取线程ID
pthread_t pthread_self(void)

打印出来的 tid 是通过 pthread 库中有函数 pthread_self 得到的,它返回⼀个 pthread_t 类型的变量,指代的是调⽤ pthread_self 函数的线程的 “ID”。

怎么理解这个“ID”呢?这个“ID”是 pthread 库给每个线程定义的进程内唯⼀标识,是 pthread 库维持的。

由于每个进程有⾃⼰独⽴的内存空间,故此“ID”的作⽤域是进程级⽽⾮系统级(内核不认识)。

其实 pthread 库也是通过内核提供的系统调⽤(例如clone)来创建线程的,⽽内核会为每个线程创建系统全局唯⼀的“ID”来唯⼀标识这个线程。

使⽤PS命令查看线程信息

运⾏代码后执⾏:

$ ps -aL | head -1 && ps -aL | grep mythread
PID LWP TTY TIME CMD
2711838 2711838 pts/235 00:00:00 mythread
2711838 2711839 pts/235 00:00:00 mythread
-L 选项:打印线程信息

LWP 是什么呢?LWP 得到的是真正的线程ID。之前使⽤ pthread_self 得到的这个数实际上是⼀个地址,在虚拟地址空间上的⼀个地址,通过这个地址,可以找到关于这个线程的基本信息,包括线程ID,线程栈,寄存器等属性。

在 ps -aL 得到的线程ID,有⼀个线程ID和进程ID相同,这个线程就是主线程,主线程的栈在虚拟地址空间的栈上,⽽其他线程的栈在是在共享区(堆栈之间),因为pthread系列函数都是pthread库提供给我们的。⽽pthread库是在共享区的。所以除了主线程之外的其他线程的栈都在共享区。

线程终⽌

如果需要只终⽌某个线程⽽不终⽌整个进程,可以有三种⽅法:

从线程函数return。这种⽅法对主线程不适⽤,从main函数return相当于调⽤exit。

线程可以调⽤pthread_ exit终⽌⾃⼰。

⼀个线程可以调⽤pthread_ cancel终⽌同⼀进程中的另⼀个线程。

pthread_exit函数

功能:线程终⽌
原型:
    void pthread_exit(void *value_ptr);
参数:
    value_ptr:value_ptr不要指向⼀个局部变量
返回值:
    ⽆返回值,跟进程⼀样,线程结束的时候⽆法返回到它的调⽤者(⾃⾝)

需要注意,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是⽤malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。

pthread_cancel函数

功能:取消⼀个执⾏中的线程
原型:
    int pthread_cancel(pthread_t thread);
参数:
    thread:线程ID
返回值:成功返回0;失败返回错误码

线程等待

为什么需要线程等待?

已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。

创建新的线程不会复⽤刚才退出线程的地址空间。

功能:等待线程结束
原型
    int pthread_join(pthread_t thread, void **value_ptr);
参数:
    thread:线程ID
    value_ptr:它指向⼀个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码

调⽤该函数的线程将挂起等待,直到id为thread的线程终⽌。thread线程以不同的⽅法终⽌,通过pthread_join得到的终⽌状态是不同的,总结如下:

如果thread线程通过return返回,value_ ptr所指向的单元⾥存放的是thread线程函数的返回值。

如果thread线程被别的线程调⽤pthread_ cancel异常终掉,value_ ptr所指向的单元⾥存放的是常数PTHREAD_ CANCELED。

如果thread线程是⾃⼰调⽤pthread_exit终⽌的,value_ptr所指向的单元存放的是传给pthread_exit的参数。

如果对thread线程的终⽌状态不感兴趣,可以传NULL给value_ ptr参数。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void* thread1(void* arg)
{
	printf("thread 1 returning ... \n");
	int* p = (int*)malloc(sizeof(int));
	*p = 1;
	return (void*)p;
}
void* thread2(void* arg)
{
	printf("thread 2 exiting ...\n");
	int* p = (int*)malloc(sizeof(int));
	*p = 2;
	pthread_exit((void*)p);
}
void* thread3(void* arg)
{
	while (1) { //
		printf("thread 3 is running ...\n");
		sleep(1);
	}
	return NULL;
}
int main(void)
{
	pthread_t tid;
	void* ret;
	// thread 1 return
	pthread_create(&tid, NULL, thread1, NULL);
	pthread_join(tid, &ret);
	printf("thread return, thread id %X, return code:%d\n", tid, *(int*)ret);
	free(ret);
	// thread 2 exit
	pthread_create(&tid, NULL, thread2, NULL);
	pthread_join(tid, &ret);
	printf("thread return, thread id %X, return code:%d\n", tid, *(int*)ret);
	free(ret);
	// thread 3 cancel by other
	pthread_create(&tid, NULL, thread3, NULL);
	sleep(3);
	pthread_cancel(tid);
	pthread_join(tid, &ret);
	if (ret == PTHREAD_CANCELED)
		printf("thread return, thread id %X, return code:PTHREAD_CANCELED\n",tid);
	else
		printf("thread return, thread id %X, return code:NULL\n", tid);
}
运⾏结果:
[root@localhost linux]# ./a.out
thread 1 returning ...
thread return, thread id 5AA79700, return code:1
thread 2 exiting ...
thread return, thread id 5AA79700, return code:2
thread 3 is running ...
thread 3 is running ...
thread 3 is running ...
thread return, thread id 5AA79700, return code:PTHREAD_CANCELED

分离线程

默认情况下,新创建的线程是joinable的,线程退出后,需要对其进⾏pthread_join操作,否则⽆法释放资源,从⽽造成系统泄漏。

如果不关⼼线程的返回值,join是⼀种负担,这个时候,我们可以告诉系统,当线程退出时,⾃动释放线程资源。

int pthread_detach(pthread_t thread);

可以是线程组内其他线程对⽬标线程进⾏分离,也可以是线程⾃⼰分离

pthread_detach(pthread_self());

joinable和分离是冲突的,⼀个线程不能既是joinable⼜是分离的。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void* thread_run(void* arg)
{
	pthread_detach(pthread_self());
	printf("%s\n", (char*)arg);
	return NULL;
}
int main(void)
{
	pthread_t tid;
	if (pthread_create(&tid, NULL, thread_run, "thread1 run...") != 0) {
		printf("create thread error\n");
		return 1;
	}
	int ret = 0;
	sleep(1);//很重要,要让线程先分离,再等待
	if (pthread_join(tid, NULL) == 0) {
		printf("pthread wait success\n");
		ret = 0;
	}
	else {
		printf("pthread wait failed\n");
		ret = 1;
	}
	return ret;
}

【Unity3D插件】XCharts插件完全教程《全网最全》-专栏文章目录 最近在做图表类需求功能的时候,发现了一款强大的Unity3D插件,也就是XCharts图表插件,功能强大,支持多种图表。官方介绍:一款基于UGUI的功能强大、简单易用的数据可视化图表插件。支持折线图、饼状图、饼图、雷达图、散点图、热力图、环形图、K线图、极坐标、平行坐标等十多种内置图表,以及3D饼图、3D金字塔、漏斗图、仪表盘、水位图、象形柱图、甘特图、矩形树图等拓展图表。内置丰富示例和模板,参数可视化配置,效果实时预览,纯代码绘制。支持折线图、柱状图、饼图、雷达图、散点图、热力图等常见图表。 阅读详情

相关推荐

PSF(点扩散函数)与去卷积算法消除图像模糊

本文旨在总结图像处理中使用去卷积的传统方法来进行图像去模糊的相关知识。

m0_53607446的博客 6012

【linux】线程概念与控制

详细讲解和实操了linux下线程概念与使用

You build it, you run it 3346

RK3588 EVB开发板原理图讲解【六】

该原理图展示了eMMC Flash与主控芯片之间的连接关系,以及相关的电源、信号线路和去耦电容等。

weixin_48721556的博客 1165

【Linux】多线程(概念,控制)

💬 hello!各位铁子们大家好哇。今日更新了Linux线程的内容。

qinjh_的博客 4107

MATLAB双目相机标定:从工具箱实战到参数精解

本文详细讲解了使用MATLAB进行双目相机标定的完整实战流程与参数精解。从拍摄合格的棋盘格图像、设置关键参数(如径向畸变系数),到分析重投影误差、优化结果并正确导出和使用内外参,提供了从操作到原理的全面指导,帮助读者为立体视觉应用奠定精准基础。

weixin_29041767的博客 257

在 SAP Fiori 里玩转 Manage Views:把过滤器与列表布局固化成你的默认工作台

本文介绍了SAP Fiori应用中"Manage Views"功能的核心价值和使用方法。该功能允许用户保存和复用个性化界面设置,包括筛选条件、列布局等,将重复操作简化为一次性配置。文章从技术实现、用户操作和治理建议三个维度展开: 功能本质:View存储的是界面状态而非业务模型,是提升个人生产力的工具 核心价值:固化高频操作,支持默认视图设置,实现"开箱即用"的工作状态 操作指南:详细说明了收藏、重命名、设为默认、自动应用等关键功能 治理建议:区分标准视图、个人视图和公

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 125

【Linux】线程概念与控制

下面是一个简化图有了页帧,该如何管理呢?先描述再组织,操作系统引入了。

2401_86449430的博客 1万+

【30】软考软件设计师——UML类图与用例图满分精讲|下午第3题常考核心

本文是《软件设计师·50讲通关|从零基础到工程师职称》专栏第30篇,聚焦**模块四:应用技术(下午题)第3道高频大题**,UML建模是历年下午必考核心,单题分值稳定10~12分。全文深度拆解两大核心UML图表:**类图**与**用例图**,超详细讲解类图三层结构、可见性修饰符、五大核心关系(泛化/关联/依赖/聚合/组合)的判定标准与绘图规范;吃透用例图参与者、系统边界、三大关系(包含/扩展/泛化)的底层逻辑,搭配独家**关系秒杀口诀、标准绘图模板、真题改错技巧**;全文适配补图、判断关系、分析场景、纠错优化

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 572

【Linux线程】Linux线程编程基础:概念、创建与管理

在当今的软件开发领域,多线程编程已经成为了一种不可或缺的技术。特别是在Linux操作系统环境下,多线程编程更是被广泛地应用于各种高性能、高并发的应用场景中。然而,多线程编程也是一项极具挑战性的任务,它要求开发者具备扎实的编程基础,对并发控制、资源管理等有深入的理解

EterNity_TiMe_的计算机学习之路 3625

2025年数学建模国赛高教社杯A题、B题、C题、D题、E题详细思路和代码 模型||插值与拟合

核心思想:构造一个精确通过所有已知离散数据点(xi, yi)的函数y = f(x),并以此函数来估算或预测未知点的值。基本假设:我们认为已知的数据点是100%精确、无误差的(或者误差可忽略不计),比如理论计算值、高精度仪器测量值等。我们的目标是“还原”或“重建”出点与点之间的真实函数关系。关键特征精确性:曲线或曲面必须穿过每一个样本点。局部性:插值结果严重依赖于局部数据点的分布和数值。用途:用于“补全”数据、填充缺失值、进行函数近似等。常见方法多项式插值:拉格朗日插值、牛顿插值。

2201_76125261的博客 802

VN5620以太网测试——环境搭建篇

CANoe(CAN open environment)VN5620 :是一个紧凑而强大的接口,用于以太网网络的分析、仿真、测试和验证。VN5620 接口支持各种可能的应用。它适用于与其他总线系统、网络参与(例如在模拟和生成帧、测试中的负载和错误)的同步以太网监控。在2021年Vector公司的以太网接口卡VN5610和VN5640设备已经陆续停产,相应被VN5620和VN5650代替。

诊断协议那些事儿's blog 8927

【Linux】Linux线程概念和线程控制

本文介绍了Linux中线程的概念和线程控制--线程创建,终止,等待,分离

qq_67582098的博客 2602

SAP 错误消息调试之七种武器:让所有的错误消息都能被定位

目录 长生剑 - SAPGUI Where Used List 碧玉刀 - ABAP调试器观察点 霸王枪 - ABAP调试器动态断点 多情环 - ABAP代码静态扫描 孔雀翎 - SAT 离别钩 - ST05 拳头 - 迷之方法??? Jerry在2018年开始用中文在微信公众号平台上写作之前,在SAP官方社区上总共写了639篇英文博客。 其中有一篇写于2013年介绍ABAP调试技巧的博客:

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2807

【Linux系统】初见线程,概念与控制

本文深入解析了Linux线程的概念、实现原理及控制方法。主要内容包括:1. 线程是进程内部的执行分支,在Linux中通过轻量级进程(LWP)实现,使用PCB结构体描述;2. 线程共享进程资源,但拥有独立的执行流和栈空间;3. 通过pthread库提供的接口(如pthread_create、pthread_join等)实现线程创建、终止、等待和分离;4. 详细分析了线程ID的本质、地址空间布局以及线程局部存储特性;5. 比较了线程与进程在资源管理、切换开销等方面的差异。文章还探讨了页表机制、物理内存管理、TL

记录学习与成长 3845

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Linux:线程概念 | 线程控制

当CPU调度执行该“”进程“时,只会执行原本进程中的一部分代码和数据,执行我们要执行任务的一部分任务,我们将这种比传统“进程”更加轻量化的进程就称为线程!)下,其中一些线程抢占锁的能力是非常强的,导致其他线程长时间无法获得锁资源,导致线程饥饿问题。我们也将这种线程称为轻量级进程!在Linux中,如果操作系统真的支持线程,此时在计算机中必然存在大量的线程,所以OS需要对线程进行管理。如果不关心线程的返回值,join是一种负担,这个时候,我们可以将线程设置为分离状态,告诉系统,当线程退出时,自动释放线程资源!

Zhenyu_Coder的博客 2506

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

【Linux】线程概念和线程控制

初识Linux中的线程,理解线程的各种概念,理解进程地址空间中的页表转换,介绍pthread线程库并理解线程库!

YoungMLet的博客 5267

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【Linux探索学习】第二十九弹——线程概念:Linux线程的基本概念与线程控制详解

【Linux探索学习】第二十九弹:线程的基本概念和线程控制的相关知识点,理清线程与进程的关系与区别!!

2301_80220607的博客 5571

Linux线程-概念和控制

Linux多线程-概念和控制零、前言一、Linux线程概念1、什么是线程2、vfork函数/pthread线程库3、线程优缺点及其他分析二、Linux进程VS线程1、进程和线程三、Linux线程控制1、POSIX线程库2、线程创建3、线程ID及线程地址空间布局4、线程终止5、线程等待6、线程分离 零、前言 本章主要讲解学习Linux中的线程 一、Linux线程概念 1、什么是线程 概念: 在一个程序里的一个执行路线就叫做线程(thread),更准确的定义是:线程是“一个进程内部的控制序列”

~ 2607

Linux的线程概念与控制

首先Linux内核不区分"进程"和"线程",统一用task_struct管理。CPU处理的是一个个task_struct。进程1个或多个task_struct(PCB) +代码和数据线程(轻量级进程) =1个task_struct(PCB) (它通过指针共享了其所属进程的代码和数据我们之前讲的传统的进程是一个主线程。一个进程的多个task_struct(PCB),被认为是多个轻量级进程,主轻量级进程的id即lwp(light weight peocess)与进程的pid相同。

博客 | 复习知识点 + 练习 + 最终的领悟 | 全力以赴 1425

【Linux】多线程1——线程概念与线程控制

初步认识线程的概念,并熟悉线程控制接口

Pursue quality, not quantity. 1612

【Linux】线程概念

目录 1. 线程 1.1. 线程概念 1.2. Linux下的线程 线程的优点 线程的缺点 1.3. 进程与线程 2.线程控制 2.1. 线程创建 2.2. 线程等待 2.3. 线程终止 2.4. 线程分离 3.线程ID 1. 线程 1.1. 线程概念 一般而言,线程是在进程内部运行的一个执行分支(执行流),属于进程的一部分,粒度要比进程更加细和轻量化。 一个进程内是可能存在多个进程的。 那么操作系统内就存在更多的线程,所以操作系统管理线程的方式依旧是:先描述,再组

Edward_Asia的博客 2052

【Linux】线程概念与线程控制

线程的概念与控制,页表相关内容

weixin_69380220的博客 1287

【Linux】多线程——线程概念|进程VS线程|线程控制

早期我们的计算机还只能单个进程运行,这样的话每个进程就只能独立存在,不可以进行每个进程交互,在这个基础上我们的先人(大佬)看看能不能多个进程同时运行,也就有了现在的多进程,那对比单个进程,多进程有什么优势呢?值不值得我们学习呢?咱们带上这两个问题来康康Linux下的多线程。⭐主体。

AAlykk的博客 2124

【Linux】线程的概念与控制

线程概念认识和使用,分页式存储了解,封装线程库。

2301_81577798的博客 1万+

线程概念,控制

线程是程序内部的一个独立执行流,是CPU调度的基本单位。它共享进程的大部分资源(如内存),但拥有独立的运行时状态(如栈和寄存器)。 线程控制主要包括其创建、执行、同步和销毁。通过互斥锁、信号量等同步机制,解决多个线程并发访问共享资源时可能引发的数据不一致问题,确保程序正确、高效地并发运行。

2402_84532723的博客 2922

Linux之线程概念与控制

Linux之线程概念与控制

2302_81120572的博客 1356
上一篇: Linux 详谈线程概念与控制(一)
下一篇: Linux 详谈线程同步与互斥
万我.
博客等级 码龄1年 460粉丝 93原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值