表头文件
#include
定义函数
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
函数说明——设置信号处理方式
signum——收到的指令
handler——执行的命令(执行名为handler的函数)
返回值——成功返回前一次调用signal函数时传入的函数指针,如果是第一次调用则返回SIG_DFL。出错返回SIG_ERR并设置errno
2.示例
#include
#include
void handler(int signum)
{
printf("get signum: %d\n",signum);
printf("never quit\n");
}
int main()
{
signal(SIGINT,handler);
while(1);
return 0;
}
运行结果:但按下ctrl+c时无法终止进程
get signum: 2
never quit
表头文件
#include
定义函数
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
函数说明——检查或修改与指定信号相关联的处理动作(可同时两种操作)。当接收到signum信号,程序会进入act.sa_handler或act.sa_sigaction这个函数进行工作
signum——捕捉到的信号。产生信号函数必须和此信号相同才能正常响应信号
act——指定新的信号处理的数据
oldact —— 之前处理过的信息的处理的数据
返回值——成功返回0。失败返回-1,错误原因置于errno中
2.参数取值
const struct sigaction默认如下
struct sigaction {
void (*sa_handler)(int);//信号处理程序接受1个参数:
//void handler(int sig)
void (*sa_sigaction)(int, siginfo_t *, void *);//信号处理程序接受3个参数:
//void handler(int sig, siginfo_t *info, void *ucontext)
sigset_t sa_mask;
int sa_flags;//一般为SA_SIGINFO:信号处理程序接受3个参数
void (*sa_restorer)(void);
};
在这其中siginfo_t 结构体默认如下
siginfo_t {
int si_signo;/*信号数*/
int si_errno;/*一个errno值*/
int si_code;/*信号代码*/
int si_trapno;/*触发的陷阱数
来自硬件信号
( 未使用的大多数架构)*/
pid_t si_pid;/*发送进程ID */
uid_t si_uid;/*发送进程的真实用户ID */
int si_status;/*退出值或信号*/
clock_t si_utime;/*用户时间消耗*/
clock_t si_stime;/*系统时间消耗*/
sigval_t si_value;/*信号值*/
int si_int;/* POSIX.1b信号*/
void * si_ptr;/* POSIX.1b信号*/
int si_overrun;/*定时器超时计数;POSIX。1 b定时器*/
int si_timerid;/*定时器标识;POSIX.1b计时器*/
void * si_addr;/*导致错误的内存位置*/
long si_band;/* Band event (was int in
glibc 2.3.2 and earlier) */
int si_fd;/*文件描述符*/
short si_addr_lsb;/*地址的最小有效位
( Linux 2.6.32版本后)*/
void * si_lower;/*地址违规时的下界
(Linux 3.19版本后)*/
void * si_upper;/*地址违规的上界
(Linux 3.19)*/
int si_pkey;/* PTE上的保护键导致错误(Linux 4.6)*/
void * si_call_addr;/*系统调用指令的地址
(Linux 3.5)*/
int si_syscall;/*系统呼叫试图数
(Linux 3.5)*/
unsigned int si_arch;/*系统调用尝试的体系结构(Linux 3.5)*/
}
3.示例
1个参数:
struct sigaction act;
act.sa_handler=handler;//接收到信号后程序进入handler函数
act.sa_flags=0;//信号处理程序接受1个参数
sigaction(SIGUSR1,&act,NULL);//有信号来进入handler函数
//void handler(int sig);
3个参数:
struct sigaction act;
act.sa_sigaction=handler;//接收到信号后程序进入handler函数
act.sa_flags=SA_SIGINFO;//信号处理程序接受3个参数
sigaction(SIGUSR1,&act,NULL);//有信号来进入handler函数
//void handler(int sig, siginfo_t *info, void *ucontext);
表头文件
#include
定义函数
int sigqueue(pid_t pid, int sig, const union sigval value);
函数说明——向指定进程产生一个指定信号
pid——接收信号程序的进程号
sig——传递的信号。必须和signum配置的信号相同sigaction才能正常响应此信号
value——传递的值,默认如下
返回值——成功返回0,表示信号成功地排队到接收端的过程。否错误返回-1,并设置errno来指示错误
//const union sigval结构体默认如下
union sigval {
int sival_int;
void *sival_ptr;
};
2.示例
最后信号例程演示
接收到信号工作的程序1:
#include
#include
#include
#include
void handler(int sig, siginfo_t *info, void *ucontext)
{
printf("sig=%d\n",sig);
if(ucontext!=NULL)
{
printf("get data %d\n",info->si_int);
printf("get data %d\n",info->si_value.sival_int);
// printf("get data %p\n",(char *)(info->si_value.sival_ptr));
//接触到信号后,结构体里面的数据确实有ptr了,但是你只能输出这个地址,不能读,不能写,因为在这个进程中认为这个地址没有读写权限,直接读和写是违法操作
printf("from:%d\n",info->si_pid);
}
}
int main()
{
printf("getpid=%d\n",getpid());
struct sigaction act;
act.sa_sigaction=handler;//接收到信号后程序进入handler函数
act.sa_flags=SA_SIGINFO;//信号处理程序接受3个参数
sigaction(SIGUSR1,&act,NULL);//有信号会进行act相关函数进行工作,产生信号程序产生的信号**必须**为SIGUSR1(10)sigaction才能正确响应
while(1);
return 0;
}
产生信号程序2:
#include
#include
#include
#include
int main(int argc,char **argv)
{
int pid=atoi(argv[1]);//响应进程ID号
int sigunm=atoi(argv[2]);//给响应进程一个信号
union sigval value;
value.sival_int = 100;//响应程序接收到**正确**信号后可以读这个值
// value.sival_ptr="HE";//字符串的首地址赋值给ptr
// printf("%d,%p\n",value.sival_int,(char *)(value.sival_ptr));
sigqueue(pid,sigunm,value);//产生一个信号
printf("pid=%d\n",getpid());
return 0;
}
运行结果:先运行程序1等待接受信号,再运行程序2产生信号
程序1:运行命令:./demo1
程序2:运行命令:./demo2 9585 10
程序2:输出信息:pid=9587
程序1:输出信息:
sig=10
get data 100
get data 100
from:9625
大家不妨试一试代码执行效果