ch04:信号处理

 
第四讲 信号处理
信号是进程间通信的最简单形式
信号的生命周期
简单信号
#include <signal.h>
void *signal(int signum, void *handler);
SIG_IGN, SIG_DFL, SIGKILL, SIGSTOP
可靠信号 (sigset_t)
信号和系统调用
 
Linux信号系统api
       发送信号
       int tkill(pid_t pid, int signum);
       int raise(int signum);
       使用sigset_t
       #include <signal.h>
       int sigemptyset(sigset_t *set);
       int sigfillset(sigset_t *set); // 将当前全部的有效信号添加到set中
       int sigaddset(sigset_t *set, int signum);
       int sigdelset(sigset_t *set, int signum);
       int sigismember(const sigset_t *set, int signum);
       EINVAL
      
       #include<signal.h>
       int sigaction(int signum, struct sigaction *act, struct sigaction *oact);
       struct sigaction{
              __sighandler_t sa_handler;
              sigset_t sa_mask;
              int sa_flags;
}
void handler(int signum);
SA_NOCLDSTOP, SA_NODEFER, SA_RESETHAND, SA_RESTART
 
while( *src )
       *dest++ = *src++;
int sigprocmask(int what, const sigset_t *set, sigset_t *oldset);
SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK
sigprocmask(SIG_BLOCK, NULL, &currentSet);
 
sigset_t hup;
sigemptyset(&hup);
sigaddset(&hup, SIGHUP);
sigprocmask(SIG_BLOCK, &hup, NULL);
while(*src)
       *dest++ = *src++;
sigprocmask(SIG_UNBLOCK, &hup,NULL);
      
int sigpending(sigset_t *set);
 
int pause(void);
int sigsuspend(const sigset_t *mask);
errno = EINTR      
信号
SIGABRT, SIGALM, SIGBUS, SIGCHLD, SIGCONT,SIGFPE, SIGHUP, SIGILL, SIGINT, SIGIO, SIGKILL, SIGPIPE, SIGPROF, SIGPWR, SIGQUIT, SIGSEGV, SIGSTOP, SIGSYS, SIGTERM, SIGTRAP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGUSR1, SIGUSR2, SIGVTALRM, SIGWINCH, SIGXCPU, SIGXFSZ
 
编写信号处理程序
重新打开日志文件
#include <error.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
 
volatile int reopenLog = 0;
 
void logstring(int logfd, char *str)
{
       write(logfd,str,strlen(str));
}
 
void hupHandler(int signum)
{
       reopenLog = 1;
}
 
int main()
{
       int done = 0;
       struct sigaction sa;
       int rc;
       int logfd;
      
       logfd = STDOUT_FILENO;
      
       memset(&sa, 0, sizeof(sa));
       sa.sa_handler = hupHandler;
      
       if (sigaction(SIGHUP, &sa, NULL))
          {
              perror("sigaction");
       }
 
       while (!done)
       {
              rc = sleep(5);
             
              if (rc)
              {
                     if (reopenLog)
                     {
                            logstring(logfd,"*reopening log files at sig hup request/n");
                            reopenLog = 0;
                     }
                     else
                     {
                            logstring(logfd,"*sleep interrupted by unkown signal/n");
                            done = 1;
                     }
              }
              else
              {
                     logstring(logfd, "periodic message/n");
              }
       }
       return 0;
}
实时信号
SIGRTMIN, SIGRTMAX
#define _GNU_SOURCE 1
 
#include <sys/signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
 
int nextSig = 0;
int sigOrder[10];
 
void handler(int signo)
{
       sigOrder[nextSig++] = signo;
}
 
int main()
{
       sigset_t mask;
       sigset_t oldmask;
       struct sigaction act;
       int i;
 
       sigemptyset(&mask);
       sigaddset(&mask, SIGRTMIN);
       sigaddset(&mask, SIGRTMIN + 1);
       sigaddset(&mask, SIGUSR1);
 
       act.sa_handler = handler;
       act.sa_mask = mask;
       act.sa_flags = 0;
 
       sigaction(SIGRTMIN, &act, NULL);
       sigaction(SIGRTMIN + 1, &act, NULL);
       sigaction(SIGUSR1, &act ,NULL);
 
       sigprocmask(SIG_BLOCK, &mask, &oldmask);
       raise(SIGRTMIN + 1);
       raise(SIGRTMIN);
       raise(SIGRTMIN);
       raise(SIGRTMIN + 1);
       raise(SIGRTMIN);
       raise(SIGUSR1);
       raise(SIGUSR1);
      
       sigprocmask(SIG_SETMASK, &oldmask, NULL);
 
       printf("signals received:/n");
 
       for (i = 0; i < nextSig; i++)
       {
              if (sigOrder[i] < SIGRTMIN)
              {
                     printf("/t%s/n",strsignal(sigOrder[i]));
              }
              else
              {
                     printf("/tSIGRTIM + %d/n",sigOrder[i] - SIGRTMIN);
              }    
       }    
       return 0;
}
 
获取信号信息
得到信号上下文
void handler(int signum, siginfo_t *siginfo, void *context);
SA_SIGINFO
#include <signal.h>
struct sigaction{
       union{
       __sighandler_t sa_handler;
       __sigaction_t sa_sigaction;
}
sigset_t sa_mask;
unsigned long sa_flags;
}
       #define sa_handler __sigactin_handler.sa_handler
       #define sa_sigaction __sigaction_handler.sa_sigaction
       Si_signo si_code: SI_USER, SI_QUEUE, SI_TKILL, SI_KERNEL
       SIGSEGV SEGV_MAPER
               SEGV_ACCERR
SIGBUS     BUS_ADDRALN
           BUS_ADDERR
           BUS_OBJERR
SIGCHLD CLD_EXITED
                 CLD_KILLED
                 CLD_STOPPED
       例子
#include <sys/signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
 
#ifndef SI_TKILL
#define SI_TKILL -6
#endif
 
void handler(int signo, siginfo_t *info, void *f)
{
       static int count = 0;
       printf("caught signal sent by ");
      
       switch(info->si_code)
       {
              case SI_USER:
                     printf("kill()/n");
                     break;
              case SI_QUEUE:
                     printf("sigqueue()/n");
                     break;
              case SI_TKILL:
                     printf("tkill() or raise()/n");
                     break;
              case CLD_EXITED:
                     printf("kernel telling us child exited/n");
                     exit(0);
       }
      
       if (++count == 4)
              _exit(1);
}
 
int main()
{
       struct sigaction act;
       union sigval val;
      
       pid_t pid = getpid();
      
       val.sival_int = 1234;
      
       act.sa_sigaction = handler;
       sigemptyset(&act.sa_mask);
       act.sa_flags = SA_SIGINFO;
       sigaction(SIGCHLD, &act, NULL);
 
       kill(pid, SIGCHLD);
       sigqueue(pid, SIGCHLD, val);
       raise(SIGCHLD);
 
       if (!fork())
       {
              _exit(0);
       }
       sleep(60);
       return 0;
}
#include <sys/signal.h>
#include <stdlib.h>
#include <stdio.h>
 
void handler(int signo, siginfo_t *info, void *f)
{
       printf("caught");
      
       if (info->si_signo == SIGSEGV)
       {
              printf("segv accessing %p", info->si_addr);
       }
 
       if (info->si_code == SEGV_MAPERR)
       {
              printf("segv_maperr");
       }
      
       printf("/n");
       _exit(1);
}
 
int main()
{
       struct sigaction act;
    act.sa_sigaction = handler;
       sigemptyset(&act.sa_mask);
       act.sa_flags = SA_SIGINFO;
       sigaction(SIGSEGV, &act, NULL);
       *((int*)NULL) = 1;
       return 0;
}
 
使用信号发送数据
#include <signal.h>
void *sigqueue(pid_t pid ,int signum, const union sigval value);
union sigval{
       int sival_int;
       void *sival_ptr;
}
#include <sys/signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
 
void handler(int signo, siginfo_t *si ,void *context)
{
       printf("%d/n", si->si_value.sival_int);
}
 
int main()
{
       sigset_t mask;
       sigset_t oldmask;
       struct sigaction act;
       int me = getpid();
       union sigval val;
      
       act.sa_sigaction = handler;
       act.sa_mask = mask;
       act.sa_flags = SA_SIGINFO;
       sigaction(SIGRTMIN, &act, NULL);
      
       sigemptyset(&mask);
       sigaddset(&mask, SIGRTMIN);
      
       sigprocmask(SIG_BLOCK, &mask, &oldmask);
       val.sival_int = 1;
       sigqueue(we, SIGRTMIN, val);
       val.sival_int++;
       sigqueue(we, SIGRTMIN, val);
       val.sival_int++;
       sigqueue(we, SIGRTMIN, val);
       sigprocmask(SIG_SETMASK, &oldmask, NULL);
 
       return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值