本文介绍了在应用程序先前由“root"运行后,QSerialPort 无法打开 tty的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an application (using QSerialPort) that reads and writes from a serial port. When I run this application as the root user, then run it again as a non-root user, I am no longer able to write to the serial port, receiving the following error:

QIODevice::write (QSerialPort): device not open

非 root 用户在 dialout 组中,而相关 /dev/tty** 文件的权限似乎没有改变:

The non-root user is in the dialout group, and the permissions on the /dev/tty** file in question appear to be unchanged:

crw-rw---T 1 root dialout ......

最奇怪的是,当我只是使用我的 shell 以非 root 用户身份写入文件时,我确实不会收到错误:

Weirdest of all, I do not get an error when I simply use my shell to write to the file as the non-root user:

$> echo "foo bar baz" >> /dev/ttyS0
$> echo $?
0

我发现唯一能解决问题的方法是重启机器.

The only thing I've found that appears to fix the problem is rebooting the machine.

这里可能发生了什么?

我在 Debian 7 上.

I'm on Debian 7.

推荐答案

更新: 这是 Qt 中的一个错误,将在 5.6.2 版本中修复,该版本将在稍后发布月.

Update: this is a bug in Qt, and will be fixed in version 5.6.2, which is due for release later this month.

在 Linux 和 Mac 上,QSerialPort 在打开串行端口时会在 /var/lock/ 中创建一个锁定文件.锁文件有权限0644,即只有文件的创建者可以写入.

On Linux and Mac, QSerialPort creates a lock file in /var/lock/ when opening a serial port. The lockfile has permissions 0644, i.e. only the creator of the file can write to it.

如果打开串口的进程死掉了,或者串口被其他方式不当关闭,锁文件不会被删除.lockfile包含打开串口的进程的PID;如果进程不再运行,Qt 将尝试简单地获取锁,更改文件中的 PID.

If the process that opened the serial port dies or if the serial port is somehow improperly closed by any other means, the lock file will not be deleted. The lockfile contains the PID of the process that opened the serial port; if the process is no longer running, Qt will attempt to simply take possession of the lock, changing the PID in the file.

但是,由于lockfile有0644权限,如果不正确关闭的进程是由root运行的,新进程将无法删除或覆盖lockfile,导致权限错误.

However, since the lockfile has 0644 permissions, if the improperly-closing process was run by root, the new process will be unable to delete or overwrite the lockfile, resulting in a permissions error.

这是已针对 5.6.2 版修复.

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

Note that QSerialPort does clean up after itself: when its destructor is called, the port is closed and the lockfile is deleted. However, by default, Qt does not call object destructors when SIGTERM or SIGINT causes the program to exit. (Personally, I think this is also a bug, but I recognize that this is more a matter of opinion.)

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

Also see the suggested dupe question. As can be seen from this question, the current behavior is actually an improvement--previously, the application would simply hang!

这篇关于在应用程序先前由“root"运行后,QSerialPort 无法打开 tty的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 17:53