【Linux】语言级文件接口与系统级文件接口

目录

前言

一、回顾C语言中的文件操作

二、认识文件缓冲区

三、Linux系统提供的文件接口

四、文件描述符fd简介

Linux下C语言文件接口简单模拟实现


前言

每个编程语言都有自己的文件操作方法,在不同的操作系统下相同的语言有相同的文件操作方法。这是如何实现的呢?

本文将通过讲述语言级文件接口与系统级文件接口的关系来回答这个问题。


一、回顾C语言中的文件操作

我们以C语言为例,我们先来简单回顾一下C语言中的文件操作。

文件打开关闭

//打开⽂件
FILE * fopen ( const char * filename, const char * mode );
//关闭⽂件
int fclose ( FILE * stream );

mode表示文件的打开模式,下面都是文件的打开模式:

文件访问
模式字符串
含义解释若文件已存在的动作若文件不存在的动作
"r"打开文件以读取从头读打开失败
"w"创建文件以写入销毁内容创建新文件
"a"后附后附到文件写到结尾创建新文件
"r+"读扩展打开文件以读/写从头读错误
"w+"写扩展创建文件以读/写销毁内容创建新文件
"a+"后附扩展打开文件以读/写写到结尾创建新文件
文件访问模式标签 "b" 可以可选地指定以二进制模式打开文件。

文件的读写 

函数名功能适用于
fgetc字符输入函数所有输入流
fputc字符输出函数所有输出流
fgets文本行输入函数所有输入流
fputs文本行输出函数所有输出流
fscanf格式化输入函数所有输入流
fprintf格式化输出函数所有输出流
fread⼆进制输入文件
fwrite⼆进制输出文件

二、认识文件缓冲区

在Linux下运行以下两段代码:

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

int main()
{
    int cnt = 5;
    while (cnt--)
    {
        printf("test!!!!, %d   ", cnt);
        sleep(1);
    }
    return 0;
}
#include <stdio.h>
#include <unistd.h>

int main()
{
    int cnt = 5;
    while (cnt--)
    {
        printf("test!!!!, %d\n", cnt);
        sleep(1);
    }
    return 0;
}

我们会发现,第一段代码在5秒之后所有内容一次性将所有内容刷新到显示器上;第二段代码每一秒在显示器上刷新一条内容。

为什么会这样呢?

因为编程语言的文件结构体中为我们提供了一个语言级的缓冲区,这个缓冲区可以让CPU一次性向硬件中写入较多的数据,减少写入次数,提高运行效率。

我们可以通过fflush函数将缓冲区内数据立即刷新到文件中。

三、Linux系统提供的文件接口

文件打开

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

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

pathname: 要打开或创建的目标文件

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。

参数:

        O_RDONLY: 只读打开

        O_WRONLY: 只写打开

        O_RDWR : 读,写打开

        这三个常量,必须指定一个且只能指定一个

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

返回值:

        成功:新打开的文件描述符

        失败:-1

文件关闭

#include <unistd.h>

int close(int fd);

关闭文件描述符fd对应的文件;

返回值:

        成功:0

        失败:-1

 文件读取

#include <unistd.h>

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

从文件描述符fd对应的文件中读取至多count字节个字符到buf中;

返回值:

        成功:读取的字符个数

        失败:-1

 文件写入

#include <unistd.h>

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

从buf中写入至多count字节个字符到文件描述符fd对应的文件中;

返回值:

        成功:写入的字符个数

        失败:-1

四、文件描述符fd简介

fd 是 File descriptor 的缩写,中文名叫做:文件描述符文件描述符是一个非负整数,本质上是一个索引值。

想要真正理解fd是什么,就要先知道Linux进程是如何管理文件的。

每一个进程被创建时,都会建立一个files_struct结构体来管理打开的文件,结构体源码如下:

/*
 * Open file table structure
 */
struct files_struct {
    // 读相关字段
    atomic_t count;
    bool resize_in_progress;
    wait_queue_head_t resize_wait;

    // 打开的文件管理结构
    struct fdtable __rcu *fdt;
    struct fdtable fdtab;

    // 写相关字段
    unsigned int next_fd;
    unsigned long close_on_exec_init[1];
    unsigned long open_fds_init[1];
    unsigned long full_fds_bits_init[1];
    struct file * fd_array[NR_OPEN_DEFAULT];
};

files_struct 这个结构体我们说是用来管理所有打开的文件的。怎么管理?本质上就是数组管理的方式,所有打开的文件结构都在一个数组里。这可能会让你疑惑,数组在那里?有两个地方:

  1. struct file * fd_array[NR_OPEN_DEFAULT] 是一个静态数组,随着 files_struct 结构体分配出来的,在 64 位系统上,静态数组大小为 64;
  2. struct fdtable 也是个数组管理结构,只不过这个是一个动态数组,数组边界是用字段描述的;

 所以fd我们可以理解为Linux进程文件管理结构体中的数组对应的下标;


Linux下C语言文件接口简单模拟实现

7.mystdio · 梁羽赫/Code_in_linux - 码云 - 开源中国 (gitee.com)icon-default.png?t=N7T8https://gitee.com/yuhe-liang/code_in_linux/tree/master/7.mystdio

  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值