linux高级编程(线程)(1)

虚拟地址:

线程:

        概念:线程是轻量级进程,一般是一个进程中的多个任务。
        进程是系统中最小的资源分配单位。(竞争计算机资源的最小单位)(进程能分配硬件资源,线程不行)线程是系统中最小的执行单位。


    特征:
    1、共享资源(除了栈区都共享)-->每个进程有独立的栈区,其他空间其实都用的是所从属的进程的,有效减少内存开销
    2、效率高  30%
    3、三方库: pthread  clone   posix
            3.1 编写代码头文件: pthread.h
            3.2 编译代码加载库: -lpthread   library 
            libpthread.so
            gcc 1.c -lpthread 

缺点:
    1,线程和进程相比,稳定性,稍微差些(一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程稳定。)
    2,线程的调试gdb,相对麻烦些。

线程与进程区别:
    变量开销:进程:3G(物理内存总量),线程:8M(单个程序栈的最大空间)

    资源:
        线程比进程多了共享资源。  IPC(进程间通信)
        线程又具有部分私有资源。
        进程间只有私有资源没有共享资源。
    空间:
        进程空间独立,不能直接通信。
        线程可以共享空间,可以直接通信。

线程的设计框架 

   创建多线程 --> 线程空间操作 --> 线程资源回收

线程创建:pthread_create():

int pthread_create(
        pthread_t *thread, const pthread_attr_t *attr,
        void *(*start_routine) (void *), void *arg);
    功能:该函数可以创建指定的一个线程。
    参数:thread 线程id,需要实现定义并由该函数返回。
          attr   线程属性,一般是NULL,表示默认属性。
          start_routine 指向指针函数的函数指针。
                  本质上是一个函数的名称即可。称为
                  回调函数,是线程的执行空间。

          arg  回调函数的参数,即参数3的指针函数参数。
          如果想要传多个参数:使用结构体
          返回值:成功 0
          失败 错误码

注:

       一次pthread_create执行只能创建一个线程。
      每个进程至少有一个线程称为主线程。
      主线程退出则所有创建的子线程都退出。 
      主线程必须有子线程同时运行才算多线程程序。
      线程id是线程的唯一标识,是CPU维护的一组数字。
      pstree 查看系统中多线程的对应关系。
      多个子线程可以执行同一回调函数。

pthread_self():

pthread_t pthread_self(void);
   功能:获取当前线程的线程id
   参数:无
   返回值:成功 返回当前线程的线程id
                 失败  -1; 

线程退出:

自行退出-->自杀-->exit()

void pthread_exit(void *retval);  //与return的效果类似
        功能:子线程自行退出
        参数: retval 线程退出时候的返回状态,临死遗言。
        返回值:无

强制退出-->他杀-->pthread_cancel()

int pthread_cancel(pthread_t thread);
        功能:请求结束一个线程
        参数:thread 请求结束一个线程tid
        返回值:成功 0
                      失败 -1;

pthread_join()

 int pthread_join(pthread_t thread, void **retval);    
     功能:阻塞回收。通过该函数可以将指定的线程资源回收,该函数具有
          阻塞等待功能,如果指定的线程没有结束,则回收线程会阻塞。
     参数:thread  要回收的子线程tid
        retval  要回收的子线程返回值/状态。-->ptread_exit(值);
     返回值:成功 0
                   失败 -1;

为什么要用ret要使用二级void指针:

因为ret期望来存储类似于函数指针,字符串(字符串使用字符数组存储)的值,这种变量本身就是一级指针,如果我们要在传参这种操作中能使被调修改主调,必须使用*运算,所以我们传进去的二级指针

期望的传参操作:

void* ret;
pthread_create(&tid,NULL,th,NULL);
pthread_join(tid,&ret); //传入一级指针地址
printf("ret %s\n",(char *)ret); //转换为需要的类型
printf("ret %d\n",*((char *)ret)); //取两次*运算

子线程的回收策略:

1、如果预估子线程可以有限范围内结束则正常用pthread_join等待回收。
2、如果预估子线程可能休眠或者阻塞则等待一定时间后强制回收。
3、如果子线程已知必须长时间运行则,不再回收其资源。

期望传回的地址:

原理:子线程退出的时候,可以返回一个内存地址
      该值所在的内存中可以存储任何数据,只要
      地址存在,则数据都可以正常返回。
    
    地址有三种:
    0、栈区变量  错误,子线程结束该地址失效。
    1、全局变量  失去意义,本质可以直接访问。

所以可以传回的地址:

    2、静态变量 
    3、堆区变量

分离属性(attribute):

设置分离属性,目的线程消亡,自动回收空间。

pthread_attr_init

int pthread_attr_init(pthread_attr_t *attr);
    功能,初始化一个attr的变量
    参数:attr,需要变量来接受初始值
    返回:0  成功,
    非0 错误

 pthread_attr_destroy

int pthread_attr_destroy(pthread_attr_t *attr);
      功能:销毁attr变量。
      attr,属性变量
      返回:0  成功,
      非0 错误;

pthread_attr_setdetachstate

功能:把一个线程设置成相应的属性
    参数,attr,属性变量,有init函数初始化他。
    detachstate:有2个可选值,
    设置分离属性:
    PTHREAD_CREATE_DETACHED(分离线程)
    PTHREAD _CREATE_JOINABLE(非分离线程)

第二种设置分离属性的函数:pthread_deatch

int pthread_deatch(pthread_t thread);
    功能,设置分离属性
    参数,线程id号,填自己的id        

清理函数:

pthread_cleanup_push()

void pthread_cleanup_push(void (*routine)(void *), void *arg);
    功能:注册一个线程清理函数
    参数,routine,线程清理函数的入口
        arg,清理函数的参数。
    返回值,无

需要满足以下条件才会调用注册的回调函数:

1.线程被取消的时候(pthread_cancel)

2.线程主动退出的时候(pthread_exit)

3.pthread_cleanup_pop的参数为非0值(pthread_cleanup_pop)

pthread_cleanup_pop:

void pthread_cleanup_pop(int execute);
    功能:调用清理函数
    execute,非0  执行清理函数
        0 ,不执行清理
            
    返回值,无

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

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

相关文章

解析QAnything启动命令过程

一.启动命令过程日志 启动命令bash ./run.sh -c local -i 0 -b hf -m Qwen-1_8B-Chat -t qwen-7b-chat。输入日志如下所示: rootMM-202203161213:/mnt/l/20230918_RAG方向/QAnything# bash ./run.sh -c local -i 0 -b hf -m Qwen-1_8B-Chat -t qwen-7b-chat From …

Leetcode Java学习记录——栈和队列 IDEA

文章目录 栈和队列stack Classqueue InterfaceDeque Interfaceadd 和 push Priority Queue -- Class题目 codestyleIDEA 操作快捷键选择代码生成类 栈和队列 stack Class google stack java 8/12 empty() peek() pop() push(E item) search(Object o) 最近相关性会用到栈 …

湘潭大学软件工程数据库总结

文章目录 前言试卷结构给学弟学妹的一些参考自己的一些总结 前言 自己可能很早很早之前就准备复习了,但是感觉还是没有学到要点,主要还是没啥紧迫的压力,我们是三月份开学,那时候实验室有朋友挺认真开始学习数据库了,…

理性决策的艺术:从购房到择偶的数学智慧;37% 规则,做出最佳决策的秘诀;用数学模型解决人生难题

在面对人生重大决策时,如购房或择偶,我们常常感到迷茫和困惑。然而,如果我们能够将这些看似复杂的问题简化为数学模型,我们就能以更加理性和系统的方式做出决策。 37%规则 1950年代,当时几位数学家开始研究这样一个问…

值得收藏!盘点那些适合普通人方便又好用的AIGC工具!(下)

【导读】接上一篇文章,盘点国内外适合普通人能够轻松上手的AIGC工具(上)。今天又为大家整理了一些好用又方便的AI设计工具、AI办公工具、AI编程工具、AI指令工具和AI检测工具,如果有没更新到的工具也欢迎大家评论区交流。 一 、A…

Kafka 入门指南

Kafka 入门指南 简介 Kafka 是一个由 Apache 软件基金会开发的开源流处理平台。它最初由 LinkedIn 开发,并在 2011 年作为开源项目发布。Kafka 是一个分布式、可扩展、高吞吐量的消息队列系统,广泛应用于实时数据流处理场景。 主要概念 1. 主题 (Top…

C#/WPF 自制截图工具

在日常使用电脑办公时,我们经常遇到需要截图然后保存图片,我们往往需要借助安装截图工具才能实现,现在我们通过C#自制截图工具,也能够轻松进行截图。 我们可以通过C#调用WindousAPI来实现截图,实例代码如下&#xff1a…

AI基本概念(人工智能、机器学习、深度学习)

人工智能 、 机器学习、 深度学习的概念和关系 人工智能 (Artificial Intelligence)AI- 机器展现出人类智慧机器学习 (Machine Learning) ML, 达到人工智能的方法深度学习 (Deep Learning)DL,执行机器学习的技术 从范围…

算法 —— 滑动窗口

目录 长度最小的子数组 无重复字符的最长子串 最大连续1的个数 将x减到0的最小操作数 找到字符串中所有字母异位词 长度最小的子数组 sum比target小就进窗口,sum比target大就出窗口,由于数组是正数,所以相加会使sum变大,相减…

关于redis的运维面试题-1

1. 什么是Redis? Redis(Remote Dictionary Server)是一个开源的内存数据结构存储,通常用作数据库、缓存和消息代理。它支持多种数据结构,如字符串(strings)、哈希(hashes&#xff0…

大二暑假 + 大三上

希望,暑假能早睡早起,胸围达到 95,腰围保持 72,大臂 36,小臂 32,小腿 38🍭🍭 目录 🍈暑假计划 🌹每周进度 🤣寒假每日进度😂 &…

DiskGeniusV5.6.0.1565发布!

DiskGenius是一款功能强大的磁盘管理和数据恢复工具,V5.6.0.1565上线。新版本变化比较大,增加新的功能,修正已经问题,值得试一下。提醒大家,磁盘管理软件涉及数据安全,请始终使用最新版本! 下面…

JS hook

参照: JS 逆向之 Hook JS Hook 与 过 debugger 一、常用Hook 1. eval (function() {let _eval eval;eval function(val) {if (val.indexof(debugger) -1) {_eval_cache(obj);}} })(); 2. JSON.parse() (function () {var parse_ JSON.parse;JSON.parse …

C++ initializer_list类型推导

目录 initializer_list C自动类型推断 auto typeid decltype initializer_list<T> C支持统一初始化{ }&#xff0c;出现了一个新的类型initializer_list<T>&#xff0c;一切类型都可以用列表初始化。提供了一种更加灵活、安全和明确的方式来初始化对象。 class…

IO-Link OD介绍

IO-Link OD&#xff08;On-request Data&#xff0c;按需数据&#xff09;是IO-Link通信中的一种重要数据类型&#xff0c;主要用于参数读写、指令交互、事件上传等动作。以下是关于IO-Link OD的结构、构成以及功能使用的详细说明&#xff1a; 结构与构成 定义&#xff1a;OD…

堆排序(Heap Sort)

堆排序是一种高效的排序算法&#xff0c;它利用了堆的数据结构来实现。堆是一种特殊的完全二叉树&#xff0c;分为最大堆和最小堆两种类型。在最大堆中&#xff0c;父节点的值大于等于其子节点的值&#xff1b;而在最小堆中&#xff0c;父节点的值小于等于其子节点的值。 堆排…

【C命名规范】遵循良好的命名规范,提高代码的可读性、可维护性和可复用性

/******************************************************************** * brief param return author date version是代码书写的一种规范 * brief &#xff1a;简介&#xff0c;简单介绍函数作用 * param &#xff1a;介绍函数参数 * return&#xff1a;函数返回类型说明 * …

同一个excel表格,为什么在有的电脑上会显示#NAME?

一、哪些情况会产生#NAME?的报错 1.公式名称拼写错误 比如求和函数SUM&#xff0c;如果写成SUN就会提示#NAME&#xff1f;报错。 2.公式中的文本值未添加双引号 如下图&#xff1a; VLOOKUP(丙,A:B,2,0) 公式的计算结果会返回错误值#NAME?&#xff0c;这是因为公式中文本…

【PLC】三菱PLC如何和汇川伺服实现485通信

前言 一开始选用的是汇川SV660P脉冲型伺服&#xff0c;由于生产需求需要对伺服的个别参数进行读取和写入操作&#xff0c;但是SV660P并不支持这种情况&#xff0c;因此需要使用485通信来满足。PLC这边选用的是三菱FX5U。 开始 1、首先准备按照下图的引脚提示准备好一根带屏蔽…

全志H616交叉编译工具链的安装与使用

交叉编译的概念 1. 什么是交叉编译&#xff1f; 交叉编译是指在一个平台上生成可以在另一个平台上运行的可执行代码。例如&#xff0c;在Ubuntu Linux上编写代码&#xff0c;并编译生成可在Orange Pi Zero2上运行的可执行文件。这个过程是通过使用一个专门的交叉编译工具链来…