【Linux:文件】基础IO

🎬 个人主页艾莉丝努力练剑
专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:


文章目录

  • [1 ~> 文件操作:C语言文件操作 + 系统级别文件操作](#1 ~> 文件操作:C语言文件操作 + 系统级别文件操作)
    • [1.1 基础认知](#1.1 基础认知)
    • [1.2 C语言文件操作(库函数层面)](#1.2 C语言文件操作(库函数层面))
      • [1.2.1 关键细节与示例](#1.2.1 关键细节与示例)
      • [1.2.2 要点补充](#1.2.2 要点补充)
    • [1.3 系统级别文件操作(系统调用层面)](#1.3 系统级别文件操作(系统调用层面))
      • [1.3.1 关键细节与示例](#1.3.1 关键细节与示例)
      • [1.3.2 要点补充(含open函数)](#1.3.2 要点补充(含open函数))
  • [2 ~> 文件描述符fd](#2 ~> 文件描述符fd)
    • [2.1 文件描述符的核心定义](#2.1 文件描述符的核心定义)
    • [2.2 默认fd与对应设备文件](#2.2 默认fd与对应设备文件)
    • [2.3 分配规则](#2.3 分配规则)
    • [2.4 内核底层结构:核心](#2.4 内核底层结构:核心)
  • [3 ~> 重定向](#3 ~> 重定向)
    • [3.1 核心定义](#3.1 核心定义)
    • [3.2 基础重定向示例(基于fd分配规则)](#3.2 基础重定向示例(基于fd分配规则))
    • [3.3 dup2系统调用(重定向专用的接口)](#3.3 dup2系统调用(重定向专用的接口))
    • [3.4 minishell中添加重定向功能(核心逻辑)](#3.4 minishell中添加重定向功能(核心逻辑))
  • [4 ~> 如何理解"一切皆文件"](#4 ~> 如何理解“一切皆文件”)
    • [4.1 多态调用和"一切皆文件"的关系](#4.1 多态调用和“一切皆文件”的关系)
    • [4.2 "一切皆文件"的核心本质](#4.2 “一切皆文件”的核心本质)
    • [4.3 底层实现(FILE与file_operations结构体)](#4.3 底层实现(FILE与file_operations结构体))
    • [4.4 总结"一切皆文件"](#4.4 总结“一切皆文件”)
  • [5 ~> 缓冲区](#5 ~> 缓冲区)
    • [5.1 缓冲区的定义、作用、引入原因](#5.1 缓冲区的定义、作用、引入原因)
      • [5.1.1 缓冲区的定义](#5.1.1 缓冲区的定义)
      • [5.1.2 缓冲区的核心作用](#5.1.2 缓冲区的核心作用)
      • [5.1.3 一句话说明为什么要引入缓冲区机制](#5.1.3 一句话说明为什么要引入缓冲区机制)
    • [5.2 缓冲类型(标准IO库,C库提供)](#5.2 缓冲类型(标准IO库,C库提供))
    • [5.3 缓冲区刷新条件](#5.3 缓冲区刷新条件)
    • [5.4 关键示例:缓冲区的坑以及验证](#5.4 关键示例:缓冲区的坑以及验证)
    • [5.5 库函数与系统调用的缓冲区差异](#5.5 库函数与系统调用的缓冲区差异)
    • [5.6 FILE结构体与缓冲区:关联底层](#5.6 FILE结构体与缓冲区:关联底层)
    • [5.7 自定义简易libc IO库(理解缓冲区实现)](#5.7 自定义简易libc IO库(理解缓冲区实现))
  • [6 ~> 打通C语言与系统IO的关联(核心总结)](#6 ~> 打通C语言与系统IO的关联(核心总结))
    • [6.1 库函数与系统调用的关系](#6.1 库函数与系统调用的关系)
    • [6.2 关键关联点](#6.2 关键关联点)
    • [6.3 核心总结](#6.3 核心总结)
  • 结尾


1 ~> 文件操作:C语言文件操作 + 系统级别文件操作

1.1 基础认知

文件 = 属性(元数据)+ 内容,所有文件操作本质是「内容操作」和「属性操作」;Linux下一切皆文件(磁盘、键盘、显示器、网卡等均被抽象为文件),文件操作本质是进程对文件的操作,底层依赖操作系统的系统调用,而非直接通过语言库函数。

注:0KB空文件占用磁盘空间(仅存储属性);磁盘是永久性外设,文件存储具有持久性,文件操作本质是对外设的IO操作。

1.2 C语言文件操作(库函数层面)

核心函数:fopen、fread、fwrite、fclose,依赖stdio.h头文件,返回值为FILE*(文件指针),底层封装系统调用,提供用户级缓冲区。

1.2.1 关键细节与示例

c 复制代码
#include <stdio.h>

#include <string.h>

// 1. 打开文件(w模式:不存在则创建,存在则清空)

FILE *fp = fopen("myfile", "w");

if(!fp){ printf("fopen error!\n"); return 1; }

// 2. 写文件(往myfile写入5次hello bit!)

const char *msg = "hello bit!\n";

int count = 5;

while(count--){

    fwrite(msg, strlen(msg), 1, fp); // 参数:内容、单个元素长度、元素个数、文件指针

}

// 3. 读文件(读取myfile内容,类比fwrite)

FILE *fp = fopen("myfile", "r");

char buf[1024];

while(1){

    ssize_t s = fread(buf, 1, strlen(msg), fp);

    if(s > 0){ buf[s] = 0; printf("%s", buf); }

    if(feof(fp)){ break; } // 检测文件结束

}

// 4. 关闭文件(必须执行,刷新缓冲区+释放资源)

fclose(fp);

1.2.2 要点补充

  • 1、C默认打开3个流:stdin(标准输入,对应键盘,fd=0)、stdout(标准输出,对应显示器,fd=1)、stderr(标准错误,对应显示器,fd=2),类型均为FILE*;

  • 2、打开方式核心区别:r(只读,文件不存在报错)、w(只写,创建/清空)、a(追加,创建/写末尾)、r+/w+/a+(读写,区别在于是否创建、是否清空);

  • 3、简单实现cat命令:通过命令行参数argv[1]获取文件名,循环fread读取内容并printf输出。

1.3 系统级别文件操作(系统调用层面)

核心函数: open、read、write、close,依赖fcntl.h、unistd.h等头文件,是文件操作的底层接口,无用户级缓冲区,直接与内核交互。

1.3.1 关键细节与示例

c 复制代码
#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <string.h>

// 1. 打开/创建文件(核心参数:路径、标志位、权限)

umask(0); // 清除权限掩码,确保创建文件权限为0644

int fd = open("myfile", O_WRONLY|O_CREAT, 0644);

if(fd < 0){ perror("open"); return 1; } // 失败返回-1,perror打印错误信息

// 2. 写文件(类比fwrite,无缓冲区)

const char *msg = "hello bit!\n";

int len = strlen(msg);

int count = 5;

while(count--){

 write(fd, msg, len); // 参数:文件描述符、内容、长度,返回实际写入字节数

}

// 3. 读文件(类比fread)

int fd = open("myfile", O_RDONLY);

char buf[1024];

while(1){

    ssize_t s = read(fd, buf, strlen(msg));

    if(s > 0){ printf("%s", buf); }

    else{ break; } // s=0(文件结束)或-1(错误),退出循环

}

// 4. 关闭文件

close(fd);

1.3.2 要点补充(含open函数)

1、open 函数核心参数:

  • flags(必选1个,可选多个用|连接):O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写)、O_CREAT(创建)、O_APPEND(追加)、O_TRUNC(清空);

  • mode:仅O_CREAT存在时有效,指定文件权限(如0644:所有者读写、组只读、其他只读),受umask掩码影响(需提前umask(0)清除------就近原则);

2、返回值: 成功返回文件描述符(非负整数),失败返回-1;

3、标志位传递逻辑: 通过位或(|)组合,如O_WRONLY|O_CREAT,表示"只写打开,文件不存在则创建",底层通过位与(&)判断标志位是否生效。


2 ~> 文件描述符fd

2.1 文件描述符的核心定义

文件描述符(fd)是Linux中用于标识 "已打开文件"的非负小整数本质:fd是进程中files_struct结构体中fd_array数组的下标,通过fd可找到对应的file结构体(内核中描述已打开文件的对象)。

2.2 默认fd与对应设备文件

Linux进程默认打开3个文件描述符,固定对应如下设备,无需手动open:

  • fd = 0:标准输入(stdin),对应键盘;

  • fd = 1:标准输出(stdout),对应显示器;

  • fd = 2:标准错误(stderr),对应显示器。

c 复制代码
#include <stdio.h>

#include <unistd.h>

#include <string.h>

int main(){

    char buf[1024];

    ssize_t s = read(0, buf, sizeof(buf)); // 从fd=0(键盘)读取

    if(s > 0){

        buf[s] = 0;

        write(1, buf, strlen(buf)); // 写入fd=1(显示器)

        write(2, buf, strlen(buf)); // 写入fd=2(显示器)

    }

    return 0;
}

2.3 分配规则

核心规则:fd_array数组中,分配「当前未被使用的最小下标」作为新的文件描述符。

c 复制代码
#include <stdio.h>

#include <fcntl.h>

int main(){

    close(0); // 关闭fd=0(释放该下标)

    int fd = open("myfile", O_RDONLY); // 分配最小未使用下标0

    printf("fd: %d\n", fd); // 输出fd: 0

    close(fd);

    return 0;
}

注: 关闭fd = 1或fd = 2后,新open的文件fd会分别变为1或2,这是重定向的底层原理。

2.4 内核底层结构:核心

  • 1、进程结构体task_struct/usr/src/kernels/.../include/linux/sched.h):包含指针*files,指向files_struct结构体;

  • 2、files_struct 结构体/usr/src/kernels/.../include/linux/fdtable.h):核心是fd_array指针数组,每个元素指向file结构体;

  • 3、file结构体/usr/src/kernels/.../include/linux/fs.h):描述已打开文件的元信息(inode、权限、读写位置等),包含f_op指针(指向file_operations结构体)。


3 ~> 重定向

3.1 核心定义

重定向:改变文件描述符对应的"实际文件/设备",使原本输出到A设备的内容,输出到B文件/设备(常见:> 输出重定向、>> 追加重定向、< 输入重定向)。

本质:修改进程fd_array数组中,对应fd下标指向的file指针,使其指向目标文件(而非默认设备)。

3.2 基础重定向示例(基于fd分配规则)

c 复制代码
#include <stdio.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdlib.h>

int main(){

    close(1); // 关闭fd=1(原本指向显示器)

    // 新打开文件,分配最小未使用下标1,此时fd=1指向myfile

    int fd = open("myfile", O_WRONLY|O_CREAT, 0644);

    if(fd < 0){ perror("open"); return 1; }

    printf("fd: %d\n", fd); // 原本输出到显示器,现在输出到myfile(fd=1)

    fflush(stdout); // 强制刷新缓冲区(否则可能不写入)

    close(fd);

    exit(0);
}

现象: printf输出的内容不会显示在显示器,而是写入myfile文件中。

3.3 dup2系统调用(重定向专用的接口)

  • 函数原型: int dup2(int oldfd, int newfd); (将newfd重定向到oldfd,使newfd指向oldfd对应的文件)

不过这个newfd和oldfd的名字取得不好,如果掉个个儿会好理解不少。

  • dup2系统调用核心作用: 简化重定向代码,无需手动close(fd),直接关联两个fd。
c 复制代码
#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

int main() {

    // 打开log文件,获取oldfd

    int oldfd = open("./log", O_CREAT | O_RDWR, 0644);

    if (oldfd < 0) { perror("open"); return 1; }

    // 将fd=1(stdout)重定向到oldfd(log文件)

    dup2(oldfd, 1);

    // 后续printf都会写入log文件,而非显示器

    char buf[1024] = {0};

    while(1){

        read(0, buf, sizeof(buf)-1);

        printf("%s", buf);

        fflush(stdout);

    }

    return 0;
}

3.4 minishell中添加重定向功能(核心逻辑)

  • 1、解析命令行:识别重定向符号(<、>、>>),分离命令与目标文件名;

  • 2、重定向实现(子进程中执行):根据重定向类型,open目标文件,用dup2关联对应fd(输入重定向关联fd=0,输出/追加关联fd=1);

  • 3、核心代码片段(关键逻辑):

c 复制代码
#define InputRedir 1  // < 输入重定向

#define OutputRedir 2 // > 输出重定向

#define AppRedir 3    // >> 追加重定向

int redir = NoneRedir; // 重定向类型

char *filename = nullptr; // 目标文件名

// 解析重定向符号(从命令行末尾反向查找)

void ParseRedir(char command_buffer[], int len){

    int end = len - 1;

    while(end >= 0){

        if(command_buffer[end] == '<'){

            redir = InputRedir;

            command_buffer[end] = 0;

            filename = &command_buffer[end]+1;

            break;

        }else if(command_buffer[end] == '>'){

            if(command_buffer[end-1] == '>'){

                redir = AppRedir;

                command_buffer[end-1] = 0;

            }else{

                redir = OutputRedir;

            }

 command_buffer[end] = 0;

            filename = &command_buffer[end]+1;

            break;

        }

        end--;

    }

}

// 执行重定向(子进程中调用)

void DoRedir(){

    if(redir == InputRedir){ // 输入重定向:fd=0关联文件

        int fd = open(filename, O_RDONLY);

        dup2(fd, 0);

    }else if(redir == OutputRedir){ // 输出重定向:fd=1关联文件(清空)

        int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);

        dup2(fd, 1);

    }else if(redir == AppRedir){ // 追加重定向:fd=1关联文件(追加)

        int fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, 0666);

        dup2(fd, 1);

    }
}

4 ~> 如何理解"一切皆文件"

4.1 多态调用和"一切皆文件"的关系

Linux "一切皆文件" 和多态(尤其是 C 语言中通过函数指针实现的多态思想)有极强的关联,而且多态是 "一切皆文件" 能够落地的核心底层支撑。

  • 1、一切皆文件: 统一对外提供open/read/write/close接口,屏蔽设备差异;

  • 2、多态体现(贴合课件结构体):file_operations结构体中的 read/write 等是函数指针(统一接口),不同设备(键盘 / 磁盘)给这些指针赋不同实现;

  • 3、落地:调用read (fd,...)时,内核通过fd找到file->f_op,执行对应设备的read逻辑,即 "同一接口,不同实现"。

注:非 OOP 类多态,是 C 语言函数指针多态,课件第四章 file_operations 结构体就是直接体现。

4.2 "一切皆文件"的核心本质

Linux将所有设备(键盘、显示器、磁盘、网卡)、管道、socket等,均抽象为 "文件" ,统一用一套文件操作接口(open、read、write、close)访问,简化开发。

核心好处: 开发者无需区分设备类型,只需调用相同的IO接口,即可操作所有系统资源(读文件、读键盘、写显示器、网络通信均可用read/write)。

4.3 底层实现(FILE与file_operations结构体)

  • 1、FILE结构体:每个已打开的"文件 / 设备",内核都会创建一个FILE结构体,存储其元信息(inode、权限、读写位置、f_op指针等);
  1. file_operations结构体:核心是"函数指针数组",每个函数指针对应一个文件操作(readwriteopenclose等),不同设备对应不同的函数实现;

  2. 关联逻辑:file结构体的f_op指针,指向该设备对应的file_operations结构体,当调用read/write时,内核通过f_op找到对应设备的read / write实现,完成具体操作。

关键结构体片段

c 复制代码
// FILE结构体(核心成员)

struct file {

    struct inode *f_inode; // 文件inode(元数据)

    const struct file_operations *f_op; // 指向操作函数集

    loff_t f_pos; // 当前读写位置

    unsigned int f_flags; // 打开权限

    fmode_t f_mode; // 访问模式(只读/只写等)

};

// file_operations结构体(核心成员,函数指针)

struct file_operations {

    struct module *owner;

    loff_t (*llseek) (struct file *, loff_t, int); // 移动读写位置

    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); // 读操作

    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); // 写操作

    int (*open) (struct inode *, struct file *); // 打开操作

    int (*release) (struct inode *, struct file *); // 关闭操作

    // 其他操作(ioctl、mmap等)

};

4.4 总结"一切皆文件"

"一切皆文件" 的核心是"抽象与统一":操作系统(OS)通过FILE结构体抽象所有资源,通过file_operations结构体统一操作接口,不同设备只需实现自身的read / write等函数,即可被系统识别和访问,无需修改上层IO逻辑。


5 ~> 缓冲区

5.1 缓冲区的定义、作用、引入原因

5.1.1 缓冲区的定义

缓冲区是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。

缓冲区: 内存中预留的一块存储空间,用于缓存输入 / 输出数据(IO),减少系统调用次数,协调CPU(高速)与外设(低速,磁盘、显示器等)的速度差异,提升程序执行效率。

5.1.2 缓冲区的核心作用

缓冲区的核心作用: 减少CPU状态切换(用户态→内核态)的损耗(系统调用需切换状态,频繁调用损耗大),例如:一次读取大量数据到缓冲区,后续访问直接操作内存,无需再次调用read。

5.1.3 一句话说明为什么要引入缓冲区机制

为了减少使用系统调用的次数,提高效率 ,我们就可以采用缓冲机制 。比如我们从磁盘里取信息,可以在磁盘文件进行操作时,可以一次从文件中读出大量的数据到缓冲区中,以后对这部分的访问就不需要再使用系统调用了,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。

5.2 缓冲类型(标准IO库,C库提供)

标准IO库(printffwrite等)提供3种缓冲类型(全缓冲、行缓冲、无缓冲 ),系统调用(readwrite)无缓冲区:

  • 1、全缓冲区:填满缓冲区后,才执行系统调用(默认用于磁盘文件),一般普通文件就是全缓存;

  • 2、行缓冲区:遇到换行符(\n)或缓冲区填满,执行系统调用(默认用于终端,如stdin、stdout),显示器就是行缓冲;

  • 3、无缓冲区:不缓存数据,直接执行系统调用(默认用于stderr,确保错误信息及时显示)。

5.3 缓冲区刷新条件

缓冲区刷新条件重点结论:

  • 1、缓冲区填满;

  • 2、调用fflush函数(强制刷新,如fflush(stdout));

  • 3、进程正常结束(自动刷新缓冲区);

  • 4、关闭文件(fclose会自动刷新缓冲区)。

5.4 关键示例:缓冲区的坑以及验证

c 复制代码
#include <stdio.h>

#include <fcntl.h>

#include <unistd.h>

int main() 
{
	close(1); // 关闭stdout(fd=1)

	// 重定向fd=1到log.txt(磁盘文件,全缓冲)

	int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
	printf("hello world: %d\n", fd); // 写入缓冲区,未填满,不刷新

	close(fd); // 未刷新缓冲区,log.txt为空

	return 0;
}

解决方法:close(fd)前添加fflush(stdout),强制刷新缓冲区,内容才会写入文件。

易错点:将fd = 2(stderr,标准错误流)重定向到文件,用perror输出,无需fflush,内容直接写入(因为stderr无缓冲)。

5.5 库函数与系统调用的缓冲区差异

c 复制代码
#include <stdio.h>

#include <string.h>

#include <unistd.h>

int main() {

    const char *msg0="hello printf\n";

    const char *msg1="hello fwrite\n";

    const char *msg2="hello write\n";

    printf("%s", msg0); // 库函数,有缓冲区

    fwrite(msg1, strlen(msg1), 1, stdout); // 库函数,有缓冲区

    write(1, msg2, strlen(msg2)); // 系统调用,无缓冲区

    fork(); // 父子进程写时拷贝,缓冲区数据被复制

    return 0;
}

观察到的现象:重定向到文件(全缓冲)后,printffwrite输出2次(父子各1次),write输出1次(无缓冲,已提前写入)。

结论: printffwrite(C库函数,被C语言封装的系统调用)有用户级缓冲区(C标准库提供),write(系统调用)无缓冲区;缓冲方式会随输出目标变化(终端→行缓冲,文件→全缓冲)。

5.6 FILE结构体与缓冲区:关联底层

C语言标准库中的**FILE结构体**,其本质是:"封装了fd + 用户级缓冲区",核心成员如下:

c 复制代码
typedef struct _IO_FILE FILE;

struct _IO_FILE {

    int _flags; // 缓冲类型(全缓冲/行缓冲/无缓冲)

    int _fileno; // 封装的文件描述符(fd)

    char* _IO_write_base; // 缓冲区起始地址

    char* _IO_write_ptr; // 缓冲区当前写入位置

    char* _IO_write_end; // 缓冲区结束地址

    // 其他缓冲区相关成员
};

核心逻辑: FILE* fp = fopen(...)本质是创建FILE结构体,打开文件获取fd,初始化缓冲区,后续fread / fwrite均操作缓冲区,满足条件后调用系统调用刷新到内核。

5.7 自定义简易libc IO库(理解缓冲区实现)

核心思路: 我们模拟FILE结构体,实现myfopenmyfwrite、myfflush、myfclose,封装fd和缓冲区,手动控制刷新逻辑------艾莉丝这里简单写一段demo,帮助我们理解缓冲区。

c 复制代码
// my_stdio.h

#pragma once

#define SIZE 1024

#define FLUSH_LINE 1 // 行缓冲

#define FLUSH_FULL 2 // 全缓冲

struct IO_FILE {

    int flag; // 缓冲类型

    int fileno; // 文件描述符

    char outbuffer[SIZE]; // 用户级缓冲区

    int size; // 缓冲区当前数据长度

    int cap; // 缓冲区容量(SIZE)

};

typedef struct IO_FILE mFILE;

mFILE *myfopen(const char *filename, const char *mode);

int myfwrite(const void *ptr, int num, mFILE *stream);

void myfflush(mFILE *stream);

void myfclose(mFILE *stream);

核心实现:mfopen打开文件获取fd,初始化缓冲区;mfwrite将数据写入缓冲区,满足条件(行缓冲遇\n、全缓冲填满)调用mfflush;mfflush调用write将缓冲区数据写入内核,清空缓冲区;mfclose关闭文件前刷新缓冲区。


6 ~> 打通C语言与系统IO的关联(核心总结)

6.1 库函数与系统调用的关系

核心关系:C语言文件操作库函数(fopen、fread等),是对系统调用接口(open、read等)的封装,目的是提供用户级缓冲区,简化开发、提升效率。

层级关系(从上到下):用户程序 → C标准库(库函数,带缓冲区) → 系统调用接口(无缓冲区) → 内核 → 硬件设备。

6.2 关键关联点

  • 1、FILE* 与 fd:FILE结构体封装了fd,fopen本质是调用open获取fd,再初始化缓冲区,后续所有库函数操作,最终都会通过fd调用系统调用;

  • 2、缓冲区关联:C库提供用户级缓冲区,内核也有内核级缓冲区(提升整机性能),库函数刷新缓冲区后,数据进入内核缓冲区,内核再按需写入硬件;

  • 3、操作逻辑关联:无论是fwrite还是write,最终都是通过内核的file_operations结构体,调用对应设备的写函数,完成数据写入;

  • 4、重定向关联:重定向修改的是fd对应的file指针,库函数(printf)操作stdout(fd=1),底层还是通过fd访问文件,因此重定向对库函数和系统调用均生效。

6.3 核心总结

  • 1、所有文件操作的底层,都是系统调用,库函数只是"中间层",核心作用是提供缓冲区;

  • 2、fd是内核识别文件的标识,FILE*是C库封装后的标识,二者一一对应;

  • 3、缓冲区分为"用户级(C库提供)"和"内核级(OS提供)",用户程序的数据,需经过两次刷新(用户→内核→硬件),才能最终写入设备;

  • 4、Linux"一切皆文件",统一了IO接口,使得库函数与系统调用的封装更加合理,开发者无需关注底层设备差异。


结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!

往期回顾

【Linux:文件】基础IO:文件操作的系统调用和库函数各个接口汇总及代码演示

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა

相关推荐
lili-felicity2 小时前
CANN多模型并发部署与资源隔离
开发语言·人工智能
you-_ling2 小时前
IO编程相关知识
c语言·vscode
ujainu2 小时前
CANN仓库中的AIGC开发者体验工程:昇腾AI软件栈如何让百万开发者“一见倾心”
人工智能·aigc
_OP_CHEN2 小时前
【Linux系统编程】(二十七)手撕动静态库原理与实战:从底层逻辑到代码落地
linux·操作系统·动态库·静态库·c/c++·库的原理与制作
南烟斋..2 小时前
Linux设备驱动开发完全指南:从启动流程到Platform驱动模型
linux·驱动开发·uboot
小龙报2 小时前
【51单片机】深度解析 51 串口 UART:原理、配置、收发实现与工程化应用全总结
c语言·开发语言·c++·stm32·单片机·嵌入式硬件·51单片机
铁蛋AI编程实战2 小时前
DeepSeek mHC解析(流形约束超连接)
人工智能·深度学习·机器学习
weixin_6682 小时前
GitHub 2026年AI项目详细数据汇总表-AI分析-分享
人工智能·github
承渊政道2 小时前
C++学习之旅【C++中模板进阶内容介绍】
c语言·c++·笔记·学习·visual studio