Linux —— 基础I/O

news2024/11/29 6:30:59

一,背景介绍

        狭义的文件存放在磁盘上,广义上在Linux下一切皆文件;磁盘上的文件一般为永久存储的外设,本质上对文件的操作,即为对外设的输入和输出(简称I/O);空文件并不是不占磁盘文件,只是没有内容,文件=属性(元数据)+内容;对文件的内容操作,如fread、fwrite、fgets、fgetc,fputc,fputs等;对文件的属性操作,如fseek、ftell、rewind等;

        从系统角度,对文件的操作,其实就是进程对文件的操作;是通过系统调用接口,来实现操作的;

当前路径,每个进程都有一个内置属性cwd(即当前工作目录);

[wz@192 ~]$ ll /proc/29286
total 0
dr-xr-xr-x. 2 wz wz 0 8月   7 19:11 attr
-rw-r--r--. 1 wz wz 0 8月   7 19:11 autogroup
-r--------. 1 wz wz 0 8月   7 19:11 auxv
-r--r--r--. 1 wz wz 0 8月   7 19:11 cgroup
--w-------. 1 wz wz 0 8月   7 19:11 clear_refs
-r--r--r--. 1 wz wz 0 8月   7 19:10 cmdline
-rw-r--r--. 1 wz wz 0 8月   7 19:11 comm
-rw-r--r--. 1 wz wz 0 8月   7 19:11 coredump_filter
-r--r--r--. 1 wz wz 0 8月   7 19:11 cpuset
lrwxrwxrwx. 1 wz wz 0 8月   7 19:11 cwd -> /home/wz/Desktop
-r--------. 1 wz wz 0 8月   7 19:11 environ
lrwxrwxrwx. 1 wz wz 0 8月   7 19:11 exe -> /home/wz/Desktop/target
dr-x------. 2 wz wz 0 8月   7 19:10 fd
...

 在任何C程序,都会默认打开三个文件(硬件):

  • 标准输入,stdin,键盘文件;
  • 标准输出,stdout,显示器文件;
  • 标准错误,stderr,显示器文件;

注,所有外设硬件,本质上即对应read/write的核心操作;可通过C接口,直接对stdin/stdout/stderr进行读写操作;默认打开这三个文件,其他函数使用需求,如scanf、printf、perror等,另外fprintf、fscanf;其他语言也是如此,C++中是cin、cout、cerr;

二,系统接口函数

        open、close、read、write;

open 打开或创建文件

close 关闭文件

 

read 读取文件

write 写入文件

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

int main()
{
    int fd = open("log.txt", O_WRONLY|O_CREAT, 0644);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    const char* msg = "hello world\n";
    write(fd, msg, strlen(msg));
    close(fd);
    return 0; 
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int fd = open("log.txt", O_RDONLY);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    char buffer[1024];
    ssize_t s = read(fd, buffer, sizeof(buffer)-1);
    if(s>0)
    {
        buffer[s] = '\0';
        printf("%s\n", buffer);
    }
    close(fd);
    return 0; 
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int fd = open("log.txt", O_WRONLY|O_APPEND);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    const char* msg = "hello world append\n";
    write(fd, msg, strlen(msg));
    close(fd);
    return 0; 
}

注:

  • O_WRONLY|O_CREAT 对应C语言 w ;
  • O_RDONLY 对应C语言 r ;
  • O_WRONLY|O_APPEND 对应C语言 a ;

标签flags,O_WRONLY、O_CREAT、O_RDONLY、O_APPEND都是宏;

/usr/include/asm-generic/fcntl.h

#define O_ACCMODE 00000003
#define O_RDONLY  00000000
#define O_WRONLY  00000001
#define O_RDWR    00000002
#ifndef O_CREAT
#define O_CREAT   00000100  /* not fcntl */
#endif
#ifndef O_EXCL
#define O_EXCL    00000200  /* not fcntl */
#endif
#ifndef O_NOCTTY
#define O_NOCTTY  00000400  /* not fcntl */
#endif
#ifndef O_TRUNC
#define O_TRUNC   00001000  /* not fcntl */
#endif
#ifndef O_APPEND                                                                 
#define O_APPEND  00002000
#endif

        编程语言使用自己的接口,封装系统接口,是因为需兼容自身语法特征,且系统调用使用成本较高,不具备可移植性;

三,文件描述符

        Linux进程默认会有三个已打开的文件描述符,即0(stdin键盘)、1(stdout显示器)、2(stderr显示器);系统接口函数的返回值即为文件描述符,是从0开始的小整数,实际上是数组的下标;新文件的文件描述符使用当前没被使用的最小下标;

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

int main()      
{      
    int fd1 = open("log1.txt", O_WRONLY|O_CREAT, 0644);      
    int fd2 = open("log2.txt", O_WRONLY|O_CREAT, 0644);      
    int fd3 = open("log3.txt", O_WRONLY|O_CREAT, 0644);      
    int fd4 = open("log4.txt", O_WRONLY|O_CREAT, 0644);      
      
    printf("fd1=%d\n",fd1);  
    close(fd1);    
    printf("fd2=%d\n",fd2);                                                          
    printf("fd3=%d\n",fd3);      
    printf("fd4=%d\n",fd4);      
    return 0;       
}   
//新建的文件会从3开始
[wz@192 Desktop]$ ./target 
fd1=3
fd2=4
fd3=5
fd4=6

结构体指针files

  • 进程task_struct包含一个结构体指针files;

结构体指针files指向的表files_struct

  • 该表包含一个结构体指针数组;
  • 该数组中元素指向打开的文件;

文件结构体

四,输出重定向

//关闭默认打开的1指向的文件,即stdout
//此时新创建的文件,fd将会是1
//本来printf应打印到显示器,此时应该写入到log.txt
int main()    
{    
    close(1);    
    int fd = open("log.txt", O_WRONLY|O_CREAT, 0644);    
    printf("fd=%d\n",fd); 
    close(fd);                                                                                     
    return 0;    
}   
//此时不仅没有打印到屏幕,也没有写入到log.txt
[wz@192 Desktop]$ ./target 
[wz@192 Desktop]$ cat log.txt 
[wz@192 Desktop]$ 

FILE

  • FILE结构体内部包括,文件对应的文件描述符下标fd、及应用层C语言提供的缓冲区数据
  • 向普通文件写入是全缓冲,向屏幕文件写入是行缓冲;
int main()    
{    
    close(1);    
    int fd = open("log.txt", O_WRONLY|O_CREAT, 0644);    
    printf("fd=%d\n",fd); 
    fflush(stdout);
    close(fd);                                                                                     
    return 0;    
}   
//刷新到了log.txt文件
[wz@192 Desktop]$ ./target 
[wz@192 Desktop]$ cat log.txt 
log.txt fd=1

//语言层次上
int main()    
{    
    printf("stdin fd=%d\n",stdin->_fileno);    
    printf("stdout fd=%d\n",stdout->_fileno);    
    printf("stderr fd=%d\n",stderr->_fileno);                                        
    FILE* fp = fopen("log.txt", "r");    
    printf("log.txt fd=%d\n",fp->_fileno);    
    pclose(fp);    
    return 0;    
} 
[wz@192 Desktop]$ ./target 
stdin fd=0
stdout fd=1
stderr fd=2
log.txt fd=3

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

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

相关文章

Xamarin.Android实现手写板的功能

目录 1、背景说明2、实现效果3、代码实现3.1 整体思路3.2 核心绘画类-PaintView.cs3.3 对话框类-WritePadDialog.cs3.4 前端实现类-MainActivity3.5 布局文件3.5.1 write_pad.xml3.5.2 activity_main布局文件 4、知识总结5、代码下载6、参考资料 1、背景说明 在实际使用过程中…

【动态规划刷题 6】 买卖股票的最佳时机含冷冻期 买卖股票的最佳时机含手续费

买卖股票的最佳时机含冷冻期 链接: 买卖股票的最佳时机含冷冻期 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票…

【赠书活动|第四期《互联网广告系统:架构、算法与智能化》】

文章目录 内容简介作者简介读者对象大咖推荐抽奖方式 广告平台的建设和完善是一项长期工程。例如&#xff0c;谷歌早于2003年通过收购Applied Semantics开展Google AdSense 项目&#xff0c;而直到20年后的今天&#xff0c;谷歌展示广告平台仍在持续创新和提升。广告平台是负有…

2024软考系统架构设计师论文写作要点

一、写作注意事项 系统架构设计师的论文题目对于考生来说&#xff0c;是相对较难的题目。一方面&#xff0c;考生需要掌握论文题目中的系统架构设计的专业知识;另一方面&#xff0c;论文的撰写需要结合考生自身的项目经历。因此&#xff0c;如何将自己的项目经历和专业知识有机…

内网穿透:实现公网访问内网群晖NAS的方法

公网远程访问内网群晖NAS 7.X版 【内网穿透】 文章目录 公网远程访问内网群晖NAS 7.X版 【内网穿透】前言1. 在群晖控制面板找到“终端机和SNMP”2. 建立一条连接公网数据隧道3. 获取公网访问内网群晖NAS的数据隧道入口 前言 群晖NAS作为应用较为广泛的小型数据存储中心&#…

RabbitMQ学习——发布订阅/fanout模式 topic模式 rabbitmq回调确认 延迟队列(死信)设计

目录 引出点对点(simple)Work queues 一对多发布订阅/fanout模式以登陆验证码为例pom文件导包application.yml文件rabbitmq的配置生产者生成验证码&#xff0c;发送给交换机消费者消费验证码 topic模式配置类增加配置生产者发送信息进行发送控制台查看 rabbitmq回调确认配置类验…

Shopee虾皮买家号注册时需要注意什么问题

虾皮是一家在线购物平台&#xff0c;如果您打算在虾皮上注册一个买家账号&#xff0c;以下是一些需要注意的问题&#xff1a; 账号安全&#xff1a;确保您选择一个安全的密码&#xff0c;并定期更改密码&#xff0c;以保护您的账号免受未经授权的访问。 个人信息&#xff1a;…

idea报“Could not autowire. No beans of ‘UserMapper‘ type found. ”错解决办法

原因和解决办法 1.原因 idea具有检测功能&#xff0c;接口不能直接创建bean的&#xff0c;需要用动态代理技术来解决。 2.解决办法 1.修改idea的配置 1.点击file,选择setting 2.搜索inspections,找到Spring 3.找到Spring子目录下的Springcore 4.在Springcore的子目录下…

uni-app使用vue语法进行开发注意事项

目录 uni-app 项目目录结构 生命周期 路由 路由跳转 页面栈 条件编译 文本渲染 样式渲染 条件渲染 遍历渲染 事件处理 事件修饰符 uni-app 项目目录结构 组件/标签 使用&#xff08;类似&#xff09;小程序 语法/结构 使用vue 具体项目目录如下&#xff1a; 生命…

三步免费接入 Claude 2.0,支持多账号轮询!

Claude 2.0 已经发布了一段时间&#xff0c;经过我的非暴力测试&#xff0c;比 ChatGPT 3.5 的能力是要强的&#xff0c;有更强大的上下文 100k&#xff0c;相当于 10 万字的上下文记忆,非常适合处理长文档和大的代码段&#xff0c;虽说有些方面略逊色 ChatGPT 4.0 &#xff0c…

日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理

日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理 目录 日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理 1、在线Json &#xff0c;可以在线进行json 格式验证&#xff0c;解析转义等操作 2、Gif动图分解&#xff0c;在线把 gif 图分解成一张张单图 3、在线P…

仓储10、20代电子标签接口文档

标签注册 仓储10代注册 右下角左下角组合按键触发注册 注册成功&#xff1a;右上角绿灯变红灯&#xff0c;并显示信号强度的数值 ​ 仓储20代注册 右下角左下角组合按键触发注册 注册成功&#xff1a;右上角绿灯变红灯&#xff0c;并显示信号强度的数值 ​ 查询电子标签信息…

dinput8.dll导致游戏打不开的解决方法,快速修复dinput8.dll文件

当你尝试启动某个游戏时&#xff0c;如果遇到dinput8.dll文件缺失或损坏的错误提示&#xff0c;可能会导致游戏无法正常运行。dinput8.dll是DirectInput API的一部分&#xff0c;它提供了游戏手柄、键盘和鼠标等输入设备的支持。本文将详细介绍dinput8.dll的作用、导致游戏无法…

核心板如何选择合适的封装?

▍引言 核心板如何选择合适的封装&#xff1f; 核心板是一种集成了CPU、内存、存储、网络等功能的微型计算机模块&#xff0c;可以作为嵌入式系统的核心部件&#xff0c;或者作为开发板的扩展模块。核心板的封装方式决定了它与底板或者开发板的连接方式&#xff0c;影响着核心…

PP-ChatOCR:基于文心大模型的通用图像关键信息抽取利器,开发提效50%!

在日常生活中&#xff0c;大家经常会遇到图像关键信息自动抽取的场景&#xff0c;比如身份证拍照上传自动识别、发票拍照上传自动报销等。 在这个领域&#xff0c;现有的AI技术方案已经能解决一部分需求&#xff0c;但是依然存在一些痛点&#xff0c;比如发票的种类样式极其繁多…

低代码、逻辑、规则、数据分析、协同工具集合,解决企业不同需求

大家好&#xff0c;我是为IT部门兄弟操碎了心的“软件部长”&#xff0c;随着企业IT建设的不断发展&#xff0c;软开企服也在经历了数十年的项目中积累了丰富的经验&#xff0c;为此开始了IT软件的研发之路&#xff0c;之后就一发不可收拾。。。才有了现在出现在市面上的JVS。 …

CVPR 2023 | Attention-Based Point Cloud Edge Sampling

注1:本文系“计算机视觉/三维重建论文速递”系列之一,致力于简洁清晰完整地介绍、解读计算机视觉,特别是三维重建领域最新的顶会/顶刊论文(包括但不限于 CVPR, ICCV, ECCV, NeurIPS等)。本次介绍的论文是: CVPR 2023 | Attention-Based Point Cloud Edge Sampling CVPR 2023 | …

Vue2嵌入HTML页面空白、互相传参、延迟加载等问题解决方案

一、需求分析 最近做的一个用H5加原生开发的html项目&#xff0c;现需要集成到Vue2.0项目里面来。遇到的相关问题做个记录和总结&#xff0c;以便能帮到大家避免踩坑。 二、问题记录 1、页面空白问题 将html页面通过iframe的方式嵌入进来之后&#xff0c;发现页面是空白的&am…

Why Test?

Why Test&#xff1f; 可测试性&#xff08;testability&#xff09;是一种设计的属性&#xff0c;衡量了全面测试制造设计的正确性的难易程度。原始的设计和测试过程是分开的&#xff0c;只有在设计周期的结尾考虑测试。而DFT将测试和设计融合在一起。 来自foundary的device…

Java面向对象++

面向对象编程(高级部分) 类变量和类方法 类变量 类变量也叫静态变量/静态属性&#xff0c;是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。 定义语法: 访问修饰符static数据类型变量…