MacOS 使用文件锁实现单实例进程

2018-01-26  本文已影响54人  topws1

项目中有个功能会占用本地的代理服务器,当系统中已有进程时,就会导致新运行的进程创建的代理服务器失效。当然,正常情况下,Mac系统不会因为你点击了APP就会有多个进程,BUT,总会意外,比如你更改了你的应用版本 Or 其他我也不知道的原因。

废话不多说了吧,先来介绍下文件锁

fcntl 文件锁(功能强大,有兴趣可以单独去了解,小白作者也是瞎比比)

当我们有多个进程想要访问同一个文件时,为了避免读写冲突,就需要对文件上锁。同理可得,如果一个文件上锁了,说明我的应用已经打开了,所以就不能再运行了。。。

int fcntl(int,int, ...)

fcntl拥有多个可变参数,能够对文件的某一部分进行上锁。第一个参数是要操作的文件的描述符;第二个参数是cmd操作,只能是F_GETLK, F_SETLK, 或者 F_SETLKW;第三个是一个指向flock结构体的指针。

struct flock {
    off_t   l_start;    /* starting offset */
    off_t   l_len;      /* len = 0 means until end of file */
    pid_t   l_pid;      /* lock owner */
    short   l_type;     /* lock type: read/write, etc. */
    short   l_whence;   /* type of l_start */
};

苹果的文档中对几个参数描述的还可以,看不懂Google下就好了。简单来说pid不用传,别的参数挨个给就好了,毕竟我们只是需要上锁,其他的不用考虑。

具体实现:

- (BOOL)checkIsLocked{
    NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
    NSString *filPath = [bundlePath stringByAppendingPathComponent:@"CSLockFile"];
    
    int fd = 0;
    fd = open(filPath.UTF8String, O_RDWR | O_CREAT);
    if (fd < 0) {
        [self macAlert:@"Application is running"];
        return 1;
    }
    
    struct flock fl;
    fl.l_type = F_WRLCK;
    fl.l_len = 0;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    
    //if wrong ,all return -1
    if (fcntl(fd, F_SETLK, &fl) == -1) {
        if (errno == EACCES || errno == EAGAIN) {
            close(fd);
            return 1;
        }
              return 1;
    }
     ftruncate(fd, 0);

    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读