Linux C 学习之 - fcntl 函数

来源:互联网 发布:做账软件哪个好 编辑:程序博客网 时间:2024/05/16 05:59
小编在这片文章中就不说 fcntl 如何使用了,如果有不明白的地方,请转到去问度娘:“ Linux fcntl”, 她会告诉我们一大堆。
在这里我把我今天用这个函数遇到的一些问题列举下,如有写的不对的地方,还望各位高手指正,不甚感激!
include <unistd.h>#include <fcntl.h>#include <stdio.h>int main(){int fd;int ret;struct flock rflk, wflk;fd = open("txt", O_RDONLY);if(fd < 0) {perror("open failed");return 1;}ret = fcntl(fd, F_GETFD); printf("current descriptor flags: %d\n", ret);fcntl(fd, F_SETFD, 1);printf("current descriptor flags: %d\n", ret);rflk.l_type = F_RDLCK;rflk.l_whence = SEEK_SET;rflk.l_start = 0;rflk.l_len = 10;wflk = rflk;wflk.l_type = F_WRLCK;if(fcntl(fd, F_SETLK, &rflk) == -1) {perror("read lock failed");return 1;}if(fcntl(fd, F_SETLK, &wflk) == -1) {perror("write lock failed");return 1;}close(fd);return 0;}

上面这段程序执行结果:
current descriptor flags: 0
current descriptor flags: 0
write lock failed: Bad file descriptor
错误的文件描述符,一时半会不知道什么原因,后面检查程序
这里 fd = open("txt", O_RDONLY); 打开文件只是以制度方式打开的,而我要去加一把写锁,当然出错了,于是改为 fd = open("txt", O_RDWR); 好了,把读锁和写锁都加上去了。
是不是没问题了,不然,在网上看到有人说读写锁只能同时存在一个,那这里为什么读写锁都加上去了呢? 好好想想,会不会是在同一个进程中既可以加读锁也可以加写锁,因为该文件资源都属于该进程,改进程想读就读,想写就写! 于是,咋们就来创建一个子进程。把上面的代码改了
#include <unistd.h>#include <fcntl.h>#include <stdio.h>int main(){int fd;int ret;struct flock rflk, wflk;fd = open("txt", O_RDWR);if(fd < 0) {perror("open failed");return 1;}ret = fcntl(fd, F_GETFD); printf("current descriptor flags: %d\n", ret);fcntl(fd, F_SETFD, 1);printf("current descriptor flags: %d\n", ret);rflk.l_type = F_RDLCK;rflk.l_whence = SEEK_SET;rflk.l_start = 0;rflk.l_len = 10;wflk = rflk;wflk.l_type = F_WRLCK;if(fcntl(fd, F_SETLK, &rflk) == -1) {perror("read lock failed");return 1;}if(fcntl(fd, F_SETLK, &wflk) == -1) {perror("write lock failed");return 1;}if(fork()) {if(fcntl(fd, F_SETLK, &rflk) == -1) {fprintf(stderr, "parent read lock failed\n"); }if(fcntl(fd, F_SETLK, &wflk) == -1) {fprintf(stderr, "parent write lock failed\n"); }sleep(3);} else {sleep(1); if(fcntl(fd, F_SETLK, &rflk) == -1) {fprintf(stderr, "child read lock failed\n"); }if(fcntl(fd, F_SETLK, &wflk) == -1) {fprintf(stderr, "child write lock failed\n"); }}close(fd);return 0;}
编译执行结果为:
current descriptor flags: 0
current descriptor flags: 0
child read lock failed
child write lock failed
果然,在子进程中,不能再次加锁了。
在想,读锁不是可以存在多个吗?怎么子进程中的读锁也失败了,会不会是因为父进程中有写锁,导致子进程加读写锁都失败了,把父子进程中的加写锁注释掉
再次编译,运行:
current descriptor flags: 0
current descriptor flags: 0
说明问题还真是因为父进程中有写锁。
那么如果父进程中有读锁,在子进程中加写锁是否成功呢?下面取消注释掉子进程中的加写锁:
current descriptor flags: 0
current descriptor flags: 0
child write lock failed
可见,即便父进程中没有写锁,子进程中也不能加写锁,因为父进程已经存在了读锁!


好了,先到此为止,做个总结
fcntl函数来加锁文件,网上有人说读写锁只能同时存在一个,这是不全面的,进过上面的测试代码可知。

1、在同一进程可以加多次读锁,多次写锁,并且可以同时存在!

上次这里说错了,在同一进程中,锁也并不是同时存在的,而是后面加的锁会覆盖前面加的锁!(2013/1/24修改)

2、在不同进程中,如果进程A拥有读锁或写锁, 那么进程B只能有读锁,不能加写锁

3、还需要注意的是,在上面加锁的时候我们把 fcntl 的第二个参数cmd 都置为 F_SETLK,如果把它换成 F_SETLKW,那么在不同进程间可同时加读写锁。假设进程A先拥有了某个锁,进程B想给自己加一把锁,那么就会等到进程A把锁释放掉!

4、如果调用 fcntl(fd, F_GETLK, &flk) 时,如果能够得到这样的锁,那么设置 flk.l_type == F_UNLCK, flk 其他成员值不变; 否则,如果不能得到这样的锁,重新设置 flk 的值,使 l_pid == 当前占用锁的进程。


阅读(1017) | 评论(0) | 转发(2) |
0

上一篇:网络上的一些C面试题,做个摘录

下一篇:SPEC 文件详解

相关热门文章
  • 广州传智播客最给力的Java培训...
  • 广州传智播客网页平面设计,风...
  • sar命令详解
  • 广州传智播客老师分享:学了.N...
  • 东鹏洁具营销三大趋势 售后服...
  • test123
  • 编写安全代码——小心有符号数...
  • 使用openssl api进行加密解密...
  • 一段自己打印自己的c程序...
  • sql relay的c++接口
  • linux inode中磁盘地址列表有...
  • LNMP 老是会出现502?
  • suse 运用一个shell获取本机和...
  • 虚拟机 unix 配置ip
  • hp-un 主机新系统读不到磁盘阵...
给主人留下些什么吧!~~
原创粉丝点击