Linux多线程编程(二)——线程属性

来源:互联网 发布:淘宝直播流量来源 编辑:程序博客网 时间:2024/06/05 09:03

pthread接口允许我们通过设置每个对象关联的不同属性来细调线程的行为。

在上一篇中我们调研pthread_create函数的实例中,传入的参数都是空指针,而不是指向pthread_attr_t结构的指针。可以使用pthread_attr_t结构修改线程默认 属性,并把这些属性和创建的线程联系起来。可以使用pthread_attr_init函数初始化pthread_attr_t。在调用pthread_attr_init以后,pthread_attr_t结构所包含的就是操作系统实现支持的所有线程属性的默认值。

#include <pthread.h>int pthread_attr_init(pthread_attr_t *attr);int pthread_attr_destroy(pthread_attr_t *attr);两个函数的返回值:若成功,返回0;否则,返回错误编号
如果要反初始化pthread_attr_t结构,可以调用pthread_attr_destroy函数。如果pthread_attr_init的实现对实现属性对象的内存空间是 动态分配的,pthread_attr_destroy就会释放该内存空间。除此之外,pthread_attr_destroy还会用无效的值初始化属性对象,因此,如果该属性对象被误用,将会导致pthread_create函数返回错误代码。
如果在创建线程时就知道不需要了解线程的终止状态,就可以修改pthread_attr_t结构中的detachstate设置成以下两个合法值之一:PTHREAD_CREATE_DETACHED,以分离状态启动线程;或者PTHREAD_CREATE_JOINABLE,正常启动线程,应用程序可以获取线程的终止状态。

#include <pthread.h>int pthread_attr_getdetachstate(const pthread_attr_t *restrict attr,int *detachstate);int pthread_attr_setdetachstate(pthread_attr_t *attr, int *detachstate)两个函数的返回值:若成功,返回0;否则,返回错误编号
可以调用pthread_attr_getdetachstate函数 获取当前的detachstate线程属性。第二个参数所指向的整数要么设置成PTHREAD_CREATE_DETACHED,要么设置成PTHREAD_CREATE_JOINABLE,具体要取决于给定 pthread_attr_t结构中的属性值。

可以使用函数pthread_attr_getstack和pthread_attr_setstack对线程栈属性进行管理。

#include <pthread.h>int pthread_attr_getstack(const pthread_attr_t *restrict attr,  void **restrict stackaddr,  size_t *restrict stacksize);int pthread_attr_setstack(pthread_attr_t *attr,  void *stackaddr, size_t stacksize);两个函数的返回值:若成功,返回0;否则,返回错误编号
对于进程来说,虚地址空间的大小是固定的。因为进程中只有一个栈,所以它的大小通常不是问题。但对于线程来说,同样大小的虚地址空间必须被所以的线程栈共享。如果应用程序使用了许多线程,以致这些线程栈的累计大小超过了可用的虚地址空间,就需要减少默认的线程栈大小。另一方面,如果线程调用的函数分配了大量的自动变量,或者调用的函数涉及许多很深的栈帧,那么需要的栈大小可能要比默认的大。

如果线程的虚地址空间都用完了,那可以使用malloc或者mmap来为可替代的栈分配空间,并用pthread_attr_setstack函数来改变新建线程的栈位置。由stackaddr参数指定的地址可以用作线程栈的内存范围中的最低可寻址地址,该地址与处理器结构相应的边界应对其。当然,这要假设malloc和mmap所用的虚地址范围与程序栈当前使用的虚地址范围不同。

stackaddr线程属性被定义为栈的最低内存地址,但这并不一定是栈的开始地址位置。对于一个给定的处理器结构来说,如果栈是从高地址向低地址方向增长的,那么stackaddr线程属性将是栈的结尾位置,而不是开始位置。

应用程序也可以通过pthread_attr_getstacksize和pthread_attr_setstacksize函数读取或设置线程属性stacksize。

#include <pthread.h>int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,      size_t *restrict stacksize);int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);两个函数的返回值:若成功,返回0;否则,返回错误编号
如果希望改变默认的栈大小,但又不想自己处理线程栈的分配问题,这时使用pthread_attr_setstacksize函数就非常有用。设置stacksize属性时,选择的stacksize不能小于PTHREAD_STACK_MIN。

线程属性guardsize控制着线程栈末尾之后用以避免栈溢出的扩展内存的大小。这个属性默认值是有具体实现来定义的,但常用值是系统页大小。可以把guardsize线程属性设置为0,不允许属性的这种特征行为发生:在这种情况下,不会提供警戒缓冲区。同样,如果修改了线程属性stackaddr,系统就认为我们将自己管理栈,进而使警戒缓冲区机制无效,这等同于把guardsize线程属性设置为0.

#include <pthread.h>int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,      size_t *restrict guardsize);int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);两个函数的返回值:若成功,返回0;否则,返回错误编号
如果guardsize线程属性被修改来了,操作系统可能会把它取为页大小的整数倍。如果线程的栈指针溢出到警戒区域,应用程序就可以通过信函接收到出错信息。

0 0