open函数

 int open(const char *pathname, int flags, mode_t mode);

参数说明:

(1)pathname: 表示要打开的文件路径

(2)flags: 用于指示打开文件的选项,常用的有O_RDONLY、 O_WRONLY和O_RDWR,还有一些选项如下:

  • O_APPEND: 每次进行写操作时, 内核都会先定位到文件尾, 再执行写操作
  • O_ASYNC: 使用异步I/O模式
  • O_CLOEXEC: 在打开文件的时候, 就为文件描述符设置FD_CLOEXEC标志。 这是一个新的选项, 用于解决在多线程下fork与用fcntl设置FD_CLOEXEC的竞争问题。 某些应用使用fork来执行第三方的业务, 为了避免泄露已打开文件的内容, 那些文件会设置FD_CLOEXEC标志。 但是fork与fcntl是两次调用, 在多线程下, 可能会在fcntl调用前, 就已经fork出子进程了, 从而导致该文件句柄暴露给子进程
  • O_CREAT: 当文件不存在时, 就创建文件
  • O_DIRECT: 对该文件进行直接I/O, 不使用VFS Cache
  • O_DIRECTORY: 要求打开的路径必须是目录
  • O_EXCL: 该标志用于确保是此次调用创建的文件, 需要与O_CREAT同时使用; 当文件已经存在时, open函数会返回失败
  • O_LARGEFILE: 表明文件为大文件
  • O_NOATIME: 读取文件时, 不更新文件最后的访问时间
  • O_NONBLOCK、 O_NDELAY: 将该文件描述符设置为非阻塞的( 默认都是阻塞的)
  • O_SYNC: 设置为I/O同步模式, 每次进行写操作时都会将数据同步到磁盘, 然后write才能返回
  • O_TRUNC: 在打开文件的时候, 将文件长度截断为0, 需要与O_RDWR或O_WRONLY同时使用。在写文件时, 如果是作为新文件重新写入, 一定要使用O_TRUNC标志, 否则可能会造成旧内容依然存在于文件中的错误

(3)mode: 只在创建文件时需要, 用于指定所创建文件的权限位( 还要受到umask环境变量的影响)

lseek函数

 off_t lseek(int fd, off_t offset, int whence);

该函数用于将fd的文件偏移量设置为以whence为起点, 偏移为offset的位置。 其中whence可以为三个值: SEEK_SET、 SEEK_CUR和SEEK_END, 分别表示为“文件的起始位置”、 “文件的当前位置”和“文件的末尾”, 而offset的取值正负均可。 lseek执行成功后, 会返回新的文件偏移量。文件偏移是基于某个打开文件来说的, 一般情况下, 读写操作都会从当前的偏移位置开始读写( 所以read和write都没有显式地传入偏移量) , 并且在读写结束后更新偏移量。

返回值:当lseek执行成功时, 它会返回最终以文件起始位置为起点的偏移位置。 如果出错,则返回-1, 同时errno被设置为对应的错误值。也就是说, 一般情况下, 对于普通文件来说, lseek都是返回非负的整数, 但是对于某些设备文件来说, 是允许返回负的偏移量。 因此要想判断lseek是否真正出错, 必须在调用lseek前将errno重置为0,然后再调用lseek, 同时检查返回值是否为-1及errno的值。 只有当两个同时成立时, 才表明lseek真正出错了。

read函数

 ssize_t read(int fd, void *buf, size_t count);

read尝试从fd中读取count个字节到buf中, 并返回成功读取的字节数, 同时将文件偏移向前移动相同的字节数。 返回0的时候则表示已经到了“文件尾”。 read还有可能读取比count小的字节数。

使用read进行数据读取时, 要注意正确地处理错误, 也是说read返回-1时, 如果errno为EAGAIN、EWOULDBLOCK或EINTR, 一般情况下都不能将其视为错误。 因为前两者是由于当前fd为非阻塞且没有可读数据时返回的, 后者是由于read被信号中断所造成的。 这两种情况基本上都可以视为正常情况。

write函数

 ssize_t write(int fd, const void *buf, size_t count);

write尝试从buf指向的地址, 写入count个字节到文件描述符fd中, 并返回成功写入的字节数, 同时将文件偏移向前移动相同的字节数。 write有可能写入比指定count少的字节数。

dup函数

 int dup(int oldfd);
int dup2(int oldfd, int newfd);
int dup3(int oldfd, int newfd, int flags);

(1)dup:使用一个最小的未用文件描述符作为复制后的文件描述符。
(2)dup2:使用用户指定的文件描述符newfd来复制oldfd的。 如果newfd已经是打开的文件描述符, Linux会先关闭newfd, 然后再复制oldfd。
(3)dup3:只有定义了feature宏“_GNU_SOURCE”才可以使用, 它比dup2多了一个参数, 可以指定标志——不过目前仅仅支持O_CLOEXEC标志, 可在newfd上设置O_CLOEXEC标志。 定义dup3的原因与open类似, 可以在进行dup操作的同时原子地将fd设置为O_CLOEXEC, 从而避免将文件内容暴露给子进程。

在写daemon服务程序时, 基本上都有这样的流程: 首先关闭标准输出stdout、 标准出错stderr, 然后进行dup操作, 将stdout或stderr重定向。 但是在多线程程序成为主流以后,由于close和dup操作不是原子的, 这就造成了在某些情况下, 重定向会失败。 因此就引入了dup2将close和dup合为一个系统调用, 以保证原子性, 然而这依然有问题。 大家可以回顾1.2.2节中对O_CLOEXEC的介绍。 在多线程中进行fork操作时, dup2同样会有让相同的文件描述符暴露的风险, dup3也就随之诞生了。 这三个系统调用看起来有些冗余重复, 但实际上它们也是软件工程发展的结果。

sync函数

 void sync(void);
int fsync(int fd);
int fdatasync(int fd);

(1)Linux的sync是阻塞调用 ,并不是说让所有修改过的缓存进入提交队列, 并不用等待这个工作完成,这一点和APUE上面是不同的,以这个结论为准

(2)fsync只同步fd指定的文件, 并且直到同步完成才返回,它不仅同步数据, 还会同步所有被修改过的文件元数据(包括文件的访问权限、 上次访问的时间戳、 所有者、 所有组、 文件大小等信息)

(3)fdatasync与fsync类似, 但是其只同步文件的实际数据内容, 不会影响后面数据操作的元数据

sync、 fsync和fdatasync只能保证Linux内核对文件的缓冲被冲刷了, 并不能保证数据被真正写到磁盘上, 因为磁盘也有自己的缓存。

stat函数

 #include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

(1)stat得到路径path所指定的文件基本信息
(2)fstat得到文件描述符fd指定文件的基本信息
(3)lstat与stat则基本相同, 只有当path是一个链接文件时, lstat得到的是链接文件自己本身的基本信息而不是其指向文件的信息

truncate 函数

 #include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);

(1)truncate截断的是路径path指定的文件
(2)ftruncate截断的是fd引用的文件

“截断”给人的感觉是将文件变短, 即将文件大小缩短至length长度。 实际上, length可以大于文件本身的大小, 这时文件长度将变为length的大小, 扩充的内容均被填充为0。 需要注意的是, 尽管ftruncate使用的是文件描述符, 但是其并不会更新当前文件的偏移。

最新文章

  1. springmvc之DispatcherServlet
  2. azure存储压测的问题(农码主观意识太强被坑了)
  3. SharePoint 2013 中代码创建列表查阅项字段
  4. MyBatis关联查询分页
  5. 【转】DataGridView之为每行前面添加序号
  6. Library cache lock 故障解决一例
  7. oracle系列索引
  8. 20个Linux服务器性能调优技巧
  9. PHP 文件操作类(创建文件并写入) 生成日志
  10. Kafka (一)
  11. 一个简单的基于HTTP协议的屏幕共享应用
  12. Dubbo和Spring Cloud微服务架构&#39;
  13. pywinauto简单操作写字板的例子
  14. peewee基本操作
  15. Shell脚本中的 测试开关 和 特殊参数
  16. Angular2 File Upload
  17. K8S学习笔记之修改K8S的api-server证书
  18. 洛谷 P2224 [HNOI2001]产品加工 解题报告
  19. Codeforces Round #256 (Div. 2) B (448B) Suffix Structures
  20. SQL Server 2008 清空删除日志文件 130G日志 10秒内变10M

热门文章

  1. 【2-SAT】Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals) D. Innokenty and a Football League
  2. [美团 CodeM 初赛 Round A]数列互质
  3. 数列求和 Exercise06_13
  4. IO流--FileReader&amp;&amp;FileWriter
  5. Java读取文本文件
  6. notepad++ 常用的插件及教程
  7. cs-JsonHelper
  8. Objective-C:NSSet和NSMutbaleSet的用法
  9. linux过滤ip地址
  10. Java源码阅读LinkedHashMap