Linux系统文件的基础IO

news2024/11/18 7:46:58

目录

一、C语言的文件IO操作

二、系统调用的文件IO操作

1.open打开文件

2.close关闭文件

3.write写入文件

4.read读取文件

三、文件描述符

四、文件描述符的分配规则

五、终端文件

六、C语言中的文件IO对比系统调用文件IO


文件I/O(Input/Output,输入/输出)是指计算机程序与文件系统之间的数据交换过程。

文件I/O通常包括以下几种操作:打开文件、读取文件、写入文件、关闭文件、文件定位、文件错误处理

一、C语言的文件IO操作

以w方式打开文件会默认清空文件再写入,以a方式打开文件会在文件末尾追加写入

#include <stdio.h>
#include <string.h>
int main() {
    FILE* fp = fopen("log.txt", "w"); // 打开log.txt文件,不存在就创建
    if (fp == NULL) {
        perror("fopen"); // perror函数会自动根据错误码报告错误
        return 1;
    } else {
        const char* msg = "hello world\n";
        fwrite(msg, strlen(msg), 1, fp);                                                                                                      
    }
    fclose(fp);
    return 0;
}

二、系统调用的文件IO操作

1.open打开文件

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

pathname:要打开或创建的文件名

flags:打开文件的参数选项,用或运算使用多个选项(包含在头文件<fcntl.h>中)

O_RDONLY: 只读打开

O_WRONLY: 只写打开

O_RDWR : 读,写打开

(以上三个常量,必须指定一个且只能指定一个)

O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限

O_APPEND: 追加写

O_TRUNC:如果文件已存在且成功打开,则将文件长度截断至0(清空文件再写入,如果不带 O_TRUNC选项,文件将被打开但不会自动被截断。这意味着,如果文件已经存在,它的内容不会被清空,文件指针会放在文件的开始位置,接下来的写操作会从文件的开始处覆盖现有数据。)

mode:权限位,要考虑umask权限掩码的存在

返回值:打开成功返回文件描述符,打开失败返回-1

第一个open指令通常用于打开已经存在的文件,第二个open通常用于打开并创建不存在的文件(如果使用第一个open指令打开并创建不存在的文件,该文件的权限将会是乱码)

2.close关闭文件

int close(int fd);

fd:文件描述符

返回值:关闭成功返回0,关闭失败返回-1并可以设置全局变量errno指示错误原因

3.write写入文件

ssize_t write(int fd, const void *buf, size_t count);

fd:文件描述符

buf:要写入数据的缓冲区指针

count:写入数据的字节数

返回值:ssize_t是有符号整型数,写入成功返回写入字节数,写入失败返回-1并可以设置全局变量errno指示错误原因

4.read读取文件

ssize_t read(int fd, void *buf, size_t count);

fd:文件描述符

buf:指向缓冲区的指针,用于存储从文件中读取的数据

count:要读取的最大字节数

返回值:读取成功返回读取到的字节数,若读取到文件末尾返回0,读取失败返回-1并可以设置全局变量errno指示错误原因

代码演示:

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

int main() {
    int fd = open("log.txt", O_WRONLY | O_CREAT, 0666); // 只写方式打开log.txt文件,不存在就创建,并设置文件权限为0666
    if (fd == -1) { // 打开文件失败
        perror("open");
        return 1;
    }

    const char* msg = "hello Linux File\n";                                                                                                      
    write(fd, msg, strlen(msg)); // 写入文件
    close(fd); // 关闭文件
    return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main() {
    int fd = open("log.txt", O_RDONLY); // 只读方式打开文件
    if (fd == -1) { // 打开失败
        perror("open");
        return 1;
    }

    char buf[1024]; // 用于存储从文件中读取数据的缓冲区
    ssize_t read_bytes = read(fd, buf, sizeof(buf) - 1);
    if (read_bytes == -1) { // 读取失败
        perror("read");
        close(fd);
        return 1;
    }
    buf[read_bytes] = '\0'; // 确保读取的数据以空字符结尾
    printf("Read from file: %s\n", buf);
    close(fd);
    return 0;
}

三、文件描述符

当进程打开文件时,操作系统要在内存中创建内核数据结构file来描述被打开的文件,该数据结构中有文件属性,文件内核级缓冲区等

描述进程的内核数据结构task_struct中都有一个指向文件描述符表的指针files,该指针指向一张文件描述符表files_struct,文件描述符表中最重要的部分就是一个指针数组,每一个元素就是一个被打开文件的指针file*,而文件描述符fd就是文件在指针数组中的位置下标。

Linux系统中,每个进程都会默认打开三个文件描述符为0、1、2的文件,分别为标准输入、标准输出、标准错误,对应的物理设备一般为键盘、显示器、显示器

所以我们还可以通过如下的方式进行输入输出:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main() {
    char buf[1024];
    ssize_t read_bytes = read(0, buf, sizeof(buf)); // 从键盘中读取数据
    if (read_bytes == -1) 
    {
        perror("read");
        return -1;
    }
    buf[read_bytes] = '\0';
    write(1, buf, strlen(buf)); // 向显示器写入数据
    write(2, buf, strlen(buf)); // 向显示器写入数据
    return 0;
}

四、文件描述符的分配规则

在文件描述符表files_struct的指针数组当中,找到当前没有被使用的 最小的一个下标,作为新的文件描述符。

五、终端文件

创建一个进程,在/proc路径下会有一个与进程pid同名的目录文件来保存进程信息,该目录文件下存在名为fd目录文件,用于存储该进程打开文件的信息

以进程pid为8301的进程为例,在/proc/8301/fd路径下存放着如下信息:链接文件0、1、2分别对应着标准输入、标准输出和标准错误。

这三个文件指向的位置是/dev/pts/1,查看路径/dev/pts发现其中有三个文件属性以c开头的字符设备文件。上述进程默认打开的0、1、2文件指向的就是名为1的字符设备文件。

其实该目录下存放的就是终端文件,终端设备名为0,1的文件,名为ptmx用于创建伪终端主设备和从设备对的特殊文件。

终端文件其实就是Linux系统的终端,我们可以同时打开多个终端,/dev/pts同时也会多出相应的终端文件。既然终端也是一个文件,那么我们就可以从一个终端向另一个终端进行输入

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main()
{   
    //当前终端为1
    int fd = open("/dev/pts/3", O_WRONLY | O_APPEND);//向终端3中输入
    if (fd == -1)
    {
        perror("open");
        return 1;
    }
    const char* msg = "hello linux file!";
    write(fd, msg, strlen(msg));
    close(fd);
    return 0;
}

总结:当打开Linux系统时,都会由shell进程打开标准输入,标准输出和标准错误对应的终端文件,后续进程只会shell进程已经打开的终端文件,这样就可以让多个进程都在同一终端输入输出 

六、C语言中的文件IO对比系统调用文件IO

C语言中打开文件使用fopen函数,并用FILE*类型接收其返回值。

FILE*是一个指向FILE结构体的指针,该结构体中封装了文件IO的相关的信息,例如文件描述符fd就被封装在其中。因此可以使用FILE*访问文件描述符(C语言中文件描述符叫做_fileno)

#include <stdio.h>
int main()
{
    FILE* fp = fopen("log.txt", "w"); // 以w方式打开文件
    if (fp == NULL)
    {
        perror("fopen");
        return 1;
    }
    printf("fd:%d\n", fp->_fileno); // 查看文件描述符
    fwrite("hello", 1, 5, fp); // 写入文件
    fclose(fp); // 关闭文件
    return 0;
}

C语言程序默认也会打开标准输入stdin、标准输出stdout和标准错误stderr,通过代码查看其对应的文件描述符,发现恰好也是0、1、2

#include <stdio.h>
int main()
{
    printf("stdin->fd:%d\n", stdin->_fileno);
    printf("stdout->fd:%d\n", stdout->_fileno);
    printf("stderr->fd:%d\n", stderr->_fileno);
    return 0;
}

总结,不难发现其实C语言中的文件IO操作斗士队系统调用文件IO操作的封装

为什么要进行封装呢?

因为不同操作系统的系统调用指令不同,在语言层面对其进行封装就可以根据操作系统的不同调用对应的系统调用指令,实现跨平台性 

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

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

相关文章

信安 实验2,3 使用Gpg4win进行数字签名、发送加密电子邮件

我发现了有些人喜欢静静看博客不聊天呐&#xff0c; 但是ta会点赞。 这样的人呢帅气低调有内涵&#xff0c; 美丽大方很优雅。 说的就是你&#xff0c; 不用再怀疑哦 实验2 使用Gpg4win进行数字签名 实验目的 通过实验&#xff0c;让学生掌握使用RSA算法实施数字签名的…

【1米C-SAR卫星】

1米C-SAR卫星 1米C-SAR卫星是我国自主研发的重要遥感卫星&#xff0c;主要用于海洋、陆地等观测任务&#xff0c;具备高分辨率、宽覆盖、多极化、多模式等特点。以下是对1米C-SAR卫星的详细介绍&#xff1a; 一、基本概况 发射时间&#xff1a;首颗1米C-SAR卫星于2021年11月2…

谁能给我一个ai现在无法替代画师的理由?

小白可做&#xff01;全自动AI影视解说一键成片剪辑工具https://docs.qq.com/doc/DYnl6d0FLdHp0V2ll 如何看待现如今的AI绘画 哎呀玫瑰花来了&#xff0c;所有花式都要玩完了。 我相信大家在网上已经看过了太多惊为天人的AI绘画作品&#xff0c;有人抵制&#xff0c;有人支持&a…

PMP--二模--解题--141-150

文章目录 14.敏捷--创建敏捷环境--团队构成--混合项目环境&#xff0c;通常是自组织团队&#xff0c;即团队成员自己决定谁做什么&#xff0c;而不是项目经理决定。易混--常见场景--一个新人加入141、 [单选] 在一个混合项目的执行过程中&#xff0c;不得不更换一个开发人员。新…

【爱给网:登录_注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

JS对不同浏览器的检测问题

Navigator对象也称浏览器对象&#xff0c;该对象包含了浏览器的整体信息&#xff0c;如浏览器名称&#xff0c;版本号等。Navigator对象由Navigator浏览器率先使用&#xff0c;后来各方浏览器都开始支持Navigator对象&#xff0c;逐步成为一种标准。 一、Navigator对象的属性 …

检查索引对象中是否存在缺失值pandas.Index.hasnans

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 检查索引对象中是否存在缺失值 pandas.Index.hasnans [太阳]选择题 题目代码中执行结果是&#xff1f; import pandas as pd import numpy as np idx1 pd.Index([1, 2, np.nan, 4]) print…

破局证券公司结算业务系统信创国产化建设难点,探索实现路径与策略

数字化和国产化是金融IT行业目前的两大趋势。在金融行业&#xff0c;除了数字化以外&#xff0c;国产化也是核心趋势。信创建设从政府办公电脑开始&#xff0c;目的是借助政府的力量培养自主可控生态&#xff0c;而真正的繁荣还要靠行业大客户的支持&#xff0c;其中金融行业是…

spring揭秘24-springmvc02-5个重要组件

文章目录 【README】【1】HanderMapping-处理器映射容器【1.1】HanderMapping实现类【1.1.1】SimpleUrlHandlerMapping 【2】Controller&#xff08;二级控制器&#xff09;【2.1】AbstractController抽象控制器&#xff08;控制器基类&#xff09; 【3】ModelAndView(模型与视…

【x**3专享#2】编译 uboot 和 kernel 的文件结构

虚拟机交叉编译环境配置及内核编译步骤说明书 请先查看前篇文章内容 1. 获取虚拟机 IP 地址 打开虚拟机终端&#xff0c;执行以下命令查看虚拟机 IP 地址&#xff1a;ifconfig或者ip addr记录 eth0 或 ens33 等网络接口的 inet 后面的 IP 地址 2. 使用 Xftp 连接虚拟机 打开…

【C++拓展(四)】秋招建议与心得

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; C拓展 1. 前言2. 今年秋招形势到底如何?3. 学历…

基于微信小程序的旅游助手的设计与实现(源码+定制+文档讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

【hot100-java】【零钱兑换】

R9-dp篇 class Solution {public int coinChange(int[] coins, int amount) {int ncoins.length;int [][] fnew int[n1][amount1];//除2防止下面1溢出Arrays.fill(f[0],Integer.MAX_VALUE/2);f[0][0]0;for (int i0;i<n;i){for (int c0;c<amount;c){if(c<coins[i]) f[i…

webpack打包Vue项目【完整版】

文章目录 前言Vue 相关包&#xff1a;项目搭建1. 初始化项目2. 安装 Vue 和 Webpack3. 创建目录结构4. 创建文件项目5. 配置 Webpack6. 配置 Babel7. package.json8. 打包和运行 前言 基于 上一篇 webpack 的配置详解 &#xff0c;我们已经知道了 webpack 在项目中的常用的配置…

IP地址与智能家居能够碰撞出什么样的火花呢?

感应灯、远程遥控空调&#xff0c;自动感应窗帘——智能家居已经在正逐步走入我们的生活&#xff0c;为我们带来前所未有的便捷与舒适体验。而在这一进程中&#xff0c;IP地址又能够与智能家居碰撞出什么样的火花呢&#xff1f; 一、IP地址&#xff1a;智能家居的连接基石 智…

SOLIDWORKS 2025新版本揭秘 | 设计、协作和数据管理篇

除非另有说明&#xff0c;否则所有增强功能均适用于 3DEXPERIENCE SOLIDWORKS 和 SOLIDWORKS Cloud Services。 1&#xff5c;更髙效的协作和数据管理 直接从 SOLIDWORKS 访问社区&#xff0c;轻松与业界同行建立联系并开展协作。 利用实时通知时刻关注蕞新动态&#xff0c;…

基于Hive和Hadoop的图书分析系统

本项目是一个基于大数据技术的图书分析系统&#xff0c;旨在为用户提供全面的图书信息和深入的图书销售及阅读行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以…

腾讯云SDK产品功能

本文主要介绍音视频终端 SDK&#xff08;腾讯云视立方&#xff09;的核心功能。 直播推流 音视频终端 SDK&#xff08;腾讯云视立方&#xff09;为终端直播场景提供强大的 RTMP、RTC 推流能力&#xff0c;配合云直播&#xff08;CSS&#xff09;全球布局的2000节点&#xff0…

山丹县综能智慧新能源:“智能二维码”,推动班组管理信息化

近日&#xff0c;为了提升管理效率&#xff0c;国电投建业光伏电站将二维码引入设备巡视和班组建设中。 首先&#xff0c;使用传统纸质巡视作业卡&#xff0c;巡视工作强度大&#xff0c;容易出现错误&#xff1b;此外&#xff0c;“三会一活动”和培训记录等班组建设过程材料…

DCDC电源PCB设计

环路 高频电流环路面积越小越好&#xff1a; 电感所在的支路不属于高频电流环路 对于BUCK电路&#xff0c;电容Ci的越靠近芯片Vi引脚越好&#xff0c;D1越靠近SW引脚越好&#xff0c;同时另一端越靠近芯片GND引脚越好&#xff1a; 示例&#xff1a; 然后是布局输出&#…