进程间信号(软中断)
信号:信号是unix中最古老的进程通信的一种方式,他是软件层次上对中断机制的模拟,是一种异步通信方式,信号可以实现用户空间进程和内核空间进程的交互,内核进程可以利用他通知用户空间进程发生了哪些系统事件,我们可以任何时候给进程发送信号而无需知道进程的状态,如果进程当前并未处于执行态,则信号则会由内核保存起来,如果进程是阻塞状态,那么信号传递会被延迟,直到阻塞结束时才会传递给进程。
信号用来通知一个事件的发生,会打断当前操作,去处理这个时间
信号也有生命周期:产生->注册->注销->处理 (阻塞:阻止信号被处理)
操作系统中定义的信号种类:
通过kill -l可以查看信号种类:总共有62种信号
两大类型:
1-31:不可靠信号
所谓不可靠信号就是,该信号发现有同样的信号在进程中注册,就会自己忽略,若上一个信号还没有
来得及注销,就会导致信号丢失。
34-64:可靠信号
当可靠信号发送给进程时,不管该信号是否已经在进程中注册,都会被再注册一次,因此信号不会丢 失,所有可靠信号都支持排队。
用户进程对信号的响应有3种:
1.忽略信号,对信号不做任何处理(有两个信号是不能被忽略的,即SIGKILL,SIGSTOP)
2.捕捉信号,定义信号处理函数,当信号发出时,执行相应的自定义处理函数
3.执行缺省操作,linux对每种信号都规定了默认的操作
信号的产生:
硬件产生:ctrl+c ,ctrl+|,ctrl+z
1.ctrl+c 发出SIGINT信号,终端驱动程序发送此信号到前台进程
2.ctrl+| 发出SIGQUIT信号,该信号与SIGINT类似
3.ctrl+z 发出SIGTSTP信号,用于交互停止进程
软件产生:kill -signum pid //向进程发送signum信号
#include <signal.h>
#include <sys/types.h>
kill():
int kill(pid_t pid,int sig)
//kill()函数与kill系统命令一样,可以发送信号给进程组,他不仅可以发送SIGKILL(立即结束进程的运行,
//不可以被阻塞,忽略或处理)信号,还可以向进程发送其他信号
raise():
int raise(int sig)
//与kill()函数不同的是,raise()函数允许进程向自身发送信号
#include <stdlib.h>
abort():
void abort(void)
//以异常方式结束进程,将SIGABRT信号发送给进程,程序异常终止。此时所有已经打开的文件流自动关闭
//所有缓冲区数据自动写回
#include <unistd.h>
sleep():
unsigned int sleep(unsigned int seconds)
//sleep()会令目前的进程暂停,直到达到参数seconds所指定的时间,或是被信号所中断
#include <unistd.h>
alarm():
unsigned int alarm(unsigned int seconds)
//seconds:指定的秒数,系统进过seconds秒向该进发送SIGALRM信号
//(一个进程只能有一个闹钟时间,如果调用alarm()之前已经设置了闹钟时间,那么任何以前的闹钟时间都会被新值所代替)
pause():
int pause(void)
//此函数用于将进程挂起,直到捕捉到信号为止,通常用来判断信号是否到达
//kill() and raise()
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
int main()
{
pid_t pid = fork();
int ret;
if(pid < 0)
{
perror(“fork error”);
return -1;
}
else if(pid == 0)
{
printf("child(pid:%d)waiting for signal\n",getpid());
raise(SIGSTOP);//子进程暂停
exit(0);
}
else
{
if(!(waitpid(pid,NULL,WNOHANG)))
{
if(ret = kill(pid,SIGKILL) == 0)
{
printf("parent kill %d\n",pid);
}
}
waitpid(pid,NULL,0);//阻塞等待子进程退出
exit(0);
}
}
//利用alarm()和pause()实现sleep()函数的功能
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int ret = alarm(5); //设置一个定时器
pause(); //捕捉定时器信号
printf("i have been wake up\n");
}