在应用程序先前由“root”运行后,QSerialPort 无法打开 tty [重复]
Posted
技术标签:
【中文标题】在应用程序先前由“root”运行后,QSerialPort 无法打开 tty [重复]【英文标题】:QSerialPort cannot open tty after application has previously been run by `root` [duplicate] 【发布时间】:2016-05-20 00:06:32 【问题描述】:我有一个从串行端口读取和写入的应用程序(使用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 上。
【问题讨论】:
【参考方案1】:更新:这是 Qt 中的一个错误,将在 5.6.2 版中修复,该版本将于本月晚些时候发布。
在 Linux 和 Mac 上,QSerialPort
在打开串行端口时会在/var/lock/
中创建一个锁定文件。锁定文件的权限为0644
,即只有文件的创建者可以写入。
如果打开串口的进程死掉了,或者串口被其他方式不当关闭,锁文件不会被删除。 lockfile包含打开串口的进程的PID;如果进程不再运行,Qt 将尝试简单地获取锁,更改文件中的 PID。
但是,由于锁文件有0644
权限,如果root
运行了不正确关闭的进程,新进程将无法删除或覆盖锁文件,导致权限错误。
这是fixed for version 5.6.2。
请注意,QSerialPort 会自行清理:当调用其析构函数时,端口会关闭并删除锁定文件。但是,默认情况下,当SIGTERM
或SIGINT
导致程序退出时,Qt 不 调用对象析构函数。 (我个人认为这也是一个错误,但我承认这更多的是见仁见智。)
另见suggested dupe question。从这个问题可以看出,当前的行为实际上是一种改进——以前,应用程序会简单地挂起!
【讨论】:
【参考方案2】:看来,您应该先从 /var/lock 目录中删除锁定文件(请自行搜索),然后再以非 root 用户打开设备。
【讨论】:
奇怪;没错,我的tty
有一个锁定文件。这是否意味着我的程序没有正确关闭或清理串行端口?另外,为什么我的echo
命令没有失败?
> 这是否意味着我的程序没有正确关闭或清理串行端口?不,这意味着这是 QLockFile 实现中的一个功能/错误(因为 QSerialPort 使用 QLockFile)。当您的应用程序以 root 启动时,它也会创建一个具有 root 权限的锁定文件。所以,当您尝试使用非 root 权限启动您的应用程序时,没有权限修改锁定文件(写在那里pid和其他信息),因此打开失败。 > 另外,为什么我的 echo 命令没有失败? Echo dows 不使用/检查锁定文件。
@KyleStrand 这没有回答你的问题吗? - 如果确实如此,请单击适当的位置:) ...我要回答,直到我意识到它似乎已经有了一个很好的答案。 +1 用户3074135
@code_fodder 如果您查看我的帐户,您会发现我了解询问/接受系统的工作原理,谢谢。我还没有接受,因为我还不明白为什么存在锁定文件,为什么它被不一致地清理等等。(另外,它确实似乎我的应用程序没有清理正确地自行启动;显然,当使用 SIGTERM 或 SIGINT 关闭应用程序时,Qt 不会自动调用析构函数。我现在已经解决了这个问题。)以上是关于在应用程序先前由“root”运行后,QSerialPort 无法打开 tty [重复]的主要内容,如果未能解决你的问题,请参考以下文章
[求助]请问虚拟机下的kali怎么安装vmware tools总提示权限不够
无法使用 Travis-CI 运行可执行文件-不确定我做错了啥