接上一篇:linux_SIGCHLD信号-子进程回收
本次来分享怎样通过信号传参,也是对sigqueue函数的调用,同时也来分享学习中断系统调用的知识,开始上菜:
此博主在CSDN发布的文章目录:【我的CSDN目录,作为博主在CSDN上发布的文章类型导读】
目录
- 1.信号传参
- 1.1.发送信号传参
- 1.2.捕捉函数传参-sigaction函数
- 2.中断系统调用
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中包含该信号。
以上就是本次的分享了,希望能对广大网友有所帮助。