flock简介

flock() 的函数原型如下所示:
     int flock(int fd, int operation);

其中,参数 fd 表示文件描述符;参数 operation 指定要进行的锁操作,该参数的取值有如下几种:
     LOCK_SH:表示要创建一个共享锁,在任意时间内,一个文件的共享锁可以被多个进程拥有;
     LOCK_EX:表示创建一个排他锁,在任意时间内,一个文件的排他锁只能被一个进程拥有;
     LOCK_UN:表示删除该进程创建的锁;
     LOCK_MAND:它主要是用于共享模式强制锁,它可以与 LOCK_READ 或者 LOCK_WRITE 联合起来使用,从而表示是否允许并发的读操作或者并发的写操作;
    
通常情况下,如果加锁请求不能被立即满足,那么系统调用 flock() 会阻塞当前进程。比如,进程想要请求一个排他锁,但此时,已经由其他进程获取了这个锁,那么该进程将会被阻塞。如果想要在没有获得这个排他锁的情况下不阻塞该进程,可以将 LOCK_NB 和 LOCK_SH 或者 LOCK_EX 联合使用,那么系统就不会阻塞该进程。flock() 所加的锁会对整个文件起作用。

注意:
     1. 对于文件的 close() 操作会使文件锁失效;
     2. 同理,进程结束后文件锁失效;

     3. flock() 的 LOCK_EX 是“劝告锁”,系统内核不会强制检查锁的状态,需要在代码中进行文件操作的地方显式检查才能生效。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>

char *psFile = "/var/log/test.log";

int main(void) {
    int fd = open(psFile, O_CREAT | O_RDWR);
    if(fd <= 0)
    {
        printf("open file fail\n");
        exit(0);
    }

    if(0 == flock(fd, LOCK_EX))
    {
        int nIndex = 0;
        while(nIndex++ < 30)
        {
            printf("do something %d,%d\n", getpid(), nIndex);
            sleep(1);
        }
    }
    flock(fd, LOCK_UN);
    close(fd);
    return EXIT_SUCCESS;
}


<fcntl.h> int fcntl(int fd, int cmd,... /* arg */) int fcntl(int fd, int cmd) int fcntl(int fd, int cmd, long arg) int fcntl(int fd,int cmd, struct flock *lock) ==> F_GETLK F_SETLK 以上的函数请根据一下: F_DUPFD用来查找大于或等于参数arg的最小且仍未使用的文件描述符,并且复制参数fd 的文件描述符。执行成功则返回新复制的文件描述符。新描述符与fd共享同一文件表项, 但是新描述符有它自己的一套文件描述符标志,其中FD_CLOEXEC文件描述符标志被清除。 请参考dp20。 F_GETFD取得close-on-exec标志。若此标志的FD_CLOEXEC位为O,代表在调用exec()相关函 数时文件将不会关闭。 F_SETFD设置close-on-exec标志。该标志以参数arg的FD_CLOEXEC位决定。 F_GETFL(FL=Flags)取得文件描述符状态标志,此标志为open(的参数flags。 F_SETFL设置文件描述符状态标志,参数arg为新标志,但只允许O_APPEND、ONONBLOCK 和O_ASYNC位的改变,其他位的改变将不受影响。 F_GETLK(LK=Lock)取得文件锁定的状态。 F_SETLK设置文件锁定的状态。此时flcok结构的Itype值必须是F_RDLCK、F_WRLCK或 F_UNLCK。如果无法建立锁定,则返回-1,错误代码为EACCES或EAGAIN。 F_SETLKWF_SETLK作用相同,但是无法建立锁定时,此调用会一直等到锁定动作成功为止。 若在等待锁定的过程中被信号中断时,会立即返回-1,错误代码为EINTR 因为我是新手学员,请根据以上的函数和他的含义做一些简单的示例,让我通俗易懂的了解他的用法,对里面的一些步骤进行注释,注释告诉我他这个是代表什么例如cmd这个位置的,内容代表什么,什么作用,因为我想了解他的用法
最新发布
09-02
当然可以!我们先从 `fcntl()` 函数的基本概念讲起,然后通过几个简单的示例帮助你理解它的使用方式。 --- ## 🔍 fcntl 函数简介 `fcntl()` 是一个多功能的文件控制函数,常用于操作文件描述符(file descriptor)的各种属性和状态。其原型定义在 `<fcntl.h>` 中: ```c #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */); ``` ### 参数说明: - `fd`:已经打开的文件描述符(例如通过 `open()` 或 `dup()` 得到的)。 - `cmd`:指定要执行的操作命令,比如复制文件描述符、设置文件状态标志、加锁等。 - `arg`(可选):根据 `cmd` 的不同,可能需要传递额外的参数,比如整数、结构体等。 --- ## ✅ 示例一:使用 F_DUPFD 复制文件描述符 ### 📌 功能说明: 使用 `F_DUPFD` 命令来复制一个文件描述符,并返回一个大于等于 `arg` 的最小可用文件描述符。 ```c #include <fcntl.h> #include <unistd.h> #include <stdio.h> int main() { int fd = open("example.txt", O_RDWR | O_CREAT, 0644); if (fd == -1) { perror("open"); return 1; } // 使用 F_DUPFD 复制文件描述符 // cmd=F_DUPFD,arg=10 表示找一个 >=10 的最小可用fd int new_fd = fcntl(fd, F_DUPFD, 10); if (new_fd == -1) { perror("fcntl"); return 1; } printf("Original fd: %d, New fd: %d\n", fd, new_fd); // 写入测试内容 const char *msg = "Hello from new_fd!\n"; write(new_fd, msg, strlen(msg)); close(fd); // 关闭原始fd close(new_fd); // 关闭复制的fd return 0; } ``` ### 🔍 注释解释: - `fd` 是通过 `open()` 打开的文件描述符。 - `F_DUPFD` 表示我们要复制这个描述符。 - `arg=10` 表示我们希望复制的描述符编号 >=10。 - `new_fd` 是新的描述符,与 `fd` 共享同一个文件表项,但有自己独立的标志。 - `write(new_fd, ...)` 可以正常写入原文件,说明新旧描述符指向的是同一个文件。 --- ## ✅ 示例二:使用 F_GETFD 和 F_SETFD 设置 close-on-exec 标志 ### 📌 功能说明: 查看和设置文件描述符的 `FD_CLOEXEC` 标志。该标志决定是否在调用 `exec()` 时自动关闭该文件描述符。 ```c #include <fcntl.h> #include <unistd.h> #include <stdio.h> int main() { int fd = open("example.txt", O_RDWR); if (fd == -1) { perror("open"); return 1; } // 获取当前 close-on-exec 标志 int flags = fcntl(fd, F_GETFD); // cmd=F_GETFD 不需要 arg printf("Original FD flags: %d\n", flags); // 设置 FD_CLOEXEC,使得 exec 时关闭该 fd fcntl(fd, F_SETFD, flags | FD_CLOEXEC); // cmd=F_SETFD, arg=flags | FD_CLOEXEC // 检查是否设置成功 flags = fcntl(fd, F_GETFD); printf("New FD flags: %d\n", flags); close(fd); return 0; } ``` ### 🔍 注释解释: - `F_GETFD` 获取当前文件描述符的标志(例如是否设置了 `FD_CLOEXEC`)。 - `F_SETFD` 设置标志,这里我们加上 `FD_CLOEXEC`。 - `FD_CLOEXEC` 设置后,如果程序调用 `exec()` 启动另一个程序,当前文件描述符会被自动关闭。 --- ## ✅ 示例三:使用 F_GETFL 和 F_SETFL 设置非阻塞模式 ### 📌 功能说明: 获取和设置文件描述符的状态标志,例如设置非阻塞 I/O。 ```c #include <fcntl.h> #include <unistd.h> #include <stdio.h> int main() { int fd = open("example.txt", O_RDWR); if (fd == -1) { perror("open"); return 1; } // 获取当前文件状态标志 int flags = fcntl(fd, F_GETFL); // cmd=F_GETFL printf("Original file flags: %d\n", flags); // 设置为非阻塞模式 fcntl(fd, F_SETFL, flags | O_NONBLOCK); // cmd=F_SETFL, arg=新标志 // 再次获取状态 flags = fcntl(fd, F_GETFL); printf("New file flags: %d\n", flags); close(fd); return 0; } ``` ### 🔍 注释解释: - `F_GETFL` 获取当前文件状态标志(如 `O_APPEND`, `O_NONBLOCK` 等)。 - `F_SETFL` 设置新的标志,这里我们添加了 `O_NONBLOCK`,表示非阻塞读写。 - 注意:不是所有标志都可以设置,比如 `O_RDONLY` 就不能改。 --- ## ✅ 示例四:使用 F_GETLK 和 F_SETLK 设置文件锁 ### 📌 功能说明: 使用 `fcntl()` 对文件进行读写锁控制。 ```c #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h> int main() { int fd = open("example.txt", O_RDWR); if (fd == -1) { perror("open"); return 1; } struct flock lock; memset(&lock, 0, sizeof(lock)); // 设置一个读锁 lock.l_type = F_RDLCK; // 读锁 lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; // 锁定整个文件 // 尝试设置锁 if (fcntl(fd, F_SETLK, &lock) == -1) { perror("fcntl F_SETLK"); close(fd); return 1; } printf("Read lock set successfully.\n"); // 解锁 lock.l_type = F_UNLCK; fcntl(fd, F_SETLK, &lock); printf("Unlocked.\n"); close(fd); return 0; } ``` ### 🔍 注释解释: - `struct flock` 定义了锁的类型、位置和长度。 - `F_SETLK` 设置锁,如果冲突则立即返回错误。 - `F_SETLKW` 是其等待版本,会阻塞直到锁可用。 - `F_GETLK` 可用于查询当前锁的状态(这里没演示)。 --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值