最新消息:

守护进程的单例运行

c admin 3567浏览 0评论

由于守护进程在后台运行,为系统或用户提供某种服务,因此通常只需要一个运行实例就可以了,而且在大部分情况下只能有一个实例在运行。例如cron进程,若有多个实例在运行,那么各个实例都会根据crontab执行一份用户指定的任务,岂不是乱了套了?还有其他很多守护进程是设备相关的,而这些设备有很可能是非共享的,所以这样的守护进程也不能运行多个。

文件锁和记录锁机制是一种实现守护进程单例运行的方法。如果每一个守护进程创建一个文件,并且在整个文件上加上一把锁,那就只允许创建一把这样的写锁,所以在此之后试图再创建一把这样的写锁就会失败,以此向后续守护进程的副本指明已经存在一个正在运行的副本了。守护进程终止时,这把锁将被自动删除。

int
lockfile(int fd) //~ try to lock the file, affecting errno when it fails.
{
    struct flock fk;
    fk.l_type = F_WRLCK;
    fk.l_start = 0;
    fk.l_whence = SEEK_SET;
    fk.l_len = 0;
    return (fcntl(fd, F_SETLK, &fk));
}

int
already_running(const char* fname) //~ return 1, if another daemon is running
{
    int fd;
    fd = open(fname, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    if( fd < 0 )
    {
        //~ in daemon process, you should use syslog, instead of stdout, for logging
        //~ syslog(LOG_ERR, "cannot open %s: %s", fname, strerror(errno));
        fprintf(stdout, "cannot open %s: %s", fname, strerror(errno));
        fflush(stdout);
        exit(1);
    }
    if( lockfile(fd) < 0 )
    {
        if( errno == EACCES || errno == EAGAIN )
        {
            //~ syslog(LOG_ERR, "cannot lock %s: %s", fname, strerror(errno));
            fprintf(stdout, "cannot lock %s: %s", fname, strerror(errno));
            close(fd);
            return 1;
        }
        //~ syslog(LOG_ERR, "cannot lock %s: %s", fname, strerror(errno));
        fprintf(stdout, "cannot lock %s: %s", fname, strerror(errno));
        fflush(stdout);
        exit(1);
    }
    ftruncate(fd, 0);
    char buf[16];
    sprintf(buf, "%ld", (long)getpid());
    write(fd, buf, strlen(buf) + 1);
    return 0;
}

转载请注明:爱开源 » 守护进程的单例运行

您必须 登录 才能发表评论!