Understanding Unix/Linux Programming-信号与play_again4.c的准备知识
来源:互联网 发布:sql回滚语句 编辑:程序博客网 时间:2024/04/28 23:14
Ctrl-C终止当前运行的程序,这个中断由一个称为信号的内核机制产生。信号是一个简单而重要的概念,下面将探讨信号的基本概念。
终端驱动程序在这里起到了相应的作用:
- 用户输入Ctrl-C
- 驱动程序收到字符
- 匹配VINTR和ISIG的字符被开启
- 驱动程序调用信号系统
- 信号系统发送SIGINT到进程
- 进程收到SIGINT
- 进程消亡
当然未必一定是Ctrl-C作为中断的控制字符,这是可以更改驱动设置的。
- 什么是信号:
信号是由单个词组成的消息。绿灯、停止标牌、裁判手势等都是信号,而这个物体和事件不是消息,走、停和出界才是消息。当按下Ctrl-C时,内核向当前正在运行的进程发送中断信号,每个信号都有一个数字编码,中断信号编码通常是2。
信号从何处来?
信号来自内核,生成信号请求来自于3个地方:
- 用户:用户通过输入控制字符请求内核产生信号
- 内核:当进程执行出错时,内核给进程发送一个信号,例如:非法段存取、浮点数溢出等等;内核也利用信号通知进程特定事件的发生。
- 进程:一个进程可以通过系统调用kill命令给另一个进程发送信号,进程之间可以通过信号通信。
- 由进程某个操作产生的信号被成为同步信号,例如,被零除。
- 由用户击键这样的外部事件产生的信号被成为异步信号。
哪里可以找到信号列表?信号编号以及它们的名字一般出现在/usr/include/signal.h中。
例如,中断信号被成为SIGINT,退出信号为SIGQUIT,非法段存取的信号是SIGSGEV。
信号的作用?视情况而定。很多信号杀死进程。某时刻进程还在运行,下一秒它就消亡了。从内存中被删除,相应的所有的文件描述符被关闭,并且从进程表中被删除。使用SIGINT可以消灭一个进程,但是进程也有办法保护自己不被杀死。
- 进程如何处理信号?
当进程接收到SIGINT时,并不一定要消亡,进程能够通过系统调用signal告诉内核,它要如何处理信号,进程有3个选择:
- 接收组织(内核)安排:通常是消亡
手册上会列出对每个信号的默认处理,SIGINT的默认处理是消亡,进程并不一定要使用默认处理,但是可以通过一下调用来恢复默认处理:
signal(SIGINT , SIG_DFL);
- 忽略信号(喂?你好?什么?我听不清!喂?我听不清!)
程序可以通过以下调用告诉内核它要忽略SIGINT信号
signal(SIG_INT , SIG_IGN);
- 调用一个函数
这当然是最灵活有用的一种咯,考虑play_again3的例子。当用户输入Ctrl-C的时候,当前程序立即退出而不调用恢复终端驱动设置恢复的函数。更好的做法时,程序在接收到SIGINT后,调用一个恢复设置的函数,然后再退出。
调用signal的第三种选择允许这种类型的响应。程序能够告诉内核,当信号到来时,应该调用哪个函数。在信号到来时调用的函数被成为信号处理函数(越看越觉得像是单片机编程中的中断处理函数)。为安装信号处理函数,程序调用:
signal( signum , functionname );
signal的返回值为-1时表示错误;而正常情况下,返回一个指向(前一个处理)函数的指针。
来看看信号处理的例子吧:
#include <stdio.h>#include <stdlib.h>#include <signal.h>void f(int) ;int main(){ void f(int) ; int i ; signal(SIGINT , f) ; // Declare the handler for(i = 0 ; i < 5 ; i ++ ){ printf("Hello!\n" ); sleep(1) ; } return 0 ;}void f(int signum ){ printf("OUCH!\n");}
很简单的例子,哈哈,下面一个例子会忽略Ctrl-C的信号,和书上不太一样,直接改上面的了:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <signal.h> 4 5 void f(int) ; 6 7 int main() 8 { 9 void f(int) ;10 int i ;11 12 signal(SIGINT , SIG_IGN) ; // Declare the handler13 14 for(i = 0 ; i < 5 ; i ++ ){15 printf("Hello!\n" );16 sleep(1) ;17 }18 19 return 0 ;20 }21 22 void f(int signum )23 {24 printf("OUCH!\n");25 }
在输出Hello!的过程中,Ctrl-C是不能产生中断的,而使用Ctrl-\是可以的,因为这个程序没有忽略或者捕捉SIGQUIT。相当于屏蔽了一个中断,却没有屏蔽另外一个中断。
- 进程终止和为设备编程
程序使用signal来告诉内核它需要忽略哪些信号,但是,对于程序员而言,有两个信号是不能被忽略和捕捉的,书上让我们自己去找。。。
这个我就偷个懒,以后再找咯
- 为设备编程:
终端控制程序的三个方面:
- 驱动程序的属性和设置
- 以应用程序的特定需求来调整驱动程序,满足这些需求
- 处理信号报告的错误或者处理特定事件
- Understanding Unix/Linux Programming-信号与play_again4.c的准备知识
- Understanding Unix/Linux Programming-用户程序play_again4.c
- Understanding Unix/Linux Programming-终端控制和信号
- Understanding Unix/Linux Programming-设备文件与磁盘连接的概念
- Understanding Unix/Linux Programming note:chapter 6:为用户编程:终端控制和信号
- Understanding Unix/Linux Programming-cp指令练习
- Understanding Unix/Linux Programming-who指令练习
- Understanding Unix/Linux Programming-pwd指令练习
- Understanding Unix/Linux Programming-stty指令练习
- Understanding Unix/Linux Programming-用户程序:play_again0
- Understanding Unix/Linux Programming-用户程序:play_again1
- Understanding Unix/Linux Programming-用户程序:play_again2
- Understanding Unix/Linux Programming-用户程序:play_again3
- Understanding Unix/Linux Programming-时钟编程:Alarms
- Understanding Unix/Linux Programming 笔记:chapter 11:连接到近端或远端的进程:服务器与Socket(套接字)
- Understanding Unix/Linux Programming note:chapter 1:执行可执行文件时的参数传递
- Understanding Unix/Linux Programming note:chapter 1:more函数的流程图
- Understanding Unix/Linux Programming 笔记:chapter 13:基于数据报(Datagram)的编程:编写许可证服务器
- Understanding Unix/Linux Programming-用户程序:play_again1
- 控制系统的带宽与二阶系统的简单定性理解
- Understanding Unix/Linux Programming-用户程序:play_again2
- Understanding Unix/Linux Programming-用户程序:play_again3
- 线性系统的频域法校正
- Understanding Unix/Linux Programming-信号与play_again4.c的准备知识
- Understanding Unix/Linux Programming-用户程序play_again4.c
- Understanding Unix/Linux Programming-事件驱动编程:编写一个视频游戏
- Understanding Unix/Linux Programming-时钟编程:Alarms
- 三相全桥MOS管驱动电路调试记录
- 笑话——如何正确理解迭代
- How a Kalman filter works, in pictures | Bzarg
- 神经网络与机器学习——基本框架学习
- 神经网络基础知识以及Rosenblatt感知器