文件描述符一般用fd(file descriptor)表示,是一个非负整数。
1 一般是从3开始的,因为一个程序运行,会默认自动的打开3个fd,分别是0(stdin) 1(stdout)以及 2 (stderr)? 2?文件描述符的范围是0~OPEN_MAX-1,而因为程序默认打开3个流,所以可打开的流个数为OPEN_MAX - 3 , 可通过命令 ulimits -a 的open files查看
3.这个int fd 代表的是数组下标,? 这个数组是程序打开的所有stream的记录。
4.每个文件的使用情况会有一个使用计数,防止不同的地方打开了同一个文件导致一个close()就关了所有的文件。
函数定义:调用open 创建或打开一个文件,函数open() 通过变参实现类似重载的效果(类似于printf,参数个数是不确定的)
??flag参数:必须有以下三个参数(其他参数可通过或操作使用)
- O_CREAT:若文件不存在则创建文件(无则创建)
- O_TRUNC:若文件只读只写成功打开,长度截断为0,清空文件(有则清空)
?其余参数:用到的时候查书,补充。
函数定义:传入的是open()的返回值fd, 若close出错会返回-1
定义:为一个打开的文件设置“当前文件偏移量”,感觉象是看一张报纸,决定眼睛盯着哪一个字。不过再文件中称之为偏移量。
..
定义
?..
定义
若写出错,返回值为-1,并且会设置errno, 可能的出错值再man 2 write的ERRORS中可看到。?
- 通过read/write实现两个文件之间的拷贝的 DEMO
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#define BUFSIZE 1024
int main(int argc, char **argv) {
if (argc < 3) {
fprintf(stderr, "Usage\n");
}
// 1.打开两个文件
int sfd = open(argv[1], O_RDONLY);
if (sfd < 0) {
perror("open 1");
exit(1);
}
int dfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (dfd < 0) {
close(sfd); //避免内存泄漏
perror("open 2");
exit(1);
}
// 2. 读sfd的内容到dfd的内容
char buf[BUFSIZE];
while (1) {
int len = read(sfd, buf, BUFSIZE);
if (len < 0) { //读取出错
perror("read");
break;
} else if (len == 0) { //读取完成
break;
}
int ret = write(dfd, buf, len);
if (ret < 0) {
perror("write");
break;
}
}
// 3. 关闭两个文件
close(dfd);
close(sfd);
exit(0);
}
比如:传达室大爷送信到邮局:有两种办法:
1.收一封信,去一次邮局。(文件I/O)
2.收到20封信,去一次邮局。(标准I/O操作,有缓冲)如果收到第6封加急的信件,则立刻去邮局。(fflush()刷新)
标准I/O:具有缓冲的机制,可大大的提高系统的效率。若有紧急需要刷新则可用fflush(),所以吞吐量大。响应速度慢。
文件I/O:无缓冲,是一次实打实的动作。响应速度快,吞吐量小。
问如何让程序变快?反应速度快用文件I/O。吞吐量大用标准I/O。
因为标准I/O有缓冲,并不会真正的写到文件里面去。
比如下面的例子,会先输出文件I/O的动作,最后调用标准I/O的动作
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
putchar('a'); // 标准I/O
write(1, "b", 1); // 系统调用(文件I/O)
putchar('a');
write(1, "b", 1);
putchar('a');
write(1, "b", 1);
exit(0);
}
// 输出结果: bbbaaa
- 通过strace ./a.out? 即可看到系统调用(文件I/O的调用顺序)?
- 转换
fileno() // 将标准I/O操作转换为文件I/O操作
fdopen() //将文件I/O转换为标准I/O使用
|