欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 【Linux基础IO】常见的对文件操作的函数、文件描述符fd、访问文件的本质分析

【Linux基础IO】常见的对文件操作的函数、文件描述符fd、访问文件的本质分析

2025/8/24 1:12:11 来源:https://blog.csdn.net/2401_84568462/article/details/139761812  浏览:    关键词:【Linux基础IO】常见的对文件操作的函数、文件描述符fd、访问文件的本质分析

目录

fopen函数

chdir函数

fclose函数

 fwrite和fread函数

open函数

umask函数

write函数

 read函数

close函数

文件描述符fd

进程访问文件的本质分析


fopen函数

参数mode:

 w方式打开文件:1、如果被打开文件不存在,系统会在使用fopen函数的进程的工作目录下创建一个新文件,文件名就是参数path。2、w方式打开文件系统会将文件的内容截断清空。

 a方式打开文件:1、如果被打开文件不存在,系统会在使用fopen函数的进程的工作目录下创建一个新文件,文件名就是参数path。2、a方式打开文件,向被打开文件写入内容在有内容的后面续写。

我们来验证一下1、如果被打开文件不存在,系统会在使用fopen函数的进程的工作目录下创建一个新文件,文件名就是参数path。(我们可以通过  ll /proc/进程PID  这一指令查看进程的cwd即进程的目前工作目录来验证;利用chdir函数来改变进程的cwd从而得以验证)。注意:/proc目录中是正在运行的进程

chdir函数

不改变进程的cwd在进程内部使用fopen函数在进程的cwd下创建一个新的文件:

改变进程的cwd:

函数的返回值:

返回被打开文件的地址,类型为FILE*,打开文件失败则返回NULL

fclose函数

 fwrite和fread函数

open函数

 常见的lags参数:

O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。使用 mode 参数来指明新文件的访问权限.
O_APPEND: 追加写

umask函数

write函数

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{umask(0);int fd = open("myfile", O_WRONLY|O_CREAT|O_TRUNC, 0644);if(fd < 0){perror("open");return 1;}int count = 5;const char *msg = "hello bit!\n";int len = strlen(msg);while(count--){write(fd, msg, len);//msg:缓冲区首地址   len: 本次读取,期望写入多少个字节的数
据。 返回值:实际写了多少字节数据}close(fd);return 0;
}

 read函数

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{int fd = open("myfile", O_RDONLY);if(fd < 0){perror("open");return 1;}const char *msg = "hello bit!\n";char buf[1024];while(1){ssize_t s = read(fd, buf, strlen(msg));//类比writeif(s > 0){printf("%s", buf);}else{break;}}close(fd);return 0;
}

close函数

 open、write、read、close函数其实都是对文件操作的系统调用接口。库函数fopen、fread、fwrite、fclose内部都是封装了上面对应的系统接口!

文件描述符fd

Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2。
0,1,2对应的物理设备一般是:键盘,显示器,显示器
输入输出可以采取如下方式:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{char buf[1024];ssize_t s = read(0, buf, sizeof(buf));if(s > 0){buf[s] = 0;write(1, buf, strlen(buf));write(2, buf, strlen(buf));}return 0;
}

进程访问文件的本质分析

1、首先我们来重新认识一下文件:

文件 = 文件内容 + 文件属性    文件分为打开的文件和没有打开的文件。

文件被打开必须要加载到内存里。

而在操作系统中其实是进程打开了文件!-----研究文件打开本质是研究文件和进程之间的关系

没有打开的文件是存放在磁盘上的,磁盘是外部设备,根据冯诺依曼体系访问文件就等于访问硬件,由于操作系统不允许用户直接访问它内部的硬件数据,因此操作系统提供了相应的系统调用供用户对文件进行操作,并且一般都是对文件操作的库函数封装了相应系统调用。例如:fprintf函数是向显示器文件流stdout、stderr中输入内容然后由显示器硬件将内容显示出来。

当我们打开文件时,操作系统会在内存中创建相应的数据结构来描述该文件。于是就有了上图中的file结构体,表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct该表最重要的部分就是存储该进程打开的文件的文件结构体对象地址的指针数组,该指针数组每个元素都是一个指向打开文件结构体对象的指针!所以,本质上,文件描述符就是该数组的下标。所以通过文件描述符就可以找到对应的文件。
操作系统什么时候回收描述被打开文件的结构体对象呢?
通常可能会有多个进程同时打开一个文件,因此多个进程的表files_struct都包含这个描述文件的结构体对象地址,其实这个被打开文件的结构体对象里存储了一个int count变量用来存储有几个进程正在打开它,当一个进程不再关闭了该文件时--count直到0 == count操作系统就会回收描述该文件的结构体对象。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词