在之前的章节中,我们在调用pthread_create函数创建线程时,第二个参数(即线程属性)都是设为NULL,即使用默认属性。一般情况下,使用默认属性已经可以解决我们开发过程中的大多数问题。

但是,有时项目中我们对线程会有些特殊的要求,比如修改线程栈的大小,直接调用线程的库函数无法满足需求,在这种情况下我们可以直接对线程属性进行设置。

类型pthread_attr_t是一个结构体,主要包括如下属性:作用域(scope)、栈尺寸(stack size)、栈地址(stack address)、优先级(priority)、分离的状态(detached state)、调度策略和参数(scheduling policy and parameters)。

线程默认的属性为非绑定、非分离、缺省的堆栈、与父进程同样级别的优先级。结构体具体定义如下:

typedef struct

{

​ int etachstate; //线程的分离状态

​ int schedpolicy; //线程调度策略

​ struct sched_param schedparam; //线程的调度参数

​ int inheritsched; //线程的继承性

​ int cope; //线程的作用域

​ size_t guardsize; //线程栈末尾的警戒缓冲区大小

​ int stackaddr_set; //线程的栈设置

​ size_t stacksize; //线程栈的大小

} pthread_attr_t;

主要结构体成员:

​ 1. 线程分离状态:etachstate

​ 2. 线程栈大小(默认平均分配):stacksize

​ 3. 线程栈警戒缓冲区大小(位于栈末尾):guardsize

线程的属性值不能直接设置,须使用相关函数进行操作。属性的初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用。使用完毕之后需调用pthread_attr_destroy函数来释放资源。

线程属性初始化

函数原型:

int pthread_attr_init(pthread_attr_t *attr);

返回值:

成功:0;失败:错误号。

函数作用:

初始化线程属性;

注意:应先初始化线程属性,再调用pthread_create创建线程。

线程属性销毁

函数原型:

int pthread_attr_destroy(pthread_attr_t *attr);

返回值:

成功:0;失败:错误号

函数作用:

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

线程的分离状态

线程的分离状态决定一个线程最后终止的时候是以怎样的方式回收资源。

非分离状态:线程的默认属性是非分离状态,这种情况下,线程运行结束后,只有当其它线程调用pthread_join()函数去回收它时,创建的线程才算终止,才能释放自己占用的系统资源。

分离状态:线程如果设置为分离状态,则它将主动与主控线程脱离关系,当它自己运行结束了,线程也就终止了,马上释放系统资源。

设置线程分离状态的函数:

设置线程属性

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

获取程属性

int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);

参数:attr:指向一个线程属性的指针

detachstate:线程分离状态

PTHREAD_CREATE_DETACHED(分离线程)

PTHREAD _CREATE_JOINABLE(非分离线程)

线程的栈地址

POSIX.1定义了两个常量_POSIX_THREAD_ATTR_STACKADDR 和_POSIX_THREAD_ATTR_STACKSIZE检测系统是否支持栈属性。也可以给sysconf函数传递_SC_THREAD_ATTR_STACKADDR或 _SC_THREAD_ATTR_STACKSIZE来进行检测。

当进程栈地址空间不够用时,指定新建线程使用由malloc分配的空间作为自己的栈空间。通过pthread_attr_setstack和pthread_attr_getstack两个函数分别设置和获取线程的栈地址。

设置线程的栈地址:

int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);

成功:0;失败:错误号

获取线程的栈地址:

int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);

成功:0;失败:错误号

参数:attr:指向一个线程属性的指针

stackaddr:返回获取的栈地址

stacksize:返回获取的栈大小

线程的栈大小

当系统中有很多线程时,可能需要减小每个线程栈的默认大小,防止进程的地址空间不够用。当线程调用的函数会分配很大的局部变量或者函数调用层次很深时,可能需要增大线程栈的默认大小。

函数pthread_attr_getstacksize和 pthread_attr_setstacksize可以设置或者获取线程的栈大小。

设置线程栈大小:

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

成功:0;失败:错误号

获取线程栈大小:

int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);

成功:0;失败:错误号

参数:attr:指向一个线程属性的指针

stacksize:返回线程的堆栈大小

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h> #define SIZE 0x10000 void *th_fun(void *arg)
{
while (1)
sleep(1);
} int main(void)
{
pthread_t tid;
int err, detachstate, i = 1;
pthread_attr_t attr;
size_t stacksize; //typedef size_t unsigned int
void *stackaddr; pthread_attr_init(&attr);
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_getdetachstate(&attr, &detachstate); if (detachstate == PTHREAD_CREATE_DETACHED) //默认是分离态
printf("thread detached\n");
else if (detachstate == PTHREAD_CREATE_JOINABLE) //默认时非分离
printf("thread join\n");
else
printf("thread un known\n"); /* 设置线程分离属性 */
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); while (1) {
/* 在堆上申请内存,指定线程栈的起始地址和大小 */
stackaddr = malloc(SIZE);
if (stackaddr == NULL) {
perror("malloc");
exit(1);
}
stacksize = SIZE;
pthread_attr_setstack(&attr, stackaddr, stacksize); //借助线程的属性,修改线程栈空间大小 err = pthread_create(&tid, &attr, th_fun, NULL);
if (err != 0) {
printf("%s\n", strerror(err));
exit(1);
}
printf("%d\n", i++);
} pthread_attr_destroy(&attr); return 0;
}

更多精彩内容,请关注公众号良许Linux,公众内回复1024可免费获得5T技术资料,包括:Linux,C/C++,Python,树莓派,嵌入式,Java,人工智能,等等。公众号内回复进群,邀请您进高手如云技术交流群。


公众号:良许Linux

有收获?希望老铁们来个三连击,给更多的人看到这篇文章

Linux系统编程 —线程属性的更多相关文章

  1. Linux系统编程——线程私有数据

    在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...

  2. linux系统编程--线程

    安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...

  3. Linux系统编程 —线程同步概念

    同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...

  4. LInux多线程编程----线程属性pthread_attr_t

    1.每个POSIX线程有一个相连的属性对象来表示属性.线程属性对象的类型是pthread_attr_t,pthread_attr_t 在文件/usr/include/bits/pthreadtypes ...

  5. linux系统编程--线程同步

    同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...

  6. Linux 系统编程 学习:10-线程:线程的属性

    Linux 系统编程 学习:10-线程:线程的属性 背景 上一讲我们介绍了线程的创建,回收与销毁:简单地提到了线程属性.这一讲我们就来具体看看,线程的属性. 概述 #include <pthre ...

  7. Linux 系统编程 学习:09-线程:线程的创建、回收与取消

    Linux 系统编程 学习:09-线程:线程的创建.回收与取消 背景 我们在此之前完成了 有关进程的学习.从这一讲开始我们学习线程. 完全的开发可以参考:<多线程编程指南> 在Linux ...

  8. Linux 系统编程 学习:11-线程:线程同步

    Linux 系统编程 学习:11-线程:线程同步 背景 上一讲 我们介绍了线程的属性 有关设置.这一讲我们来看线程之间是如何同步的. 额外安装有关的man手册: sudo apt-get instal ...

  9. 读书笔记之Linux系统编程与深入理解Linux内核

    前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...

随机推荐

  1. Qt 绘图(QBitmap,QPixmap,QImage,QPicture)

    QPainter绘图绘图设备(QPixmap,QImage,QBitmap,QPicture) 重写绘图事件,虚函数 如果窗口绘图,必须放在绘图事件里实现 绘图事件内部自动调用,窗口需要重绘的时候,状 ...

  2. JDK 8 新特性之函数式编程 → Stream API

    开心一刻 今天和朋友们去K歌,看着这群年轻人一个个唱的贼嗨,不禁感慨道:年轻真好啊! 想到自己年轻的时候,那也是拿着麦克风不放的人 现在的我没那激情了,只喜欢坐在角落里,默默的听着他们唱,就连旁边的妹 ...

  3. java开发,入职半年,对未来迷茫,如何发展?

    分享-更多精彩图片尽在大师助手 个人建议,在JAVA方面,先学好JAVA SE.不管如何,基础才是上层建筑的一切.推荐去看jdk源码,推荐1.6或者1.7版本.因为1.8版本的源码中会有很多lambd ...

  4. AD18 PCB中添加中文字符串显示乱码问题解决

    该问题是由于字符串的自体类型设置问题,AD默认是[stroke],我们点击[TrueType]即可正常显示.PS:AD18搞啥呢,默认显示输入内容不行吗,找半天!!!

  5. [ASP.NET Core开发实战]基础篇02 依赖注入

    ASP.NET Core的底层机制之一是依赖注入(DI)设计模式,因此要好好掌握依赖注入的用法. 什么是依赖注入 我们看一下下面的例子: public class MyDependency { pub ...

  6. eslint 的 使用常见问题(一)

    在source tree 远程拉去一个项目,然后无缘无故 代码各处飘红 ,然后看了很是烦躁.碰见一下几个问题,后续持更 一.升级es6 出现这个问题的原因:let是EcmaScript 6 里面才有的 ...

  7. Mono集成中使用api获取当前mono 调用堆栈的方法

    // 在mono源代码层级中加如下两个api 可以获取堆栈字符串 这两个api我新加的,原来没有.基于原来的代码改的. // add by bodong#if PLATFORM_WIN32 __dec ...

  8. 听过N次还是不会之:浏览器输入url后到底经历了什么

    有没有这种场景:当你被问起某一项知识点时,你大脑里想起经常看到过这样的问题,可是具体是怎么样就是说不清楚. 好吧,我就是这样的,于是整理一下,实在记不住,以后找起来也方便. 当你在浏览器地址栏里输入一 ...

  9. 面试【JAVA基础】锁

    1.锁状态 锁的状态只能升级不能降级. 无锁 没有锁对资源进行锁定,所有线程都能访问并修改同一个资源,但同时只有一个线程能修改成功.其他修改失败的线程会不断重试,直到修改成功,如CAS原理和应用是无锁 ...

  10. Linux平台Zabbix Agent的安装配置

    这里简单总结一下Linux平台Zabbix Agent的安装配置,实验测试的Zabbix版本比较老了(Zabbix 3.0.9),不过版本虽然有点老旧,但是新旧版本的安装步骤.流程基本差别不大.这里的 ...