我想确保用户无法运行我的应用程序的多个实例。我的伪代码如下所示:
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(...);
我尝试了它并且它有效,但我只是想确保我做得对,并且没有任何地方的捕获。
答案 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();
}