Linux - 线程属性控制

线程属性

属性值不能直接设置,须使用相关函数进行操作

初始化函数为pthread_attr_init,该函数必须在pthread_create函数之前调用

typedef struct{
    int  detachstate;  // 线程的分离状态
    int   scope;   // 线程绑定状态
    int  schedpolicy; // 线程调度策略
    struct sched_param schedparam; // 线程的调度参数
    int   inheritsched;  //线程的继承性
    size_t  guardsize; // 线程栈末尾的警戒缓冲区大小
    void *  stackaddr;  // 线程栈的位置
    size_t  stacksize;   // 线程栈的大小
}pthread_attr_t;

删除线程属性对象

函数原型
int pthread_attr_destroy(pthread_attr_t *attr);
返回值
成功返回0
出错,返回其他值
说明
删除属性对象占用的内存
调用这个函数后,相应的属性对象无效

线程分离状态(detachstate)

决定线程以何种方式终止自己
非分离状态
原有的线程等待创建的线程结束
只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源
分离线程
没有被其他的线程所等待,自己运行结束后终止线程,马上释放系统资源
线程分离状态相关函数
pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
detachstate选值
PTHREAD_CREATE_DETACHED(分离线程)
 PTHREAD _CREATE_JOINABLE(非分离线程)
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);

线程绑定scope

轻量级进程

可理解为内核线程,位于用户层和系统层之间

系统通过轻量级进程实现对线程资源的分配、对线程的控制

一个轻量级进程可以控制一个或多个线程

非绑定

启动多少轻量级进程、哪些轻量级进程来控制哪些线程由系统来控制

系统的默认处理方式

绑定

某个线程固定的“绑”在一个轻量级进程之上

被绑定的线程具有较高的响应速度,这是因为CPU时间片的调度是面向轻进程的,绑定的线程可以保证在需要的时候它总有一个轻进程可用

通过设置被绑定的轻进程的优先级和调度级可以使得绑定的线程满足诸如实时反应之类的要求

线程绑定属性设置函数

函数原型
pthread_attr_setscope(pthread_attr_t * attr, int scope)
参数说明
attr:指向属性结构的指针
scope:绑定类型
PTHREAD_SCOPE_SYSTEM(绑定的)
PTHREAD_SCOPE_PROCESS(非绑定的)
举例/*初始化属性值,均设为默认值*/pthread_attr_init(&attr);
    pthread_attr_setscope(&attr, THREAD_SCOPE_SYSTEM);pthread_create(&tid, &attr, (void *) my_function, NULL);

线程调度策略schedpolicy

函数原型
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
参数说明
attr:线程属性变量
policy:调度策略
SCHED_FIFO:先进先出
SCHED_RR:轮转法
SCHED_OTHER:其它
返回值
成功返回0
失败返回-1

线程调度参数schedparam

函数原型
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
参数说明
attr:线程属性
param:sched_param结构
sched_priority:控制一个优先权值
sched_get_priority_min():获取系统支持的最小优先权值
sched_get_priority_max ():获取系统支持的最大优先权值

线程的继承性inheritsched

设置继承调度策略
PTHREAD_INHERIT_SCHED(缺省值)
创建的线程将具有父线程的调度策略
属性对象中的调度策略参数将不起作用
PTHREAD_EXPLICIT_SCHED
线程的调度策略和父线程无关
属性对象中的调度策略参数将起作用
相关设置函数
int pthread_attr_setinheritsched(pthread_attr_t *tattr, int inherit);
int pthread_attr_getinheritsched(pthread_attr_t *tattr, int *inherit);

堆栈防护区guardsize

缺省情况下,线程的堆栈保护区大小因系统版本不同而异
取值说明
若guardsize=0,创建线程时将不会创建堆栈保护区
若guardsize>0,创建线程时将至少有一个guardsize大小的堆栈保护区
使用说明
创建线程堆栈时,一般将guardsize参数值上舍入成系统变量PAGESIZE的整数倍,来分配堆栈保护区
但程序调用pthread_attr_getguardsize()函数获得的堆栈保护区大小将是调用pthread_attr_setguardsize()函数时指定的guardsize参数值
相关函数
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize);

线程堆栈的基地址 stackaddr

默认由系统分配
如果stackaddr为非空值,线程堆栈将从指定地址开始
如果是NULL (缺省值) ,pthread_create()为其分配堆栈
相关函数
int pthread_attr_setstackaddr(pthread_attr_t *tattr, void *stackaddr);
int pthread_attr_getstackaddr(pthread_attr_t *tattr, void **stackaddr);

线程堆栈大小stacksize

定义系统为线程分配的堆栈大小(字节)
默认由系统决定大小
函数原型
int pthread_attr_setstacksize(pthread_attr_t *tattr, int size);
int pthread_attr_getstacksize(pthread_attr_t *tattr, size_t *size);
参数说明
size:线程所需堆栈的大小
size=0,系统使用缺省大小
在大多数情况下,缺省值是最合适的
堆栈的大小不能小于系统定义的最小堆栈容量PTHREAD_STACK_MIN

线程的一次性初始化

有时需要对一些posix变量只进行一次初始化(如线程键),如果多次初始化,程序就会出现错误

在顺序编程中,常使用布尔变量来一次性初始化

控制变量被静态初始化为0,任何依赖于初始化的代码都能测试该变量

如果变量值仍然为0,则它能实行初始化,然后将变量置为1,以后检查的代码将跳过初始化

但在多线程程序设计中,事情变得非常复杂

如果多个线程并发地执行初始化序列代码,两个线程可能发现控制变量为0,并且都实行初始化,而该过程本该仅仅执行一次

初始化的状态必须由互斥量保护

对一个posix静态变量的初始化,可使用用一个互斥量对该变量的初始化进行控制

但使用pthread_once对变量进行动态初始化会方便许多

线程的一次性初始化函数

函数原型

pthread_once_t once_control=PTHREAD_ONCE_INIT;

int pthread_once(pthread_once_t *once_control, void(*init_routine)(void));

参数

once_control:控制变量,必须使用PTHREAD_ONCE_INIT宏静态地初始化

init_routine:初始化函数

说明

pthread_once函数首先检查控制变量,判断是否已经完成初始化

如果完成,则返回

否则,调用初始化函数,并且记录初始化被完成

如果在一个线程初始时,另外的线程调用pthread_once,则调用线程等待,直到那个线程完成初始化返回

线程的私有数据

背景

进程内的所有线程共享相同地址空间,任何声明为静态或外部的变量,或在进程堆声明的变量,都可以被进程所有的线程读写

怎样才能使线程序拥有自己的私有数据?

函数原型

int pthread_key_create(pthread_key key, void(*destructor)(void ));

参数

key:私有数据键

destructor:清理函数

如果该参数不为空,则当每个线程结束时,系统将调用这个函数来释放绑定在这个键上的内存块

说明

函数从线程私有数据池中分配一项,将其值赋给key供以后访问使用

无论哪个线程调用pthread_key_create(),所创建的key都是所有线程可访问的,但各个线程可根据自己的需要往key中填入不同的值,这就相当于提供了一个同名而不同值的全局变量

该函数常和函数pthread_once一起使用,以便该键只被创建一次

函数原型
int pthread_setspecific(pthread_key_t key, const void *pointer)
void * pthread_getspecific(pthread_key_t key)
说明
pthread_setspecific()将pointer的值(不是所指的内容)与key相关联
pthread_getspecific()将与key相关联的数据读出来
数据类型都设为void *,因此可以指向任何类型的数据

说明

创建两个线程分别设置同一个线程私有数据为自己的线程ID

为了检验其私有性,程序错开了两个线程私有数据的写入和读出的时间

从程序运行结果可以看出,两个线程对TSD的修改互不干扰

当线程退出时,清理函数会自动执行,参数为tid

时间: 2024-10-13 00:48:05

Linux - 线程属性控制的相关文章

Linux之线程、线程控制、线程属性

一.整体大纲 二.线程相关 1. 什么是线程    LWP:light weight process 轻量级的进程,本质仍是进程(在Linux环境下) 进程:独立地址空间,拥有PCB 线程:也有PCB,但没有独立的地址空间(共享) 区别:在于是否共享地址空间. 独居(进程):合租(线程). Linux下: 线程:最小的执行单位 进程:最小分配资源单位,可看成是只有一个线程的进程. 2. Linux内核线程实现原理     (1)线程实现原理 类Unix系统中,早期是没有“线程”概念的,80年代才

Linux之线程:控制与分离

之前我一直都提到的是进程,现在多了一个线程的概念,从字面意思来看,线程应该比进程小.嘿嘿. 其实操作系统刚开始的时候,提出进程概念后,操作系统一直都是以进程作为独立运行的基本单位,然后有人感觉了,这不对呀,进程之间的中断转换太浪费了,并且用户态到核心态的切换也有点麻烦,所以在80年代中期,人们又提出了毕竟更小的独立运行的基本单位咯--线程,用来提高系统内存程序的并发执行程度.所以线程就这么出现了. 那,什么是线程呢? 其实简单来说,线程就是进程中的执行分流,从操作系统内部来说其实就是一个指令序列

Linux下线程的控制与分离

一.线程的概念: 线程是运行在进程地址空间的,是进程的执行分流.它是执行进程内部的一个代码片段为了让进程更好的完成.也可以说,进程是承担系统资源的实体,而线程进程运行调度的基本单位. 由于同一进程的多个线程共享同一地址空间,因此Text Segment.Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境: 1. 文件描述符表 2. 每种信号的处理方式(SIG_IGN.SIG_DFL或者

Linux多线程实践(3) --线程属性

初始化/销毁线程属性 int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr); 线程分离属性 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); int pthread_attr_setdetachstate(pthread_attr_t *attr, int de

linux线程创建、取消、属性设置

创建线程: #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) 参数:第一个参数为指向线程标识符的指针. 第二个参数用来设置线程属性. 第三个参数是线程运行函数的起始地址. 第四个参数是线程运行函数的参数. int pthread_join(pthread_t thread, void

UNIX环境编程学习笔记(27)——多线程编程(二):控制线程属性

lienhua342014-11-09 1 线程属性概括 POSIX 线程的主要属性包括 scope 属性.detach 属性.堆栈地址.堆栈大小.优先级.在头文件 pthread.h 中定义了结构体pthread_attr_t 来记录线程的属性. 在创建线程的函数pthread_create 的第二个参数 attr 就是一个pthread_attr_t结构体的指针,通过该参数,我们可以控制新创建的线程的属性.如果 atrr参数为 NULL,表示创建一个默认属性的新线程. pthread_att

Linux的POSIX线程属性

创建POSIX线程的函数为 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 第1个参数为线程句柄(类似于文件描述符),第3个参数为线程启动函数(输入void*.返回void*,因为指向任何结构体/基本数据类型的指针都可以被看作void*,而void*一般都可以显式强制转换成指向对应类型的指针甚至整型,这是不支持纯C编程的常见

使用信号量控制Linux线程同步

线程同步 在现实生活中,有些东西就必须是按顺序执行的,只有我完成了以后,你才能在我的劳动成果上接着干:不能我还没有完成,你就开始干活了.这就是线程同步最直白的解释了. 在进行程序设计时,亦是如此.线程同步,同步的是什么?它同步的是对共享资源(内存区域,公共变量等)或者临界区域的访问.有的时候,这些共享 资源和临界区域,就只能容忍一个线程对它进行操作(读或者写,读操作一般不控制,主要是写操作),这个时候,我们必须要对这些共享资源或者临界区域进行同 步,那么如何对它们进行线程同步呢? 在Linux中

Linux c编程:线程属性

前面介绍了pthread_create函数,并且当时的例子中,传入的参数都是空指针,而不是指向pthread_attr_t结构的指针.可以使用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来.可以使用pthread_attr_init函数初始化pthread_attr_t结构.调用pthread_attr_init以后,pthread_attr_t结构所包含的内容就是操作系统实现支持的线程所有属性的默认值.如果要修改其中个别属性的值,需要调用其他的函数. #in