C和Linux中只有一个实例的应用程序

我想确保用户不能运行我的应用程序的多个实例。 我的伪代码如下所示:

sem_t one_instance_only=sem_open(UNIQUE_NAME,O_CREAT | O_EXCL,...); if(SEM_FAILED==one_instance_only) { if(E_EXIST==errno) { // application already running exit(1); } } sem_close(...); //without the call to sem_unlink() the semaphore still lingering even if app not // running sem_unlink(...); 

我尝试了它,它的工作,但我只是想确保我做对了,没有赶上某个地方。

你实际上没有使用任何信号量功能。 你可以和一个普通的文件有相同的效果,使用O_CREAT | O_EXCL打开并在退出时取消链接。
你可以使用相同的文件来写你的PID(“pidfile”),然后如果打开失败读取PID并用它来检查它是否属于你的程序的另一个实例,或者它只是在那里,因为它不是未链接的到崩溃。

问题在于逻辑不能提供应用程序实例将执行的铁板保证。 如果现有的应用程序已经决定退出,并正在执行退出路径,但还没有调用sem_close呢? 新的实例认为“我是不必要的”,因为信号量仍然存在,并退出。 最终的结果是没有任何东西在运行。

这是否是一个问题取决于情况。 如果它是一个交互式的应用程序,你可以逃避这种事情。 个人电脑用户习惯于在没有启动东西的时候多次点击图标。

解决问题的一种方法是使用一些IPC机制。 例如,服务器的新实例可以联系现有的实例,并发出请求“请保持运行,如果可能的话”。 如果服务器不能联系,或者对请求的回应是否定的,那么它可以接管新的实例。

如果需要将请求传递给现有实例,则还需要此。 说程序有命令行参数,并且必须采取一些行动。 或者,这里是一个熟悉的例子:想一下浏览器:用户希望操作系统打开一个URL,并使用现有的浏览器实例。 如果一个新的浏览器不会被启动,那么这个URL必须作为一个请求被传送到现有的实例。 仅仅观察存在一个实例并退出是不够的,因为启动请求是一个事件,这个事件是有原因的:某人或某事想要程序做某事。 你拥有的逻辑只适用于守护进程类型的进程,它读取一个配置,然后监听请求,其启动不是触发器。

我刚刚写了一个,经过测试。

 #define PID_FILE "/tmp/pidfile" static void create_pidfile(void) { int fd = open(PID_FILE, O_RDWR | O_CREAT | O_EXCL, 0); close(fd); } int main(void) { int fd = open(PID_FILE, O_RDONLY); if (fd > 0) { close(fd); return 0; } // make sure only one instance is running create_pidfile(); }