【问题标题】:Getting exclusive access to a tty device from a root program on Linux从 Linux 上的根程序获得对 tty 设备的独占访问权
【发布时间】:2009-03-27 22:22:07
【问题描述】:

我有一个在 Linux 上以 root 身份运行的程序,它与一个 tty(实际上是一个作为 tty 实现的 LCD)通信。值得的设备是/dev/ttyUSB0。我希望写入此设备的程序能够独占访问该设备,以免受到同时运行的其他程序实例的任何干扰。

我看到有一个名为 TIOCEXCL 的 ioctl 选项,它可以防止设备的附加打开,因为“除非发出 TIOCEXCL ioctl,否则对同一文件的多次 open() 调用将成功。这将阻止除 root 以外的其他打开-拥有的进程。”我对此进行了测试,它的工作原理与宣传的一样:如果非 root 用户尝试打开 /dev/ttyUSB0(一旦我更改了权限),则打开失败并显示“设备忙”之类的内容,并且如果 root 用户尝试打开它,它可以工作。

理想情况下,我想要的是一种对 tty 的独占访问权,以便为 root 用户工作。因此,我将有多个 root 用户使用写入 LCD 的程序,但不知何故,他们对 LCD (tty) 的访问将被序列化。显然 TIOCEXCL ioctl 选项对我不起作用,因为它不会阻止 root 用户打开已经打开的 tty 设备。

我想这里有很多选择,但我正在与大家联系,看看您是否有其他想法或建议。

  1. 也许我在使用 TIOCEXCL 时遗漏了一些东西...

  2. 也许通过 open() 或 ioctl() 或其他方式获得独占访问权限。

  3. 如果有某种方法可以检测到其他进程打开了设备,我可以等待并重试。我知道 lsof 但我不愿意从这个程序内部调用它来学习这个。并且有竞争条件。 (也许我可以克服它?:))

  4. 我可以像以前那样实现锁定,以获得对 tty 设备的独占访问权限。

更新 1:

由于写入 LCD 设备的唯一程序是我的,我倾向于执行以下操作(伪代码)来锁定代码:

f = open("/dev/ttyUSB0", O_RDWR)
flock(f, LOCK_EX)

// do any ioctl's, etc.

// do any write's

// sleep a tad to not flash messages too fast on LCD
nanosleep({0, 250000000}, NULL)

flock(f, LOCK_UN)
close(f)

【问题讨论】:

  • 我想到的第一个(有点愚蠢;))问题是,你真的需要以 root 身份运行吗?或者只需要对您可以 sudo 或使用 setuid 权限的其他内容的 root 访问权限?
  • 另见内核新手邮件列表中的How to make /dev/ttyACM0 (and friends) exclusive?

标签: c linux unix tty


【解决方案1】:

【讨论】:

    【解决方案2】:

    我有一些像你一样的问题。 如果你可以破解你的 linux 内核,你可以像这样进行肮脏的破解。 在文件中

    linux/drivers/char/tty_io.c

    为函数添加新命令

    long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    {
        ...
        switch (cmd) {
        ...
        case 0x54FF:
            return put_user(tty->count, (int __user *)p);
        ...
    }
    

    tty->count 的值是当前打开描述符的计数。

    在您的应用程序中,您可以尝试此代码

    int fd, count, res;
    fd = open("/dev/ttyS0", O_RDWR|O_NOCTTY|O_NONBLOCK);
    if (fd >= 0)
    {
        count = 0;
        res = ioctl(fd, 0x54FF, &count);
        if (res>=0)
        {
            if (count > 1)
            {
                printf("Device already in use.\n")
                close(fd);
                fd = -1;
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      Answer: Root 始终具有访问权限。总是。

      也许如果你说更多关于其他什么正在抓取设备,或者你担心什么可能会抓取设备......

      【讨论】:

      • 我的 write-to-lcd 程序可能同时从多个进程调用,因此可能同时运行多个实例。虽然我并不肯定,但我认为 LCD 设备和 Linux TTY 支持的组合在这种情况下并不能可靠地将所有消息传递到 LCD。
      【解决方案4】:

      我鼓励您研究 UUCP 锁定。 Linux 上应该有一个实现它的库,但如果没有,它很容易实现。我已经在类似的情况下广泛使用它,我不希望同一程序的多个实例相互踩踏。

      附带说明一下,也许您应该重新考虑解决方案的架构。访问 LCD/ttyUSB0 的进程可以充当服务器并处理来自需要写入 LCD 的客户端进程的消息。这将需要某种形式的 IPC。这对您的项目来说可能有点过头了。

      请记住,您提出的任何解决方案都只有在访问设备的所有进程都符合协议时才有效。如果您担心以 root 身份运行的流氓进程,那么您可能会陷入破解内核以获得所需解决方案的困境。

      【讨论】:

        【解决方案5】:

        我不知道您是否已经找到了解决方案,或者您只是更改了您的设计,但这里有一个“根域”中的解决方法:

        1. 在您的系统中创建另一个与您的端口名称相同的文件或包含它的名称,例如ttyUSB0_islocked
        2. 当您打开端口时,让您的进程查找/创建并打开此文件并在其中写入一些信息,例如它的进程 ID。
        3. 在其他程序中打开端口之前,请检查此文件是否存在以及文件中是否存在具有相同进程 ID 的进程,如果没有此类进程则继续执行,否则请等待或退出。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-02-09
          • 2016-08-05
          • 2016-07-14
          • 1970-01-01
          • 2013-10-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多