文件IO总结

标准C库IO函数和Linux系统IO函数对比

标准c库IO函数

标准C库提供了一系列的输入输出(IO)函数,这些函数主要包括在 <stdio.h> 头文件中。这些函数可以大致分为几类:

  1. 文件操作函数

    • fopen:打开文件
    • fclose:关闭文件
    • freopen:重新打开文件
    • fflush:刷新输出缓冲区
    • setbufsetvbuf:设置文件的缓冲区
  2. 格式化输入输出函数

    • printffprintfsprintf:格式化输出到标准输出、文件或字符串
    • scanffscanfsscanf:从标准输入、文件或字符串读取格式化输入
  3. 字符输入输出函数

    • fgetcgetcgetchar:从文件或标准输入读取一个字符
    • fputcputcputchar:写一个字符到文件或标准输出
    • getsfgets:从标准输入或文件读取字符串
    • putsfputs:写字符串到标凈输出或文件
  4. 二进制输入输出函数

    • fread:从文件读取数据块
    • fwrite:向文件写入数据块
  5. 文件定位函数

    • fseek:设置文件位置指针
    • ftell:获取当前文件位置
    • rewind:重置文件位置指针到文件开始
  6. 错误处理函数

    • ferror:检查文件操作错误
    • feof:检查文件结束标志
    • clearerr:清除文件的错误和结束标志

这些函数共同构成了标准C库中处理文件和数据输入输出的基础,广泛用于各种程序设计中。

image-20240420155908461

FILE结构体

在C语言中,FILE 是一个用于表示文件流的类型,它是一个结构体,封装了所有用于管理打开文件的必要信息。这个类型定义在标准库头文件 <stdio.h> 中,作为处理文件输入/输出操作的核心数据结构。

作用和功能

FILE 结构体用来维护文件操作的状态信息,例如文件位置指针(用来追踪当前读写位置)、文件的结束状态、错误状态标识符,以及缓冲区的相关信息。这些信息帮助C语言的运行时系统管理和优化文件I/O操作,例如通过缓冲区来提高文件读写的效率。

使用场景

你不会直接操作 FILE 结构体的内容,因为它的具体实现是隐藏的,依赖于操作系统和C标准库的实现。而是通过指向 FILE 类型的指针来使用,这些指针通过标准I/O函数如 fopen, fprintf, fscanf, fclose 等进行管理。例如:

  • 使用 fopen() 打开文件时,这个函数返回一个 FILE * 指针,指向一个 FILE 结构体,这个结构体代表了打开的文件。
  • 使用 fprintf(), fscanf(), fgets(), fputs() 等函数进行读写操作时,你需要提供一个 FILE * 指针作为参数,这指明了要操作的文件流。
  • 使用 fclose() 关闭文件时,同样需要提供一个 FILE * 指针,以释放与该文件流关联的资源。

示例代码

这里是一个使用 FILE 指针的简单示例,展示如何打开、写入、读取和关闭一个文件:

#include <stdio.h>int main() {FILE *fp;// 打开文件fp = fopen("example.txt", "w+");if (fp == NULL) {perror("Error opening file");return -1;}// 写入文本fputs("Hello, world!", fp);// 重置文件指针到文件开始rewind(fp);// 读取文本char buffer[100];if (fgets(buffer, sizeof(buffer), fp) == NULL) {perror("Error reading from file");fclose(fp);return -1;}printf("File content: %s\n", buffer);// 关闭文件fclose(fp);return 0;
}

在这个例子中,fp 是一个指向 FILE 结构体的指针,它在整个程序中用于指代和操作 “example.txt” 文件。通过这种方式,标准库函数能够提供一个高效且易于管理的文件I/O接口。

#ifndef __FILE_defined
#define __FILE_defined 1struct _IO_FILE;/* The opaque type of streams.  This is the definition used elsewhere.  */
typedef struct _IO_FILE FILE;#endifstruct _IO_FILE {int _flags;		/* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags/* The following pointers correspond to the C++ streambuf protocol. *//* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */char* _IO_read_ptr;	/* Current read pointer */char* _IO_read_end;	/* End of get area. */char* _IO_read_base;	/* Start of putback+get area. */char* _IO_write_base;	/* Start of put area. */char* _IO_write_ptr;	/* Current put pointer. */char* _IO_write_end;	/* End of put area. */char* _IO_buf_base;	/* Start of reserve area. */char* _IO_buf_end;	/* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base;  /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno;  //通过文件描述符来定位文件
#if 0int _blksize;
#elseint _flags2;
#endif_IO_off_t _old_offset; /* This used to be _offset but it's too small.  */#define __HAVE_COLUMN /* temporary *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];/*  char* _save_gptr;  char* _save_egptr; */_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
标准c库IO函数和Linux系统IO函数关系

标准C库的IO函数和Linux系统的IO函数之间存在密切的关系,但它们属于不同的层次,并服务于不同的目的。理解这两者之间的关系,需要从它们的设计和实现角度进行考虑:

  1. 标准C库IO函数

标准C库提供的IO函数,如fopen, fread, fwrite, printf, scanf等,是高级的、跨平台的接口。它们在所有遵循C标准的系统上提供一致的功能和行为。这些函数通常实现了缓冲机制,可以提高数据处理的效率,并简化了程序员在不同操作系统之间编写可移植代码的复杂性。

  1. Linux系统IO函数

Linux系统IO函数,如open, read, write, close等,是基于UNIX的系统调用。这些函数提供了访问底层文件系统和设备的能力。它们是操作系统内核提供的接口,允许用户空间的程序直接与硬件或内核空间的资源进行交互。

关系和区别

  • 封装层次:标准C库的IO函数通常封装了系统级的调用。例如,在Linux环境中,fopen()可能内部使用了open()系统调用来实现文件的打开功能。
  • 性能考虑:虽然标准C库的函数因其缓冲机制通常更易于使用且在多数情况下性能优越,但在需要精细控制IO操作,如非阻塞IO或特定的文件描述符操作时,直接使用Linux系统调用可能更为适宜。
  • 可移植性与特定性:标准C库函数的可移植性较强,适用于任何遵循C标准的平台。相比之下,系统调用如Linux的open()read()等,虽然在遵循POSIX标准的系统间具有一定的可移植性,但它们更具平台特定性。
  • 用途:对于大多数应用程序,标准C库提供的接口已足够使用。但在开发需要直接与操作系统交互的底层软件或设备驱动等时,可能需要使用系统调用。

总结来说,标准C库的IO函数为开发者提供了一层抽象,使得程序员可以在不直接涉及操作系统细节的情况下,编写可在多种平台上运行的程序。而当需要直接与操作系统底层交互或进行特定的操作时,则可能需要直接使用Linux系统的IO函数。

网络通信时优先使用Linux的系统IO函数

image-20240420160908288

虚拟地址空间

image-20240420204504954

虚拟地址空间是操作系统中使用的一种内存管理技术,它允许计算机的软件像拥有远超实际物理内存容量的内存空间一样进行操作。通过虚拟地址空间,每个进程都拥有一块独立的、连续的内存区域,这块内存区域被称为进程的虚拟内存。以下是虚拟地址空间的几个关键概念和好处:

关键概念

  1. 虚拟内存与物理内存

    • 虚拟内存:虚拟内存是一个连续的地址空间,这些地址不直接对应物理内存中的实际位置。虚拟内存由操作系统管理,它通过内存管理单元(MMU)来将虚拟地址映射到物理地址。
    • 物理内存:物理内存是计算机实际安装的RAM。虚拟内存中的数据最终存储在这里。
  2. 地址映射

    • 操作系统通过使用页表来管理虚拟地址到物理地址的映射。当程序访问一个虚拟地址时,MMU查看页表以找到对应的物理地址。
  3. 分页与换页

    • 分页:为了管理内存,操作系统将虚拟内存和物理内存分割成大小相同的块,这些块称为“页”。
    • 换页:当所需的数据不在物理内存中时,操作系统会从硬盘中将数据的页调入内存,这个过程叫做“换页”。

好处

  1. 内存保护

    • 每个进程拥有自己的虚拟地址空间,使得一个进程不能直接访问另一个进程的内存,增加了系统的稳定性和安全性。
  2. 内存虚拟化

    • 进程可以使用比实际物理内存更多的内存空间。不用的页可以被换出到硬盘上,需要时再换入,这使得程序可以使用大量的内存而不受物理内存大小的限制。
  3. 简化编程

    • 开发者无需关心内存的物理布局,每个进程看到的都是一个连续的内存空间,简化了程序的内存管理。
  4. 有效地使用物理内存

    • 操作系统可以更有效地使用物理内存,通过需求分页(只有当页被实际访问时才加载到物理内存)减少内存的浪费。

虚拟地址空间的概念对于现代计算机系统至关重要,它不仅提高了计算机的性能和安全性,也极大地简化了程序的开发和执行。

MMU(内存管理单元)作用

MMU(内存管理单元)是计算机硬件的一个重要组成部分,它负责处理虚拟内存和物理内存之间的地址转换。MMU使得操作系统可以实现复杂的内存管理技术,如虚拟内存、分页、内存保护等。以下是MMU的几个关键功能和特点:

关键功能

  1. 地址转换
    MMU将虚拟地址(程序中使用的地址)转换为物理地址(实际内存中的地址)。这一转换通常通过查询一个称为页表的数据结构完成,页表存储了虚拟地址到物理地址的映射信息。

  2. 内存保护
    MMU可以设置内存访问权限,防止程序访问不允许的内存区域。例如,它可以确保用户程序不会访问系统内存或其他程序的专用内存,从而提供一个稳定和安全的运行环境。

  3. 缓存管理
    在现代计算机系统中,MMU还管理CPU缓存和内存之间的一致性,确保数据在内存和缓存之间正确同步。

实现方式

MMU的实现可以根据具体的硬件和需求有所不同,但一般包括以下几个部分:

  • 转换后备缓冲器(TLB)
    TLB是一种高速缓存,用于存储最近使用的地址映射,以加速地址转换过程。由于访问TLB比查找页表快得多,TLB可以显著提高地址转换的效率。

  • 页表
    页表是存储在内存中的数据结构,记录了虚拟地址到物理地址的映射。当TLB中没有找到所需的地址映射时,MMU会查找页表。

应用

MMU在各种计算设备中都非常重要,从服务器到个人计算机,再到移动设备。它使得操作系统能够更有效地管理内存,提供更好的多任务处理能力,以及保护应用程序不互相干扰。

总结

总的来说,MMU是现代计算机架构中不可或缺的部分,它通过管理虚拟和物理内存之间的交互,提高了系统的性能和安全性。MMU的设计和实现是计算机工程的一个核心领域,对操作系统的效能和稳定性起着决定性作用。

文件描述符

PCB进程控制块可以看作一个大的结构体,其中文件描述符表是一个数组,默认大小时1024,每个进程默认能打开1024个文件。

文件描述符是操作系统提供的一个抽象概念,用于表达和跟踪对文件或其他数据流(如管道、网络连接等)的访问。在类Unix系统(如Linux、macOS)中,文件描述符是非常核心的概念,也被广泛使用。

基本概念

文件描述符通常表现为一个非负整数,操作系统使用这个整数来唯一标识一个已打开文件的引用。程序通过这个整数可以读取、写入或修改对应的文件或数据流。

标准文件描述符

在类Unix操作系统中,有三个预定义的标准文件描述符,它们分别是:

  1. 标准输入(Standard Input) - 文件描述符编号为0。它通常用来接收输入,例如从键盘读取数据。
  2. 标准输出(Standard Output) - 文件描述符编号为1。用于输出数据,如向终端或文件输出数据。
  3. 标准错误(Standard Error) - 文件描述符编号为2。专用于输出错误信息,通常也输出到终端。

使用和管理

在编程中,当你打开一个文件时,操作系统会分配一个文件描述符,并通过系统调用如 open() 返回这个描述符。之后,你可以使用如 read()write()close() 这样的系统调用,通过文件描述符进行操作。例如:

#include <unistd.h>
#include <fcntl.h>int main() {int fd = open("example.txt", O_RDONLY);if (fd == -1) {perror("Error opening file");return 1;}char buffer[128];ssize_t bytes_read = read(fd, buffer, sizeof(buffer));if (bytes_read == -1) {perror("Error reading file");close(fd);return 1;}close(fd);return 0;
}

在上面的例子中,open() 返回一个文件描述符 fd,用于后续的读取和关闭操作。

重要性

文件描述符为操作系统提供了一种统一的方式来处理各种类型的输入输出资源。无论是文件、设备、管道还是网络连接,都可以通过文件描述符进行抽象和管理。这种设计简化了资源管理,提高了操作系统的灵活性和扩展性。

总之,文件描述符是操作系统管理打开的文件和其他资源的一种基本方式,它在系统级编程中扮演着重要的角色。通过文件描述符,操作系统能够有效地控制对文件和其他I/O资源的访问。

image-20240420211211116
FILE*和文件描述符区别

FILE* 和文件描述符都是用于文件操作的概念,但它们来自不同的编程接口,并且在使用上有明显的区别。这两者在 C 语言和 Unix-like 系统中非常常见。

文件描述符

文件描述符是 Unix 和 Unix-like 系统(包括 Linux 和 macOS)中用于文件操作的低级别表示。它是一个小的整数值,用于代表一个打开的文件、管道或网络连接。文件描述符由操作系统内核管理,并且是 POSIX 编程接口的一部分。

  • 操作:使用文件描述符的函数主要包括 open(), read(), write(), close() 等系统调用。
  • 性质:它们提供了对文件操作的基本控制,例如,直接读写数据,但没有内置的缓冲机制。
  • 用例:文件描述符通常用于需要更细粒度控制的场景,比如网络编程和并发服务器的实现。

FILE*

FILE* 是 C 标准库中定义的一个数据类型,是一个指向 FILE 结构的指针,用于表示打开的文件流。FILE 结构体封装了文件操作的很多细节,包括缓冲、位置指示器等。

  • 操作:与 FILE* 相关的函数包括 fopen(), fprintf(), fscanf(), fgets(), fputs(), fclose() 等。
  • 性质FILE* 提供了缓冲机制,这意味着对文件的读写操作可能不会立即执行,而是在缓冲区填满或刷新缓冲区时执行,这可以提高文件操作的效率。
  • 用例FILE* 适用于需要标准化文件操作和自动缓冲的场景,常见于普通的文件处理和数据输出。

主要区别

  1. 接口层级FILE* 是一个高级抽象,提供了缓冲机制和多种便利的文件操作函数;文件描述符则是较低级的接口,提供了更直接的文件控制方法。
  2. 使用环境FILE* 主要用于标准C库中,跨平台性好,而文件描述符更多地与 Unix-like 系统的底层操作关联。
  3. 性能和控制:文件描述符提供了更底层的控制,可能更适合性能敏感或需要精细操作控制的应用;而 FILE* 的缓冲机制适合大多数通用程序,可以简化开发并提高效率。
  4. 语言和标准FILE* 符合 ISO C 标准,而文件描述符则是 POSIX 标凈的一部分。

根据你的应用需求,你可以选择适合的接口进行文件操作。如果你在写跨平台的程序,可能会更倾向于使用 FILE*;如果你需要进行底层的系统编程,可能会选择文件描述符。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/1202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux内核之内核通知文件系统创建的路径:fsnotify_create用法实例(五十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【图解计算机网络】从浏览器地址输入到网页显示的整个过程

从浏览器地址输入到网页显示的整个过程 整体流程DHCPhttp协议报文组装DNSTCP协议封装与TCP三次握手IP协议封装与路由表MAC地址与ARP协议交换机路由器 整体流程 从往浏览器输入一个地址到网页的显示&#xff0c;要经过很长的一个流程&#xff0c;中间涉及到计算机网络的许多知识…

*Linux系统的进程和计划任务管理

目录 一、查看进程 1、程序和进程的关系 *2、ps查看静态进程信息 1&#xff09;ps aux 2&#xff09;ps -elf *3、top查看动态进程信息 4、pgrep查看进程信息 5、pstree查看进程树 二、控制进程 1、进程启动方式 2、进程的前后台调度 3、终止进程的运行 三、计划任…

React【Day4】

路由快速上手 1. 什么是前端路由 一个路径 path 对应一个组件 component 当我们在浏览器中访问一个 path 的时候&#xff0c;path 对应的组件会在页面中进行渲染 2. 创建路由开发环境 # 使用CRA创建项目 npm create-react-app react-router-pro# 安装最新的ReactRouter包 …

Git TortoiseGit 安装使用详细教程

前言 Git 是一个免费的开源分布式版本控制系统&#xff0c;是用来保存工程源代码历史状态的命令行工具&#xff0c;旨在处理从小型到非常大型的项目&#xff0c;速度快、效率高。《请查阅Git详细说明》。TortoiseGit 是 Git 的 Windows Shell 界面工具&#xff0c;基于 Tortoi…

第 2 章:FFmpeg简介

2.1 历史 历史 一些相关术语介绍&#xff1a; 容器&#xff08;Container&#xff09;格式&#xff1a;一种文件封装格式&#xff0c;里边主要包含了流&#xff0c;一般会使用一个特定的后缀名标识&#xff0c;例如.mov、.avi、.wav等。流 &#xff08;Stream&#xff09;&am…

政安晨:【Keras机器学习示例演绎】(五)—— 利用视觉变换器进行物体检测

目录 导言 导入和设置 准备数据集 实施多层感知器&#xff08;MLP&#xff09; 实施补丁创建层 显示输入图像的补丁 实施补丁编码层 构建 ViT 模型 运行实验 评估模型 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与…

第二届 Oceanbase 开发者大会 实录

第二届 Oceanbase 开发者大会 实录 今天很有幸参加了Oceanbase 开发者大会&#xff0c;我是真的我一开始还不知道什么是Oceanbase &#xff0c;直到我开了会才知道。看来真的需要多参加一些这样活动。 会议议程 我们科普一下什么是Oceanbase OceanBase 是阿里巴巴集团推出…

如何进行数据库的迁移与同步——【DBA 从入门到实践】第四期

在日常的数据库运维工作中&#xff0c;我们时常会面临数据库替换、机房搬迁、业务测试以及数据库升级等任务&#xff0c;这些任务都需要对数据进行迁移和同步操作。【DBA 从入门到实践】第4期&#xff0c;将引导大家深入了解数据库迁移的流程&#xff0c;并探讨在迁移过程中可用…

AJAX——图书管理案例

1.渲染列表 自己的图书数据&#xff1a;给自己起个外号&#xff0c;并告诉服务器&#xff0c;默认会有三本书&#xff0c;基于这三本书做数据的增删改查。 // 目标1&#xff1a;渲染图书列表 // 1.1 获取数据 // 1.2 渲染数据const creator 哈哈 // 封装-获取并渲染图书列表函…

《QT实用小工具·二十八》基于qt开发的各种曲线

1、概述 源码放在文章末尾 该项目实现了各种曲线的绘制&#xff0c;下面是项目的demo演示&#xff1a; 项目部分代码如下&#xff1a; #include "frmsmoothcurve.h" #include "ui_frmsmoothcurve.h" #include "smoothcurve.h" #include "…

cocos creator 3.6 发布web手机端 加载进度条添加

cocos creator 升级到3.x之后加载进度条取消了&#xff0c;测试了多个3.x版本最终以creator 3.6.3版本&#xff0c;构建了简单的进度加载 参考链接&#xff1a; https://forum.cocos.org/t/topic/137113 打包web-mobile后&#xff0c;没有进度条。加载的时候只显示一个黑屏。…

【小程序】IOS wx小程序解压获取源文件

根据自己手机的系统&#xff0c;获取wx小程序的缓存目录 一、微信小程序文件存放路径 安卓&#xff1a; /data/data/com.tencent.mm/MicroMsg/{{user哈希值}}/appbrand/pkg/iOS越狱&#xff1a; /User/Containers/Data/Application/{{系统UUID}}/Library/WechatPrivate/{{user…

1.为什么选择Vue框架

参考&#xff1a;百战程序员 为什么选择Vue框架 Vue是什么&#xff1f; 渐进式 JavaScript 框架&#xff0c;易学易用&#xff0c;性能出色&#xff0c;适用场景丰富的 Web 前端框架 为什么要学习Vue Vue是目前前端最火的框架之一Vue是目前企业技术栈中要求的知识点Vue可以…

HarmonyOS 状态管理

在声明式 UI 框架中&#xff0c;数据的改变触发 UI 的重新渲染。在 ArkUI 中不是所有数据的变化都会触发 UI 重新渲染&#xff0c;只有 状态变量 才会引起 UI 重新渲染。 状态变量 状态变量&#xff1a; 指被状态装饰器装饰的变量&#xff0c;只有这种变量的改变才会引起 UI …

【leetcode面试经典150题】63. 删除链表的倒数第 N 个结点(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

软考141-上午题-【软件工程】-杂题+小结

一、杂题 真题1&#xff1a; 真题2&#xff1a; 真题3&#xff1a; 真题4&#xff1a; 真题5&#xff1a; 真题6&#xff1a; 真题7&#xff1a; 真题8&#xff1a; 真题9&#xff1a; 真题10&#xff1a; 真题11&#xff1a; 真题12&#xff1a; 真题13&#xff1a; 真题14&a…

paddlepaddle-gpu安装

背景 之前安装paddlepaddle-gpu遇到各种问题&#xff0c;安装不成功&#xff0c;之前使用了wsldocker的方式&#xff0c;可查看我之前博客&#xff1a;记录paddlepaddle-gpu安装&#xff0c;这要会导致我整个开发流程比较割裂 cuda版本 强烈推荐cuda11.8&#xff0c;paddlep…

SpringBoot项目错误:找不到主类(解决办法)

清理和重新编译项目即可&#xff0c;在项目中点击右键Maven-Reload project&#xff0c;之后再重新运行就行了

蓝桥杯第十五界软件测试线下省赛题目分析及解决

PS 需要第十五界蓝桥杯被测系统或者功能测试模板、单元测试被测代码、自动化测试被测代码请加&#x1f427;:1940787338 备注&#xff1a;15界蓝桥杯省赛软件测试 题目1&#xff1a;功能测试 题目描述 ​ 某物流公司的货运收费标准根据重量、距离和节假日三个因素来确定。如…