C++ 防止Linux上的多进程实例

C++ 防止Linux上的多进程实例,c++,linux,process,C++,Linux,Process,在Linux平台上,进程(C++应用程序)检查其实例是否尚未运行的最佳方法是什么?您可以使用文件和文件锁来完成此任务,但请注意,它并不完美,不要复制臭名昭著的Firefox bug,即使它尚未运行,也会拒绝启动 它的基本逻辑是: Invariant: File xxxxx will exist if and only if the program is running, and the contents of the file will contain the PID of th

在Linux平台上,进程(C++应用程序)检查其实例是否尚未运行的最佳方法是什么?

您可以使用文件和文件锁来完成此任务,但请注意,它并不完美,不要复制臭名昭著的Firefox bug,即使它尚未运行,也会拒绝启动

它的基本逻辑是:

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文件的访问(即充当互斥体,以确保进程级并发的安全)。

Michael解决方案的一个相关替代方案是在已知位置(可能在/var/run或/tmp下)创建一个目录并使用系统调用的成功/失败作为确保互斥的机制。这与CVS多年来使用的互斥技巧相同,因为在大多数(可能是所有)商品操作系统上,目录创建是原子的。当目录+PID创建进程意外死亡且无法清理时,PID文件仍然有用。此外,在检查现有目录+PID是否有效时,我建议显式检查
/proc//exe
符号链接,以验证它是否指向可执行文件,而不仅仅是假设PID没有被回收

您可以使用一个。这比使用文件锁要安全得多。

对于桌面应用程序,检查当前用户是否启动了实例可能更可行,这样两个用户就可以运行自己的实例


您可以使用一些库((GTK+)或(Qt)),也可以自己使用。除了前面提到的pid文件外,您还可以在用户主目录的某个位置打开FIFO或UNIX域套接字。通过这种方式,您可以与正在运行的实例进行通信,例如,打开正在运行的实例的窗口,或者告诉正在运行的实例打开新文件/URI/任何内容。

执行此操作的标准方法是在某处创建一个pid文件,通常包含程序的pid

你不需要把pid放在那里,你可以在上面加一个独占锁。如果打开该文件进行读/写操作,并使用LOCK_EX | LOCK_NB将其聚集,则如果该文件已锁定,则该文件将失败。这是无竞争条件的,如果程序崩溃,锁将自动释放

通常情况下,您希望按每个用户执行此操作,因此用户的主目录是放置文件的好地方


如果是守护进程,像/var/run这样的地方会更好。

使用套接字而不是文件并尝试绑定到预定义的端口不是更简单吗?顺便问一下,为什么我不能在没有所有pid验证的情况下使用文件锁定?@Jack,你可以在没有pid验证的情况下使用文件锁定,但是当程序实际崩溃并且无法清理文件时,你就有可能假设程序是打开的(想想Firefox的问题)。另外,Rakis提出了一个好的观点,即在Linux上,您可以使用“/proc”中的数据验证PID是否属于您的程序。。。有一些编程方法可以更通用地跨UNIX变体实现这一点(至少您可以调用“ps”并解析其输出,尽管我相信您可以调用一些函数来直接获取流程信息)。要检查流程是否存在,请调用kill(pid,0)。当进程存在时,此操作将成功,否则将失败。当心在不同机器上运行的进程@杰克:据我所知,你可以使用文件锁定。当程序启动时,执行一个try-lock操作,如果成功,则它是第一个实例。@Jack:未能绑定到预定义的(可能是暂时的)除了运行同一程序的另一个实例外,端口可能会由于许多原因而失败。如何处理在不清理信号量的情况下崩溃的程序?从手册页:POSIX命名信号量具有内核持久性:如果未被sem_unlink()删除,则信号量将存在,直到系统关闭。崩溃在这里肯定是个问题。