【Linux】线程属性的定义如何修改线程属性(附图解与代码实现)

news2024/11/19 22:42:18

我们知道,在创建线程时,会用到pthread_create()函数 ,我们来简单介绍一下该函数:

pthread_create(线程的tid , 线程属性 , 工作函数名 , 函数需要的参数);

这篇博客要讲的线程属性,便是用于进行线程的初始化的,我们可以通过对线程属性的修改来自定义线程,接下来我们来了解一下什么线程属性

线程属性中的成员

线程属性是一个结构体,用法为 pthread_attr_t 变量名(本篇博客里默认变量名为attr)

线程属性结构体中的成员分别有:线程的警戒缓冲区、线程的优先级指针、线程的退出状态、线程栈地址、线程栈大小

接下来,我们来介绍一下该结构体中的这几个成员

线程的警戒缓冲区

首先我们要知道,每当一个线程被创建出来的时候,都会有一个相应的线程栈出现,而栈存在溢出问题(栈的溢出都是上溢),线程栈是申请在堆空间的

一旦栈发生溢出,数据就会向上覆盖,影响甚至破坏到库、栈区等空间中的数据。但更可怕的是,由于用户对用户空间中的内容具有读写权限,线程栈上溢所导致的对这些内容的修改,系统是不会报错的,只有当数据溢出到内核层时,我们才能够发现问题,但此时已经晚了,数据已经全被破坏了,所以我们需要来给每个线程栈“加个盖子”,也就是所谓的“警戒缓冲区”。

警戒缓冲区的大小一般为4K,这块内存是不可读写的,所以当线程栈发生上溢,想要修改这块内存中的内容时,系统就会发现有线程非法操作内存,并杀死该线程,这样就可以保护其他内存中的数据

线程的优先级指针

表示线程的优先级,一般情况下不建议修改,因为会影响系统的稳定性,一般只有杀毒软件或系统的防御软件才会修改其优先级

线程退出状态

线程的退出状态有两种,分别是回收态(PTHREAD_JOINABLE)和分离态(PTHREAD_DETACH)

线程栈地址

由于当修改线程属性时,线程还没有被创建,自然也就没有地址可存,所以默认情况下都是nil,表示空

线程栈大小

线程栈大小一般情况下都是8M,但是我们知道,8M如果用二进制表示时非常大的数,将这么大的数放进去仅仅表示线程栈的大小其实没什么意义,所以默认情况下,这里存放的数据就是0,表示8M,申请空间时也是申请8M大小的空间

修改线程属性的相关函数

在了解了线程属性的组成之后,我们就要来了解一下修改线程属性的相关函数了

先介绍下一会会用到的几个变量:

  • pthread_attr_t attr ; //定义一个线程属性结构体
  • int exit_state ; //线程属性中的退出状态
  • void* thread_stack_addr ; //线程属性中的线程栈地址
  • size_t thread_stack_size ; //线程属性中的线程栈大小
函数功能返回值
pthread_attr_getdetachstate(&attr , &exit_state);exit_state作为传出参数,可以获取线程属性中的退出状态

回收态返回 PTHREAD_CREATE_JOINABLE

分离态返回 PTHREAD_CREATE_DETACHED

pthread_attr_setdetachstate(&attr , exit_state);通过传入参数exit_state,设置线程属性中的退出状态成功返回0,失败返回非0错误码
pthread_attr_getstack(&attr , &thread_stack_addr , &thread_stack_size);thread_stack_addr、thread_stack_size作为传出参数,可以获取线程属性中的栈地址与栈大小返回两个参数——线程栈地址与线程栈大小
pthread_attr_setstack(&attr , thread_stack_addr , thread_stack_size);通过传入参数thread_stack_addr、thread_stack_size,可以设置线程属性中的栈地址与栈大小成功返回0,失败返回非0错误码
pthread_attr_init(&attr);初始化线程属性结构体成功返回0,失败返回-1
pthread_attr_destroy(&attr);释放线程属性结构体内存成功返回0,失败返回-1

修改线程属性的具体实现

接下来,我们可以根据这些函数来实际操作一下,完成以下两个小任务

  1. 获取线程属性中默认的退出状态(难度:⭐)
  2. 获取默认状态下线程属性中的线程栈地址与大小。将线程属性中的退出状态设置为分离态,修改线程栈地址,修改线程栈大小为1M,并测试使用这种线程属性的线程,系统一共能够创建多少个?(难度:⭐⭐⭐⭐)

PS:64位机下,即使你修改了线程栈大小,创建的数目和原来还是一样的,因为你的修改是无效的,系统创建的线程栈大小还是8M,修改线程栈大小只有32位机有效

一、获取线程属性中默认的退出状态,以下是代码实现

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <fcntl.h>

int main()
{
    pthread_attr_t attr;
    //1.初始化线程属性
    pthread_attr_init(&attr);
    //2.检测线程属性中的线程退出状态
    int detach_status;
    pthread_attr_getdetachstate(&attr , &detach_status);
    //3.判断是回收态还是分离态
    if(detach_status == PTHREAD_CREATE_JOINABLE)
    {
        printf("线程属性默认为回收态\n");
    }
    else
    {
        printf("线程属性默认为分离态\n");
    }
    //4.释放线程属性结构体内存
    pthread_attr_destroy(&attr);
    printf("进程退出!\n");
}

怎么样,是不是很简单呢?  接下来,我们来完成第二个小任务

二、获取默认状态下线程属性中的线程栈地址与大小。将线程属性中的退出状态设置为分离态,修改线程栈地址,修改线程栈大小为1M,并测试使用这种线程属性的线程,系统一共能够创建多少个,以下是代码实现

//pthread_addr_change.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <pthread.h>
#include <fcntl.h>

void* thread_jobs(void* arg)
{
    while(1)
    {
        sleep(1);
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_attr_t attr;
    //1.初始化线程属性
    pthread_attr_init(&attr);
    //2.检测线程属性中的线程退出状态
    int detach_status;
    pthread_attr_getdetachstate(&attr , &detach_status);
    //3.判断是回收态还是分离态并打印
    if(detach_status == PTHREAD_CREATE_JOINABLE)
    {
        printf("线程属性默认为回收态\n");
    }
    else
    {
        printf("线程属性默认为分离态\n");
    }
    //4.将线程属性中的退出态修改为分离态
    pthread_attr_setdetachstate(&attr , PTHREAD_CREATE_DETACHED);
    //5.获取线程属性中线程栈的初始地址与大小并打印
    void* thread_stack_addr;
    size_t thread_stack_size;
    pthread_attr_getstack(&attr , &thread_stack_addr , &thread_stack_size);
    printf("线程栈地址为 %p , 线程栈大小为 %d \n" , thread_stack_addr , (int)thread_stack_size);
    //6.通过malloc函数修改线程栈的初始地址,并将线程栈大小改为1M
    pthread_t tid;
    thread_stack_size = 0x100000;//0x100000代表1M
    int flag = 0;
    int errno;
    while(1)
    {
        //如果malloc函数的返回值为NULL,就说明分配失败,内存已经用完
        if((thread_stack_addr = (void*)malloc(thread_stack_size)) == NULL)
        {
            perror("thread_addr malloc failed!\n");
            exit(0);//进程退出
        }
        //修改栈初始地址和大小
        pthread_attr_setstack(&attr , thread_stack_addr , thread_stack_size);
        //创建线程,并判断是否创建失败
        if((errno = pthread_create(&tid , &attr , thread_jobs , NULL)) > 0)
        {
            perror("thread create failed!\n");
            exit(0);//进程直接退出
        }
        else
        {
            flag++;
            printf("flag = %d\n",flag);
        }
    }
    pthread_attr_destroy(&attr);
    return 0;  
}

结果如下图所示:

以上就是本篇博客的全部内容了,大家有什么地方没有看懂的话,可以在评论区留言给我,咱要力所能及的话就帮大家解答解答

今天的学习记录到此结束啦,咱们下篇文章见,ByeBye!

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

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

相关文章

卷积和反卷积的一些计算细节记录

一、卷积计算 多通道输入的情况 维度计算公式 参考&#xff1a; https://blog.csdn.net/qq_42596142/article/details/111467409 https://blog.csdn.net/v_july_v/article/details/51812459 https://www.cnblogs.com/wenshinlee/p/12591492.html 二、反卷积计算&#xff…

【音视频|ALSA】ALSA是什么?ALSA框架详细介绍

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

相似性搜索:第 5 部分--局部敏感哈希 (LSH)

SImilarity 搜索是一个问题&#xff0c;给定一个查询的目标是在所有数据库文档中找到与其最相似的文档。 一、介绍 在数据科学中&#xff0c;相似性搜索经常出现在NLP领域&#xff0c;搜索引擎或推荐系统中&#xff0c;其中需要检索最相关的文档或项目以进行查询。在大量数据中…

Linux常用命令——consoletype命令

在线Linux命令查询工具 consoletype 输出已连接的终端类型 补充说明 consoletype命令用于打印已连接的终端类型到标准输出&#xff0c;并能够检查已连接的终端是当前终端还是虚拟终端。 语法 consoletype实例 [rootlocalhost ~]# consoletype pty在线Linux命令查询工具

云原生场景下高可用架构的最佳实践

作者&#xff1a;刘佳旭&#xff08;花名&#xff1a;佳旭&#xff09;&#xff0c;阿里云容器服务技术专家 引言 随着云原生技术的快速发展以及在企业 IT 领域的深入应用&#xff0c;云原生场景下的高可用架构&#xff0c;对于企业服务的可用性、稳定性、安全性越发重要。通…

Springboot+vue的人事管理系统(有报告),Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的人事管理系统&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的人事管理系统&#xff0c;采用M&#xff08;model…

2023年【四川省安全员B证】报名考试及四川省安全员B证考试内容

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 四川省安全员B证报名考试根据新四川省安全员B证考试大纲要求&#xff0c;安全生产模拟考试一点通将四川省安全员B证模拟考试试题进行汇编&#xff0c;组成一套四川省安全员B证全真模拟考试试题&#xff0c;学员可通过…

程序装载:“640K内存”真的不够用么?

目录 背景 程序装载面临的挑战 内存分段 内存分页 小结 背景 计算机这个行业的历史上有过很多成功的预言&#xff0c;最著名的自然是“摩尔定律”。当然免不了的也有很多“失败”的预测&#xff0c;其中一个最著名的就是&#xff0c;比尔盖茨在上世纪 80 年代说的“640K …

计网面试复习自用

五层&#xff1a; 应用层&#xff1a;应用层是最高层&#xff0c;负责为用户提供网络服务和应用程序。在应用层&#xff0c;用户应用程序与网络进行交互&#xff0c;发送和接收数据。典型的应用层协议包括HTTP&#xff08;用于网页浏览&#xff09;、SMTP&#xff08;用于电子邮…

操作系统学习笔记5-内存管理

文章目录 1、CPU执行程序的基本过程2、CPU位数、OS位数、内存地址总线数、内存数据总线数目、逻辑地址位数、物理地址位数3、内存管理逻辑图4、编译、链接5、装入操作6、绝对装入7、静态重定位装入8、动态重定位装入9、内存保护10、单一连续分配10、固定分区分配11、动态分区分…

Java并发面试题:(三)sleep和wait方法区别,notify 和 notifyAll方法

sleep和wait wait, notify 和 notifyAll这些方法不在thread类里面? JAVA提供的锁是对象级的而不是线程级的&#xff0c;每个对象都有锁&#xff0c;通过线程获得。如果线程需要等待某些锁那么调用对象中的wait()方法就有意义了。如果wait()方法定义在Thread类中&#xff0c;线…

文件操作合集 - C语言

前言 由于我们每次打开程序写入的数据都是在内存中处理,关闭程序就直接没有了,下次还需要重新进行操作录入数据等,这里我们就可以使用文件来保存数据,更加持久化,下面我们基于c语言来介绍一些文件操作. 文件指针: 文件的打开和关闭 文件在读写之前应该先打开文件&#xff0c;在…

Linux:进程控制

目录 一、进程创建 写时拷贝 二、进程终止 echo $? 如何终止进程 _exit与exit 三、进程等待 进程等待的必要性 进程等待的操作 wait waitpid status 异常退出情况 status相关宏 options 四、进程程序替换 1、关于进程程序替换 2、如何进行进程程序替换 程序…

记录一次典型oom的处理过程

背景 有同学反馈收到应用RT的报警&#xff0c;其中的流量都来自于网关集群中的一台机器。因为负责网关&#xff0c;就上去看了下并进行排查。整体是一个比较明显的oom&#xff0c;这里只是记录下排查过程&#xff0c;老司机可以略过了。 初步现象 常规步骤&#xff0c;使用t…

maven 新建模块 导入后 按Ctrl 点不进新建模块pom定义

新建的ruoyi-common-mybatisplus 模块,导入一直不正常 画出的模块一直导入不进来 这是提示信息 这是正常的提示信息 加上 <version>3.6.3</version> 后,才一切正常

Bootstrap的导航菜单组件相关知识

目录 01-最基本的导航示例02-设置导航的对齐方式02-1-设置导航在水平方向上的对齐方式 02-2-设置导航在垂直方向上进行布局03-设计标签页导航04-带下拉菜单的标签页导航05-设计胶囊式导航05-1-基本的胶囊式导航05-2-带下拉菜单的胶囊式导航 06-让导航菜单项可以切换(激活导航菜…

精品基于django的高校竞赛比赛管理系统Python

《[含文档PPT源码等]精品基于django的高校竞赛管理系统》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django 前端技术&#xff1a;JavaScri…

宝塔面板部署express以及MySql项目

第一次在宝塔面板上部署express和MySql项目&#xff0c;部署过程一直跑不通接口&#xff0c;特此记录一下。 在部署的时候&#xff0c;建议第一步把数据库MySql给跑通&#xff0c;中间好多原因是由于数据库的原因给引起的。 一.连接数据库 &#xff08;1&#xff09;在宝塔面…

IP 协议的相关特性(部分)

IP 协议的报文格式 4位版本号&#xff1a; 用来表示IP协议的版本&#xff0c;现有的IP协议只有两个版本&#xff0c;IPv4&#xff0c;IPv6。 4位首部长度&#xff1a; 设定和TCP的首部长度一样 8位服务类型&#xff1a; &#xff08;真正只有4位才有效果&#xff09;&#xf…

教你快速解决unity无法添加脚本bug

原因一 就是报错的字面意思&#xff0c;文件名与类名不一致&#xff01; 原因二 与版本不兼容的汉化导致系统出错&#xff01; 解决办法一 使用原版本自带的英文显示 解决办法二 更换汉化包 我其实更加推荐使用英文版本的Unity&#xff01;