【C语言】文件I/O的不同方式:文件描述符fd和FILE *

C语言中的文件I/O 在Linux系统中,当我们打开或创建一个文件(或套接字)时,操作系统会提供一个文件描述符(File Descriptor,FD),这是一个非负整数,我们可以通过它来进行读写等操作。然而,文件描述符本身只是操作系统为应用程序操作底层资源(如文件、套接字等)所提供的一个引用或“句柄”。在Linux中,文件描述符0、1、2是有特殊含义的。0是标准输入(stdin)的文件描述符。1是标准输出(stdout)的文件描述符。2是标准错误(stderr)的文件描述符。 阅读详情

fd(文件描述符)和 FILE *(文件指针)是 C 语言中用于处理文件 I/O 的两种不同机制,分别属于 低层系统调用接口 和 标准库函数接口。它们在使用方式、功能特性和适用场景上有明显区别。


📌 一、基本概念对比

特性fd(文件描述符)FILE *(文件指针)
类型int 类型整数FILE * 指针类型
所属接口POSIX 系统调用(如 Linux/Unix)ANSI C 标准库(stdio.h)
示例函数open(), read(), write(), close()fopen(), fread(), fwrite(), fclose()
缓冲机制无缓冲(直接系统调用)有缓冲(性能更好)

1.1 缓冲机制的作用

  • FILE * 的缓冲:C 标准库中的 FILE * 提供了用户空间的缓冲区。当你使用像 fread() 或 fwrite() 这样的函数读写数据时,数据首先被存储到这个缓冲区中。只有当缓冲区满、执行 fflush() 操作、或关闭文件时,这些数据才会一次性地传输到内核空间并最终写入磁盘或其他设备。这种方式减少了实际 I/O 操作的次数,从而提高了效率。

  • fd 的无缓冲:直接使用系统调用如 read() 和 write() 对应的是文件描述符 fd。每次调用都会导致一次从用户空间到内核空间的切换,并且每次调用都可能产生一次实际的 I/O 操作。这种模式下没有额外的用户空间缓冲,所以对于小块数据的频繁读写来说,可能会更慢,因为每次操作都有固定的开销。

1.2 示例说明

假设你需要写入一条日志信息到文件:

  • 使用 fd:

    write(fd, "Log message\n", strlen("Log message\n"));
    

    每次调用 write() 都会产生一次系统调用,这对于频繁的日志记录来说开销较大。

  • 使用 FILE *:

    fprintf(fp, "Log message\n");
    

    数据首先会被写入用户空间的缓冲区,只有在缓冲区满了或者显式调用 fflush(fp) 时,才会真正触发一次系统调用。这样可以在不影响功能的前提下,大幅减少系统调用的频率。

🧱 二、核心区别详解

1. 抽象层级不同

  • fd 是操作系统层面的 底层接口,直接操作内核提供的文件描述符。
  • FILE * 是 C 标准库对 fd 的封装,提供了更高层次的抽象和缓冲机制。

2. 跨平台性

  • fd:主要用于 Unix/Linux 系统,在 Windows 上不兼容。
  • FILE *:跨平台支持好(Windows、Linux、Mac 都支持),推荐用于可移植代码。

3. 缓冲机制

  • fd:没有缓冲,每次读写都直接访问磁盘或设备,效率较低。
  • FILE *:自带缓冲区,减少实际 I/O 操作次数,提高性能。

4. 功能丰富性

  • FILE * 支持格式化输入输出(如 fprintf, fscanf),而 fd 不支持,只能处理原始字节流。

🛠️ 三、常见函数对照表

操作fd 接口(系统调用)FILE * 接口(标准库)
打开文件open("file.txt", O_RDONLY)fopen("file.txt", "r")
读取数据read(fd, buf, size)fread(buf, 1, size, fp)
写入数据write(fd, buf, size)fwrite(buf, 1, size, fp)
关闭文件close(fd)fclose(fp)
文件定位lseek(fd, offset, SEEK_SET)fseek(fp, offset, SEEK_SET)
获取当前位置lseek(fd, 0, SEEK_CUR)ftell(fp)

🔁 四、如何相互转换?

从 fd 转换为 FILE *

int fd = open("file.txt", O_RDONLY);
FILE *fp = fdopen(fd, "r");  // 成功后可以用标准库函数读写

从 FILE * 转换为 fd

FILE *fp = fopen("file.txt", "r");
int fd = fileno(fp);  // 获取对应的文件描述符

🎯 五、适用场景对比

场景推荐使用
需要高性能、直接控制文件偏移fd
需要格式化读写(如文本日志)FILE *
跨平台开发FILE *
嵌入式系统、驱动开发、网络通信fd
需要缓冲优化性能FILE *

✅ 六、示例对比

使用 fd:

#include <fcntl.h>
#include <unistd.h>

int fd = open("test.txt", O_WRONLY | O_CREAT, 0644);
const char *msg = "Hello, world!\n";
write(fd, msg, strlen(msg));
close(fd);

使用 FILE *:

#include <stdio.h>

FILE *fp = fopen("test.txt", "w");
fprintf(fp, "Hello, world!\n");
fclose(fp);

🧾 总结一句话:

  • fd 是更接近系统的底层接口,适合需要精确控制和高效处理的场景;
  • FILE * 是 C 标准库封装的高层接口,使用简单、功能丰富,适用于大多数应用程序开发;
Linux中文件描述符fd与文件指针FILE*互相转换实例解析 主要介绍了Linux中文件描述符fd与文件指针FILE*互相转换实例解析,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下 立即下载

相关推荐

MPN – 制造商物料编号(延伸)

此外,用户还可以在物料主数据中定义阻止MPN材料的原因,以及在采购订单创建时,是否可以将现有的MPN材料修改为其他MPN材料,从而实现对MPN材料的精细控制和管理。通过使用AMPL,用户可以指定每个MPN材料是否仅能为特定工厂或整个企业所有工厂采购、采购的时间段、是否必须属于特定修订级别、是否只能从特定制造商工厂采购以及是否被阻止及其原因。通过AMPL管理,企业可以规范采购流程,避免使用未经批准的材料,从而提高采购的透明度和效率,同时也为质量控制提供了保障‌。3、QM中的制造商物料。质量信息记录QI01。

yanzibing99的博客 2484

LinuxC语言文件操作之普通文件(fd)和二进制流文件(FILE)之间的转换

一、Linux 的文件操作 一、pandas是什么? 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、使用步骤 1.引入库 代码如下(示例): import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarnings('ignore') import ssl ssl._c

qq1140920745的博客 1663

深入解析STM32定时器中央对齐模式3的双中断机制

本文深入解析了STM32定时器中央对齐模式3的双中断机制。该模式在一个PWM周期内,会在计数器到达ARR(上溢)和0(下溢)时各触发一次更新中断,实现更精细的实时控制。文章详细阐述了其工作原理、配置方法,并指导如何在中断服务函数中通过DIR位区分中断来源,同时探讨了其在电机控制、数字电源等场景下的应用优势与CPU负载挑战。

weixin_29164185的博客 492

linux c fopen open 互相转换 文件指针 到 文件描述符 FILE* 转 FD

FILE*--fileno()--->fd; 实例如下: #include <stdio.h> int main() { FILE *fp = NULL; int i = 0; fp = fopen("test.txt", "w+"); fclose(fp); while(i++<1500) { fp = fopen("test.txt", "a"); // "注意W+对int fd = fileno(fp);的影响" if (fp == NULL) ...

whatday的专栏 1222

FreeSwitch采用mrcp协议对接科大讯飞asr和tts以及对话系统

FreeSwitch采用mrcp协议对接科大讯飞asr和tts对接过程

shanghaimoon的专栏 8839

No Target Connected 错误时的一种情况

STM32的SWD烧录模式No Target Connected 错误的一种情况 STM32的SWD烧录模式No Target Connected 错误时的一种处理情况 这是我第一次烧板子的时候遇到的问题,在给板子download的时候出现了“No Target Connected”的错误,这里讲一种解决方法。不一定适用于全部状况,但是可以作为一种纠错方法。 打开 Options for Target… 1.首先点击Options for Target…这个像魔棒一样的按键打开,会出现这个页面 2.点击

Logan_CodeGou的博客 1万+

FILE *与FD的区别

文章目录 FILE *是文件流操作,目的是为了提高程序的执行效率,相关的接口如:writev、readv,这两个函数可以读写大块数据。 FD是文件描述符,只能读写数据到一块内存中。若通过FD读写不连续的内存块,write、read需要多次调用syscall,这样就增加了额外的系统开销,导致效率并不高;但是,通过文件流的方式,比如writev、readv,即可实现调用一次syscall,可完成多块不连续内存块的读写操作。 ...

qq_38933775的博客 782

保姆级教程:用Docker一键部署vLLM大模型推理服务(附常见报错解决方案)

本文提供了一份详细的Docker化vLLM大模型推理服务部署指南,涵盖从环境准备到性能调优的全流程。通过容器化技术解决大语言模型部署中的显存利用率、吞吐量等核心问题,并附常见报错解决方案,帮助开发者快速构建高效、可扩展的AI推理服务。

weixin_29248313的博客 490

文件指针FILE*及文件描述符fd

文件指针 在C语言中,通过文件指针可以对文件进行相应的操作,定义说明文件指针的一般形式为:FILE *指针变量标识符。 FILE实际是由系统定义的一个结构体,它包含的字段有文件描述符和缓冲区等。 通常程序运行后会打开:stdin--文件输入流,stdout--文件输出流,stderr--文件错误流,它们对应了键盘、显示器、显示器,它们的类型都为FILE*。   由于fwrite,prin

hm108106的博客 2312

LangFlow开源神器:拖拽构建AI Agent与MCP协议集成实战

LangFlow 15万星开源神器:拖拽搭建 AI Agent,一键部署 API / MCP / JSON 在AI应用开发领域,传统编码方式往往需要处理复杂的API调用、数据处理和流程编排,这让很多开发者望而却步。LangFlow作为GitHub上获得15万星的开源项目,通过可视化拖拽的方式彻底改变了AI Agent的开发体验。本文将完整介绍如何使用LangFlow快速构建功能强大的AI Agent,并实现API、MCP协议和JSON配置的一键部署。 1. LangFlow与AI Agent核心概念解析 1

weixin_33717117的博客 932

上位机介绍:C# 开发者的必知基础

上位机是指在工业控制系统中,位于上层、负责人机交互和数据管理的计算机/软件,与“下位机”(PLC、传感器、变频器、单片机等硬件设备)相对应,核心是“向下通信控制设备,向上展示交互数据”。下位机:一线干活的“工人”(执行采集、控制指令);上位机:指挥管理的“办公室人员”(发指令、看数据、做报表)。C#开发者掌握上位机开发的核心是“通信+UI+稳定性基础层:搞懂WinForms/WPF基础、串口/Modbus通信,能实现核心功能;进阶层:掌握分层设计、异步编程、工业级容错(断线重连、数据校验);

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1558

Linux文件描述符与FILE指针互相转换

在Linux中,文件描述符(file descriptor, fd)和FILE指针(也称为文件流指针,FILE pointer)是两种常见的文件操作接口。文件描述符是一个整数,通过系统调用直接操作文件,而FILE指针是通过C标准库函数操作文件。

不脱发的程序猿 735

国产麒麟V10系统命令大全,100个实用命令助你玩转系统!

国产麒麟V10系统命令大全,100个实用命令助你玩转系统!

网络技术联盟站 1906

文件I/O和标准I/O的区别

一、先来了解下什么是文件I/O和标准I/O: 文件I/O:文件I/O称之为不带缓存的IO(unbuffered I/O)。不带缓存指的是每个read,write都调用内核中的一个系统调用。也就是一般所说的低级I/O——操作系统提供的基本IO服务,与os绑定,特定于linix或unix平台。 标准I/O:标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件

知秋一叶 1万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Linux下 文件描述符(fd)与 文件指针(FILE*)

一、文件描述符(fd)我们都知道在Linux下一切皆文件。当然设备也不例外,如果要对某个设备进行操作,就不得不打开此设备文件,打开文件就会获得该文件的文件描述符fd( file discriptor), 它就是一个很小的整数,每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。 图中文件描述符

MaHua的博客 2万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Linux -- I/O接口,文件标识符fd、file结构体、缓冲区、重定向、简单封装C文件接口

文件相关

大学在读,感谢关注 1233

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【linux基础I/O(一)】文件描述符的本质&重定向的本质

本篇文章主要讲解了IO的系统调用接口, 文件描述符的本质, 重定向的本质与重定向的系统调用,内附代码和图文讲解,看完就能学会

杭电码农-NEO的博客 2696

理解文件描述符(fd)与 文件指针(FILE*),及二者的区别

所有对设备和文件的操作都是使用文件描述符来进行的。 文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程所打开的文件的记录表:当打开一个现存文件或创建一个新文件时,内核就向进程返回一个文件描述符;当需要读写文件时,需要把文件描述符作为参数传递给相应的函数。 通常,一个进程启动时,都会打开3个文件: 标准输入:对应文件描述符为0(STDIN_FILENO) 标准输出:对应文件描...

weixin_42904113的博客 2164

FILE* 和文件描述符及其相互转换【系统编程】

开始之前先来介绍使用系统接口open来打开一个文件的流程:open -> 从PCB也就是task_struct中找到files指针 -> file指针指向结构体files_struct -> files_struct中有一个重要的部分是fd_array[]数组,里面包含一个file指针 -> 通过这个file指针就可以指向一个file结构体 -> 这个file结构体中含有文件的所以信息,于是就找到了相应的文件。,当使用FILE是就能通过文件描述符找到底层的file结构体,获取文件信息。

tang20030306的博客 1352

【Linux的文件篇章 - 文件I/O和文件描述符】

Linux学习笔记011 --- 文件I/O、文件描述符、位图、重定向等知识

m0_69455439的博客 998

【Linux基础I/O】文件描述符及重定向

这篇文章只讲解了Linux的I/O的一半的内容,后面我们还要了解Linux的文件系统和动静态库和缓冲区的问题,希望大家可以继续关注。

weixin_64906519的博客 2088

【C 语言】征服文件 I/O:透视数据流、FILE* 核心机制与高效实践全指南

本文深度剖析 C 语言文件操作核心机制,实现数据的持久化存储。 首先阐述了文件流 (Stream) 这一数据管道概念,以及FILE* 作为流的控制阀门的结构与职责。全面覆盖所有 I/O 方式:包括字符/行操作(fgetc/fputs)、格式化 I/O(fprintf/fscanf)以及随机读写(fseek/ftell)等实用技术。重点揭示了文件缓冲区提高 I/O 效率的工作原理与管理方法,并以详尽案例纠正了 feof 和 ferror 的常见误用。

Marathon_X的博客 1510

逐层深入:从 fopen 到文件描述符,透彻理解基础 I/O

本文深入探讨了不同编程语言对文件操作进行封装的原因及其底层实现。文章从C语言的fopen等标准库函数出发,揭示其背后的Linux系统调用如open和read的裸接口,解释了文件描述符、权限控制(umask)等核心概念。通过分析内核数据结构(如task_struct和file),展示了文件描述符如何在内核中管理。最终指出封装的目的在于提供跨平台兼容性、用户态缓冲及更高级的抽象,从而提升开发效率并隐藏底层复杂性。全文以技术深度解析了文件操作从用户态到内核态的完整链路。

2501_91839423的博客 945

[Linux]文件/文件描述符fd

文件=内容+属性操作系统提供系统调用接口进程:打开的文件 = 1 : n操作系统来做操作系统在运行时,可能会打开很多文件,那么,操作系统该如何对文件进行管理呢?文件的属性与文件内容一样,在磁盘中同样有保存。我们使用对这些对象进行管理。那么,对于文件的管理,就转换成了对链表的增删查改。被打开的文件在内存中,未被打开的文件在磁盘中。所有的文件操作,都是在内存中操作的。因此,研究文件操作的本质就是研究进程和被打开文件的关系。

m0_71071692的博客 1196

Linux 文件操作 与 文件描述符fd

其实就是一个小整数那么我们知道问及那描述符是一个从0开始的小整数,当我们打开文件时,操作系统在内存中要为文件创建对应的数据结构来描述目标文件,就有了file结构体,而表示文件是否被进程打开,就要把进程和文件关联起来,每个进程都有一个指针files,专门指向一张表files_struct 那么这张表最重要的就是包含一个指针数组,每个元素都是一个只想打开文件的指针,所以文件描述符的本质是数组的下标。

subenhao的博客 1086

嵌入式Linux:文件I/O和标准I/O库

文件 I/O (Input/Output)和标准 I/O 库是用于在 C 语言中进行文件操作的两种不同的方法。

不脱发的程序猿 1191
上一篇: 数据如何在各种网络硬件设备中流转
下一篇: 【Linux基础】系统 I/O 函数:open read write lseek等函数原型、参数说明以及返回值描述
思路可以啊
博客等级 码龄6年 91粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值