1、信号相关概念
1、 信号是 Linux 进程间通信的最古老的方式之一,是事件发生时对进程的通知机制,有时也称之为软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。
2、发往进程的诸多信号,通常都是源于内核。引发内核为进程产生信号的各类事件如下:
对于前台进程,用户可以通过输入特殊的终端字符来给它发送信号。比如输入Ctrl+C 通常会给进程发送一个中断信号。
硬件发生异常,即硬件检测到一个错误条件并通知内核,随即再由内核发送相应信号给相关进程。比如执行一条异常的机器语言指令,诸如被 0 除,或者引用了无法访问的内存区域。
系统状态变化,比如 alarm 定时器到期将引起 SIGALRM 信号,进程执行的 CPU 时间超限,或者该进程的某个子进程退出。
运行 kill 命令或调用 kill 函数。
3、使用信号的两个主要目的是:
让进程知道已经发生了一个特定的事情。
强迫进程执行它自己代码中的信号处理程序。
4、信号的特点:
简单
不能携带大量信息
满足某个特定条件才发送
优先级比较高
5、查看系统定义的信号列表:kill –l
6、 前 31 个信号为常规信号,其余为实时信号。
2、信号相关函数
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
-功能:给任何进程的pid, 发送任何信号sig
-参数:
-pid:需要发送的进程id;
>0:将信号发送给指定的进程
=0:将信号发送给当前进程组
=-1:将信号发送给每一个权限接受这个信号的进程
<-1:这个pid=某个进程组的ip取反(-12345)
-sig:需要发送的信号的编号或者宏值,0表示不发送任何信号
-sig:需要发送的信号的编号或者宏值
kill(getppid(),9);
kill(getpid(),9);
int raise(int sig);
-功能:给当前进程发送信号
-参数:
-sig:要发送的信号
-返回值:
-成功 0
-失败 非0
void abort(void):
-功能:发送SIGABRT信号给当前进程,杀死当前进程
kill(getpid(),SIGABRT);
*/
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<unistd.h>
int main()
{
pid_t pid=fork();
if(pid==0)
{
//子进程
int i=0;
for(i=0;i<5;i++)
{
printf("child process");
sleep(1);
}
}
else if(pid>0)
{
//父进程
printf("parent process\n");
sleep(2);
printf("kill child process now\n");
kill(pid,SIGINT);
}
return 0;
}
/*
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
-功能:给任何进程的pid, 发送任何信号sig
-参数:
-pid:需要发送的进程id;
>0:将信号发送给指定的进程
=0:将信号发送给当前进程组
=-1:将信号发送给每一个权限接受这个信号的进程
<-1:这个pid=某个进程组的ip取反(-12345)
-sig:需要发送的信号的编号或者宏值,0表示不发送任何信号
-sig:需要发送的信号的编号或者宏值
kill(getppid(),9);
kill(getpid(),9);
int raise(int sig);
-功能:给当前进程发送信号
-参数:
-sig:要发送的信号
-返回值:
-成功 0
-失败 非0
void abort(void):
-功能:发送SIGABRT信号给当前进程,杀死当前进程
kill(getpid(),SIGABRT);
3、ALARM函数
/*
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
-功能:设置定时器(闹钟),函数调用,开始倒计时,当倒计时为0时
函数会发送一个信号:SIGALARM
-参数:
seconds:倒计时时长,单位:秒。如果参数为0,定时器无效(不进行倒计时)
取消一个定时器,通过alarm(0).
-返回值:
-倒计时剩余的时间
-SIGALARM:默认终止当前进程,每一个进程有且只有唯一一个定时器。
alarm(10); ->返回0
过了1s
alarm(5); ->返回9
*/
#include<stdio.h>
#include<unistd.h>
int main()
{
int seconds=alarm(5);
printf("seconds =%d\n",seconds); //0
sleep(2);
seconds=alarm(2); //不阻塞
printf("seconds =%d\n",seconds); //
while(1)
{
}
return 0;
}
4、SIGALRM 函数
/*
#include <sys/time.h>
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
- 功能:设置定时器(闹钟)。可以替代alarm函数。精度微妙us,可以实现周期性定时
- 参数:
- which : 定时器以什么时间计时
ITIMER_REAL: 真实时间,时间到达,发送 SIGALRM 常用
ITIMER_VIRTUAL: 用户时间,时间到达,发送 SIGVTALRM
ITIMER_PROF: 以该进程在用户态和内核态下所消耗的时间来计算,时间到达,发送 SIGPROF
- new_value: 设置定时器的属性
struct itimerval { // 定时器的结构体
struct timeval it_interval; // 每个阶段的时间,间隔时间
struct timeval it_value; // 延迟多长时间执行定时器
};
struct timeval { // 时间的结构体
time_t tv_sec; // 秒数
suseconds_t tv_usec; // 微秒
};
过10秒后,每个2秒定时一次
- old_value :记录上一次的定时的时间参数,一般不使用,指定NULL
- 返回值:
成功 0
失败 -1 并设置错误号
*/
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
// 过3秒以后,每隔2秒钟定时一次
int main() {
struct itimerval new_value;
//设置值
new_value.it_interval.tv_sec=2;
new_value.it_interval.tv_usec=0;
//设置延迟时间
new_value.it_value.tv_sec=3;
new_value.it_value.tv_usec=0;
int ret=setitimer(ITIMER_REAL,&new_value,NULL); //非阻塞的
printf("定时器开始了...\n");
if(ret==-1)
{
perror("setitimer");
exit(0);
}
getchar();
return 0;
}