Linux c 线程属性,线程优先级的修改

线程属性的设置,网上找的文章总感觉不够全面,还是结合man手册查看。

线程属性设置,分两个方式,一种是在创建之前,通过pthread_attr_t 结构体传入,另一种,是线程创建完已经在运行时,通过部分函数设置。一般常见的是创建线程时传NULL,使用默认属性,后续运行时根据需要动态修改,也就第二种方式。
---/--------------补充:设置优先级,除了这里所描述的 sched_setscheduler()函数之外,还有一个函数 int setpriority(int which, id_t who, int prio);  这两个函数都是系统调用(linux man手册,man 1 ,shell 脚本命令,man 2, 系统调用,man 3 库函数), 前者可以修改其调度策略,后者只是修改调度优先级,按照这个对比来看, setpriority是针对进程 ,用于设置进程,进程组,用户进程的优先级【在调度层面,线程才是基本单位,同一个进程下的线程,只是具有相同的进程资源的关系。 所以 setpriority是不是把同属于这一个进程的线程都进行了优先级的设定?还搞不太清楚】)

一:线程创建前设置属性:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

void *(*start_routine) (void *), void *arg);

1.0 第一个参数,用来保存创建好后线程uid

2.0 第二个参数,即线程属性,通常传NULL,表示默认属性,这个属性在创建前可以设置,包括调度策略,栈大小,优先级等等

3.0 第三个参数,即线程入口函数

4.0 第四个参数,传给线程的参数

所以在创建线程前,对 第二个参数 pthred_attr_t 结构体进pthread_attr_t 进行赋值

 

1.0 pthread_attr_init(pthread_attr_t *attr);//使用默认值填充初始化

2.0//获取设置栈大小 //这个属性只能在线程创建前设置,后面不能动态修改了

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);

3.0 //设置获取调度策略

SCHED_FIFO, SCHED_RR, and

SCHED_OTHER //policy支持这三种值,

    1.0SCHED_OTHER 分时调度策略,

    2.0SCHED_FIFO实时调度策略,先到先服务

    3.0,SCHED_RR实时调度策略,时间片轮转 

   SCHED_OTHER(分时调度)是不支持优先级使用的,其他两个实时调度可以

int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);

int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);

4.0 //设置调度参数,目前这个参数里面就一个量,优先级 //用户程序设置实时任务这个优先级,值越大,优先级越高(内核里面优先级是用另外的一个值,具体查看这个文章:http://www.360doc.com/content/13/0801/09/7775902_303961368.shtml

struct sched_param {

int sched_priority; /* Scheduling priority */

};

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);

5.0//是否分离属性

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);

 

上面这些都是静态,在创建线程之前的设置。

二:一般,都在线程创建完后,动态地设置:

1.0 设置调度策略和优先级

#include <sched.h>

int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);

int sched_getscheduler(pid_t pid); //获取线程当前优先级

struct sched_param {

int sched_priority;

};

//获取支持的最大最小值

int sched_get_priority_max(int policy);

int sched_get_priority_min(int policy);

2.0 设置分离属性

int pthread_detach(pthread_t thread);

int pthread_join(pthread_t thread, void **retval);

3.0 设置线程名称

调用   prctl(PR_SET_NAME, “my_threadname”);

线程默认名称,貌似是父进程的名称,未去考究,在linux上我们用 ps -p pid -T 来查看进程号为 pid的子线程的情况,如果用上面的方式设置了线程名称,则会列出名称

关于 prctl 

process control,  #man prctl 上面的是 (2),说明这是一个系统调用函数,根据他的全名顾名思义就是用来控制 process的,(linux内核里面的实现,线程其实就是进程,只是对进行了一些资源的共享,所以经常说线程是轻量级的进程) 

关于ps 命令, -p 表示进程号, -T表示列出子线程。所以上面设置线程名称,更多的时用来调试多线程程序的时候方便调试的,毕竟在程序里面直接用线程pid就可以唯一确定线程的身份了,但是没有名称看的直接,比如没有设置名称的线程:

看一下man手册里面详细的关于PR_SET_NAME的介绍

名称长度不能超过 16bytes(包含 结束符号'\0'),也可以通过库函数 pthread_setname_np来调用,线程的这个属性,可以通过

/proc文件系统来查看,即/proc/self/task/[tid]/comm

 

====20191011补充=================

创建之前设置属性和创建好后修改属性,注意  sched_setscheduler 的第一个参数是 pid_t ,非pthread_t

pthread_t 和pid_t, 是两个不同的标识符,分别可以通过 pthread_self()  和getpid()来获取当前运行线程的相应标识符。所以上面所说线程运行起来后再动态修改优先级,这个修改放在线程体里面调用即可,通过getpid()来获取pid_t. (还没有深入了解关于具体的 pthread_t 和pid_t的区别,看到一种说法是 pthraed_t用来区分表示同一个进程之间的线程,而pid_t才是系统中认为的线程唯一标识符,没有找到关于这两个是否可以相互转换的说法,估计涉及到具体的操作系统)

demo1:创建之前就设置好优先级

//创建线程之前就定好调度优先级 
//需要相关函数头文件 #include<errno.h> #include <sched.h>
pthread_t pliveThread;

  pthread_attr_t  pthread_pro;
  pthread_attr_init(&pthread_pro);

  pthread_attr_setschedpolicy(&pthread_pro, SCHED_FIFO);
  struct sched_param s_parm;
  s_parm.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&pthread_pro, &s_parm);

  int ret = 0;
  if(0 != (ret = pthread_create(&pliveThread,&pthread_pro,live555_main,url))){
       printf("craete thread erro: %s",strerror( ret));
        return -1;
  }

demo2:创建好之后,在线程体里面自己提升优先级

    //在待提升优先级的线程体中运行
    int ret =0;
    pid_t pid =getpid();

    int curschdu = sched_getscheduler(pid);
    if(curschdu <0 )
    {
        printf( "getschedu err %s\n",strerror( errno));
    }
    printf("schedu befor %d\n",curschdu);


    struct sched_param s_parm;
    s_parm.sched_priority = sched_get_priority_max(SCHED_FIFO);
    printf("schedu max %d min %d\n",sched_get_priority_max(SCHED_FIFO),sched_get_priority_min(SCHED_FIFO));
    
    ret = sched_setscheduler(pid, SCHED_FIFO, &s_parm);
    if(ret <0)
    {
       printf( "setschedu err %s\n",strerror( errno));
    }

    curschdu = sched_getscheduler(pid);
    

    printf("schedu after %d\n",curschdu);

在android 第三方app的jni 调用中,创建的线程想提高优先级,结果返回 erro: Operation not permitted,没有权限。。。

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值