linux 线程 继承策略,Linux编程---线程

7.线程调度

1)线程调度范围

POSIX定义了两种调度模式:进程调度模式和系统调度模式.前者的竞争范围为进程内,后者则为进程间.感觉就是所谓的用户级线程和内核级线程.但Linux只有系统调度模式.在APUE也没有相关的内容.以后做了实验再来补一篇博客吧.

PTHREAD_SCOPE_PROCESS表示进程调度模式.

PTHREAD_SCOPE_SYSTEM 表示系统调度模式.

这么分,主要是为了区分线程竞争的对手.前者只在进程内区分.后者则和其他进程一起竞争.

主要在phread_attr_t类型变量中设置后,传递给pthread_create.

2)线程调度策略与优先级

SCHED_FIFO 基于优先级的先进先出调度策略.不同优先级不同队列.这种策略可能让高优先级线程独占系统.

SCHED_RR 循环调度.也就是时间片轮转.也有FIFO的优先级队列.虽然是时间片轮转,但仍有可能独占系统.

SCHED_OTHER 这种一般类UNIX系统默认为对进城的系统分时调度策略.这随系统不同,策略也不同,所以不可移植.当然,也可以采用自己定义的策略.

int sched_get_priority_max(int policy);

int sched_get_priority_min(int policy);

两个函数可以用来得到优先级的最大值和最小值.都是个int类型.

参数的意思就是上面所说的策略.把宏定义填进去就可以了.

POSIX没有对SCHED_OTHER定义优先级范围,但自定义的范围一定要在min到max的返回值之间.

3)线程调度属性

--竞争范围属性

PTHREAD_SCOPE_PROCESS和PTHREAD_SCOPE_SYSTEM

个人感觉Linux中应该没有PROCESS调度才对...因为Linux的线程和进程都是用的一种数据结构而且Linux实现的是轻量级线程.....这样应该就只有一种调度方式了吧....我在网上问了也没人回答....

--继承属性

这个主要是指明新创建的线程如何获得他的调度策略和相连的调度参数.

PTHREAD_INHERIT_SCHED和PTHREAD_EXPLICIT_SCHED

前者表示继承,后者则从后面两个属性中设置.

--调度策略属性

SCHED_FIFO

SCHED_RR

SCHED_OTHER

--调度参数属性(包含优先级)

这是一个对程序员不透明的结构体.具体的可以查看sched.h.但是至少包含一个sched_priority的成员.对于SCHED_FIFO和SCHED_RR来说sched_priority是唯一的调度参数.

有下面这么些函数来获取和设置

int pthread_attr_getscope(const pthread_attr_t *restrict attr,int *restrict contentionscope);

int pthread_attr_setscope(pthread_attr_t *attr,int contentionscope);

int pthread_attr_getinheritsched(pthread_attr_t *attr,int * inherit);

int pthread_attr_setinheritsched(pthread_attr_t *attr,int *inherit);

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

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

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

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

scope范围,inherit继承,policy策略,param参数(优先级)

这些函数成功都返回0.一般多数系统都不允许用户应用随便设置线程的调度属性,只有特权用户才行.并且一定要创建之前设置PTHREAD_EXPLICIT_SCHED属性.

4)动态改变调度策略和优先级

int pthread_getschedparam(pthread_t thread ,int *restrict policy,struct sched_param *restrict param );

int pthread_setschedparam(pthread_t thread ,int policy,const struct sched_param *param );

int pthread_setschedprio(pthread_t thread ,int prio);

这个感觉没什么好说的.前两个是改变策略和参数.第三个直接就是改变优先级.

当策略和优先级改变时,线程从运行状态切换至就绪状态,并放置到新的优先级队列中.很多系统对于SCHED_FIFO来说,一般不让随便设置成最高优先级.

------------------补充的分割线-----------------

我看上面说了有三种调度方式.前两种和上面一致.最后一种叫分时.应该就是SCHED_OTHER吧.感觉翻译有点问题.具体以后看源码再专门写一篇Linux调度策略的文章吧.

这里的优先级在Linux下是0~139.

其中前0~99是实时优先级.100~139则是非实时优先级.

并且Linux的时钟是1000HZ的.所以最小时间片为1ms.

对于非实时的一般就运行的时间片就比较少了.100级的时间片为800ms,而139级只有5ms.

这里的Linux内核版本为2.6.

----------------------------------------------------

8.线程与信号

在多线程中,信号对每个线程都是共享的.对于每一种信号,所有线程所对应的动作都是相同的.而且所有线程可能同时执行这个信号.即POSIX不支持线程范围的信号动作.

为了保证信号的一致性,统一建立所有信号的信号动作,最好用一个线程来完成其信号的设置和改变.一定不要在可能被多线程调用的函数中改变信号的动作,因为你无法保证只有一个线程调用其函数.

只要信号的动作使得线程终止,暂停或者继续,就同样会使得整个进程终止,暂停或者继续.也就是说发送SIGKILL,SIGSTOP,SIGCONT这三种信号,都是针对进程而言的.要终止线程,可以用cancel来取消线程.这样就避免了整个进程因为线程的原因产生不可预测的行为.

多线程中,信号也分为同步和异步.同步信号由线程自己来处理.对于异步就复杂了.

异步信号如果是发送给某个线程的,那么只有这个线程能收到信号.

如果是发给进程的.那么进程中所有线程都有可能收到,但是只有一个未屏蔽该信号的线程来处理.具体由哪个来执行也不确定.如果想要一个线程来接受某个异步信号,那么所有的线程都该屏蔽这个信号.

当一个信号被多个线程共享,那么这个信号句柄就得是可重入的.因为接收到信号可能让多个线程执行这个句柄.对于PISIX指明所有函数一定要是可重入的,但是Pthread则不是所有函数都可以重入.

当多线程共享数据时,不可避免的要用线程同步.如果想要用线程同步函数或者不可重入函数,那么最好不要用sigaction来建立句柄.可以使用sigwait()函数来同步异步信号.

1)信号屏蔽

正如我上面说所,每个线程都是有自己的屏蔽信号的.

int pthread_sigmask(int how,const sigset_t *restrict set,sigset_t *restrict oset);

这个函数与sigprocmask类似,但是这个函数专门用于检测或改变(或者两个都有)调用线程的私有信号屏蔽.

how参数有以下几种模式:

SIG_BLOCK: 即将set所指信号集的信号添加到当前信号屏蔽中

SIG_UNBLOCK: 将set所指信号集的信号从当前信号屏蔽中去除.

SIG_SETMASK: 将set所指信号集的信号设置为当前信号屏蔽中去.

一个线程的屏蔽信号,会从创建它的线程中继承.

当信号被屏蔽的时候,如果有此信号来则会一直悬挂到被解除屏蔽或者调用了sigwait或者线程结束.

2)向线程发送信号

int pthread_kill(pthread_t thread,int sig);

向指定线程,发送一个sig信号.当sig为0时,和kill()类似,只检查指定的线程是否存在.

3)等待信号

int sigwait(const sigset_t *restrict set,int *restrict sig);

这个函数直接从set信号集中等待信号,并且一直阻塞直到有信号来,然后直接返回,不需要设置句柄.当集合中的多个信号同时悬挂时,那么先返回信号数比较低的.

如果一直没来信号集中的信号,那么会无限期的阻塞下去.这时候就可以考虑用sigtimedwait函数了.这样就可以设置一个超时时间了.

注意用的时候还是得把其他线程中的set里的信号屏蔽掉.否则其他线程就有可能接受这个信号.

利用这个函数可以方便的实现让一个特定的线程同步等待发送给进程的异步信号.简单来说就是异步信号处理线程.

一种新的时间通知方法:SIGEV_THREAD0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值