【问题标题】:How do you check if a serial port is open in Linux?如何检查 Linux 中的串口是否打开?
【发布时间】:2018-04-06 15:06:25
【问题描述】:

如何使用 Posix/C 函数在 Linux 中检查串行端口是否已打开?我想查看串口的状态,看看串口是否打开。

我想知道哪些方法适用:

  1. 检查文件描述符看串口是否打开

  2. 检查串口文件名以查看串口是否打开,在下面的示例中为“/dev/ttyUSB0”

--

// This code is for example purposes only

int open_port()
{
  int fd;

  fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd < 0)
  {
    perror("open_port: Unable to open /dev/ttyf1 - ");
  }

  return fd;
} 

我想有一种“标准”方式可以做到这一点,这就是我想要达到的目标。

【问题讨论】:

  • 看起来很相似,但没有提供解决方案,因为这是检查端口是否打开的方法。它只是提供了一种独占锁定它的方法。
  • @Xofo:应用程序应该以独占方式锁定端口(通过打开文件描述符上的 TIOCEXCL ioctl 和/或 flock()/fcntl())以避免其他人能够打开设备并弄乱它的设置、输入或输出。 这是标准解决方案。要检查端口是否正在使用,您只需尝试打开它。如果您可以打开它,则它不会被任何其他应用程序使用。所有其他解决方案都是错误的,因为它们包含竞争条件,或者不可靠或与例如冲突。设备发现守护进程。
  • @NominalAnimal - 感谢您的评论。您的评论是一个解决方案。您是说您的解决方案是“最佳实践”解决方案。其他解决方案是什么?我认为它们值得讨论。你说 TIOCEXCL ioctl AND/OR flock()/fcntl() - 一个或两个函数安全吗?

标签: c linux serial-port


【解决方案1】:

上述问题有两个方面,实际上需要两种不同的解决方案:

  1. 使用串行端口的应用程序或服务守护程序应排除其他进程同时使用该端口。

    有两种方法可以做到这一点:独占模式和咨询锁。应用程序可以选择执行一项,或同时执行两项。

    • 打开设备后,使用ioctl(fd, TIOCEXCL)将串口设置为独占模式。在描述符关闭或进程发出ioctl(fd, TIOCNXCL) 之前,任何打开设备的尝试都将失败并出现EBUSY 错误代码。

    • 打开设备后,使用flock(fd, LOCK_EX | LOCK_NB) 尝试在打开的设备上设置独占咨询锁。其他进程仍然可以正常打开设备,甚至可以对其进行读写,但尝试在其上设置咨询群锁将失败并显示EWOULDBLOCK(如果未设置LOCK_NB,则阻塞直到解锁或关闭)。
       

    上述两种方式的区别在于,后者是协同的,允许其他进程打开设备;而前者不允许进一步打开。

    同时使用两者的原因是为了检测是否有另一个进程已经打开了设备,但没有将其置于独占模式,但希望设置了咨询锁。在这种情况下,open() 和 ioctl() 都成功了,但是 flock() 失败了。

    (我们可以使用下面讨论的这个问题的第二个方面——打开设备后,将它设置为独占模式,甚至获得它的独占锁——来检测其他进程是否打开了设备但不独占或锁定。就我个人而言,我不会打扰;我确实希望用户只在他们的系统上使用健全的应用程序。如果他们真的这样做,我希望他们有这样做的理由,所以我宁愿允许这样做奇怪的场景。标准实用程序绝对不应该发生这种情况。)
     

  2. 应用程序或守护进程可以使用lsof(来自 lsof 包)检查是否有任何进程打开了指定的文件或设备。

    这个想法是使用 root 权限运行 LANG=C LC_ALL=C lsof -F -p DEVICE 的等效项。输出将包含零行或多行。以p 开头的行(紧跟PID 和换行符\n)指定打开DEVICE 的进程。 (每一行后跟一个或多个以f 开头的行,描述该进程中哪个描述符引用设备。)

    如果应用程序或守护程序没有 root 权限,则需要安装 setuid root 的帮助程序。它提供了一个或多个设备名称。帮助程序使用stat()S_IFCHR(st_mode) 验证每个是字符设备(以避免帮助程序被用于安全漏洞);如果是,则执行上述命令。在 Linux 中,此类助手通常安装在 /usr/lib/APPLICATION/ 中,其中 APPLICATION 是应用程序或守护程序的名称。

    应用程序或守护程序本身可以通过popen("/path/to/helper 2&gt;/dev/null", "r") 执行帮助程序,并使用例如fscanf() 读取输入。 (记得使用pclose()来获取状态,并使用例如(WIFEXITED(status) &amp;&amp; !WEXITSTATUS(status))来验证命令是否成功。

    请注意,辅助程序方法可以更轻松地从 Linux 移植到其他 POSIXy 系统,只需将辅助程序替换为适合新系统的辅助程序即可。即使它不是作为 setuid root 安装的,它也为系统维护人员提供了一个简单的钩子来修改应用程序或服务的行为,如果需要的话。我个人强烈推荐 helper 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-05
    • 2012-08-03
    • 1970-01-01
    • 2013-10-12
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多