Получение эксклюзивного доступа к устройству tty из корневой программы в Linux - PullRequest
1 голос
/ 28 марта 2009

У меня есть программа, работающая от имени root в Linux, с tty (на самом деле LCD, реализованный как tty). Устройство для того, что он стоит, это / dev / ttyUSB0. Я хотел бы, чтобы моя программа, которая пишет на это устройство, имела эксклюзивный доступ к устройству, чтобы не создавать помех для других экземпляров программы, запущенных одновременно.

Я вижу, что есть опция ioctl под названием TIOCEXCL, которая не позволяет дополнительным открытиям устройства без «множественных вызовов open () к одному и тому же файлу, если не будет выполнен TIOCEXCL ioctl. Это предотвратит дополнительные открытия, кроме как с помощью собственные процессы. " Я проверил это, и оно работает так же, как рекламировалось: если пользователь без полномочий root пытается открыть / dev / ttyUSB0 (после того, как я изменил разрешения), то происходит сбой открытия с чем-то вроде «устройство занято», и если пользователь root пытается открыть его , это работает.

В идеале я хочу, чтобы этот привилегированный доступ к tty работал для пользователей root. Таким образом, у меня было бы несколько пользователей root, использующих программу, которая пишет на ЖК-дисплей, но каким-то образом их доступ к ЖК-монитору (tty) будет сериализован. Очевидно, опция TIOCEXCL ioctl не будет работать для меня, так как она не мешает корневым пользователям открывать уже открытое 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)

Ответы [ 5 ]

6 голосов
/ 28 марта 2009
0 голосов
/ 02 декабря 2014

У меня есть такая проблема, как ты. Если вы можете взломать ядро ​​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;
        }
    }
}
0 голосов
/ 22 октября 2014

Я не знаю, нашли ли вы уже решение или вы только что изменили свой дизайн, но вот работа в "земле корней":

  1. Создайте в вашей системе другой файл с таким же именем вашего порта или с чем-то вроде него, например ttyUSB0_islocked.
  2. когда вы открываете порт, ваш процесс ищет / создает, открывает этот файл и записывает некоторую информацию, например, идентификатор процесса.
  3. перед тем, как открыть порт в других программах, проверьте, существует ли этот файл и существует ли в файле процесс с таким же идентификатором процесса, а затем продолжите, если такого процесса нет, в противном случае подождите или выйдите.
0 голосов
/ 11 августа 2009

Я бы посоветовал вам изучить блокировку UUCP. В Linux должна быть библиотека, которая ее реализует, но если нет, то ее довольно легко реализовать. Я широко использовал его в подобных ситуациях, когда я не хочу, чтобы несколько экземпляров одной и той же программы наступали друг на друга.

В качестве примечания, возможно, вам следует переосмыслить архитектуру вашего решения. Процесс, который обращается к LCD / ttyUSB0, может действовать как сервер и обрабатывать сообщения от клиентских процессов, которые должны записывать данные на LCD. Это потребует некоторой формы IPC. Это может быть излишним для вашего проекта.

Имейте в виду, что любое решение, которое вы придумали, будет работать, только если все процессы, которые обращаются к устройству, соответствуют протоколу. Если вы беспокоитесь о мошенническом процессе, работающем с правами root, то вы можете застрять в ядре, чтобы получить желаемое решение.

0 голосов
/ 28 марта 2009

Ответ: Root всегда имеет доступ. Всегда.

Возможно, если бы вы сказали больше о том, что еще захватывало устройство, или то, чего вы боитесь, может захватить устройство ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...