c - 在 Linux 中如何检查串口是否打开?

标签 c linux serial-port

如何使用 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;
} 

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

最佳答案

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

  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>/dev/null", "r") 执行助手,并使用例如 fscanf() 读取输入。 (记得使用 pclose() 来获取状态,并使用例如 (WIFEXITED(status) && !WEXITSTATUS(status)) 来验证命令是否成功。

    请注意,通过简单地用适合新系统的帮助程序替换帮助程序,帮助程序方法可以更轻松地从 Linux 移植到其他 POSIXy 系统。即使它没有作为 setuid root 安装,它也为系统维护人员提供了一个简单的 Hook ,以便在需要时修改应用程序或服务的行为。我个人强烈推荐辅助方法。

关于c - 在 Linux 中如何检查串口是否打开?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49636520/

相关文章:

c - c中是否有既是一元又是二元的运算符?

c - C 中的随机数组

c++ - GTK3 没有调整大小限制

linux - 如何增加内核内部的进程能力?

php - flock 中的 LOCK_NB 是什么意思?

c - 将套接字绑定(bind)到网络接口(interface)

c++ - 用Visual C++编程串口arduino

java - 在组合框中创建选项作为可用串行端口

c - C 递归中的因式分解

c - 编写 API 以与连接在串行端口上的设备进行通信