在之前的章节中,咱们在调用 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 开发学习路线图
也心愿有小伙伴能退出我,把这份电子书做得更完满!
有播种?心愿老铁们来个三连击,给更多的人看到这篇文章
举荐浏览:
- 干货 | 程序员进阶架构师必备资源免费送
- 神器 | 反对搜寻的资源网站