如何用域名访问网站,网络推广思路,桂林seo哪家好,手机wap支付目录
信号的概念
从生活中的例子中感知信号
前台进程和后台进程
前台进程
后台进程
操作系统如何知道用户向键盘写入数据了#xff1f;
进程如何得知自己收到了信号#xff1f;
信号捕捉
signal函数
Core Dump#xff08;核心转储#xff09;
信号产生的方式
通…目录
信号的概念
从生活中的例子中感知信号
前台进程和后台进程
前台进程
后台进程
操作系统如何知道用户向键盘写入数据了
进程如何得知自己收到了信号
信号捕捉
signal函数
Core Dump核心转储
信号产生的方式
通过键盘按键产生信号
kill函数
raise函数
硬件异常产生信号
浮点数异常
非法地址异常
由软件条件产生信号
alarm函数 信号的概念
从生活中的例子中感知信号
你在网上买了很多件商品再等待不同商品快递的到来。但即便快递没有到来你也知道快递来临时你该怎么处理快递。也就是你能“识别快递”当快递员到了你楼下你也收到快递到来的通知但是你正在打游戏需5min之后才能去取快递。那么在在这5min之内你并没有下去去取快递但是你是知道有快递到来了。也就是取快递的行为并不是一定要立即执行可以理解成“在合适的时候去取”。在收到通知再到你拿到快递期间是有一个时间窗口的在这段时间你并没有拿到快递但是你知道有一个快递已经来了。本质上是你“记住了有一个快递要去取”当你时间合适顺利拿到快递之后就要开始处理快递了。而处理快递一般方式有三种1. 执行默认动作幸福的打开快递使用商品2. 执行自定义动作快递是零食你要送给你你的女朋友3. 忽略快递快递拿上来之后扔掉床头继续开一把游戏快递到来的整个过程对你来讲是异步的你不能准确断定快递员什么时候给你打电话
通过上面的例子我们可以总结出来一下四点 信号没有产生的时候其实我们已经直到怎么处理这个信号了。信号的到来我们并不清楚具体什么时候信号的到来对于我正在做的工作是异步产生的。信号产生了我们不一定要立即处理它而是我们在合适的时候处理。我们有一种能力可以将已经到来的信号进行暂时保存。 让我们转换视角将我们看成操作系统中被操作系统管理的进程在进程运行期间根本不知道操作系统什么时候会给这个进程传递一种信息当操作系统的信息来临时进程可以选择直接处理这个信息也可以将信息暂时保存下来。
到此我们可以给信号下个定义信号是一种向目标进程发送通知消息的一种机制。
在了解信号的产生之前我们还需要一点预备知识让我们对操作系统的信号机制了解的更全面一点。 前台进程和后台进程
前台进程
当我们循环执行一条输出语句时执行我们的Linux指令操作系统是没有任何相应的也就是操作系统没有能力接受用户的输入。 后台进程
只需要在运行可执行程序时指令的后面添加一个按位与的位运算符即可成为后台进程。后台进程有能力可以接受用户的输入当我么输入指令后shell会执行我们的命令。 查看后台进程
jobs
将后台进程调整为前台进程
fg number(后台每个进程的任务号
将前台进程调整为后台进程
ctrl z
//先对前台进程进行暂停
bg number
//然后在进行调整总结 前台进程有且只有一个一般情况下为shell。操作系统会自动将shell提到前台或者后台。前台进程可以被ctrlc终止掉。前台进程不可以被暂停如果被暂停该前台进程必须被放到后台。 操作系统如何知道用户向键盘写入数据了
操作系统是管理者键盘、显示器、网卡等这些硬件也是要被操作系统管理起来的。当我们使用键盘进行写入操作时键盘文件会发生变化操作系统会将这些输入的数据进行各种处理。但是根据冯诺依曼体系结构外设是不可以和CPU进行打交道的可以通过其他硬件间接联系。CPU中含有很多针脚外设通过8259主板和CPU上的针脚关联。每个针脚对应一个外设当我们键盘进行写入时高低电平会通过主板让针脚发生“变化”。这样CPU就可以知道键盘进行写入了然后读取数据对数据进行处理。这样的方式称作中断引起中断的原因称作中断源。对于CPU上的针脚操作系统也是需要进行管理的使用一个函数指针数组数组中的指针指向该针脚对应外设的读写操作函数。这个函数指针数组被称为断向量表。
因此信号的本质就是使用软件来模拟中断的行为。 进程如何得知自己收到了信号
前面的文章中我们简单提到过信号系统中总共含有62中信号其中 1-31为普通信号34-64为实时信号且没有0号信号。这篇文章我们只探讨普通信号不对实时信号做任何解释和介绍。
可以使用kill -l查看系统信号 每个信号都含有一个数字编号和一个宏定义名称这些宏定义可以在signal.h中找到,例如其中有定 义 #define SIGINT 2。
前面的文章我们介绍了每个进程都会被操作系统管理起来形成一个结构体PCB其中含有进程的属性和信息在这个结构体中就含有一个信号位图每个比特位代表对应的信号每个比特位对应的内容表示是否收到了信号。当进程收到信号之后会修改这个信号位图表示收到了某中信号。 信号捕捉
上面提到每个信号都有编号和宏定义,当进程收到某种信号时会调用系统默认的方法Linux操作系统支持我们使用函数将默认方法改写。
signal函数
//头文件
#includesignal.h
//函数名称
signal(signo,(void)(*)(int)) 第一个参数表示我们要对哪个信号进行捕捉。第二个参数是一个参数为整形的函数指针指向我们重写的函数这个函数的参数也为我们的第一个参数。 注意对于9号进程来说是不可以被重写函数的。 Core Dump核心转储
首先解释什么是Core Dump。当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部 保存到磁盘上,文件名通常是core,这叫做Core Dump。进程异常终止通常是因为有Bug,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug事后调试。一个进程允许产生多大的core文件取决于进程的Resource Limit(这个信息保存 在PCB中)。默认是不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。 首先用ulimit命令改变Shell进程的Resource Limit,允许core文件最大为1024K: $ ulimit -c 1024。 #includeiostream
using namespace std;
int main()
{int a10;a/0;return 0;
} 使用指令修改限制允许产生core文件专门制造一个浮点数异常编译并运行后会产生一个和本进程id相关的core文件我们可以发现这个文件是非常大的程序运行时如果出现这类异常会将我们的磁盘写满造成无法进行修改这也是为什么系统默认不允许产生core文件。 信号产生的方式
通过键盘按键产生信号
通过键盘进行信号的产生就像我们上面使用键盘输入crtl c可以终止一个进程当这个键盘输入组合键时会产生一个硬件中断被操作系统获取解释成为2号信号发送给目标前台进程。进程会修改自己PCB中的信号位图表示已经收到信号。
前台进程因为接收到引号直接对信号进行处理进而终止进程。
此外常用的组合键含有ctrl z 默认暂停进程 ctrl \ 默认退出进程
通过系统调用/指令产生信号
kill函数
//头文件
#includesys/types.h
#includesignal.h
//函数
int kill(pid_t pid, int sig)
参数说明 pid表示进程的pid代表向哪一个进程发送。sig表示发送信号的编号。 #includeiostream2 #includeunistd.h3 #includesignal.h4 #includesys/types.h 5 using namespace std; 10 int main() 11 { 12 coutwait 2 signalendl; 13 sleep(2); 14 kill(getpid(),9); 15 coutWTFendl; return 0;} 上面的代码演示了使用kill函数给自身进程产生了9号信号并由操作系统发送成功也可以通过另一个进程给一个指定的进程发送指定的信号。
raise函数
//头文件
#includesignal.h
//函数
int raise(int sig);参数说明 sig代表信号编号。raise专门用来给自己发送指定的信号的。 #includeiostream2 #includeunistd.h3 #includesignal.h4 #includesys/types.h5 using namespace std;10 int main()11 {12 coutwait signalendl;13 raise(9); reutrn 0;} 硬件异常产生信号
硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。再比如当前进程访问了非法内存地址,,MMU会产生异常,内核将这个异常解释SIGSEGV信号发送给进程。
浮点数异常
#includeiostream
using namespace std;
int main()
{int a10;a/0;return 0;
} 非法地址异常
#includeiostream
using namespace std;
int main()
{int* aNULL;*a100;return 0;
} 由软件条件产生信号
在之前管道的文章匿名管道如果读端关闭写端一直写入操作系统就会发送SIGPIPE13号信号终止目标进程。SIGPIPE就是一种由软件条件产生的信号。
alarm函数
//头文件
#include unistd.h
//函数
unsigned int alarm(unsigned int seconds);
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终止当前进程。
这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。打个比方,某人要小睡一觉,设定闹钟为30分钟之后响,20分钟后被人吵醒了,还想多睡一会儿,于是重新设定闹钟为15分钟之后响,“以前设定的闹钟时间还余下的时间”就是10分钟。如果seconds值为0,表示取消以前设定的闹钟,函数的返回值仍然是以前设定的闹钟时间还余下的秒数。
#includeiostream
#includeunistd.h
int cnt 0;
int main()
{alarm(1);while(true){cnt;coutcntendl;}return 0;
} 今天对Linux下信号的产生的分享到这就结束了希望大家读完后有很大的收获也可以在评论区点评文章中的内容和分享自己的看法个人主页还有很多精彩的内容。您三连的支持就是我前进的动力感谢大家的支持