要了解Linux下的文件IO,我们首先要清楚文件描述符的概念,那什么是文件描述符呢?接下来我们一起认识一下:
首先我们知道操作系统是一个“纯正”的搞管理的软件,它对硬件的管理方式是先描述起来,再组织起来;同样,当我们打开
文件时,操作系统在内存中要创建相应的数据结构来描述目标文件,这个数据结构就是file结构体,保存了文件相关的信息,表示
一个已经打开的文件对象。
几种文件相关系统调用接口的详解
在C语言中我们学习了几种文件相关操作函数,像fopen,fclose,fread,fwrite这些都是C标准库当中的函数,而在Linux下我们要解
析的 open,close,read,write,lseek都属于系统调用接口。下面我们逐个分析一下:
open:
调用open函数可以打开或者创建一个文件。若成功,返回文件描述符;若出错,返回-1。
path参数是要打开或创建文件的名字。flags参数可用来说明此函数的多个选项。用一个或多个常量进行“或”运算构成flags参
数。(这些常量在头文件<fcntl.h>中定义,在UNIX环境高级编程第三版3.3节中也有每个常量的详解)。接下来我们来看几个比
较常用的常量:
O_RDONLY 只读打开。(大多数定义为0)
O_WRONLY 只写打开。(大多数定义为1)
O_RDWR 读、写打开。(大多数定义为2)
O_EXEC 只执行打开
O_CREAT 若此文件不存在则创建它。使用此选项时,open函数需同时说明第三个参数mode,用mode指定该新文件的
访问权限位。
O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则出错。用此可以测试一个文件是否存在,如果不存在,则创
建此文件,这使测试和创建两者成为一个原子操作。
close:
可调用close函数关闭一个已经打开文件。fd代表要关闭文件的文件描述符。若成功,返回0;若出错,返回-1。
read:
调用read函数从打开文件中读数据。
若读取成功,则返回读到的字节数,如已到达文件的尾端,则返回0。
第一个参数是文件描述符,*buf是一个指向要读取文件的文件指针。count是要读取的字节数。
write:
调用write函数向打开文件写数据。若成功,返回写入的字节数;若失败,返回-1。
上面就是我们对文件进行相关操作的部分函数,这些是最基本的,这些东西定要运用的相当熟练。
我们知道,进程执行open系统调用,必须让进程和文件关联起来。每个进程的PCB中都有一个指向一张表的指针,该表最重要的
部分就是包含一个指针数组,数组里的每个元素都指向一个打开文件,所以,文件描述符就是这个指针数组的下标。我们只要拿
到文件描述符,就能找到对应的文件。可以结合下图对文件描述符有个更加深入的了解:
接下来我们看看文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述
符。下面我们验证一下
看下面这段代码:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
int fd = open("myfile",O_WRONLY|O_CREAT,00644);
if(fd < 0){
perror("open");
return -1;
}
printf("fd: %d\n",fd);
close(fd);
return 0;
}
输出结果:
我们关闭0再看:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
close(0);
int fd = open("myfile",O_WRONLY|O_CREAT,00644);
if(fd < 0){
perror("open");
return -1;
}
printf("fd: %d\n",fd);
close(fd);
return 0;
}
运行结果:
那如果关闭1呢?我们用代码来看一下结果吧:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
close(1);
int fd = open("myfile",O_WRONLY|O_CREAT,00644);
if(fd < 0){
perror("open");
return -1;
}
printf("fd: %d\n",fd);
fflush(stdout);
close(fd);
return 0;
}
看一下运行结果:
我们发现本来应该输出到显示器上的内容出现在了文件里,fd = 1。这种现象叫做输出重定向,是怎么做到输出重定向呢?
我们把本来的标准输出与fd下标为1的连接断掉之后根据文件描述符的分配工作,现在fd下标为1所表示内容已经变成了myfile的
地址,不再是显示器文件的地址,所以输出的任何消息都会往文件中写入,进而完成输出重定向。
以上内容就是对文件描述符的详解。