[glibc-manual]34.2 线程属性

来源:互联网 发布:淘宝购物车满了图片 编辑:程序博客网 时间:2024/05/17 23:25

34.2 线程属性

线程具有一系列属性;这些属性可以在线程创建的时候指定。只需要创建并填充一个 pthread_attr_t 类型的线程属性对象 ATTR,并将其作为第二个参数传递给 pthread_create 就可以指定新创建线程的属性。如传递 NULL 作为第二个参数,则等价于传递一个所有属性均为默认值的属性对象。

仅当创建新线程的时候线程属性对象才被参考。同一个线程对象可用于创建多个线程。在 pthread_create 之后修改一个线程对象并不会修改之前创建的线程的属性。

-- 函数: int pthread_attr_init (pthread_attr_t *ATTR)
pthread_attr_init 函数将对属性对象 ATTR 进行初始化,并将其属性置为默认值。(下面列举了每个属性的默认值。)

每个属性,ATTRNAME,可以通过函数 pthread_attr_setATTRNAME 单独进行设置,也可以通过函数 pthread_attr_getATTRNAME 单独获取其值。本文随后部分列举了所有的属性。

-- 函数: int pthread_attr_destroy (pthread_attr_t *ATTR)
pthread_attr_destory 销毁一个 ATTR 指向的线程属性对象,并释放与其关联的所有资源。指针 ATTR 被保留在一种未定义状态(野指针——译者注)因此你在未再次将其初始化之前不应该再度将其用于任何 pthread 函数中。

-- 函数: int pthread_attr_setattr (pthread_attr_t *OBJ, int VALUE)
将 OBJ 指向的属性对象中所包含的属性 ATTR 设置为 VALUE。本文随后将列举各种属性及其可能被赋予的值。

当赋值成功时该函数将返回 0。如果 VALUE 对于被修改的 ATTR 不具有实际意义,该函数将返回错误码 EINVAL。这组函数中的部分可能返回其它错误码,详见下文。

-- 函数: int pthead_attr_getattr (const pthread_attr_t *OBJ, int *VALUE)
将 OBJ 中 ATTR 当前的值存入 VALUE 指向的变量。
该组函数总返回 0。

Pthread 库支持以下线程属性:
detachstate
此属性决定线程是否被创建为可等待的(赋值为 PTHREAD_CREATE_JOINABLE)或脱离的(赋值为 PTHREAD_CREATE_DETACHED)。默认为 PTHREAD_CREATE_JOINABLE。
当线程处于可等待状态时,其它线程可以通过 pthread_join 函数等待线程退出并获取退出代码。部分线程资源会在线程中止后仍然保持在系统中,直到有其它线程对其调用 pthread_join 时才会被释放。
当线程处于脱离状态时,线程结束后所有资源会被立即释放;同时 pthread_join 无法被用于等待线程的退出。

schedpolicy
设定该线程的调度策略:SCHED_OTHER(正常的、非实时调度策略)、SCHED_RR(实时的,循环制)或 SCHED_FIFO(实时的、先入先出)。默认值是 SCHED_OTHER。
实时调度策略 SCHED_RR 和 SCHED_FIFO 仅允许具有超级用户权限的线程使用。如果一个不具有超级用户权限的线程尝试设置这些策略的时候, pthread_attr_setschedparam 将执行失败并返回 ENOTSUP。
线程的调度策略可以在线程创建之后通过 pthread_setschedparam 改变。

schedparam
改变线程的调度参数(调度优先级)。默认值为0。
当线程的调度策略为 SCHED_OTHER 时这个属性的作用并不明显;只有当设置调度策略为实时的 SCHED_RR 或 SCHED_FIFO 时它才会起作用。
线程调度优先级可在创建后通过 pthread_setschedparam 修改。

inheritsched
决定新创建线程的调度策略和调度参数由 SCHEDPOLICY 和 SCHEDPARAM 决定(将此参数设置为 PTHREAD_EXPLICIT_SCHED)还是继承自创建该线程的父线程(设置为 PTHREAD_INHERIT_SCHED)。默认值为 PTHREAD_EXPLICIT_SCHED。

scope
决定线程调度争夺范围。该属性默认为 PTHREAD_SCOPE_SYSTEM,意为这些线程将与系统中所有进程争夺 CPU 时间。需要注意的细节是,此时线程的优先级将被用于与系统中所有其它进程的优先级进行比较并确定效果。另外一个可能的值为 PTHREAD_SCOPE_PROCESS,意为争夺范围仅限于进程中的不同线程之间;此时线程的优先级仅用于与同进程中的其它线程的优先级进行比较,并与系统中其它进程的优先级无关。
PTHREAD_SCOPE_PROCESS 在 LinuxThreads 实现中没有获得支持。如果你尝试设置这个属性值时,pthread_attr_setscope 会失败并返回 ENOTSUP。(Glibc 2.3.2 with NTPL 0.60 仍然不支持此属性——译者注)

stacksize
改变新创建线程的栈容量。这个值确定了栈的最小体积,单位为字节(byte)。
如果属性值超过了系统最大栈容量,或者小于 PTHREAD_STACK_MIN,pthread_attr_setstacksize 会失败并返回 EINVAL。

stackaddr
为新线程提供了程序管理的栈的内存基址。STACKADDR 与之前介绍的 stacksize 属性一起可以用于确定新创建线程的栈。(手册中这两个属性的介绍非常混乱,已经修改。——译者注)

guardsize
改变线程栈的警戒区域的最小容积。默认值为一个内存分页的大小。如果这个属性被设置,它的值将被向上靠拢到最接近的内存分页大小的整数倍。如果值为 0,则系统将不会为新线程设置警戒区域。被分配作为警戒区域的内存将被用于捕获栈溢出状况。因此,当尝试在栈上分配体积巨大的结构体时,可能需要一个较大的警戒区域以捕获栈溢出的可能。
如果调用者自主管理栈区域(如果 stackaddr 属性被设置),则 guardsize 属性将被忽略。
如果这个值的大小超过了 stacksize,pthread_attr_setguardsize 将会失败并返回 EINVAL。

==========
译者补记

int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param *param);

int pthread_getschedparam(pthread_t target_thread, int *policy, struct sched_param *param);

分别用于读取、设置 target_thread 的调度策略和参数的函数。其中 struct sched_param 定义参考 sched_setscheduler 手册页:

       struct sched_param {
           ...
           int sched_priority;
           ...
       };

即其中通过 .sched_priority 成员指定调度的静态优先级。如前所述,SCHED_OTHER 策略下,sched_priority 静态优先级必须为 0,系统根据 niceness 及动态优先级算法确定进程调度优先级。除 SCHED_OTHER 之外的调度策略均为实时调度策略,要求具有超级用户权限方可设置。