复制代码

linux 大复习 信号专题

 

信号 专题 

  • 信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。

  • 信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等

  • 信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断
 
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
 
void  handler(int signal)
{
    printf("this is signal %d\n",signal);
}
int main1()
{
     
  if( signal(SIGINT,&handler) ==SIG_ERR)
  {
          perror("signal errno");
          exit(1);
  }
  pid_t pid = fork();
  if(pid ==0)
  {
      printf(" come on baby \n");
      raise(SIGKILL);
          printf(" come on baby \n");
      while(1);
  }
  else if(pid > 0)
  {
      /*
      kill(pid,SIGINT);
      printf("mei si ? \n");
      kill(pid,SIGKILL);
      printf("mei si 2 ? \n");
      */
      
  }
  else
  {
      perror("fork erno ");
      exit(0);
  }
  
  
  
    
    
    
    return 0;
}
void     handler2 (int n , siginfo_t * pinfo , void * arg)
{
    printf("father   recive  : %d\n",n);
        union sigval value=pinfo->si_value;
        printf("father   recive  : %d\n",value.sival_int);
    raise(SIGKILL);    
    return ; 
}

/*

           siginfo_t {
               int      si_signo;    // Signal number //
               int      si_errno;    // An errno value //
               int      si_code;     // Signal code //
               int      si_trapno;   // Trap number that caused
                                        hardware-generated signal
                                        (unused on most architectures) //
               pid_t    si_pid;      // Sending process ID //
               uid_t    si_uid;      // Real user ID of sending process //
               int      si_status;   // Exit value or signal //
               clock_t  si_utime;    // User time consumed //
               clock_t  si_stime;    // System time consumed //
               sigval_t si_value;    // Signal value //
               int      si_int;      // POSIX.1b signal //
               void    *si_ptr;      // POSIX.1b signal //
               int      si_overrun;  // Timer overrun count; POSIX.1b timers //
               int      si_timerid;  // Timer ID; POSIX.1b timers //
               void    *si_addr;     // Memory location which caused fault //
               long     si_band;     // Band event (was int in
                                        glibc 2.3.2 and earlier) //
               int      si_fd;       // File descriptor //
               short    si_addr_lsb; // Least significant bit of address
                                        (since Linux 2.6.32) //
           }
  */         
 void  handler3 (int n , siginfo_t * pinfo , void * arg)
{
        printf("child  recive  : %d\n",n);
    //    pid_t pid = pinfo->si_pid;
      printf("child  recive  : %d\n",pinfo->si_signo);
         union sigval value;
         value.sival_int = (pinfo->si_value).sival_int  ;
         
         printf("child  recive  date : %d\n",value.sival_int);
      
      sigqueue(getppid(), SIGUSR2, value );
      raise(SIGKILL);
        return ;
}
int main()
{
    
    
  
  pid_t pid = fork();
  if(pid ==0)
  {
      printf(" come on baby \n");
      struct sigaction  act,oldact;
      sigemptyset(&act.sa_mask);
      act.sa_flags=SA_SIGINFO;
      act.sa_sigaction =& handler3  ;
    
    sigaction(SIGUSR1,  &act,NULL); 
    printf(" come on baby \n");
  //  perror("the errno ");
      while(1);
  }
  else if(pid > 0)
  {
       
      struct sigaction  act,oldact ;
        act.sa_flags=SA_SIGINFO  ; 
        act.sa_sigaction = & handler2;
        sigemptyset(&act.sa_mask);
        sigaction(SIGUSR2,&act ,&oldact);
      //
      printf("i have sigaction SIGUSR1 \n");
      union sigval value ;
      value.sival_int = 1000; 
        usleep(5000);
        sigqueue(  pid,SIGUSR1,   value);     usleep(5000);
        
        usleep(5000);
 //      perror("the errno ");
       
      while(1);
  }
  else
  {
      perror("fork erno ");
      exit(0);
  }
}
    
View Code

 

2.不能被忽略的信号 9 /19  
    9 号信号 终止进程
    19 暂停进程 并中止
3.信号捕获过程 
        1.产生信号 2.潜入内核先处理信号,3.着看是否为用户自定义信号4.回到用户态处理信号回调,5.潜入内核继续执行,6回到用户主进程继续
4. alarm函数 默认中止进程
5.信号附带数据
        只是结构体不好找,借用师傅那句话,没有多少料
        sigaction 注册信号 sigqueue 发送信号 
 
typedef struct siginfo_t{
int si_signo;//信号编号 int si_errno;//如果为非零值则错误代码与之关联 int si_code;//说明进程如何接收信号以及从何处收到
pid_t si_pid;//适用于SIGCHLD,代表被终止进程的PID
pid_t si_uid;//适用于SIGCHLD,代表被终止进程所拥有进程的UID int si_status;//适用于SIGCHLD,代表被终止进程的状态
clock_t si_utime;//适用于SIGCHLD,代表被终止进程所消耗的用户时间
clock_t si_stime;//适用于SIGCHLD,代表被终止进程所消耗系统的时间 sigval_t si_value;
int si_int;
void * si_ptr;
void* si_addr;
int si_band;
int si_fd;
};
 
数据 携带 联合体
union sigval {
int sival_int;
void *sival_ptr;
}
6.实时信号 非实时信号
     实时信号在进程阻塞该信号的时间内,发给该进程的所有实时信号会排队,
而非实时信号则会合并为一个信号。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
    #include <errno.h>


#define excite(aaaaa)perror("aaaaa");\
                                    exit(0) 
void handle(int signum, siginfo_t * st , void * arg )
{
    if(signum== SIGUSR1)
    {
        //解除阻塞  
        sigset_t  bset; 
        sigemptyset(&bset); 
        sigaddset(&bset,SIGINT);
        sigaddset(&bset,SIGRTMIN); 
        sigprocmask(SIG_UNBLOCK, &bset, NULL);
    }
    else if(signum== SIGINT || signum== SIGRTMIN )
    {
         printf("%d signal %d information \n",signum,st->si_value.sival_int);
    }
    else
    {
    }
    
}                                    
                                    

int main()
{
    //注册信号 
        printf("sssssssssssssss\n");
    struct sigaction act;
    act.sa_sigaction =&handle ;
  sigemptyset(&act.sa_mask);
  act.sa_flags =SA_SIGINFO ; 
  
    if(sigaction(SIGINT, &act,NULL) ==-1)
    {
        excite(sigaction); 
    }
    if(sigaction(SIGUSR1, &act,NULL) ==-1)
    {
        excite(sigaction); 
    }
    if(sigaction(SIGRTMIN, &act,NULL) ==-1)
    {
        excite(sigaction); 
    }
    printf("sssssssssssssss");
    //设置阻塞 
    sigset_t  bset ;
    sigemptyset(&bset); 
    sigaddset(&bset,SIGINT);  
    sigaddset(&bset, SIGRTMIN);
    sigprocmask(SIG_BLOCK,&bset, NULL);
    
    pid_t  cpid = fork();
    if (cpid == -1) 
    {
        perror("fork");
        exit(0);
    } 
    if (cpid == 0) 
    { 
           // 发送信号 
           union sigval value ;
           value.sival_int = 10;
           int ret ;
           
           
           for(int i=0;i<10;i++)
           {
                 value.sival_int++;
                   ret = sigqueue(  getppid(),SIGINT,  value);
                   if(ret == 0)
                   {
                       printf("sennd SIGINT %d ok \n",i);
                   } 
                   else printf("sennd SIGINT %d err \n",i);
           }
                  
              value.sival_int =100;
            for(int i=0;i<10;i++)
           {
                 value.sival_int++;
                   ret = sigqueue(  getppid(),SIGRTMIN,  value);
                   if(ret == 0)
                   {
                       printf("sennd SIGRTMIN %d ok \n",i);
                   } 
                   else printf("sennd SIGRTMIN %d err \n",i);
           } 
             usleep(100);  
           kill(getppid(), SIGUSR1); 
    } 
     
     while(1) sleep(1);
}
View Code

 

 

 

 

 

 

信号问题

 1) SIGHUP:当用户退出shell时,由该shell启动的所有进程将收到这个信号,默认动作为终止进程
2)SIGINT:当用户按下了<Ctrl+C>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动作为终止里程。3)SIGQUIT:当用户按<ctrl+\>组合键时产生该信号,用户终端向正在运行中的由该终端启动的程序发出些信号。默认动作为终止进程。
4)SIGILL:CPU检测到某进程执行了非法指令。默认动作为终止进程并产生core文件
5)SIGTRAP:该信号由断点指令或其他trap指令产生。默认动作为终止里程并产生core文件。
6 ) SIGABRT:调用abort函数时产生该信号。默认动作为终止进程并产生core文件。
7)SIGBUS:非法访问内存地址,包括内存对齐出错,默认动作为终止进程并产生core文件。
8)SIGFPE:在发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误。默认动作为终止进程并产生core文件。
9)SIGKILL:无条件终止进程。本信号不能被忽略,处理和阻塞。默认动作为终止进程。它向系统管理员提供了可以杀死任何进程的方法。
10)SIGUSE1:用户定义的信号。即程序员可以在程序中定义并使用该信号。默认动作为终止进程。
11)SIGSEGV:指示进程进行了无效内存访问。默认动作为终止进程并产生core文件。
12)SIGUSR2:这是另外一个用户自定义信号,程序员可以在程序中定义并使用该信号。默认动作为终止进程。1
13)SIGPIPE:Broken pipe向一个没有读端的管道写数据。默认动作为终止进程。
14) SIGALRM:定时器超时,超时的时间由系统调用alarm设置。默认动作为终止进程。
15)SIGTERM:程序结束信号,与SIGKILL不同的是,该信号可以被阻塞和终止。通常用来要示程序正常退出。执行shell命令Kill时,缺省产生这个信号。默认动作为终止进程。
16)SIGCHLD:子进程结束时,父进程会收到这个信号。默认动作为忽略这个信号。
17)SIGCONT:停止进程的执行。信号不能被忽略,处理和阻塞。默认动作为终止进程。
18)SIGTTIN:后台进程读终端控制台。默认动作为暂停进程。
19)SIGTSTP:停止进程的运行。按下<ctrl+z>组合键时发出这个信号。默认动作为暂停进程。
21)SIGTTOU:该信号类似于SIGTTIN,在后台进程要向终端输出数据时发生。默认动作为暂停进程。
22)SIGURG:套接字上有紧急数据时,向当前正在运行的进程发出些信号,报告有紧急数据到达。如网络带外数据到达,默认动作为忽略该信号。
23)SIGXFSZ:进程执行时间超过了分配给该进程的CPU时间,系统产生该信号并发送给该进程。默认动作为终止进程。
24)SIGXFSZ:超过文件的最大长度设置。默认动作为终止进程。
25)SIGVTALRM:虚拟时钟超时时产生该信号。类似于SIGALRM,但是该信号只计算该进程占用CPU的使用时间。默认动作为终止进程。
26)SGIPROF:类似于SIGVTALRM,它不公包括该进程占用CPU时间还包括执行系统调用时间。默认动作为终止进程。
27)SIGWINCH:窗口变化大小时发出。默认动作为忽略该信号。
28)SIGIO:此信号向进程指示发出了一个异步IO事件。默认动作为忽略。
29)SIGPWR:关机。默认动作为终止进程。
30)SIGSYS:无效的系统调用。默认动作为终止进程并产生core文件。
31)SIGRTMIN~(64)SIGRTMAX:LINUX的实时信号,它们没有固定的含义(可以由用户自定义)。所有的实时信号的默认动作都为终止进程。


    1) SIGHUP:当用户退出shell
View Code

 

posted @ 2018-03-28 17:09  pg633  阅读(205)  评论(0编辑  收藏  举报