信号集操作相关函数
概念
未决信号集
没有被当前进程处理的信号
阻塞信号集
将某个信号放到阻塞信号集,这个信号就不会被进程处理
阻塞解除之后,信号被处理
自定义信号集
相关函数
int sigemptyset(sigset_t *set); 将set集合置空
int sigfillset(sigset_t *set); 将所有信号加入set集合
int sigaddset(sigset_t *set,int signo); 将signo信号加入到set集合
int sigdelset(sigset_t *set,int signo); 从set集合中移除signo信号
int sigismember(const sigset_t *set,int signo); 判断信号是否存在
sigprocmask函数 屏蔽and接触信号屏蔽, 将自定义信号集设置给阻塞信号集
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
sigpending – 读取当前进程的未决信号集
int sigpending(sigset_t *set);
参数: set -- 内核将未决信号集写入set
信号函数
siganl函数
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
测试代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <signal.h>
void myfunc(int sig)
{
printf("cathc you signal: %d\n", sig);
}
int main(int argc, const char* argv[])
{
// 注册信号捕捉函数
signal(SIGINT, myfunc);
while(1)
{
}
return 0;
}
测试结果
sigaction函数
函数原型:
int sigaction(int signum, // 捕捉的信号
const struct sigaction *act,
struct sigaction *oldact
);
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
在信号处理函数执行过程中,临时屏蔽指定的信号
int sa_flags;
0 - sa_handler
void (*sa_restorer)(void);
};
测试代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <signal.h>
void myfunc(int sig)
{
printf("hello signal: %d\n", sig);
sleep(5);
printf("wake up .....\n");
}
int main(int argc, const char* argv[])
{
// 注册信号捕捉函数
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = myfunc;
// 设置临时屏蔽的信号
sigemptyset(&act.sa_mask); // 0
// ctrl + 反斜杠
sigaddset(&act.sa_mask, SIGQUIT);
sigaction(SIGINT, &act, NULL);
while(1);
return 0;
}
测试结果
SIGCHLD信号
产生的条件
a. 子进程结束的时候
b. 子进程挂起
c. 子进程重新恢复运行状态
使用该信号回收子进程
使用时的注意事项
进程创建的时候, 父子进程共享
阻塞信号集
信号的处理动作
极端问题
1) 父进程信号处理函数注册成功之前,子进程死亡
2) 解决思路:
a) 先将SIGCHLD信号阻塞
b) 父进程的信号处理函数注册成功之后, 解除阻塞
测试
设置阻塞信号集并把所有常规信号的未决状态打印至屏幕
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <signal.h>
int main(int argc, const char* argv[])
{
// 自定义信号集
sigset_t myset, old;
// 清空 -》 0
sigemptyset(&myset);
// 添加要阻塞的信号
sigaddset(&myset, SIGINT);
sigaddset(&myset, SIGQUIT);
sigaddset(&myset, SIGKILL);
// 自定义信号集设置到内核中的阻塞信号集
sigprocmask(SIG_BLOCK, &myset, &old);
sigset_t pend;
int i = 0;
while(1)
{
// 读内核中的未决信号集的状态
sigpending(&pend);
for(int i=1; i<32; ++i)
{
if(sigismember(&pend, i))
{
printf("1");
}
else if(sigismember(&pend, i) == 0)
{
printf("0");
}
}
printf("\n");
sleep(1);
i++;
// 10s之后解除阻塞
if(i > 10)
{
// sigprocmask(SIG_UNBLOCK, &myset, NULL);
sigprocmask(SIG_SETMASK, &old, NULL);
}
}
return 0;
}
测试结果
setitimer函数测试源码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
void myfunc(int sig)
{
printf("hello\n");
}
int main(int argc, const char* argv[])
{
struct itimerval new_value;
new_value.it_interval.tv_sec = 1;
new_value.it_interval.tv_usec = 0;
new_value.it_value.tv_sec = 2;
new_value.it_value.tv_usec = 0;
signal(SIGALRM, myfunc);
setitimer(ITIMER_REAL, &new_value, NULL);
while(1)
{
}
return 0;
}