当前位置: 首页 > 面试题库 >

python信号,中断系统调用

宗政学
2023-03-14
问题内容

我正在用python编写程序。我希望阅读stdin并处理sigchld。我想处理输入中的任何一个,但不要旋转(以推测方式采样输入)。

在我进行的每个调用中,我都无法捕获被信号打断的系统调用。

我会以错误的方式处理吗?我可以不用try / except使它正常工作吗?

我主要担心的不是到目前为止的try / except。但是在程序中其他代码行中,我将需要数百人。在我看来,这似乎不是模块化的。

这是一些测试代码:

#!/usr/bin/python

from time import sleep
import select
import signal
import fcntl
import os
import sys

pipe_r, pipe_w = os.pipe()
flags = fcntl.fcntl(pipe_w, fcntl.F_GETFL, 0)
flags = flags | os.O_NONBLOCK
fcntl.fcntl(pipe_w, fcntl.F_SETFL, flags)

signal.signal(signal.SIGCHLD, lambda x,y: None)
signal.signal(signal.SIGALRM, lambda x,y: None)
signal.siginterrupt(signal.SIGCHLD,False) #makes no difference
signal.siginterrupt(signal.SIGALRM,False) #makes no difference
signal.set_wakeup_fd(pipe_w)
signal.setitimer(signal.ITIMER_REAL, 2, 2)

poller = select.epoll()
poller.register(pipe_r, select.EPOLLIN)
poller.register(sys.stdin, select.EPOLLIN)

print "Main screen turn on"
while True:
    events=[]
    try:
        events = poller.poll()
        try:
            for fd, flags in events:
                ch=os.read(fd, 1)
                if fd==pipe_r:
                    sys.stdout.write( "We get Signal" )
                if fd==sys.stdin.fileno():
                    sys.stdout.write( ch )
                sys.stdout.flush()
        except IOError as e:
            print "exception loop" + str(e)
    except IOError as e:
        print "exception poll" + str(e)

版本:

#python --version
python 2.7.3
#uname -a
Linux richard 3.2.0-32-generic #51-Ubuntu SMP Wed Sep 26 21:33:09 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

问题答案:

是的,您正在按照正确的方式进行操作。(好吧,我可能会使用selectpoll代替epoll,因为那样您的代码将可以移植到非Linux平台上……)

我在这里假设对两个或多个fds进行轮询本质上是您设计的必要条件。如果您仅添加了epoll循环来处理信号,则不需要该部分。您所需要的只是围绕该read调用的简单EINTR循环。但是,一旦有了用于其他目的的管道,将其作为信号唤醒管道进行连接是一件很合理的事情,那么,您以及您正在执行的所有其他操作都隐含了从多个fds中读取的内容。

无论哪种方式,您实际上都无法避免try障碍。(事实并非如此。您始终可以使用sigblock/ / sigprocmasketc阻止信号。它们不在Python的signal模块中,但您可以始终使用ctypes它们。但是通常您需要使用try/finally而不是try/的更多代码except。并且您的代码变得更加难以调试,因此沿着这条路没有什么意义,除非在少数情况下,您正在处理无法被中断且必须被签名的代码。)

POSIX的标准功能是许多系统调用可以被信号中断,在这种情况下,它们会因EINTR而失败。

大多数特定的平台都将可中断的呼叫列表限制为比POSIX允许的更小的呼叫列表,因此,您必须查看linux文档,以确保确切的是EINTR安全和不安全的EINTR安全,但是epoll方法家族,read/ recv/ write/send和朋友,几乎可以肯定是不安全的。

照常使用siginterrupt可能会有所帮助,但不能解决问题。特别是,不需要重新启动而不是中断就可以调用,并且在某些情况下,不需要重新启动就可以中断或完成部分结果。我很确定select,poll而且永远都无法重新启动,所以这个epoll 家庭很有可能也不是,但是您必须检查一下。无论如何,大多数BSD派生默认情况下都已重新启动,因此,如果linux是相同的,则无需进行任何更改。

Python可以用隐式EINTR循环来包装所有这些内容,我相信某些高级方法(例如sendall)可以这样做,但较低级的方法则不能。但是您可以自己整理。例如(未经测试):

def dopoll(poller):
    while True:
        try:
            return poller.poll()
        except IOError as e:
            if e.errno != EINTR:
                raise

然后,无论您poll打电话到dopoll哪里,都可以打电话。



 类似资料:
  • 前言:异常控制流 每个进程对应的程序文件由一条一条的指令组成。进程在执行的时候,会将程序文件加载到进程的内存空间中,这些指令在内存空间中是相邻的。进程会通过调整程序计数器 PC 的值,一条一条地执行指令。我们将进程执行的指令序列叫做处理器的「控制流」。 正常情况下,进程可能会顺序执行相邻的指令(“平滑的”序列),也可能通过跳转、调用和返回等程序指令转移到另一个位置开始执行(平滑流的突变)。无论是前

  • 本文向大家介绍操作系统中的信号量,包括了操作系统中的信号量的使用技巧和注意事项,需要的朋友参考一下 信号量是整数变量,用于通过使用两个原子操作(用于等待进程和信号)来解决临界区问题,它们用于进程同步。 等待和信号的定义如下- 等待 如果为正数,则等待操作会减小其参数S的值。如果S为负或零,则不执行任何操作。 信号 信号运算会增加其参数S的值。 信号量的类型 信号量有两种主要类型,即计数信号量和二进

  • 问题内容: 我的用户空间应用程序有时会在收到EINTR信号后以某种方式阻塞。 我用strace记录的内容: 我可以捕获EINTR信号吗,如何重复有关的调用,例如写入,读取或选择?即使使用与系统调用一起使用的第三方库,我如何确定EINTR发生在哪里? 为什么收到EINTR后我的应用程序被完全阻止(请参阅strace转储:我发送了SIGUSR1,通常应该处理)?为什么futex()将ERESTARTS

  • 中断(英语:Interrupt)是指 处理器接收到来自硬件或软件的信号,提示发生了某个事件,应该被注意,这种情况就称为中断。 通常,在接收到来自外围硬件(相对于中央处理器和内存)的异步信号,或来自软件的同步信号之后,处理器将会进行相应的 硬件/软件 处理。发出这样的信号称为进行中断请求(interrupt request,IRQ)。硬件中断导致处理器通过一个运行信息切换(context switc

  • 本文向大家介绍Linux被中断的系统如何调用详解,包括了Linux被中断的系统如何调用详解的使用技巧和注意事项,需要的朋友参考一下 前言 慢系统调用,指的是可能永远无法返回,从而使进程永远阻塞的系统调用,比如无客户连接时的accept、无输入时的read都属于慢速系统调用。 在Linux中,当阻塞于某个慢系统调用的进程捕获一个信号,则该系统调用就会被中断,转而执行信号处理函数,这就是被中断的系统调

  • 问题内容: 我正在尝试通过系统调用或子流程来实现事件驱动的流程。基本上,我想启动一个非阻塞系统命令,并且在该系统调用完成后,我希望一个函数被调用。这样一来,我可以启动GUI进度栏,启动系统命令并使进度栏继续运行,并在系统调用结束时停止进度栏。 我绝对不希望做的是生成一个进程,获取其进程ID,并在while循环中继续检查该进程的完成情况。 下面只是一个我如何想象它应该工作的示例(所有这些都在一个类中