Предотвращение нескольких экземпляров процессов в Linux - PullRequest
5 голосов
/ 03 июня 2010

Каков наилучший способ на платформе Linux для процесса (приложение C ++) проверить, что его экземпляр еще не запущен?

Ответы [ 5 ]

6 голосов
/ 04 июня 2010

Стандартный способ сделать это - создать где-нибудь pid-файл, обычно содержащий pid вашей программы.

Вам не нужно ставить крышку, вы можете просто поставить на нее эксклюзивный замок. Если вы откроете его для чтения / записи и скопите его с помощью LOCK_EX | LOCK_NB, он потерпит неудачу, если файл уже заблокирован. Это не связано с условиями гонки, и в случае сбоя программы блокировка будет снята автоматически.

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

Если это демон, то где-то вроде / var / run лучше.

5 голосов
/ 03 июня 2010

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

Основная логика этого:

Invariant:
    File xxxxx will exist if and only if the program is running, and the
    contents of the file will contain the PID of that program.

On startup:
    If file xxxxx exists:
        If there is a process with the PID contained in the file:
            Assume there is some instance of the program, and exit
        Else:
            Assume that the program terminated abnormally, and
            overwrite file xxxx with the PID of this program
    Else:
        Create file xxxx, and save the current PID to that file.

On termination (typically registered via atexit):
    Delete file xxxxx

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

1 голос
/ 03 июня 2010

Связанная с решением Михаэля альтернатива - создать каталог в известном месте (вероятно, в / var / run или / tmp) и использовать успех / неудачу системного вызова в качестве механизма обеспечения взаимного исключения. Это тот же прием взаимоисключения, который CVS использовал годами, поскольку создание каталогов является атомарным в большинстве (возможно, во всех) ОС. Файл PID по-прежнему полезен в том случае, когда процесс создания каталога + PID неожиданно умирает и не может быть очищен. Кроме того, при проверке, чтобы убедиться, что существующий каталог + PID действителен, я бы предложил явно проверить символическую ссылку /proc/<PID>/exe, чтобы убедиться, что она указывает на ваш исполняемый файл, а не просто предполагать, что PID не был переработан.

0 голосов
/ 03 июня 2010

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

Вы можете использовать несколько библиотек ( libunique (GTK +) или QtSingleApplication (Qt)) или сделать это самостоятельно. В дополнение к pid-файлу, упомянутому ранее, вы можете открыть сокет FIFO или UNIX-домена где-нибудь в домашнем каталоге пользователя. Таким образом, вы можете общаться с запущенным экземпляром, например. поднять окно запущенного экземпляра или указать запущенному экземпляру открыть новый файл / URI / что угодно.

0 голосов
/ 03 июня 2010

Вы можете использовать POSIX с именем семафор , чтобы сделать это. Это гораздо безопаснее, чем использование блокировки файлов.

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