当前位置: 首页 > news >正文

Linux基础IO(三)之访问文件的本质

文章目录

    • 访问文件的本质
      • 文件描述符fd
        • 0 & 1 & 2
        • 文件描述符的分配规则

访问文件的本质

image-20250323225144090

文件描述符fd

fd文件描述符就是一个小整数int,本质是数组的下标

FILE c库自己封装的结构体。这里面必定封装文件描述符fd

验证:

#include <stdio.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
  
int main()  
{  
    int fd1=open("log1.txt",O_WRONLY|O_CREAT|O_APPEND,0666);  
    int fd2=open("log2.txt",O_WRONLY|O_CREAT|O_APPEND,0666);  
    int fd3=open("log3.txt",O_WRONLY|O_CREAT|O_APPEND,0666);  
    int fd4=open("log4.txt",O_WRONLY|O_CREAT|O_APPEND,0666);  
    if(fd1<0)  
    {  
        printf("open fail!\n");  
        return 1;  
    }  
    printf("fd1:%d\n",fd1);  
    printf("fd2:%d\n",fd2);  
    printf("fd3:%d\n",fd3);                                                               
    printf("fd4:%d\n",fd4);            
    return 0;                
}

image-20250323225755882

0 & 1 & 2

Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2.

0,1,2对应的物理设备一般是:键盘,显示器,显示器

image-20250323204621204

证明:

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

int main()
{
    const char*msg="hello linux!\n";
    write(1,msg,strlen(msg));
    write(2,msg,strlen(msg));
    return 0;                                                              
}

image-20250323230541588

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

int main()
{
    char buffer[1024];
    //现在读出来的是字节,不是字符串                                                        
    ssize_t s=read(0,buffer,sizeof(buffer));
    if(s<0)return 1; 
    buffer[s]='\0';                              
    //c语言要把读出来的信息当成字符串,所以要加\0
    printf("echo : %s\n",buffer);                             
    return 0;                       
} 

image-20250323231238824

所以,进程默认就给我们打开了0(标准输入),1(标准输出),2(标准错误).

这个特性是操作系统的特性。

进程默认会打开键盘、显示器、显示器。

OS为什么默认要打开?

因为编程要用键盘输入,和显示器查看结果。


所以输入输出还可以采用如下方式:

而现在知道,文件描述符就是从0开始的小整数。

当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。

于是就有了file结构体,表示一个已经打开的文件对象。

而进程执行open系统调用,所以必须让进程和文件关联起来。

每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,

每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标。

所以,只要拿着文件描述符,就可以找到对应的文件.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.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;                                                                         
} 

image-20250323232449898


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

int main()
{
    close(1);

    int n=printf("stdin->fd:%d\n",stdin->_fileno);
    printf("stdout->fd:%d\n",stdout->_fileno);
    printf("stderr->fd:%d\n",stderr->_fileno);
    fprintf(stderr,"ret : %d\n",n);
    return 0;                                                                          
} 

image-20250323233221409

在stdin中,向显示器 printf 打印了12个字符,但是因为关掉了1(显示器),

所以,我们看不到打印的 stdin->fd:0

那为什么 fprintf 可以打印出来呢?

因为stderr文件描述符是2号,关闭的是1号

一个文件可以被多个进程同时打开

count引用计数

一个指针指向一个文件,count++

关闭文件:count–,将文件描述符的指针置空。

count==0 释放 struct file 对象

文件描述符的分配规则

open成功就return fd,否则就return -1,

因为fd本质是数组下标,所以没有负数,负数就是失败。

image-20250325131506103

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

#define filename "log.txt"

int main()
{
    int fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);
    if(fd<0)
    {
        perror("open fail!\n");
        return 1;
    }
    printf("fd:%d\n",fd);
    const char*msg="Hello Linux!\n";
    int cnt=3;
    while(cnt--)
    {
        write(fd,msg,strlen(msg));
    }
    close(fd);
    return 0;
}

image-20250325132425591

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

#define filename "log.txt"

int main()
{
	close(0);
    int fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);
    if(fd<0)
    {
        perror("open fail!\n");
        return 1;
    }
    printf("fd:%d\n",fd);
    const char*msg="Hello Linux!\n";
    int cnt=3;
    while(cnt--)
    {
        write(fd,msg,strlen(msg));
    }
    close(fd);
    return 0;
}

image-20250325132627680

close(0); -> close(1);

image-20250325132729316

为什么把1号文件描述符关了就什么都不输出了?

printf 是要向显示器打印的,但是显示器文件描述符stdoutfd=1)关闭了,所以显示不出来。

进程所匹配的文件描述符已经被关掉了。

close(1); -> close(2);

image-20250325133257903

又可以显示了,因为 printf 是向1号文件描述符打的,现在关闭2号,所以可以显示。

文件描述符的分配规则:

files_struct 数组当中,从0下标开始,找到当前没有被使用的最小的一个下标,作为新的文件描述符。

http://www.dtcms.com/a/122106.html

相关文章:

  • GaussDB使用指南
  • FFmpeg安装和使用
  • # 基于BERT的文本分类
  • 龙蜥社区荣获 OS2ATC 2025 “最具影响力开源创新贡献奖”
  • spark数据清洗案例:流量统计
  • 力扣刷题-热题100题-第34题(c++、python)
  • 机器学习代码基础——ML2 使用梯度下降的线性回归
  • 暑假实习面试复盘
  • Vue框架的Diff算法
  • 使用Ollama通过预训练模型获取句子向量(rest api方式)
  • GDB调试程序的基本命令和用法(Qt程序为例)
  • 三月份面试感触
  • OpenCV链接库失败,报错 无法解析的外部符号
  • SCI科学论文的重要组成部分
  • 达梦数据库迁移问题总结
  • 如何进行数据安全风险评估总结
  • Frida 调用 kill 命令挂起恢复 Android 线程
  • spring之JdbcTemplate、GoF之代理模式、面向切面编程AOP
  • 在Ubuntu 22.04上配置【C/C++编译环境】
  • 【码农日常】vscode编码clang-format格式化简易教程
  • (PTA) L2-011-L2-015
  • TDengine 窗口预聚集
  • 面试如何应用大模型
  • 算法刷题记录——LeetCode篇(1.6) [第51~60题](持续更新)
  • JAVA基础八股复习
  • 服务器DNS失效
  • DataGear结合AI工具制作多端适配的数据看板
  • Markdown标题序号处理工具——用 C 语言实现
  • 最新Web系统全面测试指南
  • lab-foundation开源程序AI/数据科学的瑞士军刀,开箱即用的数据科学/AI 平台 |AI/数据科学的瑞士军刀