如何使一个程序同时只能运行一个进程实例

利用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;
}


 » 相关连接:
如何避免产生僵死进程zombie proce 利用mktemp和fcntl实现进程间互斥 Linux环境进程间通信——信号 多进程编程
如何启动另一程序的执行exec 信号 互斥锁、条件变量 互斥锁的使用
创建线程 线程、全局变量、线程参数 POSIX线程编程指南
 » 本栏目最新帖:
 » 精华帖:

Powered by PHPWind v6.0 Code © 2003-08