信号

2019-06-16  本文已影响0人  loopppp
  1. cpu执行了错误的程序指令,如除0或者内存越界等,这时候cpu会收到一个硬件中断然后通知内核,进而内核发送信号给进程
  2. 用户从进程的控制终端键入了能够产生信号的字符
  3. 发生了软件事件,如套接字有数据可读或者定时器到期等
       #include <signal.h>

       typedef void (*sighandler_t)(int);

       sighandler_t signal(int signum, sighandler_t handler);
  1. 特权级进程可以发送给任何一个进程
  2. 如果非特权进程的实际用户ID或者有效用户ID和目标进程的实际用户ID或者保存的设置用户ID匹配,那么可以发送
  3. SIGCONT信号无视发送权限,所有进程都可以发送
  • 当调用信号处理函数时,会将引发该调用的信号自动添加到信号掩码中(除非调用sigaction时指定SA_NODEFER标志)
  • 使用sigaction函数建立信号处理程序时,可以额外添加一组信号掩码,这会使得在调用该处理函数时自动的阻塞这些添加的额外信号
  • 调用sigprocmask函数主动的添加或者移除信号掩码
#include <signal.h>

struct sigaction {
               void     (*sa_handler)(int);
               void     (*sa_sigaction)(int, siginfo_t *, void *);
               sigset_t   sa_mask;
               int        sa_flags;
               void     (*sa_restorer)(void);
           };

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
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    *si_lower;     /* Lower bound when address violation
                                         occurred (since Linux 3.19) */
               void    *si_upper;     /* Upper bound when address violation
                                         occurred (since Linux 3.19) */
               int      si_pkey;      /* Protection key on PTE that caused
                                         fault (since Linux 4.6) */
               void    *si_call_addr; /* Address of system call instruction
                                         (since Linux 3.5) */
               int      si_syscall;   /* Number of attempted system call
                                         (since Linux 3.5) */
               unsigned int si_arch;  /* Architecture of attempted system call
                                         (since Linux 3.5) */
           }
  1. 调用sigaction为SIGALRM信号设置处理函数,并且确保清除SA_RESTART标志,避免系统调用的重新启动
  2. 调用alarm定时器函数设置一个阻塞时间上限
  3. 执行阻塞系统调用
  4. 待系统调用返回后,屏蔽定时器(防止在定时器到期前系统调用就完成的情况)
  5. 检查系统调用失败时,是否将errno设置为EINTR
上一篇下一篇

猜你喜欢

热点阅读