从 Linux 上的 root 程序获取对 tty 设备的独占访问

发布于 2024-07-16 03:40:37 字数 1174 浏览 11 评论 0原文

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

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

我理想地想要的是一种让 root 用户能够独占 tty 访问的方法。 因此,我有多个 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)

I have a program running as root on Linux, talking to a tty (actually an LCD implemented as a tty). The device for what it's worth is /dev/ttyUSB0. I'd like to have my program that writes to this device be able to have exclusive access to the device, so as to not have any interference from other instances of the program running at the same time.

I see that there's a ioctl option called TIOCEXCL which will prevent additonal open's of the device to wit "multiple open() calls to the same file will succeed unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned processes." I tested this and it works just as advertised: if a non-root user tries to open /dev/ttyUSB0 (once I changed the permissions) then the open fails with something like "device busy" and if a root user tries to open it, it works.

What I ideally want is a way to this exclusive access to the tty to work for root users. So I'd have multiple root users using the program that writes to the LCD, but somehow their access to the LCD (tty) would be serialized. Apparently the TIOCEXCL ioctl option will not work for me since it doesn't stop root users from opening an already-opened tty device.

I guess there are a number of options here, but I am reaching out to all ya'll to see if you might have other thoughts or suggestions.

  1. Maybe I'm missing something about using TIOCEXCL...

  2. Maybe there's some other way via open() or ioctl() or what-not to get exclusive access.

  3. If there was some way I could detect that some other process has the device open, I could just wait and retry. I know about lsof but I'm loath to invoke it from inside this program just to learn this. And there are race conditions with that. (Maybe I can get over that? :) )

  4. I could implement locking like apparently used to be done to get exclusive access to tty devices.

Update 1:

Since the only program writing to the LCD device is mine, I am inclined to do something like the following (pseudo-code) to lock inside the code:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我乃一代侩神 2024-07-23 03:40:37

我有一些像你一样的问题。
如果你能破解你的 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;
        }
    }
}

i have some issue like you.
If you can hack you linux kernel, you can to do dirty hack like this.
In file

linux/drivers/char/tty_io.c

add new command to function

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

The value of tty->count is a count of current open descriptors.

In your application you can try this code

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;
        }
    }
}
决绝 2024-07-23 03:40:37

答:root 始终具有访问权限。 总是。

也许如果您更多地说明还有什么东西正在抢夺该设备,或者您担心什么可能会抢夺该设备......

Answer: Root always has access. Always.

Perhaps if you said more about what else was grabbing the device, or what you fear might grab the device...

最美不过初阳 2024-07-23 03:40:37

我鼓励您研究 UUCP 锁定。 Linux 上应该有一个库可以实现它,但如果没有,实现起来也相当容易。 我在类似的情况下广泛使用了它,在这些情况下,我不希望同一程序的多个实例相互干扰。

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

请记住,只有访问设备的所有进程都符合该协议,您提出的任何解决方案才有效。 如果您担心以 root 身份运行的流氓进程,那么您可能会不得不通过破解内核来获得您想要的解决方案。

I would encourage you to look into UUCP locking. There should be a library on Linux that implements it, but if not, it's fairly easy to implement. I've used it extensively in similar situations where I don't want multiple instances of the same program to step on each other.

As a side note, perhaps you should rethink the architecture of your solution. The process that accesses the LCD/ttyUSB0 could act as a server and handle messages from the client processes that need to write to the LCD. This would require some form of IPC. It may be overkill for your project.

Keep in mind that any solution you come up with will only work if all processes that access the device conform to the protocol. If you are worried about a rogue process running as root then you may be stuck with hacking the kernel to get the solution you want.

穿越时光隧道 2024-07-23 03:40:37

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

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

I don't know if you have already found a solution or you just changed your design but here's a work around in the "roots land":

  1. Create another file in your system with the same name of your port or something including it like ttyUSB0_islocked.
  2. when you open the port have your process look for/create and open this file and write some info like it's process Id in it.
  3. before opening the port in other programs check if this file exists and there's a process with the same process id within the file and then proceed if there's no such process other wise wait or exit.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文