Linux基础知识点-(七-线程)

news2024/11/29 12:41:30

目录

一、线程和进程

1.1 线程的基本概念

1.2 线程的优缺点

二、创建线程

2.1 pthread_create() - 创建线程函数

三、线程属性

四、线程退出

4.1 pthread_exit()

4.2 pthread_join() 

4.3 pthread_detach() 


一、线程和进程

1.1 线程的基本概念

在很多Linux的书籍基本上都是这样子描述进程(process)和线程(thread)的: 进程是资源管理的最小单位,线程是程序执行的最小单位

在操作系统设计上,从进程演化出线程。 线程的出现最主要的目的就是减小进程上下文切换开销,进程是资源管理的最小单位,那么每个进程都拥有自己的数据段、代码段和堆栈段, 这必然就造成了进程间切换时都要进行比较复杂的上下文切换等动作,因为要保存当前进程上下文的内容, 还要恢复另一个进程的上下文。如果是经常切换进程的话,这样子的开销就过于庞大。因为在进程切换上下文时, 需要重新映射虚拟地址空间、进出OS内核、寄存器切换,还会干扰处理器的缓存机制。 因此为了进一步减少CPU在进程切换时的额外开销,Linux进程演化出了另一个概念——线程。

线程是操作系统能够调度和执行的基本单位,在Linux中也被称之为轻量级进程。在Linux系统中, 一个进程至少需要一个线程作为它的指令执行体,进程管理着资源(比如cpu、内存、文件等等),而将线程分配到某个CPU上执行。在CPU眼中只认PCB(task_struct),不分进程和线程,进程中的每一个task_struct就是一个线程,他们指向同一个地址空间。

task_struct是进程内部的一个执行流,进程可以重新理解为内部只有一个执行流的进程,多线程可以理解为内部具有多个执行流的进程。 

1.2 线程的优缺点

线程的优点

  • 创建一个新线程的代价要比创建一个新进程小得多
  • 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
  • 线程占用的资源要比进程少很多
  • 能充分利用多处理器的可并行数量
  • 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
  • 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
  • I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。

线程的缺点: 

  • 性能损失
  • 健壮性降低
  • 缺乏访问控制
  • 编程难度提高

线程共享进程数据,但也拥有自己的一部分数据

  •  线程ID
  • 一组寄存器
  • errno
  • 信号屏蔽字
  • 调度优先级

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

  • 文件描述符表
  • 每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)
  • 当前工作目录
  • 用户id和组id

二、创建线程

可移植操作系统接口 (Portable Operating System Interface,缩写为POSIX), POSIX是IEEE为了在各种UNIX操作系统上运行软件而定义API接口等一系列互相关联的标准的总称, 其正式称呼为IEEEStd 1003,而国际标准名称为ISO/IEC9945,此标准源于一个大约开始于1985年的项目。 POSIX这个名称是由理查德·斯托曼(RMS)应IEEE的要求而提议的一个易于记忆的名称。 它基本上是Portable Operating System Interface(可移植操作系统接口)的缩写, 而X则表明其对Unix API的传承。 

在Linux系统下的多线程遵循POSIX标准,而其中的一套常用的线程库是 pthread,它是一套通用的线程库,是由 POSIX提出的,因此具有很好的可移植性,Linux多线程编程也正是使用它,在使用时必须包含以下头文件: 

#include <pthread.h>

除此之外在链接时需要使用库libpthread.a。因为pthread的库不是Linux系统的库, 所以在编译时要加上-lpthread 选项。

2.1 pthread_create() - 创建线程函数

pthread_create()函数是用于创建一个线程的,创建线程实际上就是确定调用该线程函数的入口点, 在线程创建后,就开始运行相关的线程函数。函数原型如下:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                    void *(*start_routine) (void *), void *arg);

参数说明

  • thread:指向线程标识符的指针。

  • attr:设置线程属性,attr为NULL表示默认属性。

  • start_routine:start_routine是一个函数指针,指向要运行的线程入口,即线程运行时要执行的函数代码。

  • arg:给start_routine指向的函数传入的参数。

  • 返回值:若线程创建成功,则返回0。若线程创建失败,则返回对应的错误代码。

三、线程属性

 上面pthread_create中需要以线程属性作为输入参数,在Linux中线程属性结构如下:

typedef struct
{
    int                   etachstate;      //线程的分离状态
    int                   schedpolicy;     //线程调度策略
    structsched_param     schedparam;      //线程的调度参数
    int                   inheritsched;    //线程的继承性
    int                   scope;           //线程的作用域
    size_t                guardsize;       //线程栈末尾的警戒缓冲区大小
    int                   stackaddr_set;   //线程的栈设置
    void*                 stackaddr;       //线程栈的位置
    size_t                stacksize;       //线程栈的大小
}pthread_attr_t;

线程的属性非常多,而且其属性值不能直接设置,须使用相关函数进行操作。线程属性主要包括如下属性: 作用域(scope)、栈大小(stacksize)、栈地址(stackaddress)、优先级(priority)、 分离的状态(detachedstate)、调度策略和参数(scheduling policy and parameters)。 默认的属性为非绑定、非分离、1M的堆栈大小、与父进程同样级别的优先级,无其他特别需求,是可以不需要考虑线程相关属性的,使用默认的属性即可。

四、线程退出

4.1 pthread_exit()

在线程创建后,系统就开始运行相关的线程函数,在该函数运行完之后,该线程也就退出了, 这是线程的一种隐式退出的方法,这与进程的退出差不多,进程完成工作后就会退出。 而另一种退出线程的方法是使用pthread_exit()函数,让线程显式退出,这是线程的主动行为。 这里要注意的是,在使用线程函数时,不能随意使用exit()退出函数来进行出错处理, 这是因为exit()函数的作用是使调用进程终止,而一个进程往往包含多个线程,因此,在使用exit()之后,该进程中的所有线程都会被退出,因此在线程中只能调用线程退出函数pthread_exit()而不是调用进程退出函数exit(),pthread_exit()函数原型如下:

void pthread_exit(void *retval);

参数说明

  • retval:如果retval不为空,则会将线程的退出值保存到retval中,如果不关心线程的退出值,形参为NULL即可。

4.2 pthread_join() 

一般情况下,进程中各个线程的运行是相互独立的,线程的终止并不会相互通知,也不会影响其他的线程, 终止的线程所占用的资源不会随着线程的终止而归还系统,而是仍为线程所在的进程持有,这是因为一个进程中的多个线程是共享数据段的。进程之间可以使用wait()系统调用来等待其他进程结束,线程也有类似的函数:

int pthread_join(pthread_t thread, void **rval_ptr);

如果某个线程想要等待另一个线程退出,并且获取它的退出值,那么就可以使pthread_join()函数完成,以阻塞的方式等待tid指定的线程结束,当函数返回时,被等待线程的资源将被收回,如果进程已经结束,那么该函数会立即返回。并且tid指定的线程必须是可结合状态的,该函数执行成功返回0,否则返回对应的错误代码。

参数说明

  • thread: 线程标识符,即线程ID,标识唯一线程。

  • rval_ptr: 用户定义的指针,用来存储被等待线程的返回值。

需要注意的是一个可结合状态的线程所占用的内存仅当有线程对其执行立pthread_join()后才会释放,因此为了避免内存泄漏,所有线程的终止时,要么已被设为detached,要么使用pthread_join()来回收资源。

4.3 pthread_detach() 

默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成系统泄漏。如果不关心线程的返回值,join是一种负担,这个时候,可以通过pthread_detach()函数将线程设置为detached,当线程退出时,自动释放线程资源,pthread_detach()函数如下:

int pthread_detach(pthread_t thread);

 参数说明

  • thread: 线程标识符,即线程ID,标识唯一线程。

  • 返回值:成功返回0,失败返回-1

joinable和detached是冲突的,一个线程不能既是joinable又是detached,可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离:pthread_detach(pthread_self()),pthread_self()返回是所在线程的线程标识符

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

/*要执行的线程*/
void *test_thread(void *arg)
{
    int num = (int)arg; 
    printf("This is test thread, arg is %d\n", num);
    sleep(5);
    /*退出线程*/
    pthread_exit(NULL);
}

int main(void)
{
    pthread_t tid;
    void *thread_return;
    int arg = 520;
    int res;

    printf("start create thread\n");
    /*创建线程,线程执行test_thread函数*/
    res = pthread_create(&tid, NULL, test_thread, (void*)(arg));
    if(res != 0)
    {
        printf("create thread fail\n");
        exit(res);
    }

    printf("create treads success\n");
    printf("waiting for threads to finish...\n");

    /*等待线程终止*/
    res = pthread_join(tid, &thread_return);
    if(res != 0)
    {
        printf("thread exit fail\n");
        exit(res);
    }
    printf("thread exit ok\n");
    return 0;
}

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

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

相关文章

Java ArrayList 面试题

Java ArrayList 面试题 文章目录 Java ArrayList 面试题ArrayList源码分析成员变量构造方法ArrayList源码分析面试题-ArrayList listnew ArrayList(10)中的list扩容几次面试题-如何实现数组和List之间的转换 ArrayList源码分析 分析ArrayList源码主要从三个方面去翻阅&#xf…

【鸿蒙】安装DevEco Studio运行HarmonyOS第一个APP(小白必看)

文章目录 前言一、DevEco Studio是什么&#xff1f;二、DevEco Studio安装运行1. 下载DevEco Studio2. 安装DevEco Studio3. 启动DevEco Studio4. 运行APP5. 修改代码 三、DevEco Studio调试注意事项总结 前言 鸿蒙OS是华为公司开发的一款基于微内核、耗时10年、4000多名研发人…

MySQL检索距离当前最近的7个小时内,靠近每个时间点数据信息

MySQL检索距离当前最近的7个小时内&#xff0c;靠近每个时间点数据信息 如果你想在最近7个小时内找到每个时间点最接近的数据&#xff0c;即使某些时间点没有数据&#xff0c;你可以使用子查询和窗口函数。以下是一个示例查询&#xff1a; sqlCopy codeSELECTt.time_point,CO…

[每周一更]-(第51期):Go的调度器GMP

参考文献 https://learnku.com/articles/41728http://go.cyub.vip/gmp/gmp-model.html#g-m-phttps://blog.csdn.net/ByteDanceTech/article/details/129292683https://www.ququ123.top/2022/04/golang_gmp_principle/ 什么是GMP? GMP模型是Go语言并发模型的核心概念&#x…

chrome浏览器自动填充密码的字号设置不生效

问题 刷新浏览器初始化字号很小 随便点击一下就会恢复我设置的字号大小 原因 给表单设置自动填充 autocomplete“on” 后&#xff0c;chrome会默认给自动填充的input表单加上 input:-webkit-autofill 私有属性 解决办法 方法一&#xff0c;对私有属性设置样式&#xff0…

matplotlib绘制折线图

代码 import matplotlib.pyplot as plt import numpy as npdef get_data(txt_path: str , epoch: int 100, target: str , target_data_len: int 5): # 函数介绍 # https://blog.csdn.net/LQ_001/article/details/130127681?csdn_share_tail%7B%22type%22%3A%22blog%22%2…

2024年的诸多跨年演讲,为什么觉得像是鸡汤?

时光如白驹过隙匆匆而已&#xff0c;转瞬间已来到2024年。伴随着新的一年的到来&#xff0c;一些互联网大佬如罗振宇、吴晓波等纷纷直播演讲&#xff0c;分享各自的思考和感悟。值不值得听呢&#xff1f;为什么有时候觉得是鸡汤&#xff1f;这里分析下可能的原因。 罗振宇的“做…

好代码网同款wordpress主题,适合搭建资源分享类网站,自带五六百的精品资源数据

代码简介&#xff1a; 好代码资源网是个还不错的资源分享类网站&#xff0c;基于wordpress搭建的。它的主题看起来还是不错的。这里分享一下这个网站的主题包。说是主题包&#xff0c;其实就是整站打包的&#xff0c;集成了主题&#xff08;wordpress美化主题包几个插件&#…

使用results.csv文件数据绘制mAP对比图

yolov5每次train完成&#xff08;如果没有中途退出&#xff09;都会在run目录下生成expX目录&#xff08;X代表生成结果次数 第一次训练完成生成exp0 第二次生成exp1…以此类推&#xff09;。expX目录下会保存训练生成的weights以及result.txt文件&#xff0c;其中weights是训练…

走进UI设计的秘密武器!6款软件值得珍藏!

Adobe Photoshop AdobePhotoshop&#xff0c;简称“PS它是一个由Adobesystems开发和发行的图像处理软件。Photoshop主要处理由像素组成的数字图像。使用其大量的编辑和绘图工具&#xff0c;可以有效地编辑图片。PS在图像、图形、文本、视频、出版等方面具有许多功能。 截至20…

API调试利器:速卖通平台的API测试与调试全攻略

想要快速注册速卖通平台的API账号&#xff1f;按照以下步骤操作&#xff0c;轻松完成注册&#xff1a; 进入速卖通平台&#xff0c;点击“卖家中心”&#xff0c;找到并点击“API管理”选项。在API管理页面中&#xff0c;点击“申请API密钥”按钮&#xff0c;填写相关信息并提…

架构设计系列9,10

架构设计系列9&#xff1a;前端架构和后端架构的区别 前端架构和后端架构都是软件系统中最关键的架构层&#xff0c;负责处理不同方面的任务和逻辑&#xff0c;两者之间是存在一些区别和联系的&#xff0c;我会从以下几个方面来阐述&#xff1a; 定位和职责 ● 前端架构主要…

普通用户用哪款电脑杀毒软件最好?

前言 各位小伙伴接触到电脑的时候&#xff0c;都一定有听过“电脑一定要安装杀毒软件”这句话。 毕竟在电脑诞生之初到今天&#xff0c;电脑木马和病毒依旧存在。 中了木马或病毒的电脑会出现什么现象&#xff1f;具体得看中了什么样的病毒。 但轻则资料泄漏、电脑瘫痪&…

el-select 多选,选有一个未选择的选项

多选有未选择这个选项后。会出现一个情况&#xff0c;绑定的数据为[‘未选择’,‘cpu1’,‘cpu2’] 进行一个处理&#xff0c;选择&#xff08;未选择&#xff09;就清除&#xff08;其它的选择&#xff09;&#xff0c;选择&#xff08;cpu&#xff09;就清除&#xff08;未选…

【Python机器学习】k近邻——k近邻分类

k-NN算法最简单的版本是只考虑一个最近邻&#xff0c;也就是想要预测的数据点最近的训练数据点&#xff0c;预测结果就是这个训练数据点的已知输出。 除了仅考虑最近邻&#xff0c;还可以考虑任意&#xff08;k个&#xff09;邻居&#xff0c;这也是k近邻算法名字的由来。在考…

【TC3xx芯片】TC3xx芯片的GTM模块详解

目录 前言 正文 1.GTM模块功能概述 1.1 GTM具体功能 1.2 GTM架构 2. GTM模块输入时钟 2.1.fGTM的值怎么计算 3. CMU 3.1 CMU功能 3.2 CMU时钟的计算 3..2.1 CLS0_CLK怎么计算 3.2.1 GTM Global Clock时钟计算 3.2.2 分频时钟的计算 4. CCM 4.1 CCM功能 4.2 CCM…

学习调整echarts中toolbox位置toolBox工具栏属性

学习调整echarts中toolbox位置toolBox工具栏属性 toolbox工具栏属性介绍示例代码代码参数说明 toolbox工具栏属性介绍 参考网址&#xff1a;https://echarts.apache.org/zh/option.html#tooltip 属性类型说明toolbox.showbooleanboolean 默认值为true&#xff0c;是否显示工具…

解密智能物流时代的未来:成本约束与需求升级的出路

引言&#xff1a; 近年来&#xff0c;中国物流行业蓬勃发展&#xff0c;为经济发展提供了重要的支撑。然而&#xff0c;随着国内外市场的竞争加剧和消费者对物流服务的期望不断提高&#xff0c;物流行业也面临着一系列的挑战。在此时&#xff0c;AR技术的应用融合给物流行业带…

高清网络视频监控平台的应用-城市大交通系统视联网

目 录 一、应用需求 二、系统架构设计 三、功能介绍 1.实时视频监控 2.云台控制 3.语音功能 4. 录像管理与回放 5.告警联动 6.多种显示终端呈现 &#xff08;1&#xff09;CS客户端 &#xff08;2&#xff09;web客户端 &#xff08;3&#xf…

【shell漫步】1 变量定义和使用

碎碎念 转眼间已经使用了一个月的shell了&#xff0c;作为一个纯小白&#xff0c;我特别理解刚入门的时候对于linux和shell一头雾水的状态&#xff0c;尤其是打算开始学&#xff0c;但是又找不到学习的“入口函数”的那种感受。所以打算整理一下shell的骨架。shell给我的感触就…