信号
参考博文
查看信号列表
kill -l
向某进程发送信号
kill -signum pid
捕捉信号,写一个信号处理函数,然后将这个函数告诉内核。当该信号产生时,由内核来调用用户自定义的函数,以此来实现某种信号的处理。
发送信号用kill命令,绑定操作函数用signal();
一、信号注册函数signal();
#include <signal.h>
#include <stdio.h>
//typedef void (*sighandler_t)(int);//定义sighandler_t为void *(int)无返回值的函数指针类型
//sighandler_t signal(int signum, sighandler_t handler);//第二个参数是函数指针类型,目的是传入函数地址。函数名相当于指针,存放着指向函数空间的地址。
void handler(int signum)
{
printf("signum is:%d\n",signum);
printf("don't quit\n");
}
int main()
{
signal(SIGINT,handler);//信号处理函数的注册,当Ctrl+C信号出现,内核调用handler函数处理 ,也可以用宏(SIG_IGN)忽略
while(1);
return 0;
}
通过kill发送信号给其他进程:
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
int main(int argc,int **argv[])
{
int signum;
int pid;
char cmd[128] ={0};
signum = atoi(argv[1]);//字符转换成整形
pid = atoi(argv[2]);
printf("signum:%d,pid:%d\n",signum,pid);
/*发送指令*/
/*方法一*/
/*
kill(pid,signum);//执行命令
printf("send kill\n");
*/
/*方法二*/
sprintf(cmd,"kill -%d %d",signum,pid);//构建字符串
system(cmd);//创建子进程执行
printf("system work\n");
return 0;
}
二、信号注册函数2 sigaction()
可以携带信息,发信号用sigqueque(),注册信号函数用sigaction()。
2.1.注册信号处理函数:
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
struct sigaction {
void (*sa_handler)(int); //信号处理程序
void (*sa_sigaction)(int, siginfo_t *, void *); //信号处理程序,能够接受额外数据和sigqueue配合使用
sigset_t sa_mask;//阻塞关键字的信号集,在调用捕捉函数之前,把信号添加到信号阻塞字,信号捕捉函数返回之前恢复为原先的值。
int sa_flags;//SA_SIGINFO表示能够接受数据
};
关于void(*sa_sigaction)(int, siginfo_t*, void *);
处理函数来说还需要有一些说明。void*
是接收到信号所携带的额外数据;而struct siginfo
这个结构体主要适用于记录接收信号的一些相关信息。
siginfo_t {
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal */
void *si_ptr; /* POSIX.1b signal */
int si_overrun; /* Timer overrun count; POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault */
int si_band; /* Band event */
int si_fd; /* File descriptor */
}
2.2.发送信号,并携带信息
int sigqueue(pid_t pid, int sig, const union sigval value);
union sigval {
int sival_int;
void *sival_ptr;
};
例程
/*信号处理函数注册*/
#include <signal.h>
#include <stdio.h>
//int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
/* struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);//与上一个2选1,此可携带信息
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};*/
void handle(int signum,siginfo_t *info,void *content)
{
printf("signum:%d\n",signum);
if(content != NULL){
printf("si_pid:%d\n",info->si_pid);
printf("si_int:%d\n",info->si_int);
printf("sival_int: %d\n",info->si_value.sival_int);//读取结构体里面的由sigqueue函数发送的联>
合体si_value里面的数据
}
}
int main()
{
printf("pid:%d\n",getpid());
struct sigaction act;
act.sa_sigaction = handle;//绑定操作函数
act.sa_flags = SA_SIGINFO;//表示能接受数据
sigaction(SIGUSR1,&act,NULL);//注册信号函数,接受该信号后采取结构体act里面的操作,第三个参数做数据备
份,不用则NULL
while(1);
return 0;
}
/*信号发送*/
#include <signal.h>
#include <stdio.h>
//int sigqueue(pid_t pid, int sig, const union sigval value);
/* union sigval {
int sival_int;
void *sival_ptr;
};*/
int main(int argc,int **argv)
{
int pid;
int signum;
signum = atoi(argv[1]);
pid = atoi(argv[2]);
union sigval value;
value.sival_int = 10;
sigqueue(pid,signum,value);
printf("pid:%d,done\n",getpid());
return 0;
}