pthread 简要使用指南 线程属性(pthread_attr_t)
2015-03-25 14:47
411 查看
先上代码。suse linux上pthread_attr_init,man(3)上面的例子:
[cpp]
view plaincopyprint?
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* To get pthread_getattr_np() declaration */
#endif
#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 *attr1, char *prefix)
{
int s, i;
size_t v;
void *stkaddr;
struct sched_param sp;
pthread_attr_t *attr = new pthread_attr_t;
pthread_attr_init(attr);
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() is a non-standard GNU extension that
retrieves the attributes of the thread specified in its
first argument */
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); /* Terminate all threads */
}
int main(int argc, char *argv[])
{
pthread_t thr;
pthread_attr_t attr;
pthread_attr_t *attrp; /* NULL or &attr */
int s;
attrp = NULL;
/* If a command-line argument was supplied, use it to set the
stack-size attribute and set a few other thread attributes,
and set attrp pointing to thread attributes object */
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(); /* Terminates when other thread calls exit() */
}
运行结果:
[cpp]
view plaincopyprint?
linux:/home/hsl/pthread # ulimit -s
8192
linux:/home/hsl/pthread # ./pattr.r
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 = 0x7f8ac216e000
Stack size = 0x801000 bytes
linux:/home/hsl/pthread # ./pattr.r 0x30000000
posix_memalign() allocated at 0x7fe07d5e2000
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 = 0x7fe07d5e2000
Stack size = 0x30000000 bytes
平时使用pthread_create()来创建的线程,其中的pthread_attr_t *attr参数一般来说使用NULL,也就是ptread_create()使用默认值来创建线程已经能满足大部分的使用。
pthread_attr_t这个结构,suse linux中位于/usr/include/bits/pthreadtypes.h这个文件中,不同的pthreads实现版本具体位置可能不太一样,具体结构内容也不一样。但是其实我们不需要了解这个结构具体是什么样子的,因为所有的属性值的设置或获取都由特定函数完成。
在使用pthread_attr_t结构的变量之前,需要进行初始化,使用之后,也需要销毁:
[cpp]
view plaincopyprint?
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
根据函数名字,基本上就可以大概看出这个函数是干嘛的了。
pthread_attr_init()使用默认值初始化一个pthread_attr_t结构的非空指针;
pthread_attr_destroy()销毁一个pthread_attr_t结构的非空指针对象;
pthread_attr_t中包含了如下线程属性:
* Detach state : PTHREAD_CREATE_JOINABLE 或是 PTHREAD_CREATE_DETACHED;
该属性表示线程是否与同进程中的其他线程进行关联、同步。
PTHREAD_CREATE_JOINABLE:表示本线程可以被同进程的其他线程使用pthread_join()来进行同步等待。并且线程的所占用的资源在被pthread_join()之后才会被释放。如果PTHREAD_CREATE_JOINABLE状态的线程,没有被同进程内的其他线程phread_join(),会造成系统资源泄露。
PTHREAD_CREATE_DETACHED:表示本线程不允许同进程的其他线程使用phread_join()进程等待返回。该状态下,如果有其他进程对该线程使用pthread_join(),那么pthread_join()将会立即返回,错误码通过phread_join()的返回值返回。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
pthread_attr_setdetachstate()调用后,detachstate被设置到attr中去。
pthread_attr_getdetachstate()调用后,attr中的Detach state属性被获取出来,并存放到*detachstate中去。
在线程创建之后,PTHREAD_CREATE_JOINABLE状态的线程可以在线程内或线程外调用pthread_detach()来把当前为PTHREAD_CREATE_JOINABLE的线程置为PTHREAD_CREATE_DETACHED。但是该过程是不可逆的,也就是PTHREAD_CREATE_DETACHED状态的线程,不可以重新设置为PTHREAD_CREATE_JOINABLE。
* Scope : PTHREAD_SCOPE_SYSTEM 或是 PTHREAD_SCOPE_PROCESS;
该属性决定了线程间竞争资源(CPU等)的级别。
PTHREAD_SCOPE_SYSTEM : 表示拥有该属性的线程,将与系统中所有线程一起竞争资源(CPU等);
PTHREAD_SCOPE_PROCESS : 表示拥有该属性的线程,仅与同一进程中的线程竞争资源(CPU等)。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
int pthread_attr_getscope(pthread_attr_t *attr, int *scope);
* Inherit scheduler : PTHREAD_INHERIT_SCHED 或是 PTHREAD_EXPLICIT_SCHED
该属性决定了线程的调度参数是从创建的进程中继承,或是由SchedPolicy和SchedParam属性确定。
PTHREAD_INHERIT_SCHED : 新的线程继承创建线程的调度策略和参数;
PTHREAD_EXPLICIT_SCHED: 新的线程继承策略和参数由schedpolicy和schedparam属性确定。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched);
*Scheduling policy : SCHED_FIFO, SCHED_RR, 以及 SCHED_OTHER
当Inherit scheduler属性为PTHREAD_EXPLICIT_SCHED时,本属性决定了新线程的调度策略。
SCHED_OTHER是默认的调度策略。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);
*Scheduling priority: 优先级值
该属性实际就是线程的优先级。当Inherit scheduler属性为PTHREAD_EXPLICIT_SCHED时,本属性有效。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
int pthread_attr_getschedparam(pthread_attr_t *attr, struct sched_param *param);
所用系统支持的优先级最大最小值可以使用如下函数查询:
[java]
view plaincopyprint?
int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);
这两个函数的参数为:SCHED_FIFO, SCHED_RR, 以及 SCHED_OTHER。不同的调度策略优先级最大最小值可能不一样。
*Guard size : 栈保护区大小
线程所使用的内存栈的栈顶,存在一个栈保护区。该区域不允许读写,如果线程中对该区域进行了读或写操作,线程会收到一个SIGSEGV信号。该属性默认值为系统的页大小。该属性被设置时,系统会自动将该属性大小补齐为页大小的整数倍。
如果栈保护区大小为0,那么创建出来的线程将没有栈保护区。
如果栈地址被指定,那么本属性将被忽略。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
*Stack address : 动态分配的栈地址及栈大小
该属性设置新线程所用栈的栈地址以及栈大小。当进程的栈地址空间不够使用时,可以使用动态分配出来的内存空间作为新创建线程的栈空间。使用本属性后,栈保护区大小属性失效。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);
*Stack size :栈大小
通过该属性,可以调整线程的栈空间大小。系统默认的线程栈大小可以通过指令:ulimit -s来查询。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
[cpp]
view plaincopyprint?
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* To get pthread_getattr_np() declaration */
#endif
#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 *attr1, char *prefix)
{
int s, i;
size_t v;
void *stkaddr;
struct sched_param sp;
pthread_attr_t *attr = new pthread_attr_t;
pthread_attr_init(attr);
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() is a non-standard GNU extension that
retrieves the attributes of the thread specified in its
first argument */
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); /* Terminate all threads */
}
int main(int argc, char *argv[])
{
pthread_t thr;
pthread_attr_t attr;
pthread_attr_t *attrp; /* NULL or &attr */
int s;
attrp = NULL;
/* If a command-line argument was supplied, use it to set the
stack-size attribute and set a few other thread attributes,
and set attrp pointing to thread attributes object */
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(); /* Terminates when other thread calls exit() */
}
#ifndef _GNU_SOURCE #define _GNU_SOURCE /* To get pthread_getattr_np() declaration */ #endif #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 *attr1, char *prefix) { int s, i; size_t v; void *stkaddr; struct sched_param sp; pthread_attr_t *attr = new pthread_attr_t; pthread_attr_init(attr); 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() is a non-standard GNU extension that retrieves the attributes of the thread specified in its first argument */ 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); /* Terminate all threads */ } int main(int argc, char *argv[]) { pthread_t thr; pthread_attr_t attr; pthread_attr_t *attrp; /* NULL or &attr */ int s; attrp = NULL; /* If a command-line argument was supplied, use it to set the stack-size attribute and set a few other thread attributes, and set attrp pointing to thread attributes object */ 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(); /* Terminates when other thread calls exit() */ }
运行结果:
[cpp]
view plaincopyprint?
linux:/home/hsl/pthread # ulimit -s
8192
linux:/home/hsl/pthread # ./pattr.r
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 = 0x7f8ac216e000
Stack size = 0x801000 bytes
linux:/home/hsl/pthread # ./pattr.r 0x30000000
posix_memalign() allocated at 0x7fe07d5e2000
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 = 0x7fe07d5e2000
Stack size = 0x30000000 bytes
linux:/home/hsl/pthread # ulimit -s 8192 linux:/home/hsl/pthread # ./pattr.r 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 = 0x7f8ac216e000 Stack size = 0x801000 bytes linux:/home/hsl/pthread # ./pattr.r 0x30000000 posix_memalign() allocated at 0x7fe07d5e2000 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 = 0x7fe07d5e2000 Stack size = 0x30000000 bytes
平时使用pthread_create()来创建的线程,其中的pthread_attr_t *attr参数一般来说使用NULL,也就是ptread_create()使用默认值来创建线程已经能满足大部分的使用。
pthread_attr_t这个结构,suse linux中位于/usr/include/bits/pthreadtypes.h这个文件中,不同的pthreads实现版本具体位置可能不太一样,具体结构内容也不一样。但是其实我们不需要了解这个结构具体是什么样子的,因为所有的属性值的设置或获取都由特定函数完成。
在使用pthread_attr_t结构的变量之前,需要进行初始化,使用之后,也需要销毁:
[cpp]
view plaincopyprint?
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr);
根据函数名字,基本上就可以大概看出这个函数是干嘛的了。
pthread_attr_init()使用默认值初始化一个pthread_attr_t结构的非空指针;
pthread_attr_destroy()销毁一个pthread_attr_t结构的非空指针对象;
pthread_attr_t中包含了如下线程属性:
* Detach state : PTHREAD_CREATE_JOINABLE 或是 PTHREAD_CREATE_DETACHED;
该属性表示线程是否与同进程中的其他线程进行关联、同步。
PTHREAD_CREATE_JOINABLE:表示本线程可以被同进程的其他线程使用pthread_join()来进行同步等待。并且线程的所占用的资源在被pthread_join()之后才会被释放。如果PTHREAD_CREATE_JOINABLE状态的线程,没有被同进程内的其他线程phread_join(),会造成系统资源泄露。
PTHREAD_CREATE_DETACHED:表示本线程不允许同进程的其他线程使用phread_join()进程等待返回。该状态下,如果有其他进程对该线程使用pthread_join(),那么pthread_join()将会立即返回,错误码通过phread_join()的返回值返回。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
pthread_attr_setdetachstate()调用后,detachstate被设置到attr中去。
pthread_attr_getdetachstate()调用后,attr中的Detach state属性被获取出来,并存放到*detachstate中去。
在线程创建之后,PTHREAD_CREATE_JOINABLE状态的线程可以在线程内或线程外调用pthread_detach()来把当前为PTHREAD_CREATE_JOINABLE的线程置为PTHREAD_CREATE_DETACHED。但是该过程是不可逆的,也就是PTHREAD_CREATE_DETACHED状态的线程,不可以重新设置为PTHREAD_CREATE_JOINABLE。
* Scope : PTHREAD_SCOPE_SYSTEM 或是 PTHREAD_SCOPE_PROCESS;
该属性决定了线程间竞争资源(CPU等)的级别。
PTHREAD_SCOPE_SYSTEM : 表示拥有该属性的线程,将与系统中所有线程一起竞争资源(CPU等);
PTHREAD_SCOPE_PROCESS : 表示拥有该属性的线程,仅与同一进程中的线程竞争资源(CPU等)。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
int pthread_attr_getscope(pthread_attr_t *attr, int *scope);
int pthread_attr_setscope(pthread_attr_t *attr, int scope); int pthread_attr_getscope(pthread_attr_t *attr, int *scope);
* Inherit scheduler : PTHREAD_INHERIT_SCHED 或是 PTHREAD_EXPLICIT_SCHED
该属性决定了线程的调度参数是从创建的进程中继承,或是由SchedPolicy和SchedParam属性确定。
PTHREAD_INHERIT_SCHED : 新的线程继承创建线程的调度策略和参数;
PTHREAD_EXPLICIT_SCHED: 新的线程继承策略和参数由schedpolicy和schedparam属性确定。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched);
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched); int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched);
*Scheduling policy : SCHED_FIFO, SCHED_RR, 以及 SCHED_OTHER
当Inherit scheduler属性为PTHREAD_EXPLICIT_SCHED时,本属性决定了新线程的调度策略。
SCHED_OTHER是默认的调度策略。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);
*Scheduling priority: 优先级值
该属性实际就是线程的优先级。当Inherit scheduler属性为PTHREAD_EXPLICIT_SCHED时,本属性有效。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
int pthread_attr_getschedparam(pthread_attr_t *attr, struct sched_param *param);
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param); int pthread_attr_getschedparam(pthread_attr_t *attr, struct sched_param *param);
所用系统支持的优先级最大最小值可以使用如下函数查询:
[java]
view plaincopyprint?
int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);
int sched_get_priority_max(int policy); int sched_get_priority_min(int policy);
这两个函数的参数为:SCHED_FIFO, SCHED_RR, 以及 SCHED_OTHER。不同的调度策略优先级最大最小值可能不一样。
*Guard size : 栈保护区大小
线程所使用的内存栈的栈顶,存在一个栈保护区。该区域不允许读写,如果线程中对该区域进行了读或写操作,线程会收到一个SIGSEGV信号。该属性默认值为系统的页大小。该属性被设置时,系统会自动将该属性大小补齐为页大小的整数倍。
如果栈保护区大小为0,那么创建出来的线程将没有栈保护区。
如果栈地址被指定,那么本属性将被忽略。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
*Stack address : 动态分配的栈地址及栈大小
该属性设置新线程所用栈的栈地址以及栈大小。当进程的栈地址空间不够使用时,可以使用动态分配出来的内存空间作为新创建线程的栈空间。使用本属性后,栈保护区大小属性失效。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize); int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);
*Stack size :栈大小
通过该属性,可以调整线程的栈空间大小。系统默认的线程栈大小可以通过指令:ulimit -s来查询。
该属性值的设置及获取由如下两个函数进行:
[cpp]
view plaincopyprint?
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
相关文章推荐
- pthread 简要使用指南(五) 线程属性(pthread_attr_t)
- pthread 简要使用指南(三) 线程的终止
- pthread_attr_init () 线程属性函数使用
- Linux 多线程编程( POSIX )( 二 )----->代码区 ( pthread_attr_t 线程属性实例 )
- pthread 简要使用指南
- pthread_attr_t 线程属性
- 线程的分离状态 pthread_attr_setdetachstate 函数使用
- pthread_attr_init 线程属性
- 线程属性pthread_attr_t简介
- posix多线程有感--线程高级编程(线程属性pthread_attr_t)---实时调度(代码)
- 线程属性pthread_attr_t简介
- pthread_attr_t 线程属性
- 线程堆栈大小 pthread_attr_setstacksize 的使用
- Linux 多线程编程( POSIX )( 二 )----->pthread_attr_t 线程属性
- pthread 简要使用指南(四) Cancellation Points
- pthread_attr_t 线程属性(一)
- posix多线程有感--线程高级编程(线程属性pthread_attr_t)---实时调度(代码)
- 线程属性pthread_attr_t简介(转)
- 线程属性pthread_attr_t简介
- pthread_attr_t 线程属性(二)