之前有人问我一个问题,如果做一个处理某种类型的事情的东西,让它长期运行不退出,应该怎么做?(这不就是任务队列处理器么)
不管三七二十一,为了装逼先忽悠一个版本上去:
while(true){
//do something
}
这样不就行了。
但是丢系统里面,看到CPU空转,浪费资源也是很蛋碎。改吧:
while(true){
if(empty(task_list)){
pause();
}else{
//do something;
}
}
又有问题了,你这不行啊,空队列之后,该如何唤醒进程呢?擦,这pause好像我也不熟悉,先去看两下。
哦,原来要注册信号处理函数才行。那继续改
void my_fun()
{
printf("this is fun!\n");
}
int main()
{
signal(SIGUSR1,my_fun);
while(true){
if(empty(task_list)){
pause();
}else{
//do something;
}
}
}
好像是可以了,只要有任务到来,叫任务接收进程发个SIGUSR1信号过来就行了。但是总觉得有点怪怪的,我只是想继续而已,连那个处理信号的函数好像没啥鸟用。(也许是我思路有问题)
然后又复习了下,信号处理的部分,好像我可以给这里改成使用STOP的方式
int main()
{
while(true){
if(empty(task_list)){
raise(SIGSTOP);
}else{
//do something;
}
}
}
任务到来就发SIGCONT继续。
但是还是觉得有问题,进程S状态和T状态对待信号到来的方式有所不同:
Linux进程状态:S (TASK_INTERRUPTIBLE),可中断的睡眠状态。
Linux进程状态:T (TASK_STOPPED or TASK_TRACED),暂停状态或跟踪状态。
S状态的时候,可以接受比较多的信号,从而更灵活的处理信号;
T状态下,除了SIGCONT,其他信号是滴水不进的(不允许用户进程通过signal系列的系统调用重新设置对应的信号处理函数。)
查看linux下的大多数进程,大部分都是S状态的,基本看不到T状态下的进程。平常我们Ctrl+Z就是发送STOP信号,暂停进程,这个pause也是暂停进程,他们都是把进程挂起放到外存中,除了对信号处理有分别之外,还有其他分别么?
所以目前得到的结论就是,这两种状态只是信号处理上有区别,根据进程三态模型看,本质上都是把进程挂起了。