Как мне синхронизировать два процесса? - PullRequest
6 голосов
/ 30 октября 2008

У меня есть один HW-интерфейс, который я хочу использовать из двух приложений (процессов) на одной рабочей станции. HW требует одного вызова инициализации, тогда любое приложение использует одну и ту же функцию (в той же библиотеке), чтобы выполнить много транзакций с HW.

Таким образом, каждое приложение должно работать так:

main()
    // I don't know if another app already init'ed the HW
    ret = hw_init_lock(non-blocking)

    if ret = OK
        // no one else has done this, I have to
        init_hw()
    else
       //someone else has already init'ed the HW, I gotta make sure it stays that way
       //as long as I'm alive
       increment_hw_init_ref_counter()

    hw_trans_lock(blocking)
    hw_trans()
    hw_trans_unlock()
    ....

    //exit app, uninit hw if we are last out
    ret = decrement_hw_init_ref_counter()
    if ret == 0
        uninit_hw()

    exit(0)

Какой механизм я могу использовать в вызовах блокировки и подсчета ссылок, которые используются двумя приложениями? Я имею в виду именованные каналы, т.е. mkfifo ().

Ответы [ 6 ]

9 голосов
/ 30 октября 2008

Семафор POSIX - это путь. Поскольку вы хотите использовать один и тот же семафор в разных процессах, вам необходимо использовать именованный семафор .:

Именованный семафор идентифицируется Наименование формы / somename. Два процессы могут работать на том же названный семафор, передавая тот же имя для sem_open (3).

4 голосов
/ 30 октября 2008

Семафоры и мьютексы / условные переменные являются хорошими, очень высокопроизводительными примитивами, которые подходят для использования между потоками или между процессами.

Все они основаны на идее (и, как правило, на реальности) тестирования и установки или других элементарных операций, выполняемых над общей памятью.

Если вы планируете распространять свои процессы по сети, то семафоры и мьютексы могут быть вам неподходящими - они работают только на одной машине. Трубы и розетки, как правило, расширяются в сети.

Краткое описание мьютексов, условных переменных и семафоров:

Мьютексы

Мьютекс - это примитив, который может быть заблокирован или разблокирован. Процесс / поток, который заблокировал это, должен быть тем, чтобы разблокировать это. Этот аспект владение позволяет операционной системе применять некоторые интересные оптимизации, такие как наследование приоритетов и протокол потолка приоритета (чтобы избежать инверсии приоритетов). однако , мьютекс не имеет счетчика, связанного с ним. В общем, вы не можете заблокировать уже заблокированный мьютекс и сохранить память, которая была «заблокирована дважды» (я думаю, что есть некоторые расширения, которые позволяют это сделать, но они не доступны везде)

Переменные условия

Мьютекс отлично подходит для ... ну, взаимное исключение. Но что если вам нужно заблокировать условие, связанное с объектом, к которому вы имеете взаимное исключение? Для этого вы используете условную переменную или CV. Резюме связано с мьютексом. Например, скажем, у меня есть очередь входных данных, к которым мои процессы хотят получить доступ. Один захватывает мьютекс, чтобы он мог смотреть в очередь без страха вмешательства. Тем не менее, он находит очередь пустой и хочет ждать, пока что-то поступит в очередь. Поэтому он ожидает переменную условия «очередь не пуста». Интересная часть здесь состоит в том, что, поскольку CV связано с мьютексом, мьютекс получает , автоматически повторно получает , как только передается переменная условия. Таким образом, как только процесс просыпается после ожидания в CV, он знает, что он снова имеет эксклюзивный доступ к очереди. не знает, что на самом деле в очереди есть что-то - возможно, два процесса ждали резюме - одна вещь пришла - и первый приоритет получил и снял «вещь» перед вторая вещь проснулась. Таким образом, всякий раз, когда вы используете CV, вам нужно ПРОВЕРИТЬ условие, например:

mutex_enter(m);
while (! condition) {
   cond_wait(m, c); // drop mutex lock;  wait on cv;  reacquire mutex
}
//processing related to condition
mutex_exit(m);

семафоры

ОК, это мьютексы и условные переменные. Семафоры проще. Их можно увеличивать и уменьшать любыми процессами. У них есть память - они считают - так что вы можете использовать их, чтобы определить, сколько из условий произошло. Не так с переменными состояния. Кроме того, поскольку семафоры могут быть уменьшены одним процессом и увеличены другим, они не имеют аспекта владения - поэтому нет наследования приоритетов, предотвращение инверсии приоритетов невозможно.

Теперь, наконец, все эти механизмы требуют общей памяти для эффективной реализации. Это может быть хорошо для вас, но имейте в виду - если вы считаете, что ваше приложение может в конечном итоге распространяться, то мьютексы, условные переменные и семафоры могут не подойти Трубы и разъемы, хотя и требуют гораздо больших затрат, могут быть достаточно просто расширены по сети.

2 голосов
/ 30 октября 2008

Так как вам нужно только одно семафорное число, достаточно мьютекса.

2 голосов
/ 30 октября 2008

Использование семафоров POSIX .

1 голос
/ 25 марта 2015

Я думаю, что если мы хотим синхронизировать несколько запущенных процессов, то мы можем использовать очень простой метод, называемый блокировками файлов.

Пожалуйста, обратитесь к этой статье для более подробной информации: http://blog.markedup.com/2014/07/easy-mode-synchronizing-multiple-processes-with-file-locks/

1 голос
/ 30 октября 2008

Я предполагаю, что

... что используется двумя приложениями?

означает, что вы хотите, чтобы эти две вещи выполнялись как отдельные процессы? Если это не так, и они выполняются как один процесс (с несколькими потоками), то предложения семафоров и мьютексов являются наилучшим вариантом и должны быть довольно простыми.

Обратите внимание, что ответ будет зависеть от того, как именно вы получаете доступ к этому оборудованию. Например, если он открыт через файл, тогда можно использовать обычную блокировку файла.

Однако, если вы пытаетесь синхронизировать доступ к оборудованию между двумя процессами, это другой вопрос. Я думаю, первое, что нужно сказать, это то, что будет проще синхронизировать, если вы сможете, иметь один процесс, отвечающий за доступ к оборудованию. В этой модели у вас может быть один процесс, который выступает в качестве сервера для аппаратного обеспечения - прием запросов от других процессов и выполнение операций чтения и записи от их имени. Подойдет практически любая форма межпроцессного взаимодействия, но для простоты может быть уместно что-то вроде очереди сообщений ( link ) с некоторой соответствующей структурой данных (например, флагом, указывающим, является ли это операцией чтения или записи , смещение от базового адреса вашего оборудования, количество байтов, буфер (в случае записи)

Если помещение всего прямого доступа к оборудованию в один процесс нецелесообразно, вам придется использовать правильную схему синхронизации. Я бы исследовал использование либо блокировки файлов (и реализации элементарной схемы мьютекса), либо использования именованных семафоров (как предложил Альбертб)

...