IO就是输入输出,这个输入输出的对象是针对主存来说的,往主存上复制数据就是输入,从主存上往外部设备上复制就是输出。这些外部设备包括磁盘驱动器,终端和网络等。对于Unix系统来说,一切都被抽象成文件,对于IO操作,实际上就是对文件进行操作。
Linux下的每一个文件都有一个类型,用来表明他在文件中所扮演的角色。 Linux下的文件类型一共有七类。普通文件,目录文件,套接字文件,管道文件,链接文件,字符设备文件,块设备文件。 对于文件的路径分为绝对路径和相对路径。 绝对路径不受任何因素的影响,可以直接使用,缺点就是路径太长太复杂。 相对路径比较短,但是受当前的工作路径影响,当前的工作路径变化了,相对路径就会跟着变化。
进程可以通过open函数进行打开一个已经存在的文件或者创建一个不存在的文件。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(char *filename, int flags, mode_t mode);
若成功返回新文件描述符,失败返回-1。
flags参数就是指明进程以哪种方式进行访问文件。 mode用来指定新文件的访问权限。
进程可以通过close函数关闭一个已经打开的文件。
#include <unistd.h>
int close(int fd);
成功返回0,失败返回-1。
文件描述符是非负整数,其中0,1,2这三个已经被系统占用,分别是标准输入,标准输出,标准错误。如果再打开一个文件,那么新的文件描述符就是3,这样依次往上之后增加。 细节注意:被关闭的文件描述符的值没有被清除为-1。程序如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd1 = -1, fd2 = -1, fd3 = -1;
fd1 = open("foo.txt", O_RDONLY, 0);
fd2 = open("fxx.txt", O_RDONLY, 0);
close(fd1);
printf("fd1= %d \n", fd1);
printf("fd2= %d \n", fd2);
printf("fd3= %d \n", fd3);
fd3 = open("fyy.txt", O_RDONLY, 0);
printf("fd1= %d \n", fd1);
printf("fd2= %d \n", fd2);
printf("fd3= %d \n", fd3);
fd1 = open("foo.txt", O_RDONLY, 0);
printf("fd1= %d \n", fd1);
printf("fd2= %d \n", fd2);
printf("fd3= %d \n", fd3);
close(fd1);
close(fd2);
close(fd3);
return 0;
}
输出结果:
hehk@hehk:~/test/C/io_test$ ./a.out
fd1= 3
fd2= 4
fd3= -1
fd1= 3
fd2= 4
fd3= 3
fd1= 5
fd2= 4
fd3= 3
读写文件:使用read和write函数进行对文件的读写。 读取文件元数据:使用stat和fstat函数获取关于文件的信息。 读取目录内容:使用opendir和closedir函数。
内核使用三个相关的数据结构来表示打开的文件。 文件描述符,文件表,v-node表。 通常一个进程中一个文件描述符指向一个文件表项,然后对应一个v-node表项。不同的文件描述符可以对应同一个文件,这样的文件就是共享文件,被两个文件描述符共享,当然还可以被两个进程共享。