我有一个 Linux 应用程序,它可以打开多个串行设备 ( /dev/ttyUSB
X) 并从中读取/写入数据。当我从命令提示符 (Ubuntu 10.04,bash) 运行它时,它运行正常。
$sudo ./my_program /dev/ttyUSB0 #sudo for permissions on the device
我希望这个程序在启动时运行,并且在它死机时重新启动 - 所以我把它放入 Upstart 配置(/etc/init/*
)并将其命名为“ my_service
”。
当我重新启动机器时,my_service 执行,my_program 运行。但是,几秒钟后(就在它打开 ttyUSB 并从中读取数据时),我的进程收到一个 SIGINT。我不知道它来自哪里。这不是设备上的权限问题,它们可以正常打开()并且几个字节可以正常传输。使用waitsiginfo()
我能够获得si_code
0x80 或SI_KERNEL
。所以我知道它不是来自另一个进程,而是来自内核本身。没有人在控制台上点击CTRL-C或ALT- - CTL- DEL- 为什么内核向我发送SIGINT
?
更糟糕的是,我的程序根据这个信号适当地退出 - 由 Upstart 重新生成,并立即再次发出 SIGINT 信号!有什么方法可以找出这个信号的来源以及原因吗?是否可以启用某种级别的内核调试来阐明这一点?为什么由 Upstart 启动时的行为与手动启动时的行为不同bash
?
答案1
问题解决了,虽然这是一个编程错误,与 Upstart 无关。该程序打开 ttyUSB 设备以进行原始(非规范)输入,但它没有清除 termios 中的 ISIG 标志。每当收到“CTRL-C”字符(0x02)时,内核就会生成 SIGINT 并将其发送给程序。这个问题不是从 bash 发生的,因为 termios 设置在文件上是持久的,并且在我的程序执行之前一定有某些东西打开了 tty 并清除了 ISIG 位。直接从 Upstart 运行它时不会发生这种情况。我仍然希望有更好的方法来记录/调试信号,ptrace 只是答案的一半!
答案2
当程序进入后台时,会发送 SIGINT(例如 ^Z)。通常,作为守护进程运行的程序会捕获信号并继续运行。
检查您是否可以从交互式 shell 启动该程序,然后通过 ^Z 将其置于后台。它也很可能会死机。
如果答案是肯定的,那么有两种可能。如果这是你的程序,你可以捕获 SIGINT。如果你无法访问源代码,或者不想花额外的时间编写此功能,或者你在某些存在信号问题的 Java VM 版本上运行该程序,那么请将你的程序包装在一个用于screen
启动和运行你的程序的脚本中。这样就screen
可以进入后台,但你的代码会被欺骗,以为它在交互式会话的前台运行。