【linux】22、信号:高级特性
程序员文章站
2022-07-12 10:31:21
...
硬件产生的信号:SIGBUS、SIGFPE、SIGILL、SIGSEGV
信号的同步生成和异步生成
同步生成:信号的产生由进程本身的执行造成的
异步生成:引发信号产生的事件,与进程执行无关
信号传递的顺序
linux内核按照信号编号的升序来传递信号。
实时信号
(1)发送进程使用sigqueue()系统调用来发送信号及其伴随数据
(2)要为该信号建立一个处理器函数,接收进程应以SA_SIGINFO标志发起狂对sigaction()的调用。
#define _POSIX_C_SOURCE 199309
#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval value);
//success 0; error -1
t_sigqueue.c
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
static int getInt(char *, char *);
int main(int argc, char **argv){
pid_t pid;
int sigNum, sigData, frequency, i;
union sigval sv;
if (argc < 4 || (argc > 1 && strcmp(argv[1], "--help") == 0)){
printf("usgae: %s pid sigNum sigData frequency\n", argv[0]);
exit(EXIT_SUCCESS);
}
pid = (pid_t)getInt(argv[1], "pid of receive function");
sigNum = getInt(argv[2], "number of signal");
sigData = getInt(argv[3], "signal carrying value");
frequency = (argc > 4) ? getInt(argv[4], "Sending frequency") : 1;
for (i = 0;i < frequency;i++){
sv.sival_int = sigData + i;
if (sigqueue(pid, sigNum, sv) == -1){
printf("sigqueue() error!\n");
exit(EXIT_FAILURE);
}
}
}
static int getInt(char *p, char *msg){
int data;
char *str;
data = strtol(p, &str, 10);
if (*str != '\0'){
printf("%s must be string\n", msg);
exit(EXIT_FAILURE);
}else if (data <= 0){
printf("%s must be greater than zero\n", msg);
exit(EXIT_FAILURE);
}
return data;
}
catch_rtsigs.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
static volatile sig_atomic_t flag = 0;
static volatile int handler_sleepTime;
static volatile int sigCount = 0;
static int getInt(char *, char *);
static void sigHandler(int, siginfo_t *, void *);
int main(int argc, char **argv){
struct sigaction sa;
int i, main_sleepTime;
sigset_t blockMask, prevMask;
if (argc != 3 || (argc > 1 && strcmp(argv[1], "--help") == 0)){
printf("usage: %s num1 num2\n"
"\tnum1: sleep time for main function\n"
"\tnum2: sleep time for sigHandler function\n", argv[0]);
exit(EXIT_FAILURE);
}
printf("pid: %d\n", getpid());
sigfillset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sigHandler;
for (i = 1;i < NSIG; i++){
if (i != SIGQUIT && i != SIGTSTP){
/*
if (sigaction(i, &sa, NULL) == -1){
printf("sigaction() error!\n");
exit(-1);
}
*/
sigaction(i, &sa, NULL);
}
}
main_sleepTime = getInt(argv[1], "main sleep time");
handler_sleepTime = (argc > 2) ? getInt(argv[2], "handler sleep time") : 1;
sigfillset(&blockMask);
sigdelset(&blockMask, SIGINT);
if (sigprocmask(SIG_SETMASK, &blockMask, &prevMask) == -1){
printf("sigprocmask() error!\n");
exit(EXIT_FAILURE);
}
sleep(main_sleepTime);
printf("main function sleep complete\n");
sigprocmask(SIG_SETMASK, &prevMask, NULL);
while (!flag)
pause();
return 0;
}
static int getInt(char *p, char *msg){
char *ch;
int data;
data = strtol(p, &ch, 10);
if (*ch != '\0'){
fprintf(stdout, "%s cannot be character\n", msg);
exit(EXIT_FAILURE);
}else if(data <= 0){
fprintf(stdout, "%s must be more than zero\n", msg);
exit(EXIT_FAILURE);
}
return data;
}
static void sigHandler(int sig, siginfo_t *si, void *ucontext){
if (sig == SIGINT){
flag = 1;
return;
}
sigCount++;
printf("Caught signal %d: %s\n", sig, strsignal(sig));
printf("si_signo=%d, si_code=%d, ",si->si_signo, si->si_code);
printf("si_pid=%ld, si_uid=%ld, ", (long)si->si_pid, (long)si->si_uid);
printf("si_value=%d\n", si->si_value.sival_int);
sleep(handler_sleepTime);
}
使用掩码来等待信号:sigsuspend()
#include <signal.h>
int sigsuspend(const sigset_t *mask);
t_sigsuspend.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <errno.h>
static volatile sig_atomic_t flag = 0;
static void printSig(char *, char *);
static void errExit(char *);
static void sigHandler(int);
int main(int argc, char **argv){
struct sigaction sa;
sigset_t blockSig, prevSig;
int i;
time_t startTime;
printSig("previous signal mask: ", "mask");
sigemptyset(&blockSig);
sigaddset(&blockSig, SIGINT);
sigaddset(&blockSig, SIGQUIT);
if (sigprocmask(SIG_BLOCK, &blockSig, &prevSig) == -1){
errExit("siprocmask()");
}
sa.sa_flags = 0;
sa.sa_handler = sigHandler;
sigemptyset(&sa.sa_mask);
for (i = 1; i< NSIG; i++){
if (i == SIGINT || i == SIGQUIT){
sigaction(i, &sa, NULL);
}
}
for (i = 1; !flag; i++){
printf("*********LOOP%d************\n", i);
printSig("before the critical section, signal mask:", "mask");
for (startTime = time(NULL); time(NULL) < startTime + 4;)
continue;
printSig("the pending signal: ", "pending");
if (sigsuspend(&prevSig) == -1 && errno != EINTR){
errExit("sigsuspend()");
}
}
if (sigprocmask(SIG_SETMASK, NULL, &prevSig) == -1){
errExit("sigprocmask");
}
printSig("At last, the signal mask:", "mask");
exit(EXIT_SUCCESS);
}
static void printSig(char *msg, char *mask){
int sig, num = 0;
sigset_t sigSet;
if (strcmp(mask, "mask") == 0){
if (sigprocmask(SIG_SETMASK, NULL, &sigSet) == -1)
errExit("sigprocmask()");
}else{
if (sigpending(&sigSet) == -1)
errExit("sigpending()");
}
printf("%s", msg);
for (sig = 1; sig < NSIG;sig++){
if (sigismember(&sigSet, sig)){
num++;
printf("%d ", sig);
}
}
if (!num)
printf("empty set\n");
else
printf("\n");
}
static void errExit(char *msg){
printf("%s error\n", msg);
exit(EXIT_FAILURE);
}
static void sigHandler(int sig){
if (sig == SIGQUIT){
flag = 1;
return;
}
printf("signal %d: %s\n", sig, strsignal(sig));
}
以同步方式等待信号
#define POSIX_C_SOURCE 199309
#include <signal.h>
int sigwaitinfor(const sigset_t *set, siginfo_t *info);
//success, signal; error, -1
(1) sigwaitinfo()系统调用挂起进程的执行,直至set指向信号集中的某一信号抵达。
(2)调用sigwaitinfo(),需要先阻塞set中的信号
上一篇: Redis的高级特性