信号的基本概念及用法

什么是信号:

信号是事件发生时对进程的通知机制,有时也称为软件中断。信号与硬件中断的相似之处在于打断了程序执行的正常流程,大多数情况下,无法预测信号到达的准确时间

信号源:

1.硬件

2.软件 (如ctrl+c 结束进程就是一个信号源)

常见的几种进程信号解释:

SIGHUP 关闭终端时会产生

SIGINT 按下ctrl+C 发送给进程的信号

SIGQUIT 按下ctrl+/ 发送给进程的信号

SIGILL 非法指令信号

SIGABRT c库函数中的abort产生的信号

SIGFPE浮点数异常

SIGSTOP 让进程暂停

SIGCONT 让进程继续

SIGPIPE 管道破裂的提示信号

信号是在PCB上写的,进程收到信号的三种响应:

1.忽略信号

2.捕获信号并处理(SIGKILL SIGSTOP 两种信号无法被忽略、无法被捕获处理)

3.缺省处理(缺省处理到底执行什么动作,可以用man 7 signal查看)

缺省处理:

TERM 缺省的动作是终止进程

IGN 忽略掉信号

Core 让进程终止并产生core文件

stop  让进程暂停

cont  让进程继续

信号的分类:

1.可靠信号和不可靠信号

不可靠表现在:

            1.当执行完信号处理函数后恢复程缺省处理动作,解决方法在函数内部递归调用

             2.当多个信号同时抵达,可能会出现信号丢失 

           1~31 不可靠信号 34~64:可靠信号

2.实时信号和非实时信号

34~64 为实时信号

实时信号与非实时信号没有快慢之分,区别就在于是否可靠

信号的具体操作:

安装/注册信号(当某个信号来时将如何处理):

void (*signal (int signo,void(*handler)(int)))(int)

signo: 要注册的信号

handler:信号处理函数

返回值为函数指针,成功返回的是旧的的信号处理函数,失败返回SIG_ERR

调用忽略信号函数:signal(SIGINT,SIG_IGN)

调用捕获信号函数:signal(SIGINT,SIG_DFL)

自定义处理函数:

  1 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<signal.h>
  5 void handler(int s)
  6 {
  7     printf("not kill");
  8 
  9 }
 10 int main()
 11 {
 12     signal(SIGINT,handler);
 13     while(1)
 14     {
 15         sleep(1);
 16         printf(" . ");
 17         fflush(stdout);                                                     
 18     }
 19 }

发送信号:

kill命令

kill函数:

int kill(pid_t pid,int signo);

pid:给那个进程发送信号,如果pid为整数,则发送到指定进程。如果pid为0,则发送到本进程组中任何进程,如果pid=-1,发送给本进程有权发送的任何一个进程,如果pid<-1,给pid绝对值进程组中的任何一个进程,如pid=-5,则发送给进程组为5中的任何一个进程

signo:发送什么信号

返回值:成功0,失败-1

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<signal.h>
  5 int main(int argc,char *argv[])
  6 {
  7     if(argc!=3)
  8     {
  9         fprintf(stderr,"usage:%s signo pid\n",argv[0]);
 10         exit(1);
 11     }
 12     int sig=atoi(argv[1]);
 13     int pid=atoi(argv[2]);
 14     kill(pid,sig);                                                          
 15 }

延时器:

int alarm(int sec);

sec :过sec秒后,信号SIGALRM抵达,若sec=0表示清除这个信号

返回值:为在alarm信号返回之前还剩下多少秒到达sec设定时间

可以用alarm做超时处理:

  1 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 int main()
  5 {
  6     alarm(3);
  7     while(1)
  8     {
  9         printf(" . ");
 10         fflush(stdout);                                                     
 11         sleep(1);
 12     }
 13 }

定时器:

settitimer(int which,const struct itimerval *new_value,struct itimerval*old_value):

which:

ITIMER_REAL:真实时间,就是电脑桌面上显示的时间,到时间后会产生SIGALRM信号

ITIMER_VIRTUAL:虚拟时间,用户模式下执行的CPU时间,到时间后会产生SIGVTALRM

ITIMER_PROF:用户态和内核太CPU时间总和(也就是执行状态的时间),到时后会产生SIGPROF信号

old_value:返回先前设置的定时器,一般为NULL

struct itimerval{

        struct timeval it_interval;  //以后每次启动的间隔时间

        struct timeval it_value;   //第一次启动时间

};

struct timeval{

       long tv_sec;  //精确到秒

       long tv_usec;  //精确到微秒

当sec usec 都为0时表示永远都不启动

  1 #include<stdlib.h>                                                          
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<sys/time.h>
  5 #include<signal.h>
  6 #include<string.h>
  7 void handler(int s)
  8 {
  9     printf("time out %d\n",s);
 10 }
 11 int main()
 12 {
 13     signal(SIGALRM,handler);
 14     struct itimerval it;
 15     memset(&it,0x00,sizeof(it));
 16     it.it_value.tv_sec=0;
 17     it.it_value.tv_usec=1;
 18     it.it_interval.tv_sec=1;
 19     setitimer(ITIMER_REAL,&it,NULL);
 20     for(;;)
 21     {
 22         printf(" . ");
 23         fflush(stdout);
 24         sleep(1);
 25     }                                                                       
 26 }

猜你喜欢

转载自blog.csdn.net/enjoymyselflzz/article/details/81626199