接上一篇:linux_SIGCHLD信号-子进程回收
本次来分享怎样通过信号传参,也是对sigqueue函数的调用,同时也来分享学习中断系统调用的知识,开始上菜:
目录
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中包含该信号。
以上就是本次的分享了,希望能对广大网友有所帮助。










