进程信号操作

/*
 设置信号捕捉操作:
  sigaction(查询或设置信号处理方式)
  相关函数 signal,sigprocmask,sigpending,sigsuspend,sigemptyset
  表头文件 #include<signal.h>
  定义函数 int sigaction(int signum,const struct sigaction
  *act ,struct sigaction *oldact);
  函数说明 sigaction()会依参数signum指定的信号编号来设置该信号的处理函数。
    参数signum可以指定SIGKILL和SIGSTOP以外的所有信号。
  如参数结构sigaction定义如下
  struct sigaction
  {
  void (*sa_handler) (int);
  sigset_t sa_mask;
  int sa_flags;
  void (*sa_restorer) (void);
  }
  sa_handler此参数和signal()的参数handler相同,代表新的信号处理函数,其他意
    义请参考signal()。
  sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号搁
  置。
  sa_restorer 此参数没有使用。
  sa_flags 用来设置信号处理的其他相关操作,下列的数值可用。
  OR 运算(|)组合A_NOCLDSTOP : 如果参数signum为SIGCHLD,则当子进程暂停时并不
    会通知父进程SA_ONESHOT/SA_RESETHAND:当调用新的信号处理函数前,将此信号处理方
    式改为系统预设的方式。
  SA_RESTART:被信号中断的系统调用会自行重启
  SA_NOMASK/SA_NODEFER:在处理此信号未结束前不理会此信号的再次
  到来。如果参数oldact不是NULL指针,则原来的信号处理方式会由此结构sigaction 返回。
  返回值 执行成功则返回0,如果有错误则返回-1。
  错误代码 EINVAL 参数signum 不合法, 或是企图拦截
  SIGKILL/SIGSTOPSIGKILL信号
  EFAULT 参数act,oldact指针地址无法存取。
  EINTR 此调用被中断

 挂起进程:
 定义2个未初始化的信号集 sigset_t
 插入信号捕捉函数
 将所有信号加入信号集:
    sigfillset(将所有信号加入至信号集)
  相关函数 sigempty,sigaddset,sigdelset,sigismember
  表头文件 #include<signal.h>
  定义函数 int sigfillset(sigset_t * set);
  函数说明 sigfillset()用来将参数set信号集初始化,然后把所有的信号加入到此信号集里。
  返回值 执行成功则返回0,如果有错误则返回-1。
  附加说明 EFAULT 参数set指针地址无法存取
 在信号集中删除定制的信号:
    sigdelset(sigset_t *set, int signum)
 设置阻塞信号集:
    函数原型:int sigprocmask(inthow, const sigset_t *set, sigset_t *oldset);
  函数说明:一个进程的信号屏蔽字规定了当前阻塞而不能递送给该进程的信号集。sigprocmask()可以用来检测或改变目前的信号屏蔽字,其操作依参数how来决定,如果     参数oldset不是NULL指针,那么目前的信号屏蔽字会由此指针返回。
  参数how:  
      SIG_BLOCK	该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。set包含了我
                们希望阻塞的附加信号。
      SIG_UNBLOCK 该该进程新的信号屏蔽字是其当前信号屏蔽字和set所指向信号集的交集。set包含了
                   我们希望解除阻塞的信号.
      SIG_SETMASK  该该进程新的信号屏蔽是set指向的值
  如果set是个空指针,则不改变该进程的信号屏蔽字,how的值也无意义。
  返回值:执行成功返回0,失败返回-1。
  错误代码:
  EFAULT	参数set,oldset指针地址无法存取
    EINTR	此调用被中断
 挂起进程:
    int sigsuspend(const sigset_t *setmask)
    用于在接受到某个信号之前,临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止。
 唤醒进程:
    定义函数 int kill(pid_t pid,int sig);
  函数说明
  kill()可以用来送参数sig指定的信号给参数pid指定的进程。参数pid有几种情况:
  pid>0 将信号传给进程识别码为pid 的进程。
  pid=0 将信号传给和目前进程相同进程组的所有进程
  pid=-1 将信号广播传送给系统内所有的进程
  pid<0 将信号传给进程组识别码为pid绝对值的所有进程
    参数sig代表的信号:
  
Signal	Description
SIGABRT	由调用abort函数产生,进程非正常退出
SIGALRM	用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS	某种特定的硬件异常,通常由内存访问引起
SIGCANCEL	由Solaris Thread Library内部使用,通常不会使用
SIGCHLD	进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
SIGCONT	当被stop的进程恢复运行的时候,自动发送
SIGEMT	和实现相关的硬件异常
SIGFPE	数学相关的异常,如被0除,浮点溢出,等等
SIGFREEZE	Solaris专用,Hiberate或者Suspended时候发送
SIGHUP	发送给具有Terminal的Controlling Process,当terminal被disconnect时候发送
SIGILL	非法指令异常
SIGINFO	BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程
SIGINT	由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGIO	异步IO事件
SIGIOT	实现相关的硬件异常,一般对应SIGABRT
SIGKILL	无法处理和忽略。中止某个进程
SIGLWP	由Solaris Thread Libray内部使用
SIGPIPE	在reader中止之后写Pipe的时候发送
SIGPOLL	当某个事件发送给Pollable Device的时候发送
SIGPROF	Setitimer指定的Profiling Interval Timer所产生
SIGPWR	和系统相关。和UPS相关。
SIGQUIT	输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程
SIGSEGV	非法内存访问
SIGSTKFLT	Linux专用,数学协处理器的栈异常
SIGSTOP	中止进程。无法处理和忽略。
SIGSYS	非法系统调用
SIGTERM	请求中止进程,kill命令缺省发送
SIGTHAW	Solaris专用,从Suspend恢复时候发送
SIGTRAP	实现相关的硬件异常。一般是调试异常
SIGTSTP	Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程
SIGTTIN	当Background Group的进程尝试读取Terminal的时候发送
SIGTTOU	当Background Group的进程尝试写Terminal的时候发送
SIGURG	当out-of-band data接收的时候可能发送
SIGUSR1	用户自定义signal 1
SIGUSR2	用户自定义signal 2
SIGVTALRM	setitimer函数设置的Virtual Interval Timer超时的时候
SIGWAITING	Solaris Thread Library内部实现专用
SIGWINCH	当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程
SIGXCPU	当CPU时间限制超时的时候
SIGXFSZ	进程超过文件大小限制
SIGXRES	Solaris专用,进程超过资源限制的时候发送

定义函数 pid_t wait (int * status);
  函数说明
  wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程
    已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子
    进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束
    状态值请参考下面的waitpid()。
  返回值
  如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。
    子进程的结束状态返回后存于status,底下有几个宏可判别结束情况:
  WIFEXITED(status)如果子进程正常结束则为非0 值。
  WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正
    常结束才能使用此宏。T
  WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真。
  WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
  WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
  WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。
*/
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

void fun(int sigum){
  while(1){
    printf("hi,I am your kid\n");
    sleep(3);
  }
}

void set_sigaction(){
  struct sigaction sa;
  sa.sa_flags = 0;
  sa.sa_handler =  fun;
  sigemptyset(&sa.sa_mask);
  sigaction(SIGUSR1, &sa, NULL);
}
void wait_p(){
  sigset_t maskset, oldset;
  set_sigaction();
  sigfillset(&maskset);
  sigdelset(&maskset, SIGUSR1);
  sigprocmask(SIG_SETMASK, &maskset, &oldset);
  sigsuspend(&maskset);
  sigprocmask(SIG_SETMASK, &oldset, NULL);
}

void tell_p(pid_t pid){
  kill(pid, SIGUSR1);
}

int main(){
  int status = 0;
  pid_t pid;
  pid_t childpid = fork();
  if(childpid < 0)exit(1);
  else if(childpid == 0)wait_p();
  else {
    pid = childpid;
    printf("this is the father\n");
  } 

  tell_p(pid);
  sleep(3);
  kill(pid, SIGKILL);
  wait(&status);
  if(WIFSIGNALED(status) != 0)printf("wait status %d\n", WTERMSIG(status));
  return 0;
}

你可能感兴趣的:(进程信号操作)