Chinaunix首页 | 论坛 | 博客
  • 博客访问: 989318
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-12-08 12:12:09

10.8 reliable signal terminology and semantics

正常的signal发出的过程是:一个signal 从他被生成,然后被delivery给接受进程,它会被接受进程的process table项加标记。如果该signal block了,就暂时不会delivery,这就叫做pending signal

Reliable signal就需要比unreliable signal提供更好的机制保证不造成signal lost

1.自动reinstall

2. 可以block signal,并且在unblock之后还可以将以前被blocksignal找出来去处理,如果更好的话,还可以支持同时queue多个pending signal.

 

Block signal的过程是这样的,首先设定你要block一个signal,然后当signal发生之后,kernel会给该process table加一些标记表明你接受到了一种signal。如果你对该signal的处理是default或者catch(当然你已经block了该signal),那么该signal就保持pending状态,直到你unblock了该signal,或者你将该signal的处理方式改为ignored。如果你是unblock了该signal,那么就会按照默认的或者你指定的方式去处理该signal,如果是改为ignored,那么当然该信号就被忽略了。

显然,block信号有个好处就是我们没有丢失以前丢失的信号,而且我们保证在某时间段内不受signal的打扰。

那么怎么样去block一个信号呢?怎么样查看block了多少个pending的信号呢?有函数:

Sigprocmask使用sigset_t类型可以设置对信号的block mask

Sigpending可以查看一个进程此时block了多少个pending的信号呢

 

关于signalqueue: 注意,block signal queueposix.1real-time extension才支持的,有的unix版本不支持queue,仅支持记录一个被blocksignalLinux里面的real time signal是采用了这个机制的 可以支持queuesignal,而linux的普通的standard signal是不支持queue的,即被blocksignal,只能记载一次发生。这个我做了测试,而所谓的real time signalsignal编号一般都大于32,位于3264之间,而且据说根据不同的libgc的实现不同,其具体的编号范围也不同,所以编码的时候据说最好要使用SIGRTMIN+n来使用,而不是直接用具体的信号值。Real time signal是没有名字的,因为他们一般用来由用户自定义其用途。具体的real time signallinux下的资料见:

下面是一段摘抄,讲述了sigqueue这个用来发送可以被queued real time signal的函数语普通kill函数的区别:

The differences between kill() and sigqueue() are:

  • sigqueue() can send extra information with the signal
  • sigqueue() fails with an error if the signal is a real-time signal which cannot be queued due to the signal buffer being full (it does not return an error code if it fails to queue a non-realtime signal however).
  • kill() guarentees that the signal will be received, though it may be merged with an already pending signal. Note that kill() allows sending a signal even when the process- or system-wide signal buffer is full, seeing as a signal without the extra data does not require a slot in the buffer.
  • kill() allows sending a signal to the current process group (pid = 0), all other processes (pid = -1), a process group id (pid = -pgid), or a specific process. sigqueue() only allows sending a signal to a specific process.

 

如下是我写的测试一般的signal是否支持被queue的代码:

#include

#include

#include

#include

#include

 

void nullhandler( int num )

{

       puts( "child received  signal" );

}

int main()

{

       setbuf( stdout, NULL );

       int pid = fork();

       if( pid == 0 )

       {

              //child

              puts("child started, we will block some signals");

              sigset_t maskset,oldset,oldset1;

              sigemptyset( &maskset );

              sigaddset( &maskset, SIGUSR1 );

              sigprocmask( SIG_BLOCK, &maskset, &oldset );

 

              struct sigaction act, oldact;

              act.sa_handler = nullhandler;

              sigemptyset( &act.sa_mask );

              if( sigaction( SIGUSR1, &act, &oldact ) < 0 )

              {

                     puts(" child install handler failed");

                     return -1;

              }

 

              puts("child went to sleep ...");

              sleep(5);

              puts("child wake up...");

 

              sigset_t pendset;

              if( sigpending( &pendset ) < 0  )

              {

                     puts("get pending signal failed");

                     return -1;

              }

              if( sigismember( &pendset, SIGUSR1 ) )

                     puts("SIGUSR1 is pending signal");

              else

                     puts("SIGUSR1 is pending signal");

 

              puts("child is unblocking signal");

              if( sigprocmask(SIG_UNBLOCK, &maskset, &oldset1 ) < 0 )

                     puts("unblock signal failed");

              else

                     puts("unblock signal success");

              puts("child  is quiting");

              exit(0);

       }

       sleep(1);

       puts( " father send  SIGUSR1 once" );

       int ret = kill( pid, SIGUSR1 );

       puts( " father send  SIGUSR1 twice" );

       ret = kill( pid, SIGUSR1 );

       waitpid( pid, 0, 0);

       puts("father is quiting");

       return 0;

 

}

如下使测试结果:

shaoting@desktopbj-LabSD:/home/shaoting/mytest> ./a.out

child started, we will block some signals

child went to sleep ...

father send  SIGUSR1 once

father send  SIGUSR1 twice

child wake up...

SIGUSR1 is pending signal

child is unblocking signal

child received  signal

unblock signal success

child  is quiting

father is quiting

可见父亲发送了2SIGUSR信号,儿子将其block,但当unblock之后,只作出一个响应,即只记录了一个信号。

阅读(752) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~