3. 应用编程---信号
📅 2026/7/4 19:58:35
👁️ 阅读次数
📝 编程学习
信号
- 1. 信号 的产生与处理
- 2. 信号 的分类
- 2.1 获取信号的描述信息 ---strsignal() / psignal()
- 3. 信号集---sigemptyset() / sigfillset() / sigaddset() / sigdelset() / sigismember()
1.信号的产生与处理
#defineSIGHUP1/* Hangup (POSIX). */#defineSIGINT2// 当用户在终端按下中断字符(通常是CTRL + C)时,内核将发送SIGINT信号给前台进程组中的每一个进程。该信号的系统默认操作是终止进程的运行。所以通常我们都会使用CTRL + C来终止一个占用前台的进程,原因在于大部分的进程会将该信号交给系统去处理,从而执行该信号的系统默认操作。#defineSIGQUIT3//当用户在终端按下退出字符(通常是CTRL + \)时,内核将发送SIGQUIT信号给前台进程组中的每一个进程。该信号的系统默认操作是终止进程的运行、并生成可用于调试的核心转储文件。进程如果陷入无限循环、或不再响应时,使用SIGQUIT信号就很合适。所以对于一个前台进程,既可以在终端按下中断字符CTRL + C、也可以按下退出字符CTRL + \来终止,当然前提条件是,此进程会将SIGINT信号或SIGQUIT信号交给系统处理(也就是没有将信号忽略或捕获),进入执行该信号所对应的系统默认操作。#defineSIGILL4//如果进程试图执行非法(即格式不正确)的机器语言指令,系统将向进程发送该信号。该信号的系统默认操作是终止进程的运行。#defineSIGTRAP5/* Trace trap (POSIX). */#defineSIGABRT6//当进程调用abort()系统调用时(进程异常终止),系统会向该进程发送SIGABRT信号。该信号的系统默认操作是终止进程、并生成核心转储文件。#defineSIGIOT6/* IOT trap (4.2 BSD). */#defineSIGBUS7//产生该信号(总线错误,bus error)表示发生了某种内存访问错误。该信号的系统默认操作是终止进程。#defineSIGFPE8//该信号因特定类型的算术错误而产生,譬如除以0。该信号的系统默认操作是终止进程。#defineSIGKILL9//此信号为“必杀(sure kill)”信号,用于杀死进程的终极办法,此信号无法被进程阻塞、忽略或者捕获,故而“一击必杀”,总能终止进程。使用SIGINT信号和SIGQUIT信号虽然能终止进程,但是前提条件是该进程并没有忽略或捕获这些信号,如果使用SIGINT或SIGQUIT无法终止进程,那就使用“必杀信号”SIGKILL吧。#defineSIGUSR110//该信号和SIGUSR2信号供程序员自定义使用,内核绝不会为进程产生这些信号,在我们的程序中,可以使用这些信号来互通通知事件的发生,或是进程彼此同步操作。该信号的系统默认操作是终止进程。#defineSIGSEGV11//这一信号非常常见,当应用程序对内存的引用无效时,操作系统就会向该应用程序发送该信号。引起对内存无效引用的原因很多,C语言中引发这些事件往往是解引用的指针里包含了错误地址(譬如,未初始化的指针),或者传递了一个无效参数供函数调用等。该信号的系统默认操作是终止进程。#defineSIGUSR212//与SIGUSR1信号相同。#defineSIGPIPE13//涉及到管道和socket,当进程向已经关闭的管道、FIFO 或套接字写入信息时,那么系统将发送该信号给进程。该信号的系统默认操作是终止进程。#defineSIGALRM14//与系统调用alarm()或setitimer()有关,应用程序中可以调用alarm()或setitimer()函数来设置一个定时器,当定时器定时时间到,那么内核将会发送SIGALRM信号给该应用程序。该信号的系统默认操作是终止进程。#defineSIGTERM15//这是用于终止进程的标准信号,也是kill命令所发送的默认信号(kill xxx,xxx表示进程pid),有时我们会直接使用"kill -9 xxx"显式向进程发送SIGKILL信号来终止进程,然而这一做法通常是错误的,精心设计的应用程序应该会捕获SIGTERM信号、并为其绑定一个处理函数,当该进程收到SIGTERM信号时,会在处理函数中清除临时文件以及释放其它资源,再而退出程序。如果直接使用SIGKILL信号终止进程,从而跳过了SIGTERM信号的处理函数,通常SIGKILL终止进程是不友好的方式、是暴力的方式,这种方式应该作为最后手段,应首先尝试使用SIGTERM,实在不行再使用最后手段SIGKILL。#defineSIGSTKFLT16/* Stack fault. */#defineSIGCLDSIGCHLD//与SIGCHLD信号同义。#defineSIGCHLD17//当父进程的某一个子进程终止时,内核会向父进程发送该信号。当父进程的某一个子进程因收到信号而停止或恢复时,内核也可能向父进程发送该信号。注意这里说的停止并不是终止,你可以理解为暂停。该信号的系统默认操作是忽略此信号,如果父进程希望被告知其子进程的这种状态改变,则应捕获此信号。#defineSIGCONT18//将该信号发送给已停止的进程,进程将会恢复运行。当进程接收到此信号时并不处于停止状态,系统默认操作是忽略该信号,但如果进程处于停止状态,则系统默认操作是使该进程继续运行。#defineSIGSTOP19//这是一个“必停”信号,用于停止进程(注意停止不是终止,停止只是暂停运行、进程并没有终止),应用程序无法将该信号忽略或者捕获,故而总能停止进程。#defineSIGTSTP20//这也是一个停止信号,当用户在终端按下停止字符(通常是CTRL + Z),那么系统会将SIGTSTP信号发送给前台进程组中的每一个进程,使其停止运行。#defineSIGTTIN21/* Background read from tty (POSIX). */#defineSIGTTOU22/* Background write to tty (POSIX). */#defineSIGURG23/* Urgent condition on socket (4.2 BSD). */#defineSIGXCPU24//当进程的CPU时间超出对应的资源限制时,内核将发送此信号给该进程。#defineSIGXFSZ25/* File size limit exceeded (4.2 BSD). */#defineSIGVTALRM26//应用程序调用setitimer()函数设置一个虚拟定时器,当定时器定时时间到时,内核将会发送该信号给进程。#defineSIGPROF27/* Profiling alarm clock (4.2 BSD). */#defineSIGWINCH28//在窗口环境中,当终端窗口尺寸发生变化时(譬如用户手动调整了大小,应用程序调用ioctl()设置了大小等),系统会向前台进程组中的每一个进程发送该信号。#defineSIGPOLLSIGIO//同SIGIO一样#defineSIGIO29//用于提示一个异步IO事件的发生,譬如应用程序打开的文件描述符发生了I/O事件时,内核会向应用程序发送SIGIO信号。#defineSIGPWR30/* Power failure restart (System V). */#defineSIGSYS31//如果进程发起的系统调用有误,那么内核将发送该信号给对应的进程。#defineSIGUNUSED31
2.信号的分类
根据可靠性将信号分为,可靠信号(1~31) 与不可靠信号(34~64)
根据时间关系将信号分为,非实时信号(等同于可靠信号)与 实时信号(等同于不可靠信号)
2.1 获取信号的描述信息 —strsignal() / psignal()
#include<string.h>#include<signal.h>char*strsignal(intsig);// C库,用于获取到参数sig指定的信号对应的描述信息,返回该描述信息字符串的指针voidpsignal(intsig,constchar*s);// C库,会将参数sig指定的信号对应的描述信息输出到标准错误,并且还允许调用者添加一些输出信息,由参数s指定
3.信号集—sigemptyset() / sigfillset() / sigaddset() / sigdelset() / sigismember()
#include<signal.h>intsigemptyset(sigset_t*set);//系统调用,用于初始化信号集,使其不包含任何信号intsigfillset(sigset_t*set);//系统调用,用于初始化信号集,使其包含所有信号(包括所有实时信号)intsigaddset(sigset_t*set,intsignum);//系统调用,用于向信号集中添加一个信号intsigdelset(sigset_t*set,intsignum);//系统调用,用于向信号集中移除一个信号intsigismember(constsigset_t*set,intsignum);//系统调用,用于测试某一个信号是否在指定的信号集中
编程学习
技术分享
实战经验