信号概念及信号编程实战1
1相关概念:
软中断信号(signal,简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。
收 到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:
第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理。
第二种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。
第三种方法是,对该信号的处理保留系统的默认值,对大部分的信 号的缺省操作是使得进程终止。此方法为缺省操作。进程通过系统调用signal来指定进程对某个信号的处理行为。
在进程表的表项中有一个软中断信号域,该域中每一位对应一个信号,当有信号发送给进程时,对应其位置位。由此可以看出,进程对不同的信号可以同时保留,但对于同一个信号,进程并不知道在处理之前来过多少个。
信号类型
发出信号的原因很多,这里按发出信号的原因简单分类,以了解各种信号:
(1) 与进程终止相关的信号。当进程退出,或者子进程终止时,发出这类信号。
(2) 与进程例外事件相关的信号。如进程越界,或企图写一个只读的内存区域(如程序正文区),或执行一个特权指令及其他各种硬件错误。
(3) 与在系统调用期间遇到不可恢复条件相关的信号。如执行系统调用exec时,原有资源已经释放,而系统资源又已经耗尽。
(4) 与执行系统调用时遇到非预测错误条件相关的信号。如执行一个并不存在的系统调用。
(5) 在用户态下的进程发出的信号。如进程调用系统调用kill向其他进程发送信号。
(6) 与终端交互相关的信号。如用户关闭一个终端,或按下break键等情况。
2信号初级api signal与kill的介绍
signal原型:typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
kill原型:int kill(pid_t pid, int sig);
通过输入ps -aux|grep a.out 可以查询相关应用程序的pid号。
3signal与kill相关编程的实战
signal:
#include <stdio.h>
#include <signal.h>
void handler(int signum)
{
printf(“get signum=%d\n”,signum);
switch(signum)
{
case 2:
printf(“SIGINT\n”);
break;
case 9:
printf(“SIGKILL\n”);
break;
case 10:
printf(“SIGUSR1\n”);
break;
}
printf(“never quit\n”);
}
int main()
{
signal(SIGINT,handler);
signal(SIGKILL,handler);
signal(SIGUSR1,handler);
while(1);
return 0;
}
可以看到这是一个while(1)死循环,在linux跑起来之后,将不会退出,平时我们可以按ctrl+c退出此类死循环,但是此时无法退出,因为按下ctrl+c后,将会给内核传递相关指令,使得不能直接退出,这个时候我们就需要使用kill指令了。可以直接kill-9加进程id号来杀死进程。我们也可以自己实现kill命令的编程。
2kill命令的编程实现:
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
int main(int argc,char **argv)
{
int signum;
int pid;
char cmd[128];
signum=atoi(argv[1]);
pid=atoi(argv[2]);
printf(“number=%d,pid=%d\n”,signum,pid);
// kill(pid,signum);
sprintf(cmd,“kill -%d %d”,signum,pid);
system(cmd);
printf(“send signal success\n”);
return 0;
}
用此代码即可实现kill命令的实现,这里我们有两种方式去实现kill命令,一是直接调用kill api来实现,二是通过system命令来间接调用kill命令,如此就完成了信号的传递。