Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 什么时候处理信号?为什么某些信息会冻结?_Linux_Bash_Bash Trap - Fatal编程技术网

Linux 什么时候处理信号?为什么某些信息会冻结?

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

打开名为“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中立即显示:

    回调函数在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'