Каков лучший способ на платформе Linux для процесса (приложение C++), чтобы проверить, что его экземпляр уже не работает?
Стандартный способ сделать это - создать где-нибудь pid-файл, обычно содержащий pid вашей программы.
Вам не обязательно помещать туда pid, вы можете просто наложить на него эксклюзивную блокировку. Если вы откроете его для чтения/записи и заблокируете его с помощью LOCK_EX | LOCK_NB, это приведет к ошибке, если файл уже заблокирован. Это не приводит к возникновению условий гонки, и блокировка будет автоматически снята, если программа завершится аварийно.
Обычно вы хотите сделать это для каждого пользователя, поэтому домашний каталог пользователя является хорошим местом для размещения файла.
Если это демон, то лучше в /var/run.
Для настольного приложения, вероятно, более целесообразно проверить, запущен ли экземпляр для текущего пользователя , чтобы два пользователя могли иметь свои собственные экземпляры работают.
Вы можете использовать либо некоторые библиотеки ( libunique (GTK +) или QtSingleApplication (Qt)), либо сделать это самостоятельно. В дополнение к pid-файлу, упомянутому ранее, вы можете открыть сокет FIFO или UNIX-домена где-нибудь в домашнем каталоге пользователя. Таким образом, вы можете общаться с запущенным экземпляром, например. поднять окно запущенного экземпляра или указать запущенному экземпляру, чтобы он открывал новый файл / URI / что-то еще.
Для этого можно использовать файлы и блокировки файлов, но будьте осторожны, это не идеально, и не копируйте печально известную ошибку 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 (т.е. действовать как мьютекс, чтобы сделать его безопасным. с точки зрения параллелизма на уровне процессов).
Связанная альтернатива решению Майкла - создать каталог в известном месте (вероятно, в / var / run или / tmp) и использовать успех / неудачу системного вызова в качестве механизма для обеспечения взаимного исключения. Это тот же прием взаимного исключения, который CVS использовала в течение многих лет, поскольку создание каталогов атомарно в большинстве (а может и во всех) массовых операционных системах. Файл PID по-прежнему полезен в случае, когда процесс создания каталога + PID неожиданно завершает работу и не может быть очищен. Кроме того, при проверке допустимости существующего каталога + PID я бы предложил явно проверить символическую ссылку / proc /
, чтобы убедиться, что она указывает на ваш исполняемый файл, а не просто предполагать, что PID не был переработан.
Для этого можно использовать именованный семафор POSIX . Это намного безопаснее, чем использование файловой блокировки.