《UNIX环境高级编程》笔记 第三章-文件IO

本章介绍关于文件I/O的系统调用。本章描述的函数都是不带缓冲的I/O,不带缓冲指的是每个read和write都调用内核中的一个系统调用。

1. 文件描述符fd

通常是一个非负整数,内核用它以标识一个特定进程正在访问的文件。当内核打开一个现有文件或创建一个新文件时,都返回一个文件描述符

标准输入 标准输出 标准错误:

每当运行一个新程序时,所有的shell都为其打开3个文件描述符,即标准输入、标准输出和标准错误。这三个描述符都链接至终端。

在头文件#include <unistd.h>中,定义了三个常量以表示标准输入、标准输出、标准错误。

/* Standard file descriptors.  */
#define	STDIN_FILENO	0	/* Standard input.  */
#define	STDOUT_FILENO	1	/* Standard output.  */
#define	STDERR_FILENO	2	/* Standard error output.  */

2. 函数open和openat

用来打开或创建一个文件,返回文件描述符

int open(const char *pathname, int flags[, mode_t mode]);
int openat(int dirfd, const char *pathname, int flags[, mode_t mode]);

仅当创建新文件时才使用最后一个参数。

  • 参数pathname:要打开或要创建的文件名字

    对于openat函数有些不同:

    • pathname指定的是绝对路径名,此时fd参数被忽略
    • pathname指定的是相对路径名,此时fd即为相对路径的开始地址,fd是通过打开目录文件获取的。
    • pathname指定的是相对路径名,fd参数是特殊值AT_FDCWD,相对路径名以当前进程的工作目录开始
  • 参数flags:

    • O_RDONLY:只读打开
    • O_WRONLY:只写打开
    • O_RDWR:读、写打开
    • O_EXEC:只执行打开

    以上几个常量必须且只能指定一个,可以与下面的常量进行或运算

    • O_APPEND:每次写都追加到文件末尾
    • O_CLOEXEC:将FD_CLOEXEC设置为文件描述符标志
    • O_CREAT:此文件不存在时创建它,此时最后一个参数mode指定该文件的访问权限位
    • O_DIRECTORY:指明pathname引用的是目录。如果不是目录则出错
    • O_EXCL:如果同时制定了O_CREAT,而文件已经存在则出错。
    • O_NOFOLLOW:如果pathname引用的是一个符号链接则出错
    • O_NONBLOCK:如果pathname引用的是一个FIFO、块特殊文件或字符特殊文件,则此选项为此文件的本次打开操作和后续的I/O操作设置非阻塞方式。
    • O_SYNC:使每次write等待物理I/O操作完成,包括由write操作引起的文件属性更新所需的I/O。
    • O_TRUNC:如果文件存在,且只写或读写打开,则将其长度截断为0。
    • O_DSYNC:每次write都等待物理I/O完成,但是如果写操作不影响读取刚写入的数据,则不等待文件属性更新
    • O_RSYNC:每个以文件描述符作为参数的read操作等待,直到所有对文件同一部分的未决写操作完成

由open和openat函数返回的文件描述符fd一定是最小的未使用文件描述符数值(比如在程序中close了文件描述符1,那么新open一个文件,返回的fd就是最小未使用的文件描述符1。)。

3. 函数creat

创建一个新文件,返回文件描述符

int creat(const char *pathname, mode_t mode);

此函数等效于

open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);

creat函数的不足之处是只能以只写方式打开创建的文件。因此如果要读的打开创建的文件,就需要先creat再close,再open。因此建议直接使用open函数创建文件。

open(path, O_RDWR | O_CREAT | O_TRUNC, mode);

4. close函数

关闭一个文件描述符引用的打开的文件

int close(int fd);

关闭一个文件时还会释放该进程加在该文件上的所有记录锁。

当一个进程终止时,内核会自动关闭它所有的打开文件。

5. lseek函数

为一个打开的文件设置偏移量(读写指针)

off_t lseek(int fd, off_t offset, int whence);
  • 参数offset:偏移量,大于0向文件尾偏移,小于0向文件头偏移
  • whence:偏移开始位置
    • SEEK_SET:从文件开头开始偏移
    • SEEK_CUR:从当前值开始偏移
    • SEEK_END:从文件尾开始偏移

函数成功返回新的文件偏移量。

lseek系统调用仅仅将当前文件偏移量记录在内核中,不引起任何I/O操作。这个偏移量用于之后的读写操作。

文件空洞:

文件偏移量可以大于文件长度,这时对该文件的下一次写操作会加长该文件,并在文件中构成一个空洞。空洞不要求在磁盘上占用存储区

如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值