C和Linux中仅限一个实例的应用程序

时间:2013-01-30 20:25:55

标签: 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(...);     

我尝试了它并且它有效,但我只是想确保我做得对,并且没有任何地方的捕获。

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

问题在于,逻辑无法提供应用程序实例将执行的铁壳保证。如果现有应用程序已决定退出并正在执行退出路径但尚未调用sem_close,该怎么办?新实例认为“我没必要”,因为信号量仍在那里,然后退出。最终结果是没有任何东西在运行。

这是否是一个问题取决于具体情况。如果它是一个交互式应用程序,你可以逃脱这种事情。当用户没有启动时,PC用户习惯于多次点击图标。

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

如果需要将请求传递给现有实例,则还需要此选项。假设程序有命令行参数,必须采取一些措施。或者,这是一个熟悉的例子:想到浏览器:用户希望操作系统打开URL,并使用现有的浏览器实例。如果不打算启动新浏览器,则必须将该URL作为请求传递给现有实例。仅仅观察存在现有实例并退出是不够的,因为启动请求是由于某种原因而发生的事件:某人或某事想要程序做某事。您拥有的逻辑仅适用于守护进程类型进程,该进程读取配置然后侦听请求,并且其启动不是任何触发器。

答案 2 :(得分:1)

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

#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();
}