http://cpp.ezbty.org/import_doc/linux_manpage/pthread_attr_destroy.3.html
名字
pthread_attr_init, pthread_attr_destroy - 初始和销毁线程属性对象
概要
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
编译并与 -pthread 一起链接。
描述
pthread_attr_init() 使用默认属性值来初始化 attr
指向的线程属性对象。在这个调用之后,单独的对象属性可以通过一组相关的函数来设定(在下面“参见”小结列出),其后这个对象可以被一次或多次用于创建线程的
pthread_create(3) 调用。
在一个已经初始化的线程属性对象上调用 pthread_attr_init() 其结果是未定义的。
当一个线程属性对象不再使用时,它应该使用 pthread_attr_destroy()
函数来销毁。销毁一个线程属性对象对使用这个对象创建的线程没有影响。
在一个线程属性对象被销毁之后,它能再次调用 pthread_attr_init()
来初始化。险些之外,对已经销毁的线程属性对象任何其它使用其结果都未定义的。
返回值
成功时,这些函数返回0;如果错误,它们返回非0值。
错误
POSIX.1-2001 为 pthread_attr_init() 说明了一个 ENOMEM 错误:Linux
上的这些函数总是会成功(但一个可移植的程序应该处理这个永远也不会返回的错误)。
遵循于
POSIX.1-2001.
注意
pthread_attr_t 类型应该对用户透明:任何不是通过 pthreads 函数对其对象的操作都是不可移植的,并且产生未定义的结果。
示例
下面这个程序使用 pthread_attr_init()
和一组相关的函数来初始一个线程属性对象,接着使用这个对象创建一个线程。一旦创建成功,该线程使用 pthread_getattr_np(3)
函数(非标准的 GNU 扩展)来获得自身的线程属性,接着显示这个属性。
如果这个程序运行时没有提供命令行参数,那么它将使用参数 attr 为空指针的
pthread_create(3),因此线程使用默认的属性来创建。在 Linux/x86-32 系统里使用 NPTL
线程实现,运行这个程序我将看到:
$ ulimit -s # 没有栈限制 ==> 默认栈尺寸是 2MB
unlimited
$ ./a.out
Thread attributes:
Detach state = PTHREAD_CREATE_JOINABLE
Scope = PTHREAD_SCOPE_SYSTEM
Inherit scheduler = PTHREAD_INHERIT_SCHED
Scheduling policy = SCHED_OTHER
Scheduling priority = 0
Guard size = 4096 bytes
Stack address = 0x40196000
Stack size = 0x201000 bytes
当我们在命令行参数里提供栈尺寸,这个程序初始化一个线程属性对象,设置这个对象的多个属性,接着把这个对象的指针传递给
pthread_create(3) 调用。在 Linux/x86-32 系统里使用 NPTL 线程实现,运行这个程序我将看到:
$ ./a.out 0x3000000
posix_memalign() allocated at 0x40197000
Thread attributes:
Detach state = PTHREAD_CREATE_DETACHED
Scope = PTHREAD_SCOPE_SYSTEM
Inherit scheduler = PTHREAD_EXPLICIT_SCHED
Scheduling policy = SCHED_OTHER
Scheduling priority = 0
Guard size = 0 bytes
Stack address = 0x40197000
Stack size = 0x3000000 bytes
程序源码
#define _GNU_SOURCE /* 引入 pthread_getattr_np() 声明 */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void
display_pthread_attr(pthread_attr_t *attr, char *prefix)
{
int s, i;
size_t v;
void *stkaddr;
struct sched_param sp;
s = pthread_attr_getdetachstate(attr, &i);
if (s != 0)
handle_error_en(s, "pthread_attr_getdetachstate");
printf("%sDetach state = %s\n", prefix,
(i == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" :
(i == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE" :
"???");
s = pthread_attr_getscope(attr, &i);
if (s != 0)
handle_error_en(s, "pthread_attr_getscope");
printf("%sScope = %s\n", prefix,
(i == PTHREAD_SCOPE_SYSTEM) ? "PTHREAD_SCOPE_SYSTEM" :
(i == PTHREAD_SCOPE_PROCESS) ? "PTHREAD_SCOPE_PROCESS" :
"???");
s = pthread_attr_getinheritsched(attr, &i);
if (s != 0)
handle_error_en(s, "pthread_attr_getinheritsched");
printf("%sInherit scheduler = %s\n", prefix,
(i == PTHREAD_INHERIT_SCHED) ? "PTHREAD_INHERIT_SCHED" :
(i == PTHREAD_EXPLICIT_SCHED) ? "PTHREAD_EXPLICIT_SCHED" :
"???");
s = pthread_attr_getschedpolicy(attr, &i);
if (s != 0)
handle_error_en(s, "pthread_attr_getschedpolicy");
printf("%sScheduling policy = %s\n", prefix,
(i == SCHED_OTHER) ? "SCHED_OTHER" :
(i == SCHED_FIFO) ? "SCHED_FIFO" :
(i == SCHED_RR) ? "SCHED_RR" :
"???");
s = pthread_attr_getschedparam(attr, &sp);
if (s != 0)
handle_error_en(s, "pthread_attr_getschedparam");
printf("%sScheduling priority = %d\n", prefix, sp.sched_priority);
s = pthread_attr_getguardsize(attr, &v);
if (s != 0)
handle_error_en(s, "pthread_attr_getguardsize");
printf("%sGuard size = %d bytes\n", prefix, v);
s = pthread_attr_getstack(attr, &stkaddr, &v);
if (s != 0)
handle_error_en(s, "pthread_attr_getstack");
printf("%sStack address = %p\n", prefix, stkaddr);
printf("%sStack size = 0x%x bytes\n", prefix, v);
}
static void *
thread_start(void *arg)
{
int s;
pthread_attr_t gattr;
/* pthread_getattr_np() 一个非标准的 GNU 扩展,
它用于取得其第一个参数引用的线程的属性。*/
s = pthread_getattr_np(pthread_self(), &gattr);
if (s != 0)
handle_error_en(s, "pthread_getattr_np");
printf("Thread attributes:\n");
display_pthread_attr(&gattr, "\t");
exit(EXIT_SUCCESS); /* 终止所有线程 */
}
int
main(int argc, char *argv[])
{
pthread_t thr;
pthread_attr_t attr;
pthread_attr_t *attrp; /* NULL or &attr */
int s;
attrp = NULL;
/* 如果命令行参数提供了,使用它来设置线尺寸属性,
以及一些其它属性,并设置 attrp 指向这个线程属性对象 */
if (argc > 1) {
int stack_size;
void *sp;
attrp = &attr;
s = pthread_attr_init(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_init");
s = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (s != 0)
handle_error_en(s, "pthread_attr_setdetachstate");
s = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
if (s != 0)
handle_error_en(s, "pthread_attr_setinheritsched");
stack_size = strtoul(argv[1], NULL, 0);
s = posix_memalign(&sp, sysconf(_SC_PAGESIZE), stack_size);
if (s != 0)
handle_error_en(s, "posix_memalign");
printf("posix_memalign() allocated at %p\n", sp);
s = pthread_attr_setstack(&attr, sp, stack_size);
if (s != 0)
handle_error_en(s, "pthread_attr_setstack");
}
s = pthread_create(&thr, attrp, &thread_start, NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
if (attrp != NULL) {
s = pthread_attr_destroy(attrp);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy");
}
pause(); /* 当其它线程调用 exit() 时终止 */
}
参看
pthread_attr_setaffinity_np(3), pthread_attr_setdetachstate(3),
pthread_attr_setguardsize(3), pthread_attr_setinheritsched(3),
pthread_attr_setschedparam(3), pthread_attr_setschedpolicy(3),
pthread_attr_setscope(3), pthread_attr_setstack(3),
pthread_attr_setstackaddr(3), pthread_attr_setstacksize(3),
pthread_create(3), pthread_getattr_np(3), pthreads(7)