linux_信号_sigqueue函数发送信号传参_sigaction函数捕捉信号传参_中断系统调用

接上一篇:linux_SIGCHLD信号-子进程回收

  本次来分享怎样通过信号传参,也是对sigqueue函数的调用,同时也来分享学习中断系统调用的知识,开始上菜:

此博主在CSDN发布的文章目录:【我的CSDN目录,作为博主在CSDN上发布的文章类型导读

1.信号传参

1.1.发送信号传参

函数作用:
  对应kill函数,但可在向指定进程发送信号的同时携带参数
头文件:
  #include <signal.h>
函数原型:
  int sigqueue(pid_t pid, int sig, const union sigval value);
函数参数:
  pid:进程ID
  sig:需要发送的信号
  value:需要携带的数据
    union sigval {
       int sival_int;
       void *sival_ptr;
       };
返回值:
  成功:0;
  失败:-1,设置errno

  向指定进程发送指定信号的同时,携带数据。但,如传地址,需注意,不同进程之间虚拟地址空间各自独立,将当前进程地址传递给另一进程没有实际意义。

1.2.捕捉函数传参-sigaction函数

函数作用:
  修改信号处理动作(通常在Linux用其来注册一个信号的捕捉函数)。
头文件:
  #include <signal.h>
函数原型:
   int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
函数参数:
  signum:需要修改默认处理动作的信号
  act:传入参数,新的处理方式。
  oldact:传出参数,旧的处理方式。
返回值:
  成功:0;
  失败:-1,设置errno

  当注册信号捕捉函数,希望获取更多信号相关信息,不应使用sa_handler而应该使用sa_sigaction。但此时的sa_flags必须指定为SA_SIGINFO。siginfo_t是一个成员十分丰富的结构体类型,可以携带各种与信号相关的数据。

例子:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
//回调函数
void func(int signo, siginfo_t *uinfo, void *val)
{
    
    
    printf("-----------signo is = %d\n", uinfo->si_signo);
    printf("-----------send pid = %u\n", uinfo->si_pid);
    printf("-----------sender's value is %d\n", uinfo->si_value);
    return ;
}

int main(void)
{
    
    
    pid_t pid = fork();
    union sigval uval;
    uval.sival_int = 887;
    if (pid > 0) //父进程
    {
    
       
        sleep(1);
        sigqueue(pid, SIGUSR1, uval);   //kill 给子进程发信号 ,同时携带数据
        wait(NULL);

    } 
    else if (pid == 0) 
    {
    
    
        int n = 5;
        struct sigaction act;
        act.sa_sigaction = func;
        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_SIGINFO;    //同sa_flags = 0;
        sigaction(SIGUSR1, &act, NULL);//注册信号捕捉函数
        while (n--) 
{
    
    
            printf("I'm child pid = %d\n", getpid());
            sleep(1);
        }
    }
    return 0;
}

2.中断系统调用

系统调用可分为两类:慢速系统调用和其他系统调用。
  1.慢速系统调用: 可能会使进程永远阻塞的一类。如果在阻塞期间收到一个信号,该系统调用就被中断,不再继续执行(早期);也可以设定系统调用是否重启。如,read、write、pause、wait…
  2.其他系统调用: getpid、getppid、fork…
结合pause,回顾慢速系统调用:
   慢速系统调用被中断的相关行为,实际上就是pause的行为: 如,read
     ① 想中断pause,信号不能被屏蔽。
     ② 信号的处理方式必须是捕捉 (默认、忽略都不可以)
     ③ 中断后返回-1, 设置errno为EINTR(表“被信号中断”)
  可修改sa_flags参数来设置被信号中断后系统调用是否重启。SA_INTERRURT不重启。 SA_RESTART重启。
扩展了解:
   sa_flags还有很多可选参数,适用于不同情况。如:捕捉到信号后,在执行捕捉函数期间,不希望自动阻塞该信号,可将sa_flags设置为SA_NODEFER,除非sa_mask中包含该信号。

以上就是本次的分享了,希望能对广大网友有所帮助。

猜你喜欢

转载自blog.csdn.net/qq_44177918/article/details/130311815