信号
对于 Linux来说,实际信号是软中断,许多重要的程序都需要处理信号。信号,为 Linux 提供了一种处理异步事件的方法。比如,终端用户输入了 ctrl+c 来中断程序,会通过信号机制停止一个程序。信号是进程间通信唯一的异步方式,是对中断的一种软件模拟(发送一个信号到这个进程去,我另一个进程铺捉到这个信号,来执行其他东西)
信号:分为3种模式,捕捉,忽略,系统默认
signal | kill | sigaction | sigqueue |
---|---|---|---|
kill -l 查看所有信号
kill -p pid 终止这个进程
signal注册信号
typedef void (*sighandler_t)(int);//这是typedef定义的函数指针,也就是sighandler具有函数指针的类型,可以sighandler p,这样在定义一个函数指针
sighandler_t signal(int signum, sighandler_t handler);//所以signal的返回类型是void*
brief:注册信号,也可以理解成我把接收到的信号,用于捕捉,忽略,还是等等
param:signum,即处理的信号,handler,我接收到signum这个信号用来进行其他事情
return:
kill给进程发送指定信号
int kill(pid_t pid, int sig);
brief:发送一个信号给这个pid
param:pid,即注册信号的pid,sig,执行信号的命令
return:成功返回0,失败返回-1
#include <signal.h>
#include <stdio.h>
void handler()
{
printf("error\n");
}
void main()
{
printf("pid = %d\n",getpid());
signal(2,handler);
while(1);
}
--------------------------------------------------------------------------------------------------------------------------------
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
void main(int argc,char **argv)
{
if(argc != 3)
{
printf("error");
exit(-1);
}
int pid;
int signum;
pid =atoi( argv[2]);//将字符型转换成int型
signum = atoi(argv[1]);
kill(pid,signum);
}
sigaction注册信号
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
struct sigaction { void (*sa_handler)(int); //信号处理程序,不接受额外数据,SIG_IGN 为忽略,SIG_DFL 为默认动作 void (*sa_sigaction)(int, siginfo_t *, void *); //信号处理程序,能够接受额外数据和sigqueue配合使用 sigset_t sa_mask;//阻塞关键字的信号集,可以再调用捕捉函数之前,把信号添加到信号阻塞字,信号捕捉函数返回之前恢复为原先的值。 int sa_flags;//影响信号的行为SA_SIGINFO表示能够接受数据 };
struct sigaction {
void (sa_handler)(int);//跟signal处理函数一样,不能携带消息 void (sa_sigaction)(int, siginfo_t *, void );//处理函数,且可以携带消息
}
补充一下siginfo结构体: siginfo_t { int si_signo; /* Signal number */ int si_errno; /* An errno value */ int si_code; /* Signal code */ 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 */ void * si_addr; /* Memory location which caused fault */ int si_band; /* Band event */ int si_fd; /* File descriptor */ }
brief:接收信号,且接收数据
param:signum,要处理的信号,act,是一个结构体指针,用于接收到这个消息来干嘛,oldact,备份
return:
sigqueue发送指定信号(和数据)
int sigqueue(pid_t pid, int sig, const union sigval value);
union sigval {
int sival_int;//整型数据 void *sival_ptr;//字符数据
};
brief:用于发送指定信号给id,和数据
param:pid,需要发送信号的id,sig,要发送的信号,value,需要发送的数据,这个数据存在联合体
return:成功返回0,失败返回-1
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
void handler(int signum,siginfo_t * info,void *ucontext)
{
printf("signum: %d\n",signum);
if(ucontext != NULL)//不等于NULL才有数据
{
printf("get data:%d",info ->si_int);//si_int和si_value.sival_int是一样的--针对额外数据是int的时候。
}
}
void main()
{
printf("pid : %d\n",getpid());
struct sigaction act;
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO;//接受数据
sigaction(10,&act,NULL);// SIGUSR1,用户自定义信号
while(1);
}
--------------------------------------------------------------------------------------------------------------------------------
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
void main(int argc,char ** argv )
{
if(argc != 3)
{
printf("error");
exit(-1);
}
int pid;
int signum;
union sigval value;
value.sival_int = 666;
pid = atoi(argv[2]);
signum = atoi(argv[1]);
sigqueue(pid,signum,value);
}
sprintf实现kill指令
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void main(int argc,char **argv )
{
int pid;
int signum;
char cmd[128];
pid = atoi(argv[2]);//atoi show char zhuanhuan int
signum = atoi(argv[1]);
sprintf(cmd,"kill -%d %d",signum,pid);//把数据打印到字符串上去
system(cmd);
}