一、产生信号

代码:

  1#include<stdio.h>
  2#include<unistd.h>
  3int main()
  4 {
 5    printf("%d\n",getpid());
 6     while(1)
 7     {
 8     }
 9     return 0;
 10 }


(1)终端输入

 [admin@localhost SIGNAL]$ ./Signal
^C

[admin@localhost SIGNAL]$ ./Signal

^\退出 (core dumped)



(2)调用系统函数

#include<signal.h>
int kill(pid_t pid,int signo);
int raise(intsigno);
<1>
[admin@localhost ~]$ ps aux |grep Signal
admin    4902  0.0  0.0  1868   332 pts/0    S+  05:13   0:00 ./Signal
admin    4904  0.0  0.0  5980   736 pts/1    S+  05:13   0:00 grep Signal
[admin@localhost ~]$ kill -SIGSEGV 4902
<2>
[root@www SIGNAL]# ./Signal &
[1] 2538
[root@www SIGNAL]# 2538
kill -11 2538
[root@www SIGNAL]#
[1]+ 段错误               (core dumped)./Signal
<3>raise函数
 
  1#include<stdio.h>
  2#include<unistd.h>
  3int main()
  4 {
 5    printf("%d\n",getpid());
 6     while(1)
 7     {
 8         sleep(5);
 9         raise(2);
 10     }
 11    return 0;
 12 }

<4>abort函数


(3)软件条件实现

unsigned int alarm(unsigned int seconds);

二、阻塞信号


信号递达、信号未决、信号阻塞


每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理

动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。


Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。


<1>信号集操作函数


#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);


<2>. sigprocmask

调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

返回值:若成功则为0,若出错则为-1



<3> sigpending

#include <signal.h>
int sigpending(sigset_t *set);

sigpending读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。



代码:

  1 #include<stdio.h>
  2 #include<signal.h>
  3 void Printpending(sigset_t *s)
  4 {
  5     int i=0;
  6     for(;i<32;i++)
  7     {
  8         if(sigismember(s,i))
  9         {
 10          printf("1");
 11         }
 12         else
 13         {
 14             printf("0");
 15         }
 16 
 17     }
 18     printf("\n");
 19 }
 20 int main()
 21 {
 22     sigset_t s,p;
 23     sigemptyset(&s);
 22     sigset_t s,p;
 23     sigemptyset(&s);
 24     sigemptyset(&p);
 25     sigaddset(&s,2);
 26     sigprocmask(SIG_BLOCK,&s,NULL);
 27     while(1)
 28     {
 29         sigpending(&p);
 30         Printpending(&p);
 31         fflush(stdout);
 32         sleep(1);
 33     }
 34 
 35     return 0;
 36 }


结果:

[admin@localhost SIGNAL]$ ./signal_group 
10000000000000000000000000000000
10000000000000000000000000000000
10000000000000000000000000000000
10000000000000000000000000000000
^C10100000000000000000000000000000
10100000000000000000000000000000
10100000000000000000000000000000
10100000000000000000000000000000
10100000000000000000000000000000
10100000000000000000000000000000
^\退出 (core dumped)


三、捕捉信号



函数:

#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct
sigaction *oact);

pause
#include <unistd.h>
int pause(void);


实现一个my_sleep(5)

代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<signal.h>
  4 void sig_alarm()
  5 {
  6 
  7 }
  8 unsigned int my_sleep(unsigned int seconds)
  9 {
 10     struct sigaction act;
 11     struct sigaction oact;
 12     unsigned int unslept=0;
 13     act.sa_flags=0;
 14     sigemptyset(&act.sa_mask);
 15     act.sa_handler=sig_alarm;
 16     sigaction(SIGALRM,&act,&oact);
 17      alarm(seconds);
 18     pause();
 19      unslept=alarm(0);
 20     sigaction(SIGALRM,&oact,NULL);
 21 
 22     return unslept;
 23 }
 24 int main()
 25 {
 26     while(1)
 27     {
 28      my_sleep(5);
 29      printf("5 seconds passed\n");
 30     }
 31     return 0;
 32 }
 结果:
[admin@localhost SIGNAL]$ ./my_sleep
5 seconds passed
5 seconds passed
5 seconds passed
^C