Linux QSerialPort无法在应用程序以前由`root'运行后打开tty`

Linux QSerialPort无法在应用程序以前由`root'运行后打开tty`,linux,qt,permissions,serial-port,debian,Linux,Qt,Permissions,Serial Port,Debian,我有一个从串行端口读写的应用程序(使用QSerialPort)。当我以root用户身份运行此应用程序,然后以非root用户身份再次运行时,我将无法再写入串行端口,并收到以下错误: QIODevice::write (QSerialPort): device not open 非root用户在拨出组中,并且有关/dev/tty**文件的权限似乎没有改变: crw-rw---T 1 root dialout ...... 最奇怪的是,当我以非root用户的身份简单地使用shell写入文件时,我没

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

QIODevice::write (QSerialPort): device not open
非root用户在
拨出
组中,并且有关
/dev/tty**
文件的权限似乎没有改变:

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

$> echo "foo bar baz" >> /dev/ttyS0
$> echo $?
0
我发现唯一能解决这个问题的方法就是重新启动机器

这里可能发生了什么


我使用的是Debian 7。

似乎,在使用非root用户打开设备之前,您应该从/var/lock目录中删除锁文件(请自己搜索)。

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

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

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

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

这是

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


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

怪异;你说得对,我的
tty
有一个锁文件。这是否意味着我的程序没有正确关闭或清理串行端口?另外,为什么我的
echo
命令没有失败?>这是否意味着我的程序没有正确关闭或清理串行端口?不,这意味着这是QLockFile实现中的一个特性/错误(因为QSerialPort使用QLockFile)。当您的应用程序以root启动时,它也会创建一个具有root权限的锁文件。。因此,当您尝试使用非root权限启动应用程序时,没有权限修改锁文件(在其中写入pid和其他信息),因此,打开时失败。>还有,为什么我的echo命令没有失败?Echo dows未使用/检查锁文件。@KyleStrand这没有回答您的问题吗?-如果有,请单击相应的位置:)。。。我本来打算回答的,直到我意识到它似乎已经有了一个很好的答案+1.user3074135@code_fodder如果您查看我的帐户,您会发现我了解ask/accept系统的工作原理,谢谢。我还没有接受,因为我觉得我还不明白锁文件存在的原因,为什么它被不一致地清理,等等。(而且,我的应用程序似乎没有正确地清理自己;显然,当应用程序使用SIGTERM或SIGINT关闭时,Qt不会自动调用析构函数。我现在已经解决了这个问题。)