信号
- 信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式
- 信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。
- 如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。
响应
用户进程对信号的响应方式:
- 忽略信号:对信号不做任何处理,但是有两个信号不能忽略:即SIGKILL及SIGSTOP。
- 捕捉信号:定义信号处理函数,当信号发生时,执行相应的处理函数。
- 执行缺省操作:Linux对每种信号都规定了默认操作
种类:
- SIGINT:ctrl+c 终止信号
- SIGQUIT:ctrl+\ 终止信号
- SIGTSTP:ctrl+z 暂停信号
- SIGALRM:闹钟信号 收到此信号后定时结束,结束进程
- SIGCHLD:子进程状态改变,父进程收到信号
- SIGKILL:杀死信号
声明
/*
功能:信号发送
-参数:pid:指定进程
-sig:要发送的信号
-返回值:成功 0;失败 -1
*/
int kill(pid_t pid, int sig);
/*
功能:进程向自己发送信号
-参数:sig:信号
-返回值:成功 0;失败 -1
*/
int raise(int sig);
/*
功能:在进程中设置一个定时器
-参数:seconds:定时时间,单位为秒
-返回值:如果调用此alarm()前,进程中已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。
*/
unsigned int alarm(unsigned int seconds)
注意:一个进程只能有一个闹钟时间。如果在调用alarm时已设置过闹钟时间,则之前的闹钟时间被新值所代替
//功能:用于将调用进程挂起直到收到信号为止。
int pause(void);
/*
功能:信号处理函数
参数:
-signum:要处理的信号//不能是SIGKILL和SIGSTOP
-handler:SIG_IGN:忽略该信号。
-SIG_DFL:采用系统默认方式处理信号。
自定义的信号处理函数指针
返回值:成功:设置之前的信号处理方式;失败:SIG_ERR
*/
void (*signal(int signum, void (*handler)(int)))(int);
// 或者:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
//给自己发送异常终止信号,(6.SIGABRO)终止并产生core文件。
void abort(void);
例子:
kill
- kill 函数发送杀死pid指向的进程的信号
- raise 发送杀死自己的信号
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t pid;
pid = fork();
if(pid < 0)
{
perror("fork fail ");
exit(1);
}
else if(pid == 0)
{
printf("child \n");
}
else
{
kill(pid,SIGKILL);
//(此处pid是子进程的进程号)杀死 pid 发送进程的信号,kill 给其他进程发送信号,指定进程号
printf("child killed\n");
sleep(1);
printf("father \n");
wait(NULL); //等待子进程结束,并回收子进程资源
raise(SIGKILL); //杀死自己的信号,函数raise 给自己发送信号
}
return 0;
}
alarm
- 定时器的使用
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
printf("%d\n",alarm(7)); //7 秒定时器,此时返回 0 ,前面没有使用定时器
sleep(2); //睡 2 秒
while(1)
{
printf("%d\n",alarm(3)); //重新设置定时器值为 3 ,返回上次定时器剩余的时间,7-2 = 5
sleep(7); //睡7秒,后会结束进程
}
return 0;
}
signal
例子1 :
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void handler(int arg)
{
printf("\nctrl + c\n");
// exit(1);
// raise(SIGKILL);
kill(getpid(),9); //9表示 SIGKILL 杀死信号
}
int main(int argc, const char *argv[])
{
signal(SIGINT,handler);
//定义自己的处理信号,当SIGINT信号发生时,调用 handler 函数处理
while(1);
return 0;
}
例子2 :
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main(int argc, const char *argv[])
{
signal(SIGINT,SIG_IGN);// ctrl +c 信号被忽略,SIG_IGN 表示忽略该信号
while(1);
return 0;
}
//测试: 通过 ctrl + c 信号不能终止这个进程