Linux:一切皆文件

news2025/1/30 12:34:41

**文件描述符**:它是一种特殊的索引,本质上是进程中`file_struct`结构体成员`fd_array`数组的下标。在Linux等系统中,文件描述符是一个非负整数,用于标识打开的文件,是内核为了高效管理已被打开的文件所创建的索引。通过文件描述符,进程可以对相应文件进行读写等操作。
- **文件打开模式**:分为主模式和副模式。
    - **主模式**:
        - `O_RDONLY`:以只读模式打开文件,即只能从文件中读取数据,不能进行写入操作。
        - `O_WRONLY`:以只写模式打开文件,只能向文件写入数据,无法读取。
        - `O_RDWR`:以读写模式打开文件,既可以读取数据也可以写入数据。
    - **副模式**:
        - `O_CREAT`:当指定文件不存在时,会自动创建该文件。
        - `O_APPEND`:追加模式,写入数据时会将数据添加到文件末尾,而不是覆盖原有内容。
        - `O_DIRECT`:直接I/O模式,绕过系统缓存,数据直接在用户空间和磁盘之间传输,通常用于对I/O性能有较高要求的场景。
        - `O_SYNC`:同步模式,保证每次写入操作都将数据同步到磁盘,确保数据的持久性,但可能会降低写入性能。
        - `O_NONBLOCK`:非阻塞模式,在进行I/O操作时,不会使进程阻塞等待,而是立即返回,常用于需要同时处理多个I/O操作的场景。

系统I/O编程

另外一个当然是标准I/O编程。这个后面再说。

(Linux 文件体系结构) 

  • open
  • write
  • read
  • Iseek
  • close
  • 伪代码示例:
    • int fd;
    • fd = open(filename, flags, mode);
    • lseek(fd, offset, whence)
    • write(fd, buf, write_len);
    • read(fd, buf, readlen);
    • close(fd);
  • 文件描述符:一个特殊的索引,用于标识被打开的文件或其他输入/输出资源。
  • 进程:是计算机中已运行的程序实例。

open/close函数

// OPEN函数所需的头文件
#include <sys/types.h>
#include <sys/stat.h>  
#include <fcntl.h>

// OPEN函数原型
// 当文件存在时
int open(const char* pathname, int flags);

// 当文件不存在,需要创建文件时
int open(const char* pathname, int flags, int perms);

// 返回值
// 成功:返回文件描述符(一个非负整数)
// 失败:返回-1
// CLOSE函数所需的头文件
#include <unistd.h>

 完整例子:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h> 

int main() {
    int fd; // 声明文件描述符变量
    fd = open("./a.txt", O_RDONLY); // 以只读方式打开文件
    if (fd < 0) { // 如果打开文件失败
        printf("open error!!\n"); // 输出错误信息
    } else {
        
        // 这里可以添加代码来读取文件内容或进行其他操作
    }
    
    // 如果需要在文件打开成功后输出空行,可以在else分支中添加printf("\n");
    close(fd)
    return 0; // 程序正常结束
}

read和write函数

一、函数定义

  1. read函数
    • 功能:从文件描述符指向的文件中读取数据。
    • 原型ssize_t read(int fd, void *buf, size_t count);
    • 参数
      • fd:文件描述符,标识要读取的文件。
      • buf:指向存储读取数据的缓冲区的指针。
      • count:要读取的字节数。
    • 返回值:成功时返回读取的字节数(可能小于count),失败时返回-1。
  2. write函数
    • 功能:向文件描述符指向的文件中写入数据。
    • 原型ssize_t write(int fd, const void *buf, size_t count);
    • 参数
      • fd:文件描述符,标识要写入的文件。
      • buf:指向包含要写入数据的缓冲区的指针。
      • count:要写入的字节数。
    • 返回值:成功时返回写入的字节数(可能小于count),失败时返回-1。

二、使用方法

  • 在使用read和write函数之前,需要打开文件并获得文件描述符。
  • 调用read函数时,应确保缓冲区足够大以存储读取的数据。
  • 调用write函数时,应确保缓冲区中的数据是要写入文件的正确数据。
  • 读取或写入操作完成后,应检查返回值以确定操作是否成功。

三、注意事项

  • 当读取或写入的数据量较大时,可能需要多次调用read或write函数。
  • 在读取或写入过程中,如果遇到错误(如文件结束、磁盘满等),read或write函数将返回-1,并设置errno以指示错误类型。
  • 在使用完文件后,应关闭文件描述符以释放资源。

复制普通文件实验步骤

  1. 打开要复制的文件
    • 使用适当的文件打开函数或方法,以只读模式打开源文件。
  2. 创建新的文件
    • 使用适当的文件创建函数或方法,以写模式创建一个新的目标文件。如果文件已存在,可以选择覆盖或报错。
  3. 把源文件内容读到缓冲区,把缓冲区内容写入新文件
    • 分配一个缓冲区来存储从源文件中读取的数据。
    • 使用文件读取函数或方法,从源文件中读取数据到缓冲区。
    • 使用文件写入函数或方法,将缓冲区中的数据写入到目标文件中。
  4. 循环执行第三步,直到读取的字节数量为0,退出循环
    • 重复执行第三步,直到文件读取函数或方法返回0,表示已经到达源文件末尾,没有更多的数据可以读取。
  5. 关闭打开的文件
    • 使用文件关闭函数或方法,关闭源文件和目标文件,释放资源。

代码:

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

#define BUFFER_SIZE 512

int main(int argc, char *argv[]) {
    int fd1, fd2;
    ssize_t read_size;
    char buffer[BUFFER_SIZE];

    // 检查命令行参数数量
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <source_file> <destination_file>\n", argv[0]);
        return EXIT_FAILURE;
    }

    // 打开源文件(只读)
    fd1 = open(argv[1], O_RDONLY);
    if (fd1 == -1) {
        perror("Error opening source file");
        return EXIT_FAILURE;
    }

    // 打开目标文件(写,如果文件不存在则创建)
    fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd2 == -1) {
        perror("Error opening destination file");
        close(fd1);
        return EXIT_FAILURE;
    }

    // 从源文件读取数据并写入目标文件
    while ((read_size = read(fd1, buffer, BUFFER_SIZE)) > 0) {
        if (write(fd2, buffer, read_size) != read_size) {
            perror("Error writing to destination file");
            close(fd1);
            close(fd2);
            return EXIT_FAILURE;
        }
    }

    // 检查read函数是否因为错误而返回-1
    if (read_size == -1) {
        perror("Error reading from source file");
    }

    // 关闭文件描述符
    close(fd1);
    close(fd2);

    return EXIT_SUCCESS;
}

标准I/O :

 

### C标准库实现了一个I/O缓存区
C标准库为了提高文件输入输出操作的效率,实现了一个I/O缓存区。在对文件进行读写操作时,数据不会立即写入磁盘或从磁盘读取,而是先在缓存区中进行处理。比如进行多次写入操作时,数据先存放在缓存区,等缓存区满或调用特定函数时才真正写入磁盘,这减少了磁盘I/O的次数,从而提升了性能。

### 常见标准I/O函数
- **fopen**:用于打开一个文件,返回一个指向文件的指针(`FILE*`类型),它需要指定文件名和打开模式(如"r" 只读、"w" 只写、"a" 追加等)。例如 `FILE *fp = fopen("test.txt", "r");` 尝试以只读模式打开名为"test.txt"的文件。
- **fclose**:用于关闭一个已打开的文件,它接受一个文件指针作为参数,在文件操作完成后应及时调用该函数关闭文件,释放相关资源,如 `fclose(fp);`。
- **fread**:从文件流中读取数据到指定的内存区域。它接受目标内存地址、每个数据项的大小、数据项的数量以及文件指针作为参数,返回实际读取的数据项数量。例如 `size_t count = fread(buffer, sizeof(char), 100, fp);` 尝试从文件指针 `fp` 指向的文件中读取100个字符到 `buffer` 中。
- **fwrite**:将数据从指定的内存区域写入到文件流中。参数与 `fread` 类似,接受源内存地址、每个数据项的大小、数据项的数量以及文件指针作为参数,返回实际写入的数据项数量。
- **fseek**:用于改变文件流的读写位置指针。它接受文件指针、偏移量以及起始位置(如 `SEEK_SET` 从文件开头、`SEEK_CUR` 从当前位置、`SEEK_END` 从文件末尾)作为参数。例如 `fseek(fp, 0, SEEK_END);` 将文件指针移动到文件末尾。
- **fflush**:强制把I/O缓存区中的数据写入到页缓存区。当需要确保数据及时写入文件时,可调用此函数,比如在一些日志记录场景中,希望数据尽快落盘就可以使用 `fflush` 。 

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

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

相关文章

【物联网】ARM核常用指令(详解):数据传送、计算、位运算、比较、跳转、内存访问、CPSR/SPSR、流水线及伪指令

文章目录 指令格式&#xff08;重点&#xff09;1. 立即数2. 寄存器位移 一、数据传送指令1. MOV指令2. MVN指令3. LDR指令 二、数据计算指令1. ADD指令1. SUB指令1. MUL指令 三、位运算指令1. AND指令2. ORR指令3. EOR指令4. BIC指令 四、比较指令五、跳转指令1. B/BL指令2. l…

项目集成Nacos

文章目录 1.环境搭建1.创建模块 sunrays-common-cloud-nacos-starter2.目录结构3.pom.xml4.自动配置1.NacosAutoConfiguration.java2.spring.factories 5.引入cloud模块通用依赖 2.测试1.创建模块 sunrays-common-cloud-nacos-starter-demo2.目录结构3.pom.xml4.application.ym…

QT交叉编译环境搭建(Cmake和qmake)

介绍一共有两种方法&#xff08;基于qmake和cmake&#xff09;&#xff1a; 1.直接调用虚拟机中的交叉编译工具编译 2.在QT中新建编译套件kits camke和qmake的区别&#xff1a;CMake 和 qmake 都是自动化构建工具&#xff0c;用于简化构建过程&#xff0c;管理编译设置&…

[cg] 使用snapgragon 对UE5.3抓帧

最近想要抓opengl 的api&#xff0c;renderdoc在起应用时会闪退&#xff08;具体原因还不知道&#xff09;&#xff0c;试了下snapgraon, 还是可以的 官网需要注册登录后下载&#xff0c;官网路径&#xff1a;Developer | Qualcomm 为了方便贴上已经下载好的exe安装包&#x…

物业巡更系统在现代社区管理中的优势与应用探讨

内容概要 在现代社区管理中&#xff0c;物业巡更系统正逐渐成为一种不可或缺的工具。结合先进的智能技术&#xff0c;这些系统能够有效地提升社区管理的各个方面&#xff0c;尤其是在巡检效率和信息透明度方面。通过实时记录巡检数据&#xff0c;物业管理人员能够确保工作人员…

速通Docker === Docker Compose

目录 Docker Compose 简介 Docker Compose 常用命令 使用 Docker Compose 启动 WordPress 普通启动方式&#xff08;使用 Docker 命令&#xff09; 使用 Docker Compose 启动 Docker Compose 的特性 Docker Compose 简介 Docker Compose 是一个用于定义和运行多容器 Dock…

Spring MVC 综合案例

目录 一. 加法计算器 1. 准备工作 2. 约定前后端交互接口 需求分析 接口定义 3. 服务器端代码 4. 运行测试 二. 用户登录 1. 准备工作 2. 约定前后端交互接口 需求分析 接口定义 (1) 登录界面接口 (2) 首页接口 3. 服务器端代码 4. 运行测试 三. 留言板 1. 准备…

数据分析系列--③RapidMiner算子说明及数据预处理

一、算子说明 1 新建过程 2 算子状态灯 状态灯说明: (1)状态指示灯&#xff1a; 红色:指示灯说明有参数未被设置或输入端口未被连接等问题; 黄色:指示灯说明还未执行算子&#xff0c;不管配置是否基本齐全; 绿色:指示灯说明一切正常&#xff0c;已成功执行算子。 (2)三角…

NLP自然语言处理通识

目录 ELMO 一、ELMo的核心设计理念 1. 静态词向量的局限性 2. 动态上下文嵌入的核心思想 3. 层次化特征提取 1. 双向语言模型&#xff08;BiLM&#xff09; 2. 多层LSTM的层次化表示 三、ELMo的运行过程 1. 预训练阶段 2. 下游任务微调 四、ELMo的突破与局限性 1. 技术突破 2. …

Time Constant | RC 和 RL 电路中的时间常数

注&#xff1a;本文为 “Time Constant” 相关文章合辑。 机翻&#xff0c;未校。 How To Find The Time Constant in RC and RL Circuits June 8, 2024 &#x1f4a1; Key learnings: 关键学习点&#xff1a; Time Constant Definition: The time constant (τ) is define…

无心剑七绝《除夕快乐》

七绝除夕快乐 除旧迎新瑞气扬 夕阳烂漫映红妆 快言美酒佳肴味 乐享天伦福满堂 2025年1月28日 平水韵七阳平韵 无心剑这首七绝以“除夕快乐”为题&#xff0c;巧妙地运用了藏头手法&#xff0c;将“除夕快乐”四字分别嵌入诗的每一句首字&#xff0c;构思精巧&#xff0c;富有新…

Object类(3)

大家好&#xff0c;今天继续给大家介绍一下object类中的方法&#xff0c;那么话不多说&#xff0c;来看。 hashcode()这个方法,帮我们算了一个具体的对象位置,这里面涉及到数据结构,简单认为它是个内存地址,然后调用Integer.toHexString ()将这个地址以16进制输出。 该方法是一…

GPU上没程序在跑但是显存被占用

原因&#xff1a;存在僵尸线程&#xff0c;运行完但是没有释放内存 查看僵尸线程 fuser -v /dev/nvidia*关闭僵尸线程 pkill -9 -u 用户名 程序名 举例&#xff1a;pkill -9 -u grs python参考&#xff1a;https://blog.csdn.net/qq_40206371/article/details/143798866

2007-2020年各省国内专利申请授权量数据

2007-2020年各省国内专利申请授权量数据 1、时间&#xff1a;2007-2020年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区名称、年份、国内专利申请授权量(项) 4、范围&#xff1a;31省 5、指标解释&#xff1a;专利是专利权的简称&…

python:洛伦兹变换

洛伦兹变换&#xff08;Lorentz transformations&#xff09;是相对论中的一个重要概念&#xff0c;特别是在讨论时空的变换时非常重要。在四维时空的背景下&#xff0c;洛伦兹变换描述了在不同惯性参考系之间如何变换时间和空间坐标。在狭义相对论中&#xff0c;洛伦兹变换通常…

电路研究9.2.3——合宙Air780EP中FTP——FTPGET 命令使用方法研究

怎么说呢&#xff0c;之前也是看的&#xff0c;但是也很迷茫&#xff0c;感觉上虽然是对的&#xff0c;但是无法联系到应用里面&#xff0c;今天研究一下FTP 命令使用方法吧。 15.29 使用方法举例 这里发现下面那些看的不懂呢&#xff0c;于是就返回FTP的应用了。 9.5.4 FTP 应…

ANSYS学习笔记(十)网格质量的诊断和提高

网格质量的好坏不能单纯只看meshing给出的网格质量结果&#xff0c;要根据实际的计算物理场景来判断&#xff0c;需要求解的地方物理量大梯度的位置网格越密越好。 网格质量&#xff1a;在有限网格数量限制下&#xff0c;离散误差小的网格是好网格&#xff0c;是高质量网格。网…

2024收尾工作

目录 开场白 栈与队列 LeetCode232. 用栈实现队列 LeetCode225. 用队列实现栈 LeetCode102. 二叉树的层序遍历 LeetCode103. 二叉树的锯齿形层序遍历 堆&#xff08;优先级队列&#xff09; 堆排序 LeetCode215. 数组中的第 k 个最大元素 总结 开场白 今天是除夕&…

搭建Spring Boot开发环境

JDK&#xff08;1.8及以上版本&#xff09; Apache Maven 3.6.0 修改settings.xml 设置本地仓库位置 <localRepository>D:/repository</localRepository> 设置远程仓库镜像 <mirror><id>alimaven</id><name>aliyun maven</name&…

jmeter中对接口进行循环请求后获取相应数据

1、工作中遇到一个场景就是对某个单一接口进行循环请求&#xff0c;并需要获取每次请求后返回的相应数据&#xff1b; 2、首先就在jmeter对接口相关组件进行配置&#xff0c;需要组件有&#xff1a;循环控制器、CSV数据文件设置、计数器、访问接口、HTTP信息头管理器、正则表达…