利用PID文件和文件锁实现。PID文件就是一个保存了进程pid的文件。
#define PIDFILE "/tmp/proc.pid"
static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
struct flock lock;
lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len;
return (fcntl(fd,cmd, &lock));
}
#define write_lock(fd, offset, whence, len) lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)
static void check_single_on()
{
int fd, val;
char buf[10];
if((fd = open(PIDFILE, O_WRONLY | O_CREAT, 0644)) <0 ) {
perror("open in check_single_on()");
exit(1);
}
/* try and set a write lock on the entire file */
if(write_lock(fd, 0, SEEK_SET, 0) <0 ) {
if(errno == EACCES || errno == EAGAIN) {
printf("daemon is already running.\n");
exit(0); /* gracefully exit, daemon is already running */
}else {
perror("write_lock");
close(fd);
exit(1);
}
}
/* truncate to zero length, now that we have the lock */
if(ftruncate(fd, 0) <0) {
perror("ftruncate");
close(fd);
exit(1);
}
/* write our process id */
sprintf(buf, "%d\n", getpid());
if(write(fd, buf, strlen(buf)) != strlen(buf)) {
perror("write in check_single_on()");
close(fd);
exit(1);
}
/* set close-on-exec flag for descriptor */
if((val = fcntl(fd, F_GETFD, 0) <0 )) {
perror("fcntl");
close(fd);
exit(1);
}
val |= FD_CLOEXEC;
if(fcntl(fd, F_SETFD, val) <0 ) {
perror("fcntl again");
close(fd);
exit(1);
}
/* leave file open until we terminate: lock will be held */
}
检测一个进程是否正在运行:
static int check_proc_running()
{
int fd, rv;
char buf[10];
if((fd = open(PIDFILE, O_RDWR | O_CREAT, 0644)) <0 ) {
perror("open in check_proc_running()");
exit(1);
}
/* try and set a write lock on the entire file */
if(write_lock(fd, 0, SEEK_SET, 0) <0 ) {
if(errno == EACCES || errno == EAGAIN) {
bzero(buf, 10);
rv = read(fd, buf, 10);
buf[rv] = '\0';
close(fd);
return atoi(buf);
}else {
perror("write_lock");
close(fd);
return -1;
}
}
close(fd);
printf("daemon is not running now.\n");
return -1;
}