linux flock 文件权限,linux 文件锁 flock

问题现象 文件存储 NAS 为多客户端提供了统一名字空间的文件共享读写能力,但在多进程/多客户端并发写同一个文件的场景中(典型的例如并发写同一个日志文件),各进程分别维护了独立的文件描述符及写入位置等上下文信息,而 NFS 协议本身并没有提供Atomic Append语义的支持,因此可能会出现写覆盖、交叉、串行等异常现象,推荐的解决方案有两种: (推荐)不同进程/客户端写入同一文件系统的不同文件中,后续分析处理时再进行归并,这个方案能够很好地解决并发写入导致的问题,同时无需使用文件锁,不会对性能造成影响。 对于并发追加写同一个文件(如日志)的场景,可以使用文件锁 + seek 机制来保证写入的原子性和一致性。但是文件锁 + seek 是一个比较耗时的操作,可能会对性能产生显著的影响。下面将对这种方式进行一个简单的介绍,以供参考。 flock + seek 使用方法 由于 NFS 协议本身没有提供对 Atomic Append 语义的支持,因此当并发写入同一文件末尾(如日志)时,很可能会出现相互覆盖的情况。在 Linux 中,通过使用 flock + seek 的方式,可以在 NFS 文件系统上做到模拟 Atomic Append,对并发追加写入同一文件提供保护和支持。

使用方式如下:

调用 fd = open(filename, O_WRONLY | O_APPEND | O_DIRECT) 以追加写的方式打开文件,并且指定 O_DIRECT(直写,不通过 Page Cache),获得文件描述符 fd。 调用 flock(fd, LOCK_EX|LOCK_NB) 尝试获取文件锁,如果获取失败(如锁已被占用)则会返回错误,此时可以继续重试或进行错误处理。 文件锁获取成功后,调用 lseek(fd, 0, SEEK_END) 将 fd 当前的写入偏移定位到文件末尾。 执行正常的 write 操作,此时写入位置应该是文件的末尾,并且由于有文件锁的保护,不会出现并发写入相互覆盖的问题。 写操作执行完成后,调用 flock(fd, LOCK_UN) 释放文件锁。 下面是一个简单的 C 语言示例程序,仅供参考:

#define _GNU_SOURCE #include #include #include #include #include #include #include

const char *OUTPUT_FILE = "/mnt/blog"; int WRITE_COUNT = 50000;

int do_lock(int fd) { int ret = -1; while (1) { ret = flock(fd, LOCK_EX | LOCK_NB); if (ret == 0) { break; } usleep((rand() % 10) * 1000); } return ret; }

int do_unlock(int fd) { return flock(fd, LOCK_UN); }

int main() { int fd = open(OUTPUT_FILE, O_WRONLY | O_APPEND | O_DIRECT); if (fd < 0) { printf("Error Open\n"); exit(-1); } for (int i = 0; i < WRITE_COUNT; ++i) { char *buf = "one line\n";

/* Lock file */

int ret = do_lock(fd);

if (ret != 0)

{

printf("Lock Error\n");

exit(-1);

}

/* Seek to the end */

ret = lseek(fd, 0, SEEK_END);

if (ret < 0)

{

printf("Seek Error\n");

exit(-1);

}

/* Write to file */

int n = write(fd, buf, strlen(buf));

if (n <= 0)

{

printf("Write Error\n");

exit(-1);

}

/* Unlock file */

ret = do_unlock(fd);

if (ret != 0)

{

printf("UnLock Error\n");

exit(-1);

}

}

return 0;

} 更详细的 flock() 使用方式可以参考以下链接:http://www.hackinglinuxexposed.com/articles/20030616.html。

说明 在NAS文件系统上使用 flock() 需要您的Linux内核版本在2.6.12及以上,如果您的内核版本较低,请使用 fcntl() 调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值