10

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

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

我试过了,它可以工作,但我只是想确保我做对了,并且在某个地方没有任何问题。

4

3 回答 3

2

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

于 2013-01-30T23:15:19.177 回答
1

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

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

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

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

于 2013-01-31T04:53:07.870 回答
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();
}
于 2014-06-25T01:33:57.560 回答