C3:文件IO
1 引言
本章描述的函数被成为不带缓冲的IO,涉及5个函数,分别时
open、read、write、lseek、close。
2 文件描述符
文件描述符为非负整数,取值范围为0 ~ OPEN_MAX - 1,调用open、create返回参数路径的文件描述符,可以作为传递给read、write。
可使用shell命令查询系统对OPEN_MAX定义,grep -rn --col OPEN_MAX /usr/include
linux三个特殊的文件描述符:
0:标准读,STDIN_FILENO,该常亮在unistd.h中定义
1:标准写,STDOUT_FILENO
2:标准错误,STDERR_FILENO
3 函数open与openat
该方法可以打开或者创建一个文件,头文件 fctnl.h
1 /* Open FILE and return a new file descriptor for it, or -1 on error. 2 OFLAG determines the type of access used. If O_CREAT or O_TMPFILE is set 3 in OFLAG, the third argument is taken as a `mode_t', the mode of the 4 created file. 5 6 This function is a cancellation point and therefore not marked with 7 __THROW. */ 8 #ifndef __USE_FILE_OFFSET64 9 extern int open (const char *__file, int __oflag, ...) __nonnull ((1)); 10 #else 11 # ifdef __REDIRECT 12 extern int __REDIRECT (open, (const char *__file, int __oflag, ...), open64) 13 __nonnull ((1)); 14 # else 15 # define open open64 16 # endif 17 #endif 18 19 #ifdef __USE_ATFILE 20 /* Similar to `open' but a relative path name is interpreted relative to 21 the directory for which FD is a descriptor. 22 23 NOTE: some other `openat' implementation support additional functionality 24 through this interface, especially using the O_XATTR flag. This is not 25 yet supported here. 26 27 This function is a cancellation point and therefore not marked with 28 __THROW. */ 29 # ifndef __USE_FILE_OFFSET64 30 extern int openat (int __fd, const char *__file, int __oflag, ...) 31 __nonnull ((2)); 32 # else 33 # ifdef __REDIRECT 34 extern int __REDIRECT (openat, (int __fd, const char *__file, int __oflag, 35 ...), openat64) __nonnull ((2)); 36 # else 37 # define openat openat64 38 # endif 39 # endif 40 # ifdef __USE_LARGEFILE64 41 extern int openat64 (int __fd, const char *__file, int __oflag, ...) 42 __nonnull ((2)); 43 # endif 44 #endif
各参数释义如下:
path:打开或者创建文件的名字。
oflag:用于指定操作类型,如下:
常量 | 释义 |
O_RDONLY | 只读打开 |
O_WRONLY | 只写打开 |
O_RDWR | 读写打开 |
O_EXEC | 只执行打开 |
O_SEARCH | 只搜索打开(仅应用于目录) |
O_APPEND | 写文件时,追加到文件末尾 |
O_CLOEXEC | 把FD_CLOEXEC设置为文件描述符标志 |
O_CREATE | 创建文件,参数mode用于指定访问权限 |
O_DIRECTORY | 如果path不是目录,则出错 |
O_EXCL | 测试文件是否存在。不能与O_CREAT公用,否则会报错 |
O_NOCTTY | 如果path是终端设备,则不降该设计分配为此进场的控制终端 |
O_NOFOLLOW | 如果path是符号链接,则出错 |
O_NONBLOCK | 如果path时FIFO、块特殊文件、字符特殊文件,则将本次打开操作及后续IO操作设置为非阻塞 |
O_SYNC | 每次write等待IO操作完成 |
O_TRUNK | 文件存在,且为写打开(包括只写、读写),则将文件长度截断为0。即写指针移位到0 |
O_TTY_INIT | |
O_DSYNC | write等待IO操作完成,如果写操作不影响读取刚写入的数据,则不需要等待文件属性被更新 |
O_RSYNC | read操作等待,直至所有对文件同一部分挂起的写操作都完成 |
openat与open区别如下:
- 如果openat的path是绝对文件名,则fd参数被忽略,openat等同于open
- path参数是相对文件名,fd指定了相对路径名的文件描述符,fd参数通过打开相对路径名所在的目录获取文件。
- path指定相对路径名,fd参数具有特殊值AT_FDCWD,则路径名表示为当前目录获取,在操作上与open函数类似。
4 函数creat
创建一个新文件,头文件fcntl.h
1 /* Create and open FILE, with mode MODE. This takes an `int' MODE 2 argument because that is what `mode_t' will be widened to. 3 4 This function is a cancellation point and therefore not marked with 5 __THROW. */ 6 #ifndef __USE_FILE_OFFSET64 7 extern int creat (const char *__file, mode_t __mode) __nonnull ((1)); 8 #else 9 # ifdef __REDIRECT 10 extern int __REDIRECT (creat, (const char *__file, mode_t __mode), 11 creat64) __nonnull ((1)); 12 # else 13 # define creat creat64 14 # endif 15 #endif 16 #ifdef __USE_LARGEFILE64 17 extern int creat64 (const char *__file, mode_t __mode) __nonnull ((1)); 18 #endif
等价于open(path, O_WRONLY | O_CREAT | O_TRUNK, mode)
5 函数close
关闭一个打开的文件,头文件 unistd.h
1 /* Close the file descriptor FD. 2 3 This function is a cancellation point and therefore not marked with 4 __THROW. */ 5 extern int close (int __fd);
关闭一个文件会释放该进程加在文件上的所以记录锁。
当一个进场终止时,内核会自动关闭它打开的所有文件,很多程序利用这一功能而不显示调用close关闭文件。
6 函数lseek
操作文件偏移量,头文件 unistd.h
1 /* Move FD's file position to OFFSET bytes from the 2 beginning of the file (if WHENCE is SEEK_SET), 3 the current position (if WHENCE is SEEK_CUR), 4 or the end of the file (if WHENCE is SEEK_END). 5 Return the new file position. */ 6 #ifndef __USE_FILE_OFFSET64 7 extern __off_t lseek (int __fd, __off_t __offset, int __whence) __THROW; 8 #else 9 # ifdef __REDIRECT_NTH 10 extern __off64_t __REDIRECT_NTH (lseek, 11 (int __fd, __off64_t __offset, int __whence), 12 lseek64); 13 # else 14 # define lseek lseek64 15 # endif 16 #endif
参数whence释义如下:
取值为SEEK_SET,则将文件偏移量设置为距离文件开始处offset个字节
取值为SEECK_CUR,则将文件偏移量设置为当前值加上offset,offset可正可负
取值为SEEK_END,则将文件偏移量设置为文件长度加上offset,offset可正可负