一、操作系统的体系结构
计算机是由一堆硬件组成的,操作系统是为了有效的控制这些硬件资源的软件。操作系统除了有效地控制这些硬件资源的分配,并提供计算机运行所需要的功能之外,为了提供程序员更容易开发软件的环境,操作系统还提供了一整组系统调用接口。
如上图所示,最中间的是硬件,操作系统是由内核和系统调用接口组成,其中内核是直接操作硬件的,内核提供了对这些硬件资源的控制和进程管理,系统调用接口向上提供了统一的调用接口方便开发人员调用。最上层就是应用程序,在应用程序中调用系统接口就能实现对硬件的操作。
二、Linux I/O系统
如上图Linux的I/O系统结构图,内核层有一个虚拟文件系统,就是使用标准的c类库封装的api,所以我们要操作文件系统只需要调用这里的api即可。
三、I/O的操作过程
1、打开文件
一个应用程序通过要求内核打开相应的文件,宣告他要访问一个I/O设备,内核返回一个非负整数,叫描述符号(Descriptor)【文件唯一标识】
2、读写文件
读:从文件拷贝n>0个字节到存储器(内存)
写:从存储器(内存)拷贝n>0个字节到文件
3、改变文件位置
4、关闭文件
对于内核而言,所有打开文件都由文件描述符引用。
文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当读写一个文件时,用open或create返回的文件描述符fd标识该文件,将其作为参数传送给read或write.而流(如: fopen)返回的是一个FILE结构指针, FILE结构是包含有文件描述符的,FILE结构函数可以看作是对fd直接操作的系统调用的封装, 它的优点是带有I/O缓存
Linux支持各种各样的文件系统格式,如ext2、ext3、reiserfs、FAT、NTFS、iso9660等等,不同的磁盘分区、光盘或其它存储设备都有不同的文件系统格式,然而这些文件系统都可以mount到某个目录下,使我们看到一个统一的目录树,各种文件系统上的目录和文件我们用ls命令看起来是一样的,读写操作用起来也都是一样的,这是怎么做到的呢?Linux内核在各种不同的文件系统格式之上做了一个抽象层,使得文件、目录、读写访问等概念成为抽象层的概念,因此各种文件系统看起来用起来都一样,这个抽象层称为虚拟文件系统(VFS,Virtual Filesystem)
四、Linux底层输入输出
我们可以去GNU下载libc的源代码和帮助文档(源码下载地址:http://ftp.gnu.org/gnu/glibc/)
打开和关闭文件流
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> int main(int argc, char *argv[]){ //open file if(argc<2){ printf("please input filename "); exit(1); }else{ int fd; umask(0000); fd = open(argv[1], O_RDWR|O_CREAT, 0666); if(fd < -1){ printf("error "); exit(1); }else{ printf("success=%d ", fd); close(fd); printf("closed "); } } return 0; }读文件(写文件的过程和读文件类似)
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]){ //open file if(argc<2){ printf("please input filename "); exit(1); }else{ int fd; umask(0000); fd = open(argv[1], O_RDWR|O_CREAT, 0666); if(fd < -1){ printf("error "); exit(1); }else{ printf("success=%d ", fd); char buf[1024]; memset(buf, 0, 1024); int returnum = read(fd, buf, 1024); if(returnum != -1){ printf("buf=%s ", buf); }else{ printf("read error "); exit(1); } close(fd); printf("closed "); } } return 0; }