13LinuxC线程学习之利用pthread_create设置线程分离属性和相关属性解释

2023-10-27

1 线程属性

  • 1)本节作为指引性介绍,linux下线程的属性是可以根据实际项目需要,进行设置,之前我们讨论的线程都是采用线程的默认属性,默认属性已经可以解决绝大多数开发时遇到的问题。如我们对程序的性能提出更高的要求那么需要设置线程属性,比如可以通过设置线程栈的大小来降低内存的使用,增加最大线程个数。
  • 2)设置线程分离的方法有两种,一个是本节的调用pthread_create的参数设置,另一个是上几节的detach。C语言设置分离建议前者,因为不需要每次都调用detach。直接设置属性即可。看个人。
    下面给出Linux内核线程属性的结构体,版本为2.2。因为2.6版本开始稳定,所以目前2021年可能已经是差异很大,但没关系,我们主要是简单看看。
typedef struct{
	int 					etachstate; 	//线程的分离状态
	int 					schedpolicy; 	//线程调度策略
	struct sched_param		schedparam; 	//线程的调度参数
	int 					inheritsched; 	//线程的继承性
	int 					scope; 			//线程的作用域
	size_t 					guardsize; 		//线程栈末尾的警戒缓冲区大小
	int						stackaddr_set;  //线程的栈设置
	void* 					stackaddr; 		//线程栈的位置
	size_t 					stacksize; 		//线程栈的大小
} pthread_attr_t; 

/*
	主要结构体成员:
	1. 线程分离状态.
	2. 线程栈大小(默认平均分配).
	3. 线程栈警戒缓冲区大小(位于栈末尾).
属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用。之后须用pthread_attr_destroy函数来释放资源。
线程属性主要包括如下属性:作用域(scope)、栈尺寸(stack size)、栈地址(stack address)、优先级(priority)、分离的状态(detached state)、调度策略和参数(scheduling policy and parameters)。
默认的属性为非绑定、非分离、缺省的堆栈、与父进程同样级别的优先级。
*/

2 与设置线程分离属性的相关函数

1)初始化线程属性pthread_attr_init。

int pthread_attr_init(pthread_attr_t *attr); 
/*
	功能:初始化线程属性。
	成功:0;失败:错误号。
*/

2)销毁线程属性所占用的资源pthread_attr_destroy

int pthread_attr_destroy(pthread_attr_t *attr); 
/*
	功能:销毁线程属性所占用的资源。
	成功:0;失败:错误号。
*/

3 线程属性结构体的相关参数讲解

3.1线程的分离状态
线程的分离状态决定一个线程以什么样的方式来终止自己。

  • 1)非分离状态:线程的默认属性是非分离状态,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。
  • 2)分离状态:分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。应该根据自己的需要,选择适当的分离状态。
  • 3)线程分离状态的函数:
//1)
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); 
/*
	设置线程属性,分离or非分离。
	参1:attr,已初始化的线程属性。
	参2:传入。detachstate:PTHREAD_CREATE_DETACHED(分离线程)或者PTHREAD _CREATE_JOINABLE(非分离线程)
*/

//2)
 	int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
/*
	获取程属性,分离or非分离
	参1:attr,已初始化的线程属性。
	参2:传出。detachstate:PTHREAD_CREATE_DETACHED(分离线程)或者PTHREAD _CREATE_JOINABLE(非分离线程)
*/ 

这里要注意的一点是,如果设置一个线程为分离线程,而这个线程运行又非常快,
它很可能在pthread_create函数返回之前就终止了,它终止以后就可能将线程号和
系统资源移交给其他的线程使用,这样调用pthread_create的线程就得到了错误的
线程号。要避免这种情况可以采取一定的同步措施,最简单的方法之一是可以在被
创建的线程里调用pthread_cond_timedwait函数,让这个线程等待一会儿,留出足
够的时间让函数pthread_create返回。设置一段等待时间,是在多线程编程里常用
的方法。但是注意不要使用诸如wait()之类的函数,它们是使整个进程睡眠,并不
能解决线程同步的问题。

3.2 线程的栈地址

  • 1)POSIX.1定义了两个常量_POSIX_THREAD_ATTR_STACKADDR 和_POSIX_THREAD_ATTR_STACKSIZE检测系统是否支持栈属性。也可以给sysconf函数传递_SC_THREAD_ATTR_STACKADDR或 _SC_THREAD_ATTR_STACKSIZE来进行检测。
  • 2)当进程栈地址空间不够用时,指定新建的线程使用malloc分配的空间作为自己的栈空间。通过pthread_attr_setstack和pthread_attr_getstack两个函数分别设置和获取线程的栈地址。
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize); 
/*
	功能:当进程栈地址不够用,新建的线程使用malloc分配的空间作为自己的栈空间。而该函数就是充当这个分配作用。
	成功:0;失败:错误号。
	参1:线程属性的指针。
	参2:返回获取的栈地址。(实际上这个参数是返回还是要设置的栈起始地址我也不是特别清楚,可以man pthread_attr_setstack查看)
	参3:要设置的栈大小。
*/
int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize); 
/*
	功能:获取当进程栈不够空间时,malloc出的空间作为栈空间的地址。
	成功:0;失败:错误号。
	参1:attr,指向一个线程属性的指针。
	参2:stackaddr,返回获取的栈地址。
	参3:stacksize,返回获取的栈大小。
*/

3.3 线程的栈大小

  • 1)当系统中有很多线程时,可能需要减小每个线程栈的默认大小,防止进程的地址空间不够用,当线程调用的函数会分配很大的局部变量或者函数调用层次很深时,可能需要增大线程栈的默认大小。
  • 2)函数pthread_attr_getstacksize和 pthread_attr_setstacksize提供设置。
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
/*
	功能:设置栈的大小。
	成功:0;失败:错误号。
	参1:线程的属性。
	参2:要设置的栈大小。
*/ 
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize); 
/*
	功能:获取设置的栈大小。
	成功:0;失败:错误号。
	参1:线程的属性。
	参2:返回线程的堆栈大小。
*/

4 利用pthread_create的参数设置线程属性分离案例

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


void *thrd_func(void *arg)
{	
	sleep(1);//防止分离的线程在pthread_create返回tid之前结束,导致tid为失败值而认为创建线程失败
    pthread_exit((void *)77);
}

int main(void)
{
    pthread_t tid;
    int ret;
    pthread_attr_t attr;
	
	//1 
    ret = pthread_attr_init(&attr);
    if (ret != 0) {
        fprintf(stderr, "pthread_init error:%s\n", strerror(ret));
        exit(1);
    }
	
	//2 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	
	//3 这一步注意:若pthread_create创建分离的线程后,并且在返回tid之前结束,tid可能是一个失败值。所以可以使分离的线程睡眠一下。
    ret = pthread_create(&tid, &attr, thrd_func, NULL);
    if (ret != 0) {
        fprintf(stderr, "pthread_create error:%s\n", strerror(ret));
        exit(1);
    }
	
	/*
	//这一步只是验证是否成功属性分离,若成功则回收失败
    ret = pthread_join(tid, NULL);
    if (ret != 0) {
        fprintf(stderr, "pthread_join error:%s\n", strerror(ret));
        exit(1);
    }
	*/

    pthread_exit((void *)1);
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

13LinuxC线程学习之利用pthread_create设置线程分离属性和相关属性解释 的相关文章

随机推荐

  • C++中类型转化

    对象类型向上向下转化 对象转化是对象间的按成员赋值 有新的存储被分配 有新对象产生 类型指针向上向下转化 转化后没有得到引得对象 也可以说没有新的存储分配 我们只是通过一个小的 转化后的对象的大小 视角去看待这个对象 因此在诸如对象的释 放
  • 网络总结知识点(网络工程师必备)一

    作者 小刘在C站 个人主页 小刘主页 每天分享云计算网络运维课堂笔记 努力不一定有收获 但一定会有收获加油 一起努力 共赴美好人生 夕阳下 是最美的绽放 树高千尺 落叶归根人生不易 人间真情 前言 本专栏为就业必修秘籍 技术分册 本张试读篇
  • 某程序员披露华为外包员工现状:工作氛围好,没有歧视,但转正后也不算正式员工?...

    有些想进互联网大厂的人在无法成为正式员工的时候 会通过成为外包员工的方式来曲线救国 但在互联网大厂中 外包员工和正式员工的差别待遇一直是比较热门的话题 最近 一个网友总结了华为外包和正式员工的区别 干货满满 先来看看 看完以后 许多人表示赞
  • iframe被拒绝_IFRAME权限被拒绝的解决方案

    iframe被拒绝 I was recently rolling my own AJAX upload script posting a form to a hidden IFRAME and using the load event to
  • TEMPLATE METHOD 模式

    Template Method 模式使用继承 来分离通用的算法和具体的上下文 简单的讲 我有一个冒泡排序的程序 用来对int 型数据排序 要想对double 类型的数据排序 可能又得重新编写一个排序程序 Template Method 模式
  • 微信小程序cover-image手机上不显示问题

    微信小程序标签cover image 在未设置宽高的情况下 在手机上不显示 但是在微信web开发者工具上却显示 如果我们想使图片宽高比保持一致 是图片不变形 解决方法 在cover image标签外放一个父容器给它设置相对定位 子元素设置绝
  • QT周记大总结

    初识UI 增加子组件 private 成员变量 QPushButton btn1 btn1 new QPushButton 关闭 this btn1 gt move 100 100 样式表 define QPushButton STYTLE
  • 毛笔字识别--详细注释解析恩培作品6

    感谢恩培大佬对项目进行了完整的实现 并将代码进行开源 供大家交流学习 一 项目简介 本项目最终达到的效果为识别毛笔字 并对字体进行分类 如下所示 项目用python实现 调用opencv等库 使用SVM对字体进行分类 由以下步骤组成 1 使
  • 设计约束文件SDC

    设计约束文件SDC 全称Synopsys design constraints 主要包括以下内容 Units Time capacitance Resistance Voltage Current Power 单位 时间 电容 电阻 电压
  • QJsonObject 类

    1 QJsonObject简介 QJsonObject类封装了一个JSON对象 JSON对象是键值对的列表 其中键是唯一的字符串 值由QJsonValue表示 QJsonObject可以转换为QVariantMap 也可以从QVariant
  • k8s动态使用glusterfs存储

    k8s中运行Heketi服务 在使用kismatic安装k8s和glusterfs后 需要配置k8s默认动态管理 provisioning 使用glusterfs 以下内容是实现这样的目的 Hekeli glusterfs的restful端
  • Scrapy框架的使用之Scrapy通用爬虫

    通过Scrapy 我们可以轻松地完成一个站点爬虫的编写 但如果抓取的站点量非常大 比如爬取各大媒体的新闻信息 多个Spider则可能包含很多重复代码 如果我们将各个站点的Spider的公共部分保留下来 不同的部分提取出来作为单独的配置 如爬
  • word目录编号自动更新排版技巧

    二 多级列表生成目录 文档中一般需要插入目录 手动添加 写上页面非常麻烦 而且文档修改后还得手动修改 今天给大家介绍一种通过多级列表生成目录的方法 1 选择多级列表 定义新的多级列表 2 选择 要修改的级别 选择1 在样式中 选择样式 级别
  • 数字电路-门电路

    摘要 本章系统地讲述了数字集成电路中的基本逻辑单元电路 门电路 由于门电路中的二极管和三极管经常工作在开关状态 所以首先介绍它们在开关状态下的工作特性 然后 重点讨论了目前广泛使用的CMOS门电路和TTL门电路 对于每一种门电路 除了讲解它
  • java21天打卡-day14 日期时间

    import java util Calendar import java util Date public class Day14 数字和日期 Date 题目1 分别打印出当前时间所属的年月日 Calendar类 题目2 计算出当前时间的
  • buuctf-[极客大挑战 2019]LoveSQL

    打开靶机进入之后是个登录界面 查看源码得知是get类型注入 因为是sql注入的题嘛 所以我们直接尝试用万能密码进行登录 用户名1 or 1 1 密码随意 成功登录 并没有得到flag 此时发现url中貌似可以进行sql注入 并且已经把万能密
  • scrapy 部署到服务器上

    1 安装依赖库 pip install scrapyd pip install scrapyd client 2 验证是否成功 cmd中输入 scrapyd deploy h 如下图ok的 3 运行 scrapyd dep 若遇到错误 报错
  • 运行报错Parsing error: The keyword ‘import‘ is reserved

    问 运行报错Parsing error The keyword import is reserved 答 分析 这是因为我们还没有在配置文件 eslintrc中配置parserOptions来指定语言版本为和模块类型 在 eslintrc添
  • uniapp 微信小程序webview 踩坑

    uniapp 微信小程序的存在许多功能上的限制和约束 有些情况不得不去使用webview进行开发实现需求 比如 原生无法满足 例如某团队维护SDK 只提供了WEB端jsSDK 且不维护小程序SDK H5可以同时适用多端 适用范围更广 H5可
  • 13LinuxC线程学习之利用pthread_create设置线程分离属性和相关属性解释

    1 线程属性 1 本节作为指引性介绍 linux下线程的属性是可以根据实际项目需要 进行设置 之前我们讨论的线程都是采用线程的默认属性 默认属性已经可以解决绝大多数开发时遇到的问题 如我们对程序的性能提出更高的要求那么需要设置线程属性 比如