3. 应用编程---信号 信号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 xxxxxx表示进程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//如果进程发起的系统调用有误那么内核将发送该信号给对应的进程。#defineSIGUNUSED312.信号的分类根据可靠性将信号分为可靠信号(1~31) 与不可靠信号(34~64)根据时间关系将信号分为非实时信号(等同于可靠信号)与 实时信号(等同于不可靠信号)2.1 获取信号的描述信息 —strsignal() / psignal()#includestring.h#includesignal.hchar*strsignal(intsig);// C库用于获取到参数sig指定的信号对应的描述信息返回该描述信息字符串的指针voidpsignal(intsig,constchar*s);// C库会将参数sig指定的信号对应的描述信息输出到标准错误并且还允许调用者添加一些输出信息由参数s指定3.信号集—sigemptyset() / sigfillset() / sigaddset() / sigdelset() / sigismember()#includesignal.hintsigemptyset(sigset_t*set);//系统调用用于初始化信号集使其不包含任何信号intsigfillset(sigset_t*set);//系统调用用于初始化信号集使其包含所有信号包括所有实时信号intsigaddset(sigset_t*set,intsignum);//系统调用用于向信号集中添加一个信号intsigdelset(sigset_t*set,intsignum);//系统调用用于向信号集中移除一个信号intsigismember(constsigset_t*set,intsignum);//系统调用用于测试某一个信号是否在指定的信号集中