APUE之第5章——标准I/O库
一、知识回顾:文件I/O
假设,每个人家里喝的水都是从自来水厂来的,自来水厂的水又是从水源地来的,这当中流动的水,就是水流,可以理解为IO流,
在 UNIX 中,UNIX 就是自来水厂,水源地就是源,家就是目的。则从水源到自来水厂的水流,就是IO输入流,从自来水厂到家的水流,就是IO输出流。
如果没有蓄水池,则每次用水都要运送一次。一万次用水就是运送一万次,这样的效率很低。若在水源地与自来水厂、自来水厂与家之间分别建造蓄水池,
则自来水厂可以随时从蓄水池中取水、为用户供水,我们需要用水时也能随时有水可用。这里的蓄水池就可以类比成缓冲。
三、标准 I/O 与文件 I/O 的区别
四、一图泛读 APUE 之标准 I/O 库
五、strace 命令跟踪 PHP 函数的系统调用
strace是一个可用于诊断、调试的Linux用户空间跟踪器,可以用它来监控用户空间进程和内核的交互,比如系统调用、信号传递、进程状态变更等。
创建一个php文件,内容如下:
lstat 函数返回文件的信息。
open打开文件,第二个参数是文件的打开模式,
O_WRONLY 只读打开,
O_CREAT 此文件不存在则创建,
O_TRUNC 如果此文件存在,而且为只读或读-写成功打开,则将其长度截断为0。
fstat 函数获得已在文件描述符 fd 打开文件的有关信息。
lseek 函数为一个打开的文件设置偏移量。
write 写入内容
close 关闭文件
由此可以看出,PHP文件函数其实就是文件I/O上的一些封装。
- 文件 I/O 是不带缓冲的 I/O(unbuffered I/O),指每个 read 和 write 都调用内核中的一个系统调用。
- 对于内核而言,所有打开的文件都通过文件描述符引用,即不带缓冲的 I/O 通过文件描述符的方式来引用一个文件。
-
大多数文件 I/O 只需用到5个函数:open、read、write、lseek、close。
- 标准 I/O 库由 ISO C 标准说明。
- 标准 I/O 库的操作围绕流进行,即带缓冲的 I/O 则通过文件流(stream)的方式来引用文件。
- 引入标准 I/O 库的目的是为了提高 I/O 的效率,尽可能地减少使用 read 和 write 调用的次数。因为系统调用会消耗较多的资源,标准 I/O 库提供了缓冲,可以通过累积一定量的数据后,集中写入到实际的文件中来减少系统调用。这样文件的读写就要经过缓冲区做缓冲,从而提高 I/O 效率。
标准I/O | 文件 I/O | |
遵循标准 | 标准 I/O 被称为高级磁盘I/O,遵循 ANSI C 相关标准。只要开发环境中有标准 I/O库,标准 I/O 就可以使用。 | 文件 I/O 被称为低级磁盘 I/O,遵循 POSIX 相关标准。任何兼容 POSIX 标准的操作系统上都支持文件 I/O。 |
缓冲机制 | 标准 I/O 默认采用缓冲机制,可以看成是在文件 I/O 的基础上封装了缓冲机制。先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数。 | 低级 I/O 一般没有采用缓冲,需要自己创建缓冲区。通过文件 I/O 读写文件时,每次操作都会执行相关系统调用。这样处理的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销。 |
操作设备 | 标准 I/O 中用 FILE(流)表示一个打开的文件,通常用来访问普通文件。针对的是控制台,打印输出到屏幕等。 | 文件 I/O 中用文件描述符表现一个打开的文件,可以访问不同类型的文件如普通文件、设备文件和管道文件等。主要针对的是文件操作、读写硬盘等。 |
以下为标准 I/O 函数和文件 I/O 函数的对比 | ||
打开 | fopen,freopen,fdopen | open |
fopen与open |
标准 I/O 使用 fopen 函数打开一个指定文件。
|
文件 I/O 使用 open 函数打开或创建一个文件。
|
关闭 | fclose | close |
fclose与close |
标准 I/O 使用 fclose 函数关闭一个打开的流。
|
文件 I/O 使用 close 函数关闭一个打开的文件。
|
读 | getc,fgetc,getchar, fgets,gets, fread | read |
标准 I/O 可以用 3 种方式进行文件读取。
|
文件 I/O 使用 read 函数从打开的文件中读取数据。
|
|
写 | putc,fputc,putchar, fputs,puts, fwrite | write |
标准 I/O 可以用 3 种方式进行文件写入。
|
文件 I/O 使用 write 函数向打开的文件写数据。
|
|
随机存取 | ftell,fseek | lseek |
标准I/O 使用 fseek 和 ftell 完成文件的随机存取。
|
文件I/O 使用 lseek 来完成文件的随机存取。
|
<?php $file = fopen("test.txt", "wr"); fwrite($file, "test\n"); fclose($file); ?>
执行如下命令:
strace php open.php
可以看到strace的结果: