其他
如何让你的程序同时只能运行一个?
思路
1.启动程序,检测标志,判断是否有同样的程序运行,是则2,否则3 2.程序退出 3.程序启动,并设置标志,以便下次启动时检测
实现方法
基本原理
-rw-r--r-- 1 root root 5 11月 24 08:19 /var/run/acpid.pid
-rw-r--r-- 1 root root 5 11月 24 08:19 /var/run/atd.pid
-rw-r--r-- 1 root root 5 11月 24 08:19 /var/run/crond.pid
-rw-r--r-- 1 root root 5 11月 24 09:08 /var/run/dhclient-wlp3s0.pid
-rw-r--r-- 1 root root 4 11月 24 08:19 /var/run/docker.pid
实现
flock结构至少包含以下字段:
short l_type; /*锁类型 F_RDLCK,F_WRLCK, F_UNLCK*/
short l_whence; /* 偏移开始的位置 SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* 开始锁定区域*/
off_t l_len; /* 锁定字节数 */
pid_t l_pid; /* 记录锁的进程ID*/
};
结合以上两者,参考代码如下:
//博客:https://www.yanbinghu.com
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#define PROC_NAME "single_instance"
#define PID_FILE_PATH "/var/run/"
static int lockFile(int fd);
static int isRunning(const char *procname);
int main(void)
{
/*判断是否已经有实例在运行*/
if(isRunning(PROC_NAME))
{
exit(-1);
}
printf("run ok\n");
sleep(20);//避免程序立即退出
return 0;
}
/*锁文件还可以使用flock,目的是类似的。不过是它是BSD系统调用,并且某些版本不支持NFS,出于移植性考虑,使用fcntl*/
static int lockFile(int fd)
{
struct flock fl;
fl.l_type = F_WRLCK;//设置写锁
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
fl.l_pid = -1;//锁定文件,设置为-1
return(fcntl(fd, F_SETLK, &fl));
}
static int isRunning(const char *procname)
{
char buf[16] = {0};
char filename[128] = {0};
sprintf(filename, "%s%s.pid",PID_FILE_PATH,procname);
int fd = open(filename, O_CREAT|O_RDWR );//可读可写,不存在时创建
if (fd < 0) {
printf("open file %s failed!\n", filename);
return 1;
}
if (-1 == lockFile(fd)) /*尝试加锁*/
{
printf("%s is already running\n", procname);
close(fd);
return 1;
}
else
{
ftruncate(fd, 0);/*截断文件,重新写入pid*/
sprintf(buf, "%ld", (long)getpid());
write(fd, buf, strlen(buf) + 1);
return 0;
}
}
编译运行
$ ./single_instance #注意root权限运行,或者调整pid文件位置
run ok
-rw-r--r-- 1 root root 6 11月 24 11:36 /var/run/single_instance.pid
single_instance is already running
简单可靠 可读可见,相比于信号量或共享内存,它更容易观察 无性能要求,启动时加锁,结束释放。 一旦出现异常没有释放,也可以手动删除文件
pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
int pidfile_write(struct pidfh *pfh);
int pidfile_close(struct pidfh *pfh);
int pidfile_remove(struct pidfh *pfh);
总结
相关精彩推荐