linux下 线程属性常用操作

来源:互联网 发布:网络渗透的目的 编辑:程序博客网 时间:2024/05/22 12:45
在linux中,可以使用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来。首先调用pthread_attr_init初始化pthread_attr_t结构,使pthread_attr_t结构所包含的内容就是操作系统实现支持的线程所有属性的默认值。然后,可以调用其他函数对想修改的个别属性进行修改。

1.线程属性的初始化(若对属性操作,必先初始化),去初始化。
     #include <pthread.h>
       int pthread_attr_destroy(pthread_attr_t *attr);
       int pthread_attr_init(pthread_attr_t *attr);
       返回值:若成功返回0,否则返回错误编号。

2.获取分离状态/设置分离属性
       #include <pthread.h>
       int pthread_attr_getdetachstate(const pthread_attr_t *attr,int *detachstate);
       int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
       返回值:若成功返回0,否则返回错误编号。
       设置PTHREAD_CREATE_DETACHED,以分离状态启动线程;或设置为PTHREAD_CREATE_JOINABLE,默认正常启动线程,应用程序可以获取线程的终止状态。

3.获取/设置调度策略
       #include <pthread.h>
       int pthread_attr_getschedpolicy(const pthread_attr_t *restrict attr,
              int *restrict policy);
       int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
    返回值:若成功返回0,否则返回错误编号。
    The supported values of policy shall include SCHED_FIFO, SCHED_RR,  and SCHED_OTHER,  which  are defined in the <sched.h> header.  
   
 POSIX 标准指定了三种调度策略:先入先出策略 (SCHED_FIFO)、循环策略 (SCHED_RR) 和自定义策略 (SCHED_OTHER)。SCHED_FIFO 是基于队列的调度程序,对于每个优先级都会使用不同的队列。SCHED_RR 与 FIFO 相似,不同的是前者的每个线程都有一个执行时间配额。
    SCHED_FIFO
 和 SCHED_RR 是对 POSIX Realtime 的扩展。SCHED_OTHER 是缺省的调度策略。
  • SCHED_FIFO
    如果调用进程具有有效的用户 ID 0,则争用范围为系统 (PTHREAD_SCOPE_SYSTEM) 的先入先出线程属于实时 (RT) 调度类。如果这些线程未被优先级更高的线程抢占,则会继续处理该线程,直到该线程放弃或阻塞为止。对于具有进程争用范围 (PTHREAD_SCOPE_PROCESS)) 的线程或其调用进程没有有效用户 ID 0 的线程,请使用SCHED_FIFOSCHED_FIFO 基于 TS 调度类。
  • SCHED_RR
    如果调用进程具有有效的用户 ID 0,则争用范围为系统 (PTHREAD_SCOPE_SYSTEM)) 的循环线程属于实时 (RT) 调度类。如果这些线程未被优先级更高的线程抢占,并且这些线程没有放弃或阻塞,则在系统确定的时间段内将一直执行这些线程。对于具有进程争用范围 (PTHREAD_SCOPE_PROCESS) 的线程,请使用 SCHED_RR(基于 TS 调度类)。此外,这些线程的调用进程没有有效的用户 ID 0
     SCHED_FIFO 和 SCHED_RR 在 POSIX 标准中是可选的,而且仅用于实时线程。

4.获取/设置继承的调度策略
       #include <pthread.h>
       int pthread_attr_getinheritsched(const pthread_attr_t *restrict attr,int *restrict inheritsched);
       int pthread_attr_setinheritsched(pthread_attr_t *attr,
              int inheritsched);
    pthread_attr_getinheritsched() 成功完成后将返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。
    EINVAL 描述: 参数 inherit 为 NULL 或 tattr 无效。
    
    pthread_attr_setinheritsched()
 成功完成后将返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。
   EINVAL 描述: 尝试将 tattr 设置为无效的值。
   ENOTSUP 
描述: 尝试将属性设置为不受支持的值。
   值 PTHREAD_INHERIT_SCHED 表示新建的线程将继承创建者线程中定义的调度策略。将忽略在 pthread_create() 调用中定义的所有调度属性。如果使用缺省值 PTHREAD_EXPLICIT_SCHED,则将使用 pthread_create() 调用中的属性。
5.获取/设置调度参数
       #include <pthread.h>
       int pthread_attr_getschedparam(const pthread_attr_t *restrict attr,
              struct sched_param *restrict param);
       int pthread_attr_setschedparam(pthread_attr_t *restrict attr,
              const struct sched_param *restrict param);
  struct sched_param
  {
    int sched_priority;
  };


在上一篇文章中,介绍了线程的创建和退出,以及相关函数的使用。其中pthread_create函数的第二个参数,是关于线程属性的设置,这也是今天所有讲述的。这些属性主要包括邦定属性、分离属性、堆栈地址、堆栈大小、优先级。其中系统默认的是非邦定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置。

(1)邦定属性。

在LINUX中,采用的是“一对一”的线程机制。也就是一个用户线程对应一个内核线程。邦定属性就是指一个用户线程固定地分配给一个内核线程,因为CPU时间片的调度是面向内核线程(轻量级进程)的,因此具有邦定属性的线程可以保证在需要的时候总有一个内核线程与之对应,而与之对应的非邦定属性就是指用户线程和内核线程的关系不是始终固定的,而是由系统来分配。

(2)分离属性。

分离属性是决定以一个什么样的方式来终止自己。在非分离情况下,当一个线程结束时,它多占用的线程没有得到释放,也就是没有真正的终止,需要通过pthread_join来释放资源。而在分离属性情况下,一个线程结束时会立即释放它所占有的系统资源。但这里有一点要注意的是,如果设置一个线程分离属性,而这个线程又运行得非常快的话,那么它很可能在pthread_create函数返回之前就终止了线程函数的运行,它终止以后就很有可能将线程号和系统资源移交给其他的线程使用,这时调用pthread_create的线程就得到错误的线程号。

这些属性都是通过一些函数来完成的,通常先调用pthread_attr_init来初始化,之后来调用相应的属性设置函数。

1、pthread_attr_init

功能:        对线程属性变量的初始化。

头文件:     <pthread.h>

函数原型:   int pthread_attr_init (pthread_attr_t* attr);

函数传入值:attr:线程属性。

函数返回值:成功: 0

                失败: -1

2、pthread_attr_setscope

功能:        设置线程绑定属性。

头文件:     <pthread.h>

函数原型:   int pthread_attr_setscope (pthread_attr_t* attr, int scope);

函数传入值:attr: 线程属性。

                scope:PTHREAD_SCOPE_SYSTEM(绑定)

                         PTHREAD_SCOPE_PROCESS(非绑定)

函数返回值得:同1。

3、pthread_attr_setdetachstate

功能:        设置线程分离属性。

头文件:      <phread.h>

函数原型:    int pthread_attr_setdetachstate (pthread_attr_t* attr, int detachstate);

函数传入值:attr:线程属性。

                detachstate:PTHREAD_CREATE_DETACHED(分离)

                                  PTHREAD_CREATE_JOINABLE(非分离)

函数返回值得:同1。

4、pthread_attr_getschedparam

功能:       得到线程优先级。

头文件:    <pthread.h>

函数原型:  int pthread_attr_getschedparam (pthread_attr_t* attr, struct sched_param* param);

函数传入值:attr:线程属性;

                param:线程优先级;

函数返回值:同1。

5、pthread_attr_setschedparam

功能:       设置线程优先级。

头文件:     <pthread.h>

函数原型:   int pthread_attr_setschedparam (pthread_attr_t* attr, struct sched_param* param);

函数传入值:attr:线程属性。

                 param:线程优先级。

函数返回值:同1。

 

函数实现:

 

[cpp] view plaincopy
  1. #include <stdlib.h>    
  2. #include <stdio.h>    
  3. #include <errno.h>    
  4. #include <pthread.h>    
  5.     
  6. static void* pthread_func_1 (void*);    
  7. static void* pthread_func_2 (void*);    
  8.     
  9. int main (int argc, char** argv)    
  10. {    
  11.   pthread_t pt_1 = 0;    
  12.   pthread_t pt_2 = 0;    
  13.   pthread_attr_t attr = {0};    
  14.   int ret = 0;    
  15.     
  16.   pthread_attr_init (&attr); //属性设置  
  17.   pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);    
  18.   pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);    
  19.       
  20.   ret = pthread_create (&pt_1, &attr, pthread_func_1, NULL);    
  21.   if (ret != 0)    
  22.   {    
  23.     perror ("pthread_1_create");    
  24.   }    
  25.       
  26.   ret = pthread_create (&pt_2, NULL, pthread_func_2, NULL);    
  27.   if (ret != 0)    
  28.   {    
  29.     perror ("pthread_2_create");    
  30.   }    
  31.     
  32.   pthread_join (pt_2, NULL);    
  33.     
  34.   return 0;    
  35. }    
  36.     
  37. static void* pthread_func_1 (void* data)    
  38. {    
  39.   int i = 0;    
  40.       
  41.   for (; i < 6; i++)    
  42.   {     
  43.     printf ("This is pthread_1./n");    
  44.        
  45.     if (i == 2)    
  46.     {    
  47.       pthread_exit (0);    
  48.     }    
  49.   }    
  50.     
  51.   return;    
  52. }    
  53.     
  54. static void* pthread_func_2 (void* data)    
  55. {    
  56.   int i = 0;    
  57.     
  58.   for (; i < 3; i ++)    
  59.   {    
  60.     printf ("This is pthread_2./n");    
  61.   }    
  62.     
  63.   return;    
  64. }    

从上面事例中,可以得到这么一个结果,就是线程一的线程函数一结束就自动释放资源,线程二就得等到pthread_join来释放系统资源。在下一篇文章中将介绍线程锁。


0 0
原创粉丝点击