TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE

TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE

TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE 的区别
TASK_INTERRUPTIBLE是可以被信号和wake_up()唤醒的,当信号到来时,进程会被设置为可运行。
而TASK_UNINTERRUPTIBLE只能被wake_up()唤醒。

信号本质

信号是在软件层次上对中断机制的一种模拟,软中断

信号来源

信号事件的发生有两个来源:

硬件来源:(比如我们按下了键盘或者其它硬件故障);

软件来源:最常用发送信号的系统函数是kill, raise, alarm和setitimer以及sigqueue函数,软件来源还包括一些非法运算等操作。

区分是什么原因唤醒进程,用signal_pending( current );

检查当前进程是否有信号处理,返回不为0表示有信号需要处理。-ERESTARTSYS 表示信号函数处理完毕后重新执行信号函数前的某个系统调用。也就是说,如果信号函数前有发生系统调用,在调度用户信号函数之前,内核会检查系统调用的返回 值,看看是不是因为这个信号而中断了系统调用.如果返回值-ERESTARTSYS,并且当前调度的信号具备-ERESTARTSYS属性,系统就会在用 户信号函数返回之后再执行该系统调用。

 实例:

186 static int inet_csk_wait_for_connect(struct sock *sk, long timeo)                                          
187 {                                                                                                          
188     struct inet_connection_sock *icsk = inet_csk(sk);                                                      
189     DEFINE_WAIT(wait);                                                                                     
190     int err;                                                                                               
191                                                                                                            
192     /*                                                                                                     
193      * True wake-one mechanism for incoming connections: only                                              
194      * one process gets woken up, not the 'whole herd'.                                                    
195      * Since we do not 'race & poll' for established sockets                                               
196      * anymore, the common case will execute the loop only once.                                           
197      *                                                                                                     
198      * Subtle issue: "add_wait_queue_exclusive()" will be added                                            
199      * after any current non-exclusive waiters, and we know that                                           
200      * it will always _stay_ after any new non-exclusive waiters                                           
201      * because all non-exclusive waiters are added at the                                                  
202      * beginning of the wait-queue. As such, it's ok to "drop"                                             
203      * our exclusiveness temporarily when we get woken up without                                          
204      * having to remove and re-insert us on the wait queue.                                                
205      */                                                                                                    
206     for (;;) {                                                                                             
207         prepare_to_wait_exclusive(sk->sk_sleep, &wait,                                                     
208                       TASK_INTERRUPTIBLE);                                                                 
209         release_sock(sk);                                                                                  
210         if (reqsk_queue_empty(&icsk->icsk_accept_queue))                                                   
211             timeo = schedule_timeout(timeo);                                                               
212         lock_sock(sk);                                                                                     
213         err = 0;                                                                                           
214         if (!reqsk_queue_empty(&icsk->icsk_accept_queue))                                                  
215             break;                                                                                         
216         err = -EINVAL;                                                                                     
217         if (sk->sk_state != TCP_LISTEN)                                                                    
218             break;                                                                                         
219         err = sock_intr_errno(timeo);                                                                      
220         if (signal_pending(current))                                                                       
221             break;                                                                                         
222         err = -EAGAIN;                                                                                     
223         if (!timeo)                                                                                        
224             break;                                                                                         
225     }                                                                                                      
226     finish_wait(sk->sk_sleep, &wait);                                                                      
227     return err;                                                                                            
228 } 
原文地址:https://www.cnblogs.com/jingzhishen/p/4873894.html