Linux系统编程.NO5——基本文件控制

本文深入解析Linux文件I/O的基本理论,包括inode结构、文件类型、内核数据结构及进程对文件的访问机制。详细介绍了open、read、write、lseek、close等基本文件I/O函数的使用方法及原理,帮助读者理解Linux文件系统的工作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3.文件I/O基本理论

3.1.索引节点inode

Linux采用“按名存取”的方式访问文件,每个文件除了文件名以外的属性都保存在inode当中,inode是一个结构体,所以每个文件的i节点中都存着许多属性:i_mode文件类型和权限,i_uid拥有者标识符,i_size文件长度(以字节为单位),i_atime最后一次访问时间,i_ctime节点最后改变的时间,i_mtime文件内容最后改变的时间,i_dtime文件删除的时间,i_gid组标识符,i_blocks文件数据块数,i_flags文件标志,i_block指向数据块的指针。
系统中的每个文件都有自己的inode号保存在索引节点表中,当要打开某个文件时,系统会将这个节点号拷贝到VFS系统的inode当中去,方便系统使用。

3.2.st_mode中的文件类型

st_mode是文件的节点结构体inode中的一个成员,该结构体类型是struct stat,st_mode是一个16位的整数,它的低12位表示的是访问权限,而前4位则表示了该文件的文件类型。
将一个文件的st_mode和0170000(0开头表示这是8进制数,换成2进制就是 1111 0000 0000)相与(也就是只保留文件st_mode的前四位,忽略后面的12位,所以这个数又叫文件类型字段的二进制掩码,宏定义为S_IFMT),得到的结果表示一种文件类型。
有7种可能的结果:
0140000(转二进制前4位是1100,宏定义为S_IFSOCK),表示这是socket文件;
0120000(转二进制前4位是1010,宏定义为S_IFLNK),表示这是符号链接文件;
0100000(转二进制前4位是1000,宏定义为S_IFREG),表示这是普通文件;
0060000(转二进制前4位是0110,宏定义为S_IFBLK),表示这是块设备文件;
0040000 (转二进制前4位是0100,宏定义为S_IFDIR),表示这是目录文件;
0020000(转二进制前4位是0010,宏定义为S_IFCHR),表示这是字符设备文件;
0010000(转二进制前4位是0001,宏定义为S_IFIFO),表示这是FIFO文件;

3.3.访问文件内核数据结构

当要访问一个文件时,系统中就会建立起相应的数据结构来记录访问文件需要的各种信息。首先进程启动,进程结构体是task_struct,它有一个成员是struct file_struct *file代表当前打开文件,而file_struct结构体中包含当前打开文件指针,它指向一个struct file,file结构体中包含文件信息以及位置,并且间接指向文件i节点。

3.4.Linux进程对文件的访问

进程访问文件,首先用户通过用户名向系统发起请求,然后系统在文件系统中寻找i节点,同时将i节点复制到内存的inode表中,可以提高文件的访问速度。内存中的inode比一般的inode要多一点信息,比如inode节点引用计数,内存inode是否被修改过等。
系统还会建立一个文件表,用于记录系统中所有打开的文件。每打开一次文件,就会增加一个表项(记录该文件的打开方式、读写指针、指向内存inode的指针等)
同时进程中的fd表也会增加一个fd表项(以文件描述符为下标),每一个进程一建立就会首先打开文件描述符为0、1、2的三个文件,其他的文件都会排在后面,用户通过文件描述符和系统调用访问该文件。

3.5.文件i/o基本函数

*3.5.1.int open(const char pathname,int flags,mode_t mode);

该函数用于用于打开或创建一个文件,一般只有第一二个参数,第一个参数是打开文件名字,第二个参数表示打开方式,是个可选参数如O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(可读写)、这三个参数必须有且只有一个,还有O_CREAT(没有就创建)、O_EXCL(和O_CREAT一起使用,如果该文件本来存在则open失败)、O_APPEND(打开文件时文件指针在文件的末尾)等多个参数,需要使用多个参数就用或运算“|”将这些flag连在一起,最常用的就是O_RDONLY|O_CREAT(只读方式打开,没有就创建)等等。第三个参数是说明该文件的权限,使用数字参数(如755)或者符号常:name量(如S_PRUSR|S_PWUSR|S_PXUSR)来表示权限。该函数的返回值是一个int类型,即文件描述符,返回为-1表示打开失败。
头文件是<sys/types.h><sys/stat.h><fcntl.h>
3.5.2.creat()
creat函数和flags为O_CREAT|O_WRONLY|O_TRUN的open函数效果一样。
*3.5.3.ssize_t read(int fd,void buf,size count);
读函数,第一个参数是想要读文件的文件描述符,第三个参数是想要读取的字节长度,第二参数是读取后的内容的存放位置,所以要使用这个函数需要事先定义一个buf准备用于存放读取的数据,该函数返回值也是int型,表示具体读取到了多少位,所以如果返回值不等于输入的count,那么表示读取出错了。
头文件是<unistd.h>
*3.5.4.ssize_t write(int fd,const void buf,size_t count);
写函数,第一个参数是需要写入的文件的文件描述符,第三个参数是想要写入的内容字节长度,第二个参数是要写入的内容,可以直接写一个字符串(如“str”),也可以事先把这个放入一个数组,该函数的返回值也是int,表示具体写入的多少位,所以如果返回值和输入的count不一样,则表示写入出错。
头文件是<unistd.h>
3.5.5.off_t lseek(int fd,off_t offset,int whence);
文件定位函数,当打开一个文件时候,就会有一个文件指针在出现在该文件的开头,读操作和写操作都会使得文件指针向后移动,当文件关闭后,指针就会消失,再次打开,文件指针就又回到开头。在一次打开的过程中多次读写的话可能导致指针位置难以确定,就需要文件定位。
函数第一个参数是指定文件的文件描述符,第二个参数是偏移量,整数都可以(为负表示向前移),第三个参数表示开始偏移的位置,有三个可以选择,SEEK_SET(文件开始位置),SEEK_CUR(文件当前位置),SEEK_END(文件结束位置)。
头文件是<sys/types.h><unistd.h>
3.5.6. int close(int fd)
关闭一个文件,参数是该文件的文件描述符,成功关闭返回0,失败返回-1.
头文件是<unistd.h>
3.5.7. void sync(void);
将缓冲区的内容写入磁盘,系统在执行写操作时,并没有直接将内容写入磁盘(也就是文件),而是先放入缓冲区,这样可以提高读写磁盘的速度,但是如果在还没有写入磁盘计算机意外关机,就可能造成信息丢失。
该函数没有返回值和参数,用于将所有缓冲区的内容写入磁盘。
头文件是<unsitd.h>
3.5.8. int fsync(int fd)/int fdatasync(int fd);
将指定文件的内容写入磁盘,成功返回0,错误返回-1.
头文件是<unistd.h>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值