我有一个应用程序(使用QSerialPort
)从串行端口读取和写入。当我以root
用户身份运行此应用程序时,再次以非root用户身份运行它,我无法再写入串口,收到以下错误:
QIODevice::write (QSerialPort): device not open
非root用户位于dialout
组中,相关/dev/tty**
文件的权限似乎保持不变:
crw-rw---T 1 root dialout ......
最奇怪的是,当我只是使用shell以非root用户身份写入文件时,不会出错:
$> echo "foo bar baz" >> /dev/ttyS0
$> echo $?
0
我发现的唯一能解决问题的方法就是重新启动机器。
这可能会发生什么?
我在Debian 7上。
答案 0 :(得分:2)
似乎,在打开具有非root用户的设备之前,你应该从/ var / lock目录中删除锁定文件(请自己搜索)。
答案 1 :(得分:2)
更新:这是Qt中的一个错误,将在5.6.2版本中修复,该版本将于本月晚些时候发布。
在Linux和Mac上,QSerialPort
在打开串行端口时会在/var/lock/
中创建一个锁定文件。锁文件具有权限0644
,即只有文件的创建者可以写入它。
如果打开串口的进程死机或串口以某种方式通过其他任何方式不正确关闭,则不会删除锁定文件。 lockfile包含打开串口的进程的PID;如果进程不再运行,Qt将尝试简单地占有锁,更改文件中的PID。
但是,由于lockfile具有0644
权限,如果root
运行了不正确关闭的进程,则新进程将无法删除或覆盖锁定文件,从而导致权限错误。
请注意,QSerialPort 会在其自身之后进行清理:当调用其析构函数时,将关闭端口并删除lockfile。但是,默认情况下,当SIGTERM
或SIGINT
导致程序退出时,Qt会不调用对象析构函数。 (就个人而言,我认为这也是 一个错误,但我认识到这更多是一个意见问题。)
另见suggested dupe question。从这个问题可以看出,当前行为实际上是改进 - 以前,应用程序只是挂起!