1. 在 Linux 操作系统中,为了响应各种各样的事件,也是定义了非常多的信号。通过 kill -l 命令,查看所有的信号。
# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
2. 信号: 又称为 软件中断。
进程执行循环任务,突然 系统给他一个信号。进程会暂停任务,转而去执行 信号处理函数。之后 返回继续执行任务。
优点:实时性很高。
举个例子让我们更好的理解信号:
##### 发送方 ----------->发信号----------> 接收方######
接收方: 进程执行循环任务,发送方给他一个信号,进程会暂停任务,转而去执行 信号处理函数,之后 返回继续执行任务.
3. 信号种类: 他们都是正数
系统信号:
SIGINT: signal interrupt 打断信号, ctrl+c
SIGKILL: signal kill 杀死进程信号, kill -9 pid
SIGSEGV: signal segment 段错误信号
用户信号:
SIGUSR1 SIGUSR2
4. 进程对收到的每一种信号,都有默认的处理方式, 每种信号处理方式不一样
一般默认都是 exit( )
进程可否自己 指定某个信号的处理方式,这样是可以的
进程如何指定 某种信号的处理方法呢??
因此引入了函数:
/*指定 当进程接收到某种信号的时候,的处理方法
#include <signal.h>
sighandler_t signal(int signum, void (*signal_handle)(int ) );
signum,你要处理的信号
signal_handle,该信号的处理方法
*/
注意:信号的对象是已经在系统内核存在的,不需要像管道通信那样创建对象。因此只需要告诉内核发什么信号,要发信号给谁。
进入函数sighandler_t signal(int signum, void (*signal_handle)(int ) )之前;先了解简单的kill函数原理:
kill函数/命令产生信号
kill命令产生信号:kill -SIGKILL pid
kill函数:给指定进程发送指定信号(不一定杀死)
int kill(pid_t pid, int sig);
返回值说明:
成功执行时,返回0。失败返回-1,errno被设为以下的某个值 EINVAL:指定的信号码无效(参数 sig 不合法) EPERM;权限不够无法传送信号给指定进程 ESRCH:参数 pid 所指定的进程或进程组不存在
参数:
pid:可能选择有以下四种
1.pid>零时,pid是信号欲送往的进程的标识。
2. pid=零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
3. pid=-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
4. pid<-1时,信号将送往以-pid为组标识的进程。
草图:

5.实例:编写一个kill()函数, 功能是杀死另一个进程;
#include <stdio.h>
int main(int argc,char *argv[])
{
int sig;
int pid;
sig=atoi(argv[1]);
pid=atoi(argv[2]);
printf("sig = %d pid =%d",sig,pid);
kill(pid,sig);
return 0;
}
任意执行程序,可以看到该进程所对应得pid是:

![]()
![]()
获取的pid号是:4259

向该进程发送9这个信号,如何让这个进程接收到呢?就是该进程的pid。
![]()
可以发现,该进程已经结束,kill函数发送的信号,系统采用默认处理该信号。接下来我们可以采用自己的方式来处理接收到的信号。
6. 引入处理函数 signal();
该函数是一个C库函数,原型为void(*signal(int sig, void(*func)(int)))(int);
首先,void(*func)(int)表示的是一个函数指针,且该函数带有一个int型参数,返回值为void。然后,signal(int sig, void (*func)(int)),表示signal函数有两个参数,第一个参数为一个int型变量,第二个是一个函数指针,无返回值,带一个int参数。所以,void (*signal(xxx))(int)表示的是signal函数返回一个函数指针,该指针指向一个带一个int型变量,返回值为void的函数。
简单的说明:参数一:int sig 处理哪个信号; 参数二:void(*func)(int) 怎么处理这个信号。
参数:
- sig -- 在信号处理程序中作为变量使用的信号码。下面是一些重要的标准信号常量:
-
宏 信号 SIGABRT (Signal Abort) 程序异常终止。 SIGFPE (Signal Floating-Point Exception) 算术运算出错,如除数为 0 或溢出(不一定是浮点运算)。 SIGILL (Signal Illegal Instruction) 非法函数映象,如非法指令,通常是由于代码中的某个变体或者尝试执行数据导致的。 SIGINT (Signal Interrupt) 中断信号,如 ctrl-C,通常由用户生成。 SIGSEGV (Signal Segmentation Violation) 非法访问存储器,如访问不存在的内存单元。 SIGTERM (Signal Terminate) 发送给本程序的终止请求信号。 - func -- 一个指向函数的指针。它可以是一个由程序定义的函数,也可以是下面预定义的函数之一。
-
SIG_DEF 默认的信号处理程序。 SIG_IGN 忽视信号。 自定义信号处理函数指针 - 返回值
-
该函数返回一个指向信号处理程序的指针。出错则返回SIG_ERR(-1)。
例1:让 内核 停顿九秒在发送信号给进程,进程跳转myfun()函数,最后又回到进程继续执行
逻辑 草图

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void myfun(int signum)
{
int i=0;
while(i<10)
{
printf("process signal signum=%d\n",signum);
sleep(1);
i++;
}
return;
}
int main()
{
int i=0;
printf("signal brfore\n");
alarm(9); //先让内核停顿九秒
signal(14,myfun);
/*停顿九秒再让内核发送14这个信号给当前进程,当前进程,
当前进程跳到myfun函数,进行打印10次,又返回到原来的进程,继续打印,直到打印20次结束
printf("signal after\n");
*/
while(i<20){
i++;
printf("prcess things,i=%d\n",i);
sleep(1);
}
return 0;
}
运行结果:

例2:子进程向父进程发送信号
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
void myfun(int signum)
{
int i=0;
while(i<5)
{
printf("process signal signum=%d i=%d\n",signum,i);
sleep(1);
i++;
}
return;
}
int main()
{
pid_t pid=fork();
if(pid==0) //子进程
{
sleep(4);
kill(getppid(),10);
exit(0);
}
if(pid>0) //父进程
{
int i=0;
signal(10,myfun);
wait(NULL);
while(1)
{
printf("parents process things = %d\n",i);
i++;
sleep(1);
}
}
return 0;
}

本文详细介绍了Linux操作系统的信号机制,包括信号的种类、默认处理方式以及如何自定义信号处理。通过kill-l命令展示了所有可用信号,并举例说明了kill函数的使用。文章还探讨了信号处理函数signal(),并提供了示例代码展示如何捕获和处理特定信号,如SIGINT和SIGALRM。此外,还介绍了进程间通过信号进行通信的方式。
&spm=1001.2101.3001.5002&articleId=126445807&d=1&t=3&u=018f1b69661d45358898775dd0b0c3b6)
631

被折叠的 条评论
为什么被折叠?



