当前位置: 首页 > news >正文

基础 IO

一.C文件IO相关接口

我们首先来看C文件的读写操作。

include <stdio.h>
int main()
{
FILE *fp = fopen("myfile", "w");
if(!fp){
printf("fopen error!\n");
}
while(1);
fclose(fp);
return 0;
}

在这个程序中我们打开文件后一直while运行,这里的 fopen 只表明为 myfile ,我们通过另一个窗口输入 ls /proc/【进程id】 可以观察到正在运行进程的信息。

我们通过ps ajx | grep test 可以查看到当前进程 test 的运行pid,再通过 ls/proc/ 【进程id】 就可以查看到进程信息,其中 cwd 指明了当前的运行路劲。我们发现程序会记录下当前路径,当我们创建文件或者打开文件时,系统会在记录的路径下寻找打开。

1.1 fopen,fwrite,fclose

fopen:

pathname:要打开的文件名字符串

mode:访问文件的模式(可读可写追加)


fwrite:

ptr: 写入数据的指针

size:指针的大小

nmemb:读写数据项的个数

stream:读入到的文件


fclose:

stream:要关闭的文件


1.2 文件的权限模式

 文件的权限分为 可读 可写 追加三种。

读模式下可以获取文件中的内容数据,写模式下可以对文件进行写入。 

r 为只读模式,r+ 为读写模式。r+ 若打开的是空文件就会返回NULL,会保留原有的内容。

w为只写模式,w+为读写模式。w下不能读取文件内容,只能对文件进行写入,若当前文件不存在会在当前路径下创建该文件。w+下可以对文件进行读写,若文件不存在会创建新文件,对文件进行写入时会对文件进行清空操作。

a为追加模式,a在写入后无读权限,a的指针指向文件末尾,对文件进行内容追加。a+可以读取写入文件的内容,并且不会清空文件内容。

1.3 文件描述符

在Linux中,文件描述符是一种用于访问文件或输入输出的抽象概念。在进程PCB中,存在一个*files 指针指向一个文件结构体,文件结构类似于数组,会将文件进行排序,将文件分为0,1,2,3,4等数字,这些数字就代表了文件。我们只要拿着这些数组下标,就能对文件进行访问。

而其中比较特殊的是0,1,2 这三个数。0代表着输入文件 stdin ,1 代表输出文件 stdout ,3 代表错误文件 stderr。从3 开始就是用户文件。进程在运行时,会默认打开0,1,2 这三个文件。

 1.4 C默认输入输出流

 C默认会打开stdin stdout stderr 三个文件,这三个文件是封装Linux底层0,1,2 三个接口。当我们在使用 scanf 函数时会将内容存到 sdtin 中,printf 时会将打印内容存放到stdout 中,perror 时会存放到stderr 中。这三个流的类型都是 FILE* ,Linux的系统调用接口不会直接给用户使用,而是根据不同的语言进行不同的封装,这样就实现了多种语言操控Linux。

 二.系统文件 I/O

根据上文描述 stdin stdout stderr 是C语言封装了Linux 的底层系统调用创造出来的。现在我们来讲解一下几个系统调用接口。

2.1 open write close

我们在用man手册时,若接口是系统调用,需要在前面加上数字2。

open:

pathname:要打开或创建的路径名称

flags:打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。

参数:

O_RDONLY:只读打开

O_WRONLY:只写打开

O_RDWR:读写打开 

O_CREAT:文件不存在时,创建文件(不能单独使用O_RDONLY创建文件)

O_APPEND:追加写文件

 若成功则返回新打开的文件描述符,若失败返回-1.


write:

fd:文件标识符,需要写入的文件。

buf:用数组来存储需要写入文件的内容。

count:写入文件内容的字节数大小。

若write成功则返回实际写入的字节数,若失败返回-1.


close:

fd:需要关闭的文件的文件标识符。 

2.2 重定向

首先我们来讲述一下文件描述符的分配规则。

来看下面代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
close(0);
//close(2);
int fd = open("myfile", O_RDONLY);
if(fd < 0){
perror("open");
return 1;
}
printf("fd: %d\n", fd);
close(fd);
return 0;
}

当我们尝试关闭了0或者2时,我们发现输出的结果为 fd:0 或者 fd:2 ,可见,文件描述符在分配时会找到数组中最小的一个小标,作为新的文件描述符。

若我们关闭关闭 1 时,当我们输入想输入到显示器上的内容输入到了文件中,这种现象就叫做输出重定向。常见的重定向有 >   >>   <

>:

echo "hello world" > test.txt  将hello world 写入文件中,若文件不存在则创建,写入后会对文件进行覆盖。


>>:

echo “hello world” >> test.txt  将hello world 追加写入文件中,指针指向文件末尾,不会对文件内容覆盖。


<:

cat < test.txt  对文件进行命令输入。如此示例是对文件内容进行打印。


重定向完成后,我们从键盘读入的数据就会直接被输入到文件中。

重定向的本质就是修改特定的文件描述符。

2.3 dup2系统调用

dup2:

dup2 是一个系统调用函数,其作用是复制文件描述符,到指定的新文件描述符。该函数会返回新的文件描述符,若出错就返回-1. 

代码示例:

include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd = open("./log", O_CREAT | O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
lose(1);
dup2(fd, 1);
for (;;) {
char buf[1024] = {0};
ssize_t read_size = read(0, buf, sizeof(buf) - 1);
if (read_size < 0) {
perror("read");
break;
}
printf("%s", buf);
fflush(stdout);
}
return 0;
}

三. 理解文件缓冲区

缓冲区是内存空间的一部分,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或者输出的数据。我们在读写文件时,如果不开辟对文件操作的缓冲区,直接通过系统调用进行读写操作,那么每次对文件进行操作时,CPU都要进行状态切换,从用户空间到内核空间,会产生一定时间消耗。为了减少系统调用次数,我们从先将数据放到缓冲区中,等产生一定量之后再进行刷新缓冲区,这样可以减少读写的次数。在数据刷新到缓冲区之前,CPU也可以做其他的工作。

标准I/O 提供了三种类型的缓冲区,全缓冲,行缓冲,无缓冲区

全缓冲区:要求填满缓冲区后才进行I/O操作,对于磁盘文件操作通常使用全缓冲的方式访问。

行缓冲区:当输入输出遇到换行符时,会被刷新,若是超过了固定的1024字符也会进行刷新。

无缓冲区:直接进行系统调用,通过是stderr,这样可以更快地将错误信息显示到屏幕。

四. Linux下一切皆文件

在Linux下所有的硬件设备,目录,进程通信,系统配置被抽象成文件。这样对于用户来说不管操作硬盘,键盘都可以用统一的命令进行操作,就像处理普通文档一样,我们不需要再去专门学习这些单独的设备的各种用法,可以用统一的一套API就可以解决问题。

http://www.dtcms.com/a/272477.html

相关文章:

  • Spring Boot中的中介者模式:终结对象交互的“蜘蛛网”困境
  • JAVA JVM的内存区域划分
  • Redis的常用命令及`SETNX`实现分布式锁、幂等操作
  • Redis Stack扩展功能
  • K8S数据流核心底层逻辑剖析
  • AI进化论06:连接主义的复兴——神经网络的“蛰伏”与“萌动”
  • k8s集群--证书延期
  • 项目进度管控依赖Excel,如何提升数字化能力
  • 调度器与闲逛进程详解,(操作系统OS)
  • UI前端与数字孪生结合案例分享:智慧城市的智慧能源管理系统
  • 数据结构笔记10:排序算法
  • Windows 本地 使用mkcert 配置HTTPS 自签名证书
  • Java并发 - 阻塞队列详解
  • XSS(ctfshow)
  • 文心大模型4.5开源测评:保姆级部署教程+多维度测试验证
  • 图书管理系统(完结版)
  • PyCharm 中 Python 解释器的添加选项及作用
  • 创始人IP如何进阶?三次关键突破实现高效转化
  • QT解析文本框数据——详解
  • pycharm中自动补全方法返回变量
  • 自动化脚本配置网络IP、主机名、网段
  • React封装过哪些组件-下拉选择器和弹窗表单
  • 常用的.gitconfig 配置
  • 【显示模块】嵌入式显示与触摸屏技术理论
  • HarmonyOS AI辅助编程工具(CodeGenie)UI生成
  • 时序数据库的存储之道:从数据特性看技术要点
  • 使用深度学习框架yolov8训练监控视角下非机动车电动车头盔佩戴检测数据集VOC+YOLO格式11999张4类别步骤和流程
  • UEditor 对接 秀米 手机编辑器流程与问题
  • ClickHouse 查看正在执行的SQL查询
  • Django--01基本请求与响应流程