在Linux 系统中/var/run下有很多以pid结尾的文件,这个其实是为了保证程序以单例模式运行而设计的。程序在启动后,首先打开(如果没有则创建)/var/run/xx.pid,然后尝试去设置文件锁,如果成功,则将程序的里程ID写入该文件,写入后注意不要关闭文件或解锁;如果加锁失败,表明程序已经有一个进程在运行了,则退出此次启动。此机制在一些程序尤其是服务器程序中很常见,例如sip服务器kamailio中就是这样保证程序以单例模式运行的。
注:程序退出后,文件锁自动解锁。
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#define DEFAULT_FILE "/var/run/test.pid"
int main(int argc, char *argv[])
{
int fd = -1;
char buf[32];
fd = open(DEFAULT_FILE, O_WRONLY | O_CREAT, 0666);
if (fd < 0) {
perror("Fail to open");
exit(1);
}
struct flock lock;
bzero(&lock, sizeof(lock));
if (fcntl(fd, F_GETLK, &lock) < 0) {
perror("Fail to fcntl F_GETLK");
exit(1);
}
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &lock) < 0) {
perror("Fail to fcntl F_SETLK");
exit(1);
}
pid_t pid = getpid();
int len = snprintf(buf, 32, "%d\n", (int)pid);
write(fd, buf, len); //Write pid to the file
printf("Hello world\n");
while(1);
return 0;
}
编译:
gcc -o test test.c
运行:
1.打开终端: ./test
cat /var/run/test.pid
23409
2.打开另一终端:./test,打印错误如下:
Fail to fcntl F_SETLK: Resource temporarily unavailable
表示程序已经有实例运行。