10、操作系统——线程的相关属性(2)
目录
一、线程调度
1、三种调度算法
(1)SCHED_FIFO(先进先出的排队方式调度)
(2)SCHED_RR实时调度策略,时间片轮转
(3)SCHED_OTHER 分时调度策略(linux默认)
2、pthread_attr_setschedpolicy/pthread_attr_getschedpolicy(获取、设置线程的调度策略)
二、线程栈合警戒区
1、pthread_attr_setstacksize/pthread_attr_getstacksize(获取、设置线程栈大小、警戒区大小)
2、各个线程相对独立的栈
三、线程退出
1、pthread_exit(线程自己退出)编辑
2、pthread_cancel(线程取消)(请线程退出)
3、创建一个线程,在1s后发送取消线程的请求,线程终止
一、线程调度
1、三种调度算法
(1)SCHED_FIFO(先进先出的排队方式调度)
静态优先级设置为1-99,则线程如果处于就绪态,就能立即抢占静态优先级为0的普通线程。
a、就绪态时,放入优先级队列的队尾位置
b、被更高优先级的线程抢占之后,会被放入优先级队列的队头位置,当所有优先级比他高的线程不再运行后,就恢复运行
c、调用sched_yield()后,会被在优先级队列的队尾位置
总结:该线程会一直运行直到发送I/O请求,或者被更高优先级线程抢占,或者调用sched_yield()主动让出CPU
(2)SCHED_RR实时调度策略,时间片轮转
与SCHED_FIFO类似,区别在于设置了时间片,当时间片耗光时,会被在优先级队列的队尾位置,可以用sched_rr_get_interval( )来获得时间片的具体数值。
(3)SCHED_OTHER 分时调度策略(linux默认)
静态优先级必须设置为0
处于 0 优先级别的这些线程按照所谓的动态优先级被调度,而动态优先级起始于线程的 nice 值,且每当一个线程已处于就绪 态但被调度器调度无视时,其动态优先级会自动增加一个单位,这样能保证这些线程竞争 CPU 的公平性。
2、pthread_attr_setschedpolicy/pthread_attr_getschedpolicy(获取、设置线程的调度策略)
二、线程栈合警戒区
1、pthread_attr_setstacksize/pthread_attr_getstacksize(获取、设置线程栈大小、警戒区大小)
2、各个线程相对独立的栈
线程的栈可能溢出,需要增大栈空间,因为有警戒区,故不需要这么做,警戒区是没有任何访问权限的内存,用来保护相邻的两条线程的栈空间不被彼此践踏。
三、线程退出
1、pthread_exit(线程自己退出)
2、pthread_cancel(线程取消)(请线程退出)
某个时刻不能等某个线程“自然死亡”(例如在while(1)中),需要令其马上结束,可以给线程发送一个取消请求,让其中断执行退出。
而当线程收到一个取消请求时,他将会如何表现取决于两个东西:
一是当前的取消状态:
PTHREAD_CANCEL_ENABLE 使能 (允许取消。默认值) PTHREAD_CANCEL_DISABLE 失能 (不允许取消)
二是当前的取消类型:
延时响应 等待线程遇到取消点时响应取消的请求
立即响应
3、创建一个线程,在1s后发送取消线程的请求,线程终止
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>void * func (void * arg)
{int * p = calloc(1,4);while(1){printf("这里是func线程,线程ID :%ld \\n" , pthread_self() );sleep(1);}*p = 1024 ;// 退出本线程并设置返回值的地址(返回了num 的地址)pthread_exit((void *)p); //返回的内存地址应该时一个堆空间
}int main(int argc, char const *argv[])
{// 创建线程pthread_t t_id = -1 ;pthread_create( &t_id , //新线程ID号NULL , // 线程属性, NULL 默认属性func, // 线程需要执行的例程(新线程需要执行的任务《函数》) NULL ); // 线程的参数printf("t_id : %ld\\n" , t_id) ;printf("这里是主函数,线程ID :%ld \\n" , pthread_self() );int * retval ;int ret_val = 0 ;sleep(1);pthread_cancel( t_id );// 阻塞等待接合线程printf("等待 function 线程退出:\\n");if( ret_val = pthread_join( t_id , (void*)&retval)){fprintf(stderr , "接合失败:%s\\n" , strerror(ret_val));}printf("结合线程成功, 退出值为:%d\\n" , *retval);// 尝试接合线程 (非阻塞)// int ret_val = 0 ;// if( ret_val = pthread_tryjoin_np( t_id , (void*)&retval))// {// fprintf(stderr , "接合失败:%s\\n" , strerror(ret_val));// }return 0;
}
上述例子可以取消线程,但是没办法结合线程的退出值