应用程序先前由“root”运行后,QSerialPort 无法打开 tty

Kyl*_*and 2 linux permissions debian qt serial-port

我有一个QSerialPort从串行端口读取和写入的应用程序(使用)。当我以root用户身份运行此应用程序,然后以非 root 用户身份再次运行它时,我无法再写入串行端口,并收到以下错误:

QIODevice::write (QSerialPort): device not open
Run Code Online (Sandbox Code Playgroud)

非 root 用户位于该dialout组中,并且相关文件的权限/dev/tty**似乎未更改:

crw-rw---T 1 root dialout ......
Run Code Online (Sandbox Code Playgroud)

最奇怪的是,当我简单地使用 shell 以非 root 用户身份写入文件时,我没有收到错误:

$> echo "foo bar baz" >> /dev/ttyS0
$> echo $?
0
Run Code Online (Sandbox Code Playgroud)

我发现唯一可以解决该问题的方法是重新启动机器。

这里可能发生了什么?

我使用的是 Debian 7。

Kyl*_*and 6

更新:这是 Qt 中的一个错误,将在 5.6.2 版本中修复,该版本将于本月晚些时候发布。

在 Linux 和 Mac 上,打开串行端口时QSerialPort创建锁定文件。/var/lock/锁定文件具有权限0644,即只有文件的创建者可以对其进行写入。

如果打开串行端口的进程死亡或者串行端口通过任何其他方式以某种方式不正确地关闭,则锁定文件将不会被删除。锁文件包含打开串口的进程的PID;如果进程不再运行,Qt 将尝试简单地占有锁,更改文件中的 PID。

但是,由于锁文件具有0644权限,如果未正确关闭的进程是由 运行的root,则新进程将无法删除或覆盖锁文件,从而导致权限错误。

版本 5.6.2已修复此问题。

请注意,QSerialPort在其自身之后进行清理:当调用其析构函数时,端口将关闭并删除锁定文件。然而,默认情况下,当或导致程序退出时,Qt不会调用对象析构函数。(我个人认为这也是一个错误,但我承认这更多是一个意见问题。)SIGTERMSIGINT

另请参阅建议的欺骗问题。从这个问题可以看出,当前的行为实际上是一种改进——以前,应用程序只会挂起