百度怎么自己做网站吗,网站模板 招聘,个人如何做微信小程序,江门网站制作开发最近同事的程序设计过程中用到了Linux的signal机制#xff0c;从而引发了我对Linux中signal机制的思考。Signal机制在Linux中是一个非常常用的进程间通信机制#xff0c;很多人在使用的时候不会考虑该机制是具体如何实现的。signal机制可以被理解成进程的软中断#xff0c;因…最近同事的程序设计过程中用到了Linux的signal机制从而引发了我对Linux中signal机制的思考。Signal机制在Linux中是一个非常常用的进程间通信机制很多人在使用的时候不会考虑该机制是具体如何实现的。signal机制可以被理解成进程的软中断因此在实时性方面还是相对比较高的。Linux中signal机制的模型可以采用下图进行描述。 个进程都会采用一个进程控制块对其进行描述进程控制块中设计了一个signal的位图信息其中的每位与具体的signal相对应这与中断机制是保持一致的。当系统中一个进程A通过signal系统调用向进程B发送signal时设置进程B的对应signal位图类似于触发了signal对应中断。发送signal只是“中断”触发的一个过程具体执行会在两个阶段发生
1、 system call返回。进程B由于调用了system call后从内核返回用户态时需要检查他拥有的signal位图信息表此时是一个执行点。
2、 中断返回。进程被系统中断打断之后系统将CPU交给进程时需要检查即将执行进程所拥有的signal位图信息表此时也是一个执行点。 综上所述signal的执行点可以理解成从内核态返回用户态时在返回时如果发现待执行进程存在被触发的signal那么在离开内核态之后也就是将CPU切换到用户模式执行用户进程为该signal绑定的signal处理函数从这一点上看signal处理函数是在用户进程上下文中执行的。当执行完signal处理函数之后再返回到用户进程被中断或者system call软中断或者指令陷阱打断的地方。 Signal机制实现的比较灵活用户进程由于中断或者system call陷入内核之后将断点信息都保存到了堆栈中在内核返回用户态时如果存在被触发的signal那么直接将待执行的signal处理函数push到堆栈中在CPU切换到用户模式之后直接pop堆栈就可以执行signal处理函数并且返回到用户进程了。Signal处理函数应用了进程上下文并且应用实际的中断模拟了进程的软中断过程。 最近写程序各种bug各种错有一回程序莫名退出没报错也没产生日志和core文件貌似正常退出一样。
但又不是在程序全部走完后退出中途莫名退出这就叫我想到了signal应该是某些函数错误后发送kill信号给主进程然后退出。
现在总结下signal各种类型 Signal Description SIGABRT 由调用abort函数产生进程非正常退出 SIGALRM 用alarm函数设置的timer超时或setitimer函数设置的interval timer超时 SIGBUS 某种特定的硬件异常通常由内存访问引起 SIGCANCEL 由Solaris Thread Library内部使用通常不会使用 SIGCHLD 进程Terminate或Stop的时候SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略 SIGCONT 当被stop的进程恢复运行的时候自动发送 SIGEMT 和实现相关的硬件异常 SIGFPE 数学相关的异常如被0除浮点溢出等等 SIGFREEZE Solaris专用Hiberate或者Suspended时候发送 SIGHUP 发送给具有Terminal的Controlling Process当terminal被disconnect时候发送 SIGILL 非法指令异常 SIGINFO BSD signal。由Status Key产生通常是CTRLT。发送给所有Foreground Group的进程 SIGINT 由Interrupt Key产生通常是CTRLC或者DELETE。发送给所有ForeGround Group的进程 SIGIO 异步IO事件 SIGIOT 实现相关的硬件异常一般对应SIGABRT SIGKILL 无法处理和忽略。中止某个进程 SIGLWP 由Solaris Thread Libray内部使用 SIGPIPE 在reader中止之后写Pipe的时候发送 SIGPOLL 当某个事件发送给Pollable Device的时候发送 SIGPROF Setitimer指定的Profiling Interval Timer所产生 SIGPWR 和系统相关。和UPS相关。 SIGQUIT 输入Quit Key的时候CTRL\发送给所有Foreground Group的进程 SIGSEGV 非法内存访问 SIGSTKFLT Linux专用数学协处理器的栈异常 SIGSTOP 中止进程。无法处理和忽略。 SIGSYS 非法系统调用 SIGTERM 请求中止进程kill命令缺省发送 SIGTHAW Solaris专用从Suspend恢复时候发送 SIGTRAP 实现相关的硬件异常。一般是调试异常 SIGTSTP Suspend Key一般是CtrlZ。发送给所有Foreground Group的进程 SIGTTIN 当Background Group的进程尝试读取Terminal的时候发送 SIGTTOU 当Background Group的进程尝试写Terminal的时候发送 SIGURG 当out-of-band data接收的时候可能发送 SIGUSR1 用户自定义signal 1 SIGUSR2 用户自定义signal 2 SIGVTALRM setitimer函数设置的Virtual Interval Timer超时的时候 SIGWAITING Solaris Thread Library内部实现专用 SIGWINCH 当Terminal的窗口大小改变的时候发送给Foreground Group的所有进程 SIGXCPU 当CPU时间限制超时的时候 SIGXFSZ 进程超过文件大小限制 SIGXRES Solaris专用进程超过资源限制的时候发送
signal对应的值
POSIX.1中列出的信号
SIGHUP 1 A 终端挂起或者控制进程终止 SIGINT 2 A 键盘中断如break键被按下 SIGQUIT 3 C 键盘的退出键被按下 SIGILL 4 C 非法指令 SIGABRT 6 C 由abort(3)发出的退出指令 SIGFPE 8 C 浮点异常 SIGKILL 9 AEF Kill信号 SIGSEGV 11 C 无效的内存引用 SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道 SIGALRM 14 A 由alarm(2)发出的信号 SIGTERM 15 A 终止信号 SIGUSR1 30,10,16 A 用户自定义信号1 SIGUSR2 31,12,17 A 用户自定义信号2 SIGCHLD 20,17,18 B 子进程结束信号 SIGCONT 19,18,25 进程继续曾被停止的进程 SIGSTOP 17,19,23 DEF 终止进程 SIGTSTP 18,20,24 D 控制终端tty上按下停止键 SIGTTIN 21,21,26 D 后台进程企图从控制终端读 SIGTTOU 22,22,27 D 后台进程企图从控制终端写
没在POSIX.1中列出而在SUSv2列出
SIGBUS 10,7,10 C 总线错误(错误的内存访问) SIGPOLL A Sys V定义的Pollable事件与SIGIO同义 SIGPROF 27,27,29 A Profiling定时器到 SIGSYS 12,-,12 C 无效的系统调用 (SVID) SIGTRAP 5 C 跟踪/断点捕获 SIGURG 16,23,21 B Socket出现紧急条件(4.2 BSD) SIGVTALRM 26,26,28 A 实际时间报警时钟信号(4.2 BSD) SIGXCPU 24,24,30 C 超出设定的CPU时间限制(4.2 BSD) SIGXFSZ 25,25,31 C 超出设定的文件大小限制(4.2 BSD)
对于SIGSYSSIGXCPUSIGXFSZ以及某些机器体系结构下的SIGBUSLinux缺省的动作是A (terminate)SUSv2 是C (terminate and dump core)。
下面是其它的一些信号 信号 值 处理动作 发出信号的原因 ---------------------------------------------------------------------- SIGIOT 6 C IO捕获指令与SIGABRT同义 SIGEMT 7,-,7 SIGSTKFLT -,16,- A 协处理器堆栈错误 SIGIO 23,29,22 A 某I/O操作现在可以进行了(4.2 BSD) SIGCLD -,-,18 A 与SIGCHLD同义 SIGPWR 29,30,19 A 电源故障(System V) SIGINFO 29,-,- A 与SIGPWR同义 SIGLOST -,-,- A 文件锁丢失 SIGWINCH 28,28,20 B 窗口大小改变(4.3 BSD, Sun) SIGUNUSED -,31,- A 未使用的信号(will be SIGSYS) 在这里- 表示信号没有实现有三个值给出的含义为第一个值通常在Alpha和Sparc上有效中间的值对应i386和ppc以及sh最后一个值对应mips。信号29在Alpha上为SIGINFO / SIGPWR 在Sparc上为SIGLOST。 处理动作一项中的字母含义如下 A 缺省的动作是终止进程 B 缺省的动作是忽略此信号 C 缺省的动作是终止进程并进行内核映像转储dump core D 缺省的动作是停止进程 E 信号不能被捕获 F 信号不能被忽略 代码测试 #includestdio.h
#includesignal.h
#includeunistd.h
#includestdlib.h
void when_alarm();
void when_sigint();
void when_sigchld(int);
void when_sigusr1();
void when_sigio();
int main()
{ int childpid;//子程序进程ID号 printf(程序已经开始运行5秒钟后将接收到时钟信号。/n); if ((childpidfork())0)//父进程 { signal(SIGALRM,when_alarm); //当接收到SIGALRM信号时调用when_alarm函数 signal(SIGINT,when_sigint); //当接收到SIGINT信号时调用when_sigint函数 signal(SIGCHLD,when_sigchld);//当接收到SIGCHLD信号时调用when_sigchld函数 signal(SIGUSR1,when_sigusr1);//当接收到SIGUSR1信号时调用when_sigusr1函数 signal(SIGIO,when_sigio);//当接收到SIGIO信号时调用when_sigio函数 alarm(5); //5秒钟之后产生SIGALRM信号 raise(SIGIO); //向自己发送一个SIGIO信号 pause(); //将父进程暂停下来等待SIGALRM信号到来 pause(); //将父进程暂停下来等待SIGUSR1信号到来 pause(); //将父进程暂停下来等待SIGCHLD信号到来 printf(------此时程序会停下来等待请按下ctrlc送出SIGINT信号-------/n); pause(); //将父进程暂停下来等待SIGINT信号到来 } else if(childpid0) //子进程 { int timer; for(timer7;timer0;timer--) //时钟计时5秒产生SIGALRM信号再过2秒子进程退出产生SIGCHLD信号 { if(timer2) printf(距离SIGALRM信号到来还有%d秒。/n,timer-2); if(timer4) kill(getppid(),SIGUSR1); //向父进程发送一个SIGUSR1信号 if((timer2)(timer0)) printf(子进程还剩%d秒退出届时会产生SIGCHLD信号。/n,timer); if(timer0) //子进程退出产生SIGCHLD信号 raise(SIGKILL); //子进程给自己发一个结束信号 sleep(1); //每个循环延时1秒钟 } } else printf(fork()函数调用出现错误/n); return 0;
}
void when_alarm()
{ printf(5秒钟时间已到系统接收到了SIGALRM信号/n);
}
void when_sigint()
{ printf(已经接收到了SIGINT信号程序将退出/n); exit(0);
}
void when_sigchld(int SIGCHLD_num)
{ printf(收到SIGCHLD信号表明我的子进程已经中止SIGCHLD信号的数值是%d。/n,SIGCHLD_num);
}
void when_sigusr1()
{ printf(系统接收到了用户自定义信号SIGUSR1。/n);
}
void when_sigio()
{ printf(系统接收到了SIGIO信号。/n);
}