【linux系统编程学习笔记】第九节:线程的属性设置—线程优先级(pthread_attr_setinheritsched调度策,pthread_attr_setschedparam设置静态优先级)

2023-11-10

 

线程优先级属性

线程优先级属性

pthread_attr_setinheritsched  设置线程是否继承父线程调度策略

pthread_attr_setschedpolicy  设置线程的调度策略

pthread_attr_setschedparam  设置静态优先级

获取静态优先级的最小值与最大值的函数

例程:测试分离属性以及栈大小

例程:测试优先级


线程优先级属性

  • 在任务的概念当中由于运行的需求,我们常常需要给任务一定分类,在系统里面就诞生出来所谓线程优先级
  • 实时线程

        单位时间相应能力强,里面拥有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_setinheritsched  设置线程是否继承父线程调度策略

#include <pthread.h> 

int pthread_attr_setinheritsched(pthread_attr_t *attr,int inheritsched);

函数功能

  • 设置线程是否继承父线程调度策略

参数:

  • attr:线程属性结构体地址
  • inheritsched:是否继承父线程的调度策略
    1. PTHREAD_EXPLICIT_SCHED:不继承,只有不继承父线程的调度策略才可以设置线程的调度策略
    2. PTHREAD_INHERIT_SCHED:继承父进程的调度策略

返回值:

  • 成功的情况下,返回值为0,失败返回非0值,errno不会被设置

pthread_attr_setschedpolicy  设置线程的调度策略

#include <pthread.h> 

int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);

函数功能

  • 设置线程的调度策略属性

参数:

  • attr:线程属性结构体地址
  • policy:调度策略
    • SCHED_FIFO:抢占式调度,同一优先级中,一旦运行到设置了这个参数的线程CPU将会一直被该线程所占领,不会分配资源给其他实时线程,会分配一点资源给非实时线程
    • SCHED_RR:轮询式调度,同一优先级总,遇到这个设置的线程,将会给其运行一段时间后,又继续给下一个人运行(相当于大家平均运行),会分配一点资源给非实时线程上面的两种是针对静态优先级1-99的实时线程才能设置的。
    • SCHED_OTHER:其他普通的调度策略,仅能设置与0静态优先级,也就是非实时线程,让这条线程成为一个由系统去自动根据动态优先级分配资源的任务。

返回值:

  • 成功的情况下,返回值为0,失败返回非0值,errno不会被设置

pthread_attr_setschedparam  设置静态优先级

#include <pthread.h> 

int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);

函数功能

  • 设置静态优先级

参数:

  • attr:线程属性结构体地址
  • param:优先级结构体,里面只有元素sched_priority,用来登记线程的静态优先级的值。

struct sched_param {     
    int sched_priority;     /* Scheduling priority */ 
}

返回值:

  • 成功的情况下,返回值为0,失败返回非0值,errno不会被设置

获取静态优先级的最小值与最大值的函数

获取最小值:

  • sched_get_priority_min(SCHED_FIFO);

获取最大值:

  • sched_get_priority_max(SCHED_FIFO);

例程:测试分离属性以及栈大小

#define _GNU_SOURCE		//注意这个宏定义不要漏了
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

void *new_thread(void *arg)
{
	int retval;
	pthread_attr_t myattr;
	size_t stack_size;

/*	
	//这个函数使用后,时灵时不灵,不建议使用
	retval = pthread_detach(pthread_self());
	if(retval != 0)
	{
		fprintf(stderr, "设置分离失败:%s\n", strerror(retval));
	}
*/	
	
	//获取本线程的属性存放到myattr这个变量中
	pthread_getattr_np(pthread_self(), &myattr);
	
	//获取线程栈的大小
	pthread_attr_getstacksize(&myattr, &stack_size);
	printf("stack size = %ld\n", stack_size);

	while(1)
	{
		sleep(1);
		printf("in thread\n");
	}

	return NULL;
}


int main(void)
{
	pthread_t tid;
	pthread_attr_t attr;

	//线程属性初始化
	pthread_attr_init(&attr);

	//设置线程的属性成为完全分离状态,再也不能用pthread_join来等待这条线程
	pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED);

	//设置线程的栈大小
	pthread_attr_setstacksize(&attr, 16*1024*1024);

	//取消行程,后面篇章详细描写
	pthread_create(&tid, &attr, new_thread, NULL);

	//线程属性销毁
	pthread_attr_destroy(&attr);

	//线程的属性成为完全分离状态,再也不能用pthread_join来等待这条线程
	//pthread_join(tid, NULL);//等待线程退出

	return 0;
}

例程:测试优先级

注意:只有在CPU只有一个内核才看得出效果

同时改变优先级还需要系统超级用户权限(没有超级用户权限,不给你执行,所以一般情况下很少会设置优先级)

虚拟机设置单核如下>>虚拟机设置=>硬件=>处理器     此处可以设置CPU数量和核数

 

#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和2资源分配很和谐

刚运行CPU就跑满了

以上俩结果中的线程3是非实时线程静态优先级0,不管怎么样系统都会给平民线程分配一点点资源,就一点点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【linux系统编程学习笔记】第九节:线程的属性设置—线程优先级(pthread_attr_setinheritsched调度策,pthread_attr_setschedparam设置静态优先级) 的相关文章

随机推荐