[APUE]第三章文件I/O
来源:互联网 发布:sql 选取时间段 编辑:程序博客网 时间:2024/06/05 12:44
Unix系统中大多数文件I/O只需用到五个函数:open、read、write、lseek、close。本章介绍的I/O是不带缓冲的,即:每个read和write都调用内核中的一个系统调用。它们不是ISO C的组成部分。
对于内核而言,所有打开的文件都通过文件描述符引用;
当打开或创建文件时,内核向进程返回一个文件描述符;
读写文件时,文件描述符将作为read和write的参数。
在 unistd.h中定义三个标准的文件描述符:
STDIN_FILENO (0) 标准输入STDOUT_FILENO (1) 标准输出STDERR_FILENO (2) 标准出错输出
文件描述符的变化范围是0~OPEN_MAX,早期的UNIX系统实现采用的上限是19,现在 大多数系统的OPEN_MAX为63。
open和openat函数
int open(const char *path, int oflag, … ); //打开或者创建一个文件
int openat(int fd,const char *path, int oflag, … ); //打开或者创建一个文件
最后一个参数为…的形式为可变参数,对于open函数只有在创建新文件时才使用最后这个参数。
由open和openat函数返回的文件描述符一定是最小的未用描述符数值。
lseek()函数
off_t lseek(int fildes, off_t offset, int whence); //为打开的文件设置偏移量
whence可选:SEEK_SET, SEEK_CUR, SEEK_END
SEEK_SET:将该文件的偏移量设置为距文件开始处offset个字节。
SEEK_CUR:将该文件的偏移量设置为其当前值加offset。
SEEK_END:将该文件的偏移量设置为文件长度加offset,offset可正可负。
如果文件描述符指向的是一个管道 FIFO 网络套接字,则lseek返回-1,并将errno设置为ESPIPE.
通常偏移量是一个非负整数,但是对有些设备来说可以是负的,所以为安全起见,对返回值不要测试它是否小于0,而要测试它是否等于-1。
当文件偏移量大于文件的长度时,对文件的下一次写将加长该文件,并在文件中构成一个空洞(没有写过的字节被读为0),文件的空洞并不占用磁盘的存储区。
#include "apue.h"intmain(void){ if (lseek(STDIN_FILENO, 0, SEEK_CUR) == -1) printf("cannot seek\n"); else printf("seek OK\n"); exit(0);}
由于文件描述符指向管道 FIFO 网络套接字时,lseek返-1,所以书中第二个示例:
cat < /etc/passwd | a.out会打印cannot seek
关于管道:
命令从标准输入到读取数据,并将数据发送到标准输出的能力,是使用了名为管道的shell特性。使用|可以把一个命令的标准输出传送到一个命令的标准输入中:
command1 | command2
上面例子中其实等价于:
cat /etc/passwd | a.out
使用重定向符号”<”,我们把标准输入的源从键盘变为文件/etc/passwd文件。把一个文件作为标准输入的源文件,cat 输出文件内容,传递给a.out
#include "apue.h"#include <fcntl.h>char buf1[] = "abcdefghij";char buf2[] = "ABCDEFGHIJ";intmain(void){ int fd; if ((fd = creat("file.hole", FILE_MODE)) < 0) err_sys("creat error"); if (write(fd, buf1, 10) != 10) err_sys("buf1 write error"); /* offset now = 10 */ if (lseek(fd, 16384, SEEK_SET) == -1) err_sys("lseek error"); /* offset now = 16384 */ if (write(fd, buf2, 10) != 10) err_sys("buf2 write error"); /* offset now = 16394 */ exit(0);}
中文版第三版这里有个错误如下:
勘误二
p55页 中文版中“从中可以看到,文件中间的30个未写入字节都被读成0,每一行开始的一个7位数是以8进制形式表示的字节偏移量。”
实际上英文原版中的内容如下:
#include "apue.h"#include <fcntl.h>intmain(int argc, char *argv[]){ int val; if (argc != 2) err_quit("usage: a.out <descriptor#>"); if ((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0) err_sys("fcntl error for fd %d", atoi(argv[1])); switch (val & O_ACCMODE) { case O_RDONLY: printf("read only"); break; case O_WRONLY: printf("write only"); break; case O_RDWR: printf("read write"); break; default: err_dump("unknown access mode"); } if (val & O_APPEND) printf(", append"); if (val & O_NONBLOCK) printf(", nonblocking"); if (val & O_SYNC) printf(", synchronous writes");#if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC) && (O_FSYNC != O_SYNC) if (val & O_FSYNC) printf(", synchronous writes");#endif putchar('\n'); exit(0);}
关于重定向的语法 >>是追加到文件末尾,5<>temp.foo表示在文件描述符5上打开文件temp.foo以供读 写。
小结
本章说明了UNIX系统提供的基本I/O函数。因为read和write都在内核执行,所以称这些函数为不带缓冲的I/O函数。在只使用read和write情况下,我们观察了不同的I/O长度对读文件所需时间的影响。我们也观察了许多将已写入的数据冲洗到磁盘上的方法,以及他们对应用程序性能的影响。
- [APUE]第三章:文件I/O
- APUE第三章 文件I/O
- apue第三章文件I/O
- 《apue》读书笔记 第三章 文件I/O
- 【APUE】3、第三章 文件I/O
- APUE学习: 第三章, 文件I/O
- APUE读书笔记-第三章 文件I/O
- APUE笔记---第三章文件I/O
- 《APUE》笔记-第三章-文件I/O
- 《APUE》读书笔记-第三章文件I/O
- APUE第三章 文件I/O
- [APUE]第三章文件I/O
- 【qianlong88的APUE读书笔记】第三章:文件I/O
- APUE学习笔记——第三章文件I/O
- APUE学习笔记第三章文件I/O
- apue学习笔记(第三章 文件I/O)
- APUE 2 - 第三章文件I/O学习-习题
- 【APUE】文件I/O
- PHP中的一些小算法
- HDU 2844 Coins(多重背包,装满可行性)
- Another git process seems to be running in this repository
- 杭电2017新生赛1004-正品的概率
- 046day(平均数的简化求法,递归(N皇后)的学习,拨钟问题的尝试)
- [APUE]第三章文件I/O
- 杭电2017新生赛1003-下起楼来我最快
- Nginx配置文件详解
- spring ioc的理解
- Spring MVC静态资源处理
- 杭电2017新生赛1002-身份证验证
- 杭电2017新生赛1001-考研
- caffe配置python接口
- Redis基本操作