C/C++进程文件锁 之 fcntl函数的用法总结(非阻塞O_NONBLOCK)
fcntl系统调用可以用来对已打开的文件描述符进行各种控制操作以改变已打开文件的的各种属性
函数原型:
- #include<unistd.h>
- #include<fcntl.h>
- int fcntl(int fd, int cmd);
- int fcntl(int fd, int cmd, long arg);
- int fcntl(int fd, int cmd ,struct flock* lock);
fcntl函数功能依据cmd的值的不同而不同。参数对应功能如下:
(1)F_DUPFD
与dup函数功能一样,复制由fd指向的文件描述符,调用成功后返回新的文件描述符,与旧的文件描述符共同指向同一个文件。
(2)F_GETFD
读取文件描述符close-on-exec标志
(3)F_SETFD
将文件描述符close-on-exec标志设置为第三个参数arg的最后一位
(4)F_GETFL
获取文件打开方式的标志,标志值含义与open调用一致
(5)F_SETF
设置文件打开方式为arg指定方式
文件记录锁是fcntl函数的主要功能。
记录锁:实现只锁文件的某个部分,并且可以灵活的选择是阻塞方式还是立刻返回方式
当fcntl用于管理文件记录锁的操作时,第三个参数指向一个struct flock *lock的结构体
- struct flock
- {
- short_l_type; /*锁的类型*/
- short_l_whence; /*偏移量的起始位置:SEEK_SET,SEEK_CUR,SEEK_END*/
- off_t_l_start; /*加锁的起始偏移*/
- off_t_l_len; /*上锁字节*/
- pid_t_l_pid; /*锁的属主进程ID */
- };
short_l_type用来指定设置共享锁(F_RDLCK,读锁)还是互斥锁(F_WDLCK,写锁).
当short_l_type的值为F_UNLCK时,传入函数中将解锁。
每个进程可以在该字节区域上设置不同的读锁。
但给定的字节上只能设置一把写锁,并且写锁存在就不能再设其他任何锁,且该写锁只能被一个进程单独使用。
这是多个进程的情况。
单个进程时,文件的一个区域上只能有一把锁,若该区域已经存在一个锁,再在该区域设置锁时,新锁会覆盖掉旧的锁,无论是写锁还时读锁。
l_whence,l_start,l_len三个变量来确定给文件上锁的区域。
l_whence确定文件内部的位置指针从哪开始,l_star确定从l_whence开始的位置的偏移量,两个变量一起确定了文件内的位置指针先所指的位置,即开始上锁的位置,然后l_len的字节数就确定了上锁的区域。
特殊的,当l_len的值为0时,则表示锁的区域从起点开始直至最大的可能位置,就是从l_whence和l_start两个变量确定的开始位置开始上锁,将开始以后的所有区域都上锁。
为了锁整个文件,我们会把l_whence,l_start,l_len都设为0。
(6)F_SETLK
此时fcntl函数用来设置或释放锁。当short_l_type为F_RDLCK为读锁,F_WDLCK为写锁,F_UNLCK为解锁。
如果锁被其他进程占用,则返回-1;
这种情况设的锁遇到锁被其他进程占用时,会立刻停止进程。
(7)F_SETLKW
此时也是给文件上锁,不同于F_SETLK的是,该上锁是阻塞方式。当希望设置的锁因为其他锁而被阻止设置时,该命令会等待相冲突的锁被释放。
(8)F_GETLK
第3个参数lock指向一个希望设置的锁的属性结构,如果锁能被设置,该命令并不真的设置锁,而是只修改lock的l_type为F_UNLCK,然后返回该结构体。如果存在一个或多个锁与希望设置的锁相互冲突,则fcntl返回其中的一个锁的flock结构。
非阻塞I/O使我们的操作要么成功,要么立即返回错误,不被阻塞
实例
if ((rsck = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
{
#ifdef DEBUG
printf("Failed to initialize raw socket\n");
#endif
exit(0);
}
// 设置非堵塞,作要么成功,要么立即返回错误,不被阻塞
fcntl(rsck, F_SETFL, O_NONBLOCK | fcntl(rsck, F_GETFL, 0));
相关文章
- C++ 使用 TinyXml 解析 XML 文件
- 安全之路 —— C/C++开3389端口(远程终端)
- qt实现web服务器加载vue应用进行C++和html混合编程-连载【6】-企业级系统开发实战连载系列 -技术栈(vue、element-ui、qt、c++、sqlite)
- 编程语言理解1-c语言,c++,java和python这些语言有何区别?编译型编程语言编译语言,解释型编程语言解释型语言
- C++第15周(春)项目2 - 用文件保存的学生名单
- C/C++下载文件_上传文件
- linux下编译利用CMakeLists.txt 编译C++写的opencv程序
- 使用C/C++的#include命令(文件包含命令)时,文件名用尖括号或双撇号(双引号)括起来的区别
- C++第11周项目5——体验文件操作
- C++实现通过UDP传输文件
- C++ 值传递 函数的分文件编写
- C++按行读取和写入文件
- 《C++覆辙录》——1.6:对常量(性)的认识误区
- 《数字图像处理与机器视觉——Visual C++与Matlab实现》——0.2 数字图像处理与识别
- C++学习必备网站推荐收藏
- 基于C++ 哈夫曼编码 实现(控制台)文件加密系统【100010605】
- 基于QT(C++)实现(窗体)UDP文件原型【100010516】
- 基于C++实现 MD5 算法的文件完整性校验程序【100010122】
- 基于QT(C++)+CSV文件存储开发(WinForm)图书管理系统【100010008】
- C++服务编译耗时优化原理及实践(美团)
- C++装饰者模式
- 为python编译C++模块时一定要注意的事情—————不要在anaconda环境下使用cmake来编译C++扩展模块!!!
- 让自己的C++程序(非服务程序)运行为一个windows service
- C++中,如何在标准库的std::string和常用库(Qt,VC等)的QString之间进行选择?
- 110、【树与二叉树】leetcode ——450. 删除二叉搜索树中的节点:递归法+迭代法(C++版本)
- C++ 基础入门 之 指针/指针定义使用/空指针/野指针/const修饰指针/指针和数值/指针和函数
- C++ 数组与字符串详解
- C++ STL简介
- C/C++实现文件加密器
- C++实操 - 如何判断是使用C还是C++编译器以及编译器版本
- c++ exports def文件
- C/C++ Windows API——将文件图标保存为PNG