回顾
- 文件操作
- open
- read
- write
- close
- lseek
今天
- 文件控制fcntl
- 文件描述符的复制dup(内存中)
- 文件锁
- 文件的周边函数
- 目录操作(待定)
1. dup和dup2
dup和dup2
-
可以复制文件描述符,但不复制文件表。
dup 返回当前可用描述符的最小值。
dup2 可以 指定文件描述符的值,如果这个值正在使用,关闭正在使用的之后再完成复制。
dup3
注解:
dup: 系统指定最小可用的描述值
dup2: 可自己指定文件描述符,如它被占用,强制关闭再使用
2. 理解
- close(fd)
- 相当于 剪断了 文件描述符与文件表之间的联系,同时将文件描述符移出文件描述符总表
- 文件描述符
- 相当于索引,本质是一个非负整数,自身不能操作文件,和文件没有直接关系。
- 文件表
- 在内存中存储,记录了文件的相关信息。文件表需要通过文件描述符找到。
- 文件
- 在 硬盘中,可以 用文件表进行 操作。
- 程序
- 使用的是 文件描述符, 通过在 描述符总表中查找对应的文件表去操作文件。如果 在描述符总表 中查不到 文件表, 文件描述符 没有意义。
3. 函数fcntl
- int fcntl(int fd,int cmd, …)
+ cmd常见用法:
- F_DUPFD 复制文件描述符
- F_GETFL/F_SETFL 设置/取得 文件表的状态(不是全部)
- F_SETLK/F_GETLK/F_SETLKW 文件锁的操作
读写权限宏定义
取某些位上数据的方法
错误:由于没有加上括号,导致 先判断3==1为0,然后flags&0,结果为0,永远无法进入判断分支
正确用法: 自身要加上括号
文件锁
由于 多个进程/线程 同时写文件时,可能出现 互相覆盖的问题,导致 数据错误。
- 解决方案
- 可以使用文件锁。
- 文件锁
- 针对 文件内存 锁定,可以 锁定 文件的某部分。
- 是一个结构体,记录了 文件锁的相关信息。
- 读锁(F_RDLCK)
- 是 共享锁,所有读进程 都可以加 读锁,但不能加 写锁。(锁 写 不锁 读)
- 写锁(F_WRLCK)
- 是 独占锁,其它进程不能 再加 任何的锁。
- 如果 当前进程 加了读锁,其它 进程 可以加读锁,不能加写锁;
- 如果 当前进程 加了写锁,其它进程 不可以加锁。
- 用 F_SETLK 方式加锁,如果加不上,返回-1(非阻塞)。
- 用 F_SETLKW 方式加锁,如果加不上,等待解锁后继续执行。(阻塞)
l_whence和l_start 联合决定 锁定的 起始位置,l_len 决定了锁定的 长度。
文件锁 只是在内存中的设定,不会真正影响文件。即使程序加了文件锁,用vi之类的编辑器可以修改文件。
经验:
开发时,读写文件 应该 先加 对应的锁,然后 在read或者write。(多进程或多线程时)
F_GETLK
- 不是取锁,而是 测试一个锁能不能加上,
- 如果能加,把 传入的锁的类型 改成 F_UNLCK,其它数据不变。
- 如果不能加, 把 当前 正在加的锁的信息返回(包括进程id)。
- 传入的flock指针 既是 传入参数(被测试的锁),又是传出参数(改 l_type为F_UNLCK或完全被新锁 替换)。
延迟写缓冲区,立即更新
sync 将所有修改过的缓冲区排入写队列,并不等于实际写磁盘
fsync 只对一个文件,并且等实际写磁盘完成才返回
fdatasync 只更新数据,不更新文件属性
获取文件属性
stat: 只使用文件路径,不需要fd
fstat:需要使用文件描述符,所以使用它之前还要open获取fd
lstat
access
6. 推荐书籍及翻译软件
星际译王 - Linux专用翻译软件
Unix环境高级编程