打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
pthread 简要使用指南(五) 线程属性(pthread

    先上代码。suse Linux上pthread_attr_init,man(3)上面的例子:  

  1. #ifndef _GNU_SOURCE  
  2.     #define _GNU_SOURCE     /* To get pthread_getattr_np() declaration */  
  3. #endif  
  4. #include <pthread.h>  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <unistd.h>  
  8. #include <errno.h>  
  9.   
  10. #define handle_error_en(en, msg) \  
  11.     do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)  
  12.   
  13. static void  
  14. display_pthread_attr(pthread_attr_t *attr1, char *prefix)  
  15. {  
  16.     int s, i;  
  17.     size_t v;  
  18.     void *stkaddr;  
  19.     struct sched_param sp;  
  20.   
  21.     pthread_attr_t *attr = new pthread_attr_t;  
  22.     pthread_attr_init(attr);  
  23.     s = pthread_attr_getdetachstate(attr, &i);  
  24.     if (s != 0)  
  25.         handle_error_en(s, "pthread_attr_getdetachstate");  
  26.     printf("%sDetach state        = %s\n", prefix,  
  27.         (i == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" :  
  28.         (i == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE" :  
  29.         "???");  
  30.   
  31.     s = pthread_attr_getscope(attr, &i);  
  32.     if (s != 0)  
  33.         handle_error_en(s, "pthread_attr_getscope");  
  34.     printf("%sScope               = %s\n", prefix,  
  35.         (i == PTHREAD_SCOPE_SYSTEM)  ? "PTHREAD_SCOPE_SYSTEM" :  
  36.         (i == PTHREAD_SCOPE_PROCESS) ? "PTHREAD_SCOPE_PROCESS" :  
  37.         "???");  
  38.   
  39.     s = pthread_attr_getinheritsched(attr, &i);  
  40.     if (s != 0)  
  41.         handle_error_en(s, "pthread_attr_getinheritsched");  
  42.     printf("%sInherit scheduler   = %s\n", prefix,  
  43.         (i == PTHREAD_INHERIT_SCHED)  ? "PTHREAD_INHERIT_SCHED" :  
  44.         (i == PTHREAD_EXPLICIT_SCHED) ? "PTHREAD_EXPLICIT_SCHED" :  
  45.         "???");  
  46.   
  47.     s = pthread_attr_getschedpolicy(attr, &i);  
  48.     if (s != 0)  
  49.         handle_error_en(s, "pthread_attr_getschedpolicy");  
  50.     printf("%sScheduling policy   = %s\n", prefix,  
  51.         (i == SCHED_OTHER) ? "SCHED_OTHER" :  
  52.         (i == SCHED_FIFO)  ? "SCHED_FIFO" :  
  53.         (i == SCHED_RR)    ? "SCHED_RR" :  
  54.         "???");  
  55.   
  56.     s = pthread_attr_getschedparam(attr, &sp);  
  57.     if (s != 0)  
  58.         handle_error_en(s, "pthread_attr_getschedparam");  
  59.     printf("%sScheduling priority = %d\n", prefix, sp.sched_priority);  
  60.   
  61.     s = pthread_attr_getguardsize(attr, &v);  
  62.     if (s != 0)  
  63.         handle_error_en(s, "pthread_attr_getguardsize");  
  64.     printf("%sGuard size          = %d bytes\n", prefix, v);  
  65.   
  66.     s = pthread_attr_getstack(attr, &stkaddr, &v);  
  67.     if (s != 0)  
  68.         handle_error_en(s, "pthread_attr_getstack");  
  69.     printf("%sStack address       = %p\n", prefix, stkaddr);  
  70.     printf("%sStack size          = 0x%x bytes\n", prefix, v);  
  71. }  
  72.   
  73. static void * thread_start(void *arg)  
  74. {  
  75.     int s;  
  76.     pthread_attr_t gattr;  
  77.   
  78.     /* pthread_getattr_np() is a non-standard GNU extension that 
  79.     retrieves the attributes of the thread specified in its 
  80.     first argument */  
  81.   
  82.     s = pthread_getattr_np(pthread_self(), &gattr);  
  83.     if (s != 0)  
  84.         handle_error_en(s, "pthread_getattr_np");  
  85.   
  86.     printf("Thread attributes:\n");  
  87.     display_pthread_attr(&gattr, "\t");  
  88.   
  89.     exit(EXIT_SUCCESS);         /* Terminate all threads */  
  90. }  
  91.   
  92. int main(int argc, char *argv[])  
  93. {  
  94.     pthread_t thr;  
  95.     pthread_attr_t attr;  
  96.     pthread_attr_t *attrp;      /* NULL or &attr */  
  97.     int s;  
  98.   
  99.     attrp = NULL;  
  100.   
  101.     /* If a command-line argument was supplied, use it to set the 
  102.     stack-size attribute and set a few other thread attributes, 
  103.     and set attrp pointing to thread attributes object */  
  104.   
  105.     if (argc > 1) {  
  106.         int stack_size;  
  107.         void *sp;  
  108.   
  109.         attrp = &attr;  
  110.   
  111.         s = pthread_attr_init(&attr);  
  112.         if (s != 0)  
  113.             handle_error_en(s, "pthread_attr_init");  
  114.   
  115.         s = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
  116.         if (s != 0)  
  117.             handle_error_en(s, "pthread_attr_setdetachstate");  
  118.   
  119.         s = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);  
  120.         if (s != 0)  
  121.             handle_error_en(s, "pthread_attr_setinheritsched");  
  122.   
  123.         stack_size = strtoul(argv[1], NULL, 0);  
  124.   
  125.         s = posix_memalign(&sp, sysconf(_SC_PAGESIZE), stack_size);  
  126.         if (s != 0)  
  127.             handle_error_en(s, "posix_memalign");  
  128.   
  129.         printf("posix_memalign() allocated at %p\n", sp);  
  130.   
  131.         s = pthread_attr_setstack(&attr, sp, stack_size);  
  132.         if (s != 0)  
  133.             handle_error_en(s, "pthread_attr_setstack");  
  134.     }  
  135.   
  136.     s = pthread_create(&thr, attrp, &thread_start, NULL);  
  137.     if (s != 0)  
  138.         handle_error_en(s, "pthread_create");  
  139.   
  140.     if (attrp != NULL) {  
  141.         s = pthread_attr_destroy(attrp);  
  142.         if (s != 0)  
  143.             handle_error_en(s, "pthread_attr_destroy");  
  144.     }  
  145.   
  146.     pause();    /* Terminates when other thread calls exit() */      
  147. }  
运行结果:
  1. linux:/home/hsl/pthread # ulimit -s  
  2. 8192  
  3.   
  4. linux:/home/hsl/pthread # ./pattr.r   
  5. Thread attributes:  
  6.         Detach state        = PTHREAD_CREATE_JOINABLE  
  7.         Scope               = PTHREAD_SCOPE_SYSTEM  
  8.         Inherit scheduler   = PTHREAD_INHERIT_SCHED  
  9.         Scheduling policy   = SCHED_OTHER  
  10.         Scheduling priority = 0  
  11.         Guard size          = 4096 bytes  
  12.         Stack address       = 0x7f8ac216e000  
  13.         Stack size          = 0x801000 bytes  
  14. linux:/home/hsl/pthread # ./pattr.r 0x30000000  
  15. posix_memalign() allocated at 0x7fe07d5e2000  
  16. Thread attributes:  
  17.         Detach state        = PTHREAD_CREATE_DETACHED  
  18.         Scope               = PTHREAD_SCOPE_SYSTEM  
  19.         Inherit scheduler   = PTHREAD_EXPLICIT_SCHED  
  20.         Scheduling policy   = SCHED_OTHER  
  21.         Scheduling priority = 0  
  22.         Guard size          = 0 bytes  
  23.         Stack address       = 0x7fe07d5e2000  
  24.         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结构的变量之前,需要进行初始化,使用之后,也需要销毁:

  1. int pthread_attr_init(pthread_attr_t *attr);  
  2. 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()的返回值返回。
    该属性值的设置及获取由如下两个函数进行:
  1. int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);  
  2. 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等)。
    该属性值的设置及获取由如下两个函数进行:
  1. int pthread_attr_setscope(pthread_attr_t *attr, int scope);  
  2. 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属性确定。
    该属性值的设置及获取由如下两个函数进行:
  1. int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);  
  2. 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是默认的调度策略。
     该属性值的设置及获取由如下两个函数进行:    
  1. int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);  
  2. int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);  

    *Scheduling priority: 优先级值

    该属性实际就是线程的优先级。当Inherit scheduler属性为PTHREAD_EXPLICIT_SCHED时,本属性有效。
    该属性值的设置及获取由如下两个函数进行:
  1. int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);  
  2. int pthread_attr_getschedparam(pthread_attr_t *attr, struct sched_param *param);  
    所用系统支持的优先级最大最小值可以使用如下函数查询:
  1. int sched_get_priority_max(int policy);  
  2. int sched_get_priority_min(int policy);  
    这两个函数的参数为:SCHED_FIFO, SCHED_RR, 以及 SCHED_OTHER。不同的调度策略优先级最大最小值可能不一样。
    *Guard size : 栈保护区大小
    线程所使用的内存栈的栈顶,存在一个栈保护区。该区域不允许读写,如果线程中对该区域进行了读或写操作,线程会收到一个SIGSEGV信号。该属性默认值为系统的页大小。该属性被设置时,系统会自动将该属性大小补齐为页大小的整数倍。
    如果栈保护区大小为0,那么创建出来的线程将没有栈保护区。
    如果栈地址被指定,那么本属性将被忽略。    
    该属性值的设置及获取由如下两个函数进行:
  1. int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);  
  2. int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);  

    *Stack address : 动态分配的栈地址及栈大小

    该属性设置新线程所用栈的栈地址以及栈大小。当进程的栈地址空间不够使用时,可以使用动态分配出来的内存空间作为新创建线程的栈空间。使用本属性后,栈保护区大小属性失效。
    该属性值的设置及获取由如下两个函数进行:
  1. int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);  
  2. int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);  
    *Stack size :栈大小
    通过该属性,可以调整线程的栈空间大小。系统默认的线程栈大小可以通过指令:ulimit -s来查询。
    该属性值的设置及获取由如下两个函数进行:
  1. int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);  
  2. int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);  

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
线程设置
Posix多线程编程—线程属性
UNIX环境编程学习笔记(27)
linux多线程
POSIX API
linux 线程函数大全
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服