Linux 什么时候处理信号?为什么某些信息会冻结?
打开名为“termA”的终端,并使用Linux 什么时候处理信号?为什么某些信息会冻结?,linux,bash,bash-trap,Linux,Bash,Bash Trap,打开名为“termA”的终端,并使用/bin/bash callback.sh运行创建的文件callback.sh cat callback.sh #!/bin/bash myCallback() { echo "callback function called at $(date)" } trap myCallback SIGUSR1 sleep 20 打开名为“termB”的新终端并运行: 在termA中20秒后显示如下所示:;它从未在termA中立即显示: 回调函数在20
/bin/bash callback.sh
运行创建的文件callback.sh
cat callback.sh
#!/bin/bash
myCallback() {
echo "callback function called at $(date)"
}
trap myCallback SIGUSR1
sleep 20
回调函数在2018年11月19日星期一08:21:52调用
该结论验证了当Bash在前台执行外部命令时,它不会处理接收到的任何信号,直到前台进程终止(请参阅)
在callback.sh中稍作更改:
cat callback.sh
#!/bin/bash
myCallback() {
echo "callback function called at $(date)"
}
trap myCallback SIGUSR1
while true; do
read -p "please input something for foo: " foo
done
添加无限while循环并删除sleep 20
打开名为“termA”的终端,用/bin/bash callback.sh运行创建的文件callback.sh
;第一次,信息会立即弹出
请为foo输入一些内容:
打开一个名为“termB”的新终端并运行pkill-USR1-f callback.sh
;第一次,信息会以termA的形式立即弹出
回调函数在2018年11月19日(星期一)09:07:14调用
问题1:回调。sh
包含一个无限while循环。这是如何解释以下情况的
在前台进程终止之前,它不会处理接收到的任何信号
在这种情况下,前台进程永远不会终止
在termB中继续,第二次运行pkill-USR1-f callback.sh
回调函数在2018年11月19日(星期一)09:07:14调用
上述信息会立即在termA中再次弹出
第2期:否请为foo输入一些内容:
如termA所示,
转到termB,第三次运行pkill-USR1-f callback.sh,
以下信息再次显示在termA中
回调函数在2018年11月19日星期一09:07:24调用
仍然没有请为foo输入内容:
显示在termA中。为什么信息
请为foo输入内容:
冻结?termA不会冻结。它只是在输入框中显示回调。只需按Enter键继续输入。在解释您的问题之前,先了解一下读取
命令的工作原理。它从stdin
读取输入数据,直到遇到EOF
。可以肯定地说,对read
命令的调用在读取磁盘上的文件时是非阻塞的。但是当stdin
连接到终端时,该命令将被阻塞,直到用户键入某个内容
信号处理器是如何工作的?
信号处理工作原理的简单说明。请参阅C
中的以下代码段,它只作用于SIGINT
(也称为CTRL+C
)
正如输出所示,每次我们发出Ctrl-C
,“Hello World!”
都会打印出来,但程序会返回到无限循环。只有在使用Ctrl-\
发出SIGQUIT
信号后,程序才真正退出。根据您的ulimit
设置,它将转储磁芯或打印出接收到的信号号
虽然循环的解释是合理的,但它并不考虑信号处理的主要原因,也就是异步事件处理。这意味着信号处理器的行为超出了程序控制的标准流程;事实上,整个程序都保存在一个上下文中,并且创建了一个新的上下文,只供信号处理程序在其中执行。一旦信号处理程序完成其操作,上下文将切换回原位,正常执行流将启动(即,而(1)
)
为了回答你的问题
该结论验证了当bash在前台执行外部命令时,它不会处理接收到的任何信号,直到前台进程终止
这里需要注意的关键是外部命令部分。在第一种情况下,sleep
是一个外部进程,但在第二种情况下,read
是shell本身的内置进程。因此,在这两种情况下,信号向这两个方向的传播是不同的
type read
read is a shell builtin
type sleep
sleep is /usr/bin/sleep
1.打开一个名为termA的终端,第一次用/bin/bash callback.sh运行创建的文件callback.sh,信息立即弹出
是的,这种行为是意料之中的。因为此时只定义了函数,陷阱处理程序被注册到函数myCallback
,并且脚本中尚未接收到信号。随着执行顺序的进行,第一次抛出来自read
提示符的消息
2.打开一个名为termB的新终端,第一次运行pkill-USR1-f callback.sh
,信息会立即在termA中弹出
是的,read
命令等待字符串,然后按Enter键pres,发出EOF
的信号,它从另一个终端接收信号SIGUSR1
,保存当前执行上下文,并通过信号处理程序切换控件,该信号处理程序打印带有当前日期的字符串
一旦处理程序完成执行,上下文将恢复到,而循环中的read
命令仍在等待输入字符串。在read
命令成功之前,所有后续的信号陷阱都会在信号处理程序中打印字符串
在termB中继续,第二次运行pkill-USR1-f callback.sh
与前面解释的相同,while循环中的read
命令一次都没有完成,只有当它成功读取字符串时,循环的下一次迭代才会开始并抛出新的提示消息
图片来源:Michael KerrisK的Linux编程接口
#include <stdio.h>
#include <signal.h>
/* signal handler definition */
void signal_handler(int signum){
printf("Hello World!\n");
}
int main(){
//Handle SIGINT with a signal handler
signal(SIGINT, signal_handler);
//loop forever!
while(1);
}
gcc -Wall -o sighdl.o signal.c
./sighdl.o
^CHello World!
^CHello World!
^CHello World!
^CHello World!
^CHello World!
^CHello World!
^CHello World!
^CHello World!
^CHello World!
type read
read is a shell builtin
type sleep
sleep is /usr/bin/sleep
$ cat goo
trap 'echo INT' INT
echo $$
read -p 'enter something: ' var
echo "you entered '$var'"
$ bash goo
24035
enter something: foo<Ctrl-C>^CINT
<Ctrl-C>^CINT
<Ctrl-C>^CINT
bar<Enter>
you entered 'bar'