浅尝辄止19-Linux基础-文件锁2

简介

文件锁主要有三套函数,分别是flock(2)fcntl(2)lockf(3)

函数名 实现类别 支持读锁 支持写锁 支持文件局部锁
flock FLOCK Χ Χ
lockf POSIX Χ
fcntl POSIX

今天就来试一下fcntl,其实这个系统调用的功能很多,文件锁只是一方面,锁的控制细节主要用struct flock来描述,其主要member可含义如下。

        struct flock {
            ...
            short l_type;    /* Type of lock: F_RDLCK,
                                   F_WRLCK, F_UNLCK */
            short l_whence;  /* How to interpret l_start:
                                   SEEK_SET, SEEK_CUR, SEEK_END */
            off_t l_start;   /* Starting offset for lock */
            off_t l_len;     /* Number of bytes to lock */
            pid_t l_pid;     /* PID of process blocking our lock
                                   (set by F_GETLK and F_OFD_GETLK) */
            ...
        };

代码演示

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char **argv){
    char *filename = "tmp";
    struct flock flock = {
        .l_start = 0,
        .l_len = 0,
        .l_type = F_WRLCK,
        .l_whence = SEEK_SET
    };
    pid_t pid = fork();
    if (pid > 0){//父进程先锁文件,2s后放开
        int fd = open(filename, O_CREAT|O_RDWR, 0666);
        if (fd >= 0){
            int ret = fcntl(fd, F_SETLK, &flock);
            if (!ret){
                printf("[%d] locked\n", getpid());
                sleep(2);
                printf("[%d] unlocked\n", getpid());
                flock.l_type = F_UNLCK;
                ret = fcntl(fd, F_SETLK, &flock);
            }
            sleep(1);
            close(fd);
        }
        waitpid(pid,NULL,0);
    }
    else if (pid == 0){//子进程1s后尝试锁文件
        int fd;
        sleep(1);
        fd = open(filename, O_WRONLY);
        if (fd >= 0){
            int ret;
            printf("[%d] opened\n", getpid());
            ret = fcntl(fd, F_SETLK, &flock);
            if (ret) printf("[%d] lockf fail, %s\n", getpid(), strerror(errno));
            ret = write(fd, filename, sizeof(filename));
            if (ret == sizeof(filename)) printf("[%d] write success\n", getpid());
            else printf("[%d] lockf fail, %s\n", getpid(), strerror(errno));
            ret = fcntl(fd, F_SETLKW, &flock);
            if (!ret){
                printf("[%d] locked\n", getpid());
                ret = write(fd, filename, sizeof(filename));
                if (ret == sizeof(filename)) printf("[%d] write success\n", getpid());
                else printf("[%d] lockf fail, %s\n", getpid(), strerror(errno));
                printf("[%d] unlocked\n", getpid());
                flock.l_type = F_UNLCK;
                ret = fcntl(fd, F_SETLK, &flock);
            }
            close(fd);
        }
        exit(EXIT_SUCCESS);
    }
    return 0;
}

输出

[65944] locked
[65945] opened
[65945] lockf fail, Resource temporarily unavailable
[65945] write success
[65944] unlocked
[65945] locked
[65945] write success
[65945] unlocked

在父进程上锁后,子进程分别进行了非阻塞申请锁和阻塞申请锁,非阻塞申请立刻返回错误,阻塞申请就一直等到父进程释放。

为什么子进程没拿到锁,也同样写入成功了?能体现写锁的环境还在寻找中!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容