linux c之sigsuspend 历程阻塞
当前位置:以往代写 > C/C++ 教程 >linux c之sigsuspend 历程阻塞
2019-06-13

linux c之sigsuspend 历程阻塞

linux c之sigsuspend 历程阻塞

副标题#e#

函数原型:

#include <signal.h>

int sigsuspend(const sigset_t *mask);

浸染:

用于在吸收到某个信号之前,姑且用mask替换历程的信号掩码,并暂停历程执行,直到收到信号为止。

The sigsuspend() function replaces the current signal mask of the calling thread with the set of signals pointed to by sigmask and then suspends the thread until delivery of a signal whose action is either to execute a signal-catching function or to terminate the process. This will not cause any other signals that may have been pending on the process to become pending on the thread.

If the action is to terminate the process then sigsuspend() will never return. If the action is to execute a signal-catching function, thensigsuspend() will return after the signal- catching function returns, with the signal mask restored to the set that existed prior to thesigsuspend() call.

It is not possible to block signals that cannot be ignored. This is enforced by the system without causing an error to be indicated.

也就是说,sigsuspend后,历程 就挂在哪里,期待着开放的信号的叫醒。系统在吸收到信号后,顿时就把此刻的信号集还原为本来的,然后调 用处理惩罚函数。

返回值:

sigsuspend返回后将规复挪用之前的的信号掩码。信号处理惩罚函数完成后,进 程将继承执行。该系统挪用始终返回-1,并将errno配置为EINTR.

Since sigsuspend() suspends process execution indefinitely, there is no successful completion return value. If a return occurs, -1 is returned and errno is set to indicate the error.

The sigsuspend() function will fail if:

[EINTR]

A signal is caught by the calling process and control is returned from the signal-catching function.

也就是说,sigsuspend后,历程就挂在哪里,期待着开放的信号的叫醒。 系统在接管到信号后,顿时就把此刻的信号集还原为本来的,然后挪用处理惩罚函数。

Stevens在《Unix环 境高级编程》一书中是如是答复的“If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend.”,由于sigsuspend是原子操纵,所以这句给人的感受就是先挪用signal handler先返回,然后 sigsuspend再返回。

int main(void) {  
   sigset_t   newmask, oldmask, zeromask;  
      
   if (signal(SIGINT, sig_int) == SIG_ERR)  
      err_sys("signal(SIGINT) error");  
      
   sigemptyset(&zeromask);  
      
   sigemptyset(&newmask);  
   sigaddset(&newmask, SIGINT);  
   /* block SIGINT and save current signal mask */
   if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)  
      err_sys("SIG_BLOCK error");  
      
   /* critical region of code */
   pr_mask("in critical region: ");  
      
   /* allow all signals and pause */
   if (sigsuspend(&zeromask) != -1)  
      err_sys("sigsuspend error");  
   pr_mask("after return from sigsuspend: ");  
      
   /* reset signal mask which unblocks SIGINT */
   if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)  
      err_sys("SIG_SETMASK error");  
      
   /* and continue processing ... */
   exit(0);  
}  
      
static void sig_int(int signo) {  
   pr_mask("\nin sig_int: ");  
   return;  
}

功效:

$a.out
in critical region: SIGINT  
^C  
in sig_int: SIGINT  
after return from sigsuspend: SIGINT


#p#副标题#e#

假如凭据sig_handler先返回,那么SIGINT是不应被打印出 来的,因为当时屏蔽字还没有规复,所有信号都是不阻塞的。那么是Stevens说错了么?虽然没有,只是 Stevens没有说请在sigsuspend的原子操纵中到底做了什么?

sigsuspend的整个原子操纵进程为:
(1) 配置新的mask阻塞当前历程;

(2) 收到信号,恢复兴先mask;

(3) 挪用该历程配置的信号 处理惩罚函数;

(4) 待信号处理惩罚函数返回后,sigsuspend返回。

大抵就是上面这个进程,噢,本来 signal handler是原子操纵的一部门,并且是在规复屏蔽字后执行的,所以上面的例子是没有问题的, Stevens说的也没错。由于Linux和Unix的千丝万缕的接洽,所以在两个平台上绝大部门的系统挪用的语义是一 致的。上面的sigsuspend的原子操纵也是从《深入领略Linux内核》一书中推断出来的。书中的描写如下:

/*The sigsuspend( ) system call puts the process in the TASK_INTERRUPTIBLE state, after 

having blocked the standard signals specified 
 by a bit mask array to which the mask parameter points. The process will wake up only when a 

nonignored, nonblocked signal is sent  
 to it. The corresponding sys_sigsuspend( ) service routine executes these statements: 
*/
      
mask &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));  
spin_lock_irq(¤t->sigmask_lock);  
saveset = current->blocked;  
siginitset(¤t->blocked, mask);  
recalc_sigpending(current);  
spin_unlock_irq(¤t->sigmask_lock);  
regs->eax = -EINTR;  
while (1) {  
    current->state = TASK_INTERRUPTIBLE;  
    schedule(  );  
    if (do_signal(regs, &saveset))  
        return -EINTR;  
}

int sigsuspend(const sigset_t *sigmask);

#p#分页标题#e#

此函数用于历程的挂起,sigmask指向一个信 号集。当此函数被挪用时,sigmask所指向的信号会合的信号将赋值给信号掩码。之后历程挂起。直到历程捕 捉到信号,并挪用处理惩罚函数返回时,函数sigsuspend返回。信号掩码规复为信号挪用前的值,同时将errno设 为EINTR。历程竣事信号可将其当即遏制。

01.#include <stdio.h>
02.#include <signal.h>
03.
04.void checkset();
05.void func();
06.void main()
07.{
08. sigset_tblockset,oldblockset,zeroset,pendmask;
09. printf("pid:%ld\n",(long)getpid());
10. signal(SIGINT,func);
11.
12. sigemptyset(&blockset);
13. sigemptyset(&zeroset);
14. sigaddset(&blockset,SIGINT);
15.
16. sigprocmask(SIG_SETMASK,&blockset,&oldblockset);
17. checkset();
18. sigpending(&pendmask);
19.
20. if(sigismember(&pendmask,SIGINT))
21. printf("SIGINTpending\n");
22.
23. if(sigsuspend(&zeroset)!= -1)
24. {
25. printf("sigsuspenderror\n");
26. exit(0);
27. }
28.
29. printf("afterreturn\n");
30. sigprocmask(SIG_SETMASK,&oldblockset,NULL);
31.
32. printf("SIGINTunblocked\n");
33.}
34.
35.void checkset()
36.{ sigset_tset;
37. printf("checksetstart:\n");
38. if(sigprocmask(0,NULL,&set)<0)
39. {
40. printf("checksetsigprocmask error!!\n");
41. exit(0);
42. }
43.
44. if(sigismember(&set,SIGINT))
45. printf("sigint\n");
46.
47. if(sigismember(&set,SIGTSTP))
48. printf("sigtstp\n");
49.
50. if(sigismember(&set,SIGTERM))
51. printf("sigterm\n");
52. printf("checksetend\n");
53.}
54.
55.void func()
56.{
57. printf("hellofunc\n");
58.}

linux c之sigsuspend 过程阻塞

    关键字:

在线提交作业