struct sched_param结构体的运用以及线程属性简单记录

一、struct sched_param结构体

#include <sched.h>
#define sched_ss_low_priority   __ss_un.__ss.__ss_low_priority
#define sched_ss_max_repl       __ss_un.__ss.__ss_max_repl
#define sched_ss_repl_period    __ss_un.__ss.__ss_repl_period
#define sched_ss_init_budget    __ss_un.__ss.__ss_init_budget


struct timespec {
	time_t tv_sec; // seconds 秒
	long tv_nsec; // and nanoseconds纳秒
};

struct sched_param 
{ 
    int32_t  sched_priority; 
    int32_t  sched_curpriority; 
    union 
    { 
        int32_t  reserved[8]; 
        struct 
        {    
            int32_t  __ss_low_priority;  
            int32_t  __ss_max_repl;  
            struct timespec     __ss_repl_period;   
            struct timespec     __ss_init_budget;   
        }           __ss;   
    }           __ss_un;    
}

struct sched_param结构体的作用

描述调度参数的结构

获取调度参数函数

pthread_attr_getschedparam()
pthread_getschedparam()
sched_getparam()
SchedGet()

设置调度参数函数

pthread_attr_setschedparam()
pthread_setschedparam()
sched_setparam()
sched_setscheduler()
SchedSet()
ThreadCreate()

sched_param成员解释

sched_priority——当您设置调度参数时,请将此成员设置为您想要使用的优先级
sched_curpriority——当您获得调度参数时,该成员被设置为线程或进程当前运行的优先级
sched_ss_low_priority——正在执行的后台或低优先级线程
sched_ss_max_repl——补给计划的最大次数,通常是由于阻塞操作
sched_ss_repl_period——该时间用作线程准备就绪时间的偏移量。
sched_ss_init_budget——应该用于线程执行预算的时间

二、线程属性pthread_attr_t简介

线程具有属性,用pthread_attr_t表示,在对该结构进行处理之前必须进行初始化,在使用后需要对其去除初始化。
调用pthread_attr_init之后,pthread_t结构所包含的内容就是操作系统实现支持的线程所有属性的默认值。
如果要去除对pthread_attr_t结构的初始化,可以调用pthread_attr_destroy函数。如果pthread_attr_init实现时为属性对象分配了动态内存空间,pthread_attr_destroy还会用无效的值初始化属性对象,因此如果经pthread_attr_destroy去除初始化之后的pthread_attr_t结构被pthread_create函数调用,将会导致其返回错误。

pthread_attr_t 结构体

typedef struct
{
       int                       detachstate;   // 线程的分离状态
       int                       schedpolicy;   // 线程调度策略
       structsched_param         schedparam;    // 线程的调度参数
       int                       inheritsched;  // 线程的继承性
       int                       scope;         // 线程的作用域
       size_t                    guardsize;     // 线程栈末尾的警戒缓冲区大小
       int                       stackaddr_set; // 线程的栈设置
       void*                     stackaddr;     // 线程栈的位置
       size_t                    stacksize;     // 线程栈的大小
} pthread_attr_t;

在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置。

线程优先级属性

在任务的概念当中由于运行的需求,我们常常需要给任务一定分类,在系统里面就诞生出来所谓线程优先级
实时线程
单位时间相应能力强,里面拥有1-99个静态优先级,数字越大,优先级越高(所谓的优先级指的经过特殊的处理,我们可以让某个人物能够在系统中被更优先的响应,从而分出的从高到低的级别),需要有管理员权限才能启动实时线程

特点:
1.实时线程分99个静态优先级,数字越大,优先级越高
2.高优先级的实时线程会完全抢占低优先级实时线程的资源(指令运行资源)
3.在实时线程当中支持抢占调度策略跟轮询调度策略
4.拥有抢占所有实时线程运行资源的能力
5.必须拥有超级用户权限才能够运行

非实时线程
单位时间中,并没有过分的去在乎响应能力的一个线程,里面只有一个静态优先级0,也就是在非实时线程中,它是没有静态优先级的概念的,他的所有的执行过程都是由系统自动分配的

特点:
1.非实时线程只有一个静态优先级,所以同时非实时线程的任务无法抢占他人的资源
2.在非实时线程当中只支持其他调度策略(自动适配的,系统分配的调度策略)
3.不拥有抢占所有运行资源的能力
4.支持动态优先级系统自适应,从-20到19的动态优先级(nice值)

线程中支持三种调度策略:
1.抢占式调度策略,在同一静态优先级的情况下,抢占调度策略的线程一旦运行到便会一直抢占CPU资源,而其他同一优先级的只能一直等到这个抢占式调度策略的线程退出才能被运行到(非实时线程会有一小部分资源分配到)
2. 轮询式调度策略,在同一静态优先级的情况下,大家一起合理瓜分时间片,不会一直抢占CPU资源(非实时线程会有一小部分资源分配到)
3.其他普通式调度策略,只能作用于非实时线程,由系统自动分配时间片,并且根据运行状态自动分配动态优先级 注意点:
抢占式调度策略跟轮询式调度策略只能在实时线程中被设置,也就是静态优先级1-99的区域内设置,普通非实时线程不能设置

pthread_attr_t 结构体的成员解释

detachstate,表示新线程是否与进程中其他线程脱离同步, 如果设置为PTHREAD_CREATE_DETACHED 则新线程不能用pthread_join()来同步,且在退出时自行释放所占用的资源。缺省为PTHREAD_CREATE_JOINABLE状态。这个属性也可以在线程创建并运行以后用pthread_detach()来设置,而一旦设置为PTHREAD_CREATE_DETACH状态(不论是创建时设置还是运行时设置)则不能再恢复到PTHREAD_CREATE_JOINABLE状态。
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);

schedpolicy,表示新线程的调度策略,主要包括SCHED_OTHER(正常、非实时)、SCHED_RR(实时、轮转法)和SCHED_FIFO(实时、抢占式,先入先出)三种,缺省为SCHED_OTHER,后两种调度策略仅对超级用户有效。运行时可以用过pthread_setschedparam()来改变。

schedparam,线程的调度参数,设置静态优先级,注意struct sched_param的结构体的填充,通过结构体中的sched_priority成员设置pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)

inheritsched,有两种值可供选择:PTHREAD_EXPLICIT_SCHED(不继承)和PTHREAD_INHERIT_SCHED(继承),前者表示新线程使用显式指定调度策略和调度参数(即attr中的值),而后者表示继承调用者线程的值。缺省为PTHREAD_EXPLICIT_SCHED。
只有不继承父线程的调度策略才可以设置线程的调度策略
pthread_attr_setinheritsched(pthread_attr_t *attr,int inheritsched);

scope,表示线程间竞争CPU的范围,也就是说线程优先级的有效范围。POSIX的标准中定义了两个值:PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示与系统中所有线程一起竞争CPU时间,后者表示仅与同进程中的线程竞争CPU。目前LinuxThreads仅实现了PTHREAD_SCOPE_SYSTEM一值。
pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);

为了设置这些属性,POSIX定义了一系列属性设置函数,包括pthread_attr_init()、pthread_attr_destroy()和与各个属性相关的pthread_attr_getXXX/pthread_attr_setXXX函数。

demo1.c

#include <stdlib.h>   
#include <stdio.h>   
#include <errno.h>   
#include <pthread.h>   
static void pthread_func_1 (void);   
static void pthread_func_2 (void);   

int main (int argc, char** argv)   
{   
  pthread_t pt_1 = 0;   
  pthread_t pt_2 = 0;   
  pthread_attr_t atrr = {0};   
  int ret = 0;   

/*初始化属性线程属性*/
  pthread_attr_init (&attr);   
  pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);   
  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);   

  ret = pthread_create (&pt_1, &attr, pthread_func_1, NULL);   
  if (ret != 0)   
  {   
    perror ("pthread_1_create");   
  }   

  ret = pthread_create (&pt_2, NULL, pthread_func_2, NULL);   
  if (ret != 0)   
  {   
    perror ("pthread_2_create");   
  }   

  pthread_join (pt_2, NULL);   

  return 0;   
}   

static void pthread_func_1 (void)   
{   
  int i = 0;   

  for (; i < 6; i++)   
  {    
    printf ("This is pthread_1.\n");   

    if (i == 2)   
    {   
      pthread_exit (0);   
    }   
  }   

  return;   
}   

static void pthread_func_2 (void)   
{   
  int i = 0;   

  for (; i < 3; i ++)   
  {   
    printf ("This is pthread_2.\n");   
  }   
  return;   
}  

线程一的线程函数一结束就自动释放资源,线程二就得等到pthread_join来释放系统资源

测试优先级demo2.c

#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sched.h>
 
 
void *start_routine(void *arg)
{
	int i, j;
 
	while(1)
	{
		fprintf(stderr, "%c ", *(char *)arg);
		for(i=0; i<100000; i++)
			for(j=0; j<1000; j++);
	}
 
	pthread_exit(NULL);
}
 
 
int main(void)
{
 
	pthread_t tid1, tid2, tid3;
	pthread_attr_t attr1, attr2;
	struct sched_param param1, param2;
 
	/* 线程属性变量的初始化 */
	pthread_attr_init(&attr1);
	pthread_attr_init(&attr2);
 
 
	/* 设置线程是否继承创建者的调度策略 PTHREAD_EXPLICIT_SCHED:不继承才能设置线程的调度策略*/
	errno = pthread_attr_setinheritsched(&attr1, PTHREAD_EXPLICIT_SCHED);
	if(errno != 0)
	{
		perror("setinherit failed\n");
		return -1;
	}
 
	/* 设置线程是否继承创建者的调度策略 PTHREAD_EXPLICIT_SCHED:不继承才能设置线程的调度策略*/
	errno = pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED);
	if(errno != 0)
	{
		perror("setinherit failed\n");
		return -1;
	}
 
	/* 设置线程的调度策略:SCHED_FIFO:抢占性调度; SCHED_RR:轮寻式调度;SCHED_OTHER:非实时线程调度策略*/
	errno = pthread_attr_setschedpolicy(&attr1, SCHED_RR);
	if(errno != 0)
	{
		perror("setpolicy failed\n");
		return -1;
	}
 
	errno = pthread_attr_setschedpolicy(&attr2, SCHED_RR);
	if(errno != 0)
	{
		perror("setpolicy failed\n");
		return -1;
	}
 
	//设置优先级的级别
	param1.sched_priority = 1;
	param2.sched_priority = 1;
	
	//查看抢占性调度策略的最小跟最大静态优先级的值是多少
	printf("min=%d, max=%d\n", sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO));
 
 
	/* 设置线程静态优先级 */
	errno = pthread_attr_setschedparam(&attr1, &param1);
	if(errno != 0)
	{
		perror("setparam failed\n");
		return -1;
	}
 
	errno = pthread_attr_setschedparam(&attr2, &param2);
	if(errno != 0)
	{
		perror("setparam failed\n");
		return -1;
	}
 
/* 创建三个测试线程 */
    /* 线程1,优先级1 */
	errno = pthread_create(&tid1, &attr1, start_routine, (void *)"1");
	if(errno != 0)
	{
		perror("create thread 1 failed\n");
		return -1;
	}
    /* 线程2,优先级1 */
	errno = pthread_create(&tid2, &attr2, start_routine, (void *)"2");
	if(errno != 0)
	{
		perror("create thread 2 failed\n");
		return -1;
	}
    /* 线程3,非实时线程,静态优先级0 */
	errno = pthread_create(&tid3, NULL, start_routine, (void *)"3");
	if(errno != 0)
	{
		perror("create thread 3 failed\n");
		return -1;
	}
 
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	pthread_join(tid3, NULL);
 
	pthread_attr_destroy(&attr1);
	pthread_attr_destroy(&attr2);
 
	return 0;
}

设置抢占性调度结果: SCHED_FIFO
在抢占性调度下,线程2一点资源都没有分配到
设置轮寻式调度结果: SCHED_RR
在轮寻式调度下,线程1和线程资源分配很和谐
线程3是非实时线程静态优先级0,不管怎么样系统都会给平民线程分配一点点资源

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值