Linux —— 基础I/O

一,背景介绍

        狭义的文件存放在磁盘上,广义上在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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uC-OS2 V2.93 STM32L476 移植:串口打印篇

前言 前几篇已经 通过 STM32CubeMX 搭建了 NUCLEO-L476RG 的 STM32L476RG 的 裸机工程&#xff0c;下载了 uC-OS2 V2.93 的源码&#xff0c;并把 uC-OS2 的源文件加入 Keil MDK5 工程&#xff0c;通过适配 Systick 系统定时器与 PendSV 实现任务调度&#xff0c;初步让 uC-OS2 …

Facebook商城号最全解析,Facebook Marketplace运营技巧

相信许多做跨境的小伙伴都听说过Facebook商城号。其实所谓的商城并不是Facebook Shop&#xff0c;而是指Facebook Marketplace&#xff0c;它不像前者需要各类入驻条件&#xff0c;只要拥有facebook账号而且所在地区有能够使用marketplace就可以在上面进行商品售卖。这种低成本…

validator入门

validator中文文档地址和英文地址 https://docs.jboss.org/hibernate/validator/4.2/reference/zh-CN/html/validator-gettingstarted.html https://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/#preface自定义hibernate-validator校验 工具类Valid…

设计模式(4)装饰模式

一、介绍&#xff1a; 1、应用场景&#xff1a;把所需的功能按正确的顺序串联起来进行控制。动态地给一个对象添加一些额外的职责&#xff0c;就增加功能来说&#xff0c;装饰模式比生成子类更加灵活。 当需要给一个现有类添加附加职责&#xff0c;而又不能采用生成子类的方法…

谷歌关闭跨域限制.(生成一个开发浏览器),Chrome关闭跨域

(一)、首先找到浏览器在电脑磁盘中的位置,并复制 (二)、复制一个浏览器的快捷方式到桌面(不影响正常浏览器) (三)、chrom鼠标右键属性&#xff0c;修改快捷方式的目标 &#xff08;四&#xff09;chrome.exe 后面添加 --disable-web-security --user-data-dir 复制的Chrome浏览…

力扣hot100刷题记录

二刷hot100&#xff0c;坚持每天打卡&#xff01;&#xff01;&#xff01;Today&#xff1a;2023-8-10 1. 两数之和 // 先求差&#xff0c;再查哈希表 public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> map new HashMap<>();for(int i 0;i&…

窥探系列之Mybatis-plus XML分页查询

mybatisPlus分页查总数 Page类在mybatisPlus中用于分页查询&#xff0c;继承Pagination类&#xff0c;Pagination类的searchCount字段控制是否查询总记录数 顺着看哪里用到了searchCount&#xff1a; com.baomidou.mybatisplus.plugins.PaginationInterceptor 是mybatisPlus…

安防监控视频汇聚EasyCVR平台的FLV视频流在VLC中无法播放的原因排查

众所周知&#xff0c;TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入&#xff0c;包括主流标准协议国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。在视频流的处理与分发上&#xff0c;视频监控…

PyTorch 微调终极指南:第 2 部分 — 提高模型准确性

一、说明 如今&#xff0c;在训练深度学习模型时&#xff0c;通过在自己的数据上微调预训练模型来迁移学习已成为首选方法。通过微调这些模型&#xff0c;我们可以利用他们的专业知识并使其适应我们的特定任务&#xff0c;从而节省宝贵的时间和计算资源。本文分为四个部分&…

如何使用 AT+WEBSERVER 指令实现自定义的 Webserver html 网页配网

开启 AT 固件中的 Webserver 指令和 FS 指令支持 乐鑫官网发布的默认通用 AT 固件不支持 webserver 配网功能&#xff0c; 需要用户自己搭建 esp-at 环境&#xff0c;并在 sdkconfig 中开启 webserver AT 指令 和 FS 指令的支持&#xff0c; 如下图所示&#xff1a; 测试 AT 固…

Elasticsearch 与 OpenSearch:揭开性能差距

作者&#xff1a;George Kobar, Ugo Sangiorgi 对于任何依赖快速、准确搜索数据的组织来说&#xff0c;强大、快速且高效的搜索引擎是至关重要的元素。 对于开发人员和架构师来说&#xff0c;选择正确的搜索平台可以极大地影响你的组织提供快速且相关结果的能力。 在我们全面的…

oracle积累增量和差异增量

积累增量和差异增量&#xff1a; 对于 RMAN 来说&#xff0c;积累增量备份和差异增量备份都是增量备份的一种形式&#xff0c;它们之间的区别在于备份的范围和备份集的方式。 积累增量备份&#xff1a;在进行积累增量备份时&#xff0c;RMAN 会备份自最后一次完全备份或增量备…

FPGA外部触发信号毛刺产生及滤波

1、背景 最近在某个项目中&#xff0c;遇到输入给FPGA管脚的外部触发信号因为有毛刺产生&#xff0c;导致FPGA接收到的外部触发信号数量多于实际值。比如&#xff1a;用某个信号源产生1000个外部触发信号&#xff08;上升沿触发方式&#xff09;给到FPGA输入IO&#xff0c;实际…

PCI 简易通讯控制器有黄色感叹号

一、问题描述 设备管理器中&#xff0c;其他设备中显示 “PCI 简易通讯控制器”驱动未安装&#xff0c;显示黄色感叹号&#xff1a; 二、原因分析 右键该驱动&#xff0c;查看属性ID&#xff0c;显示为&#xff1a; PCI \ VEN_8086&#xff06;DEV_1C3A&#xff06;SUBSYS…

14.3.4 【Linux】使用 LVM thin Volume 让 LVM 动态自动调整磁盘使用率

想像一个情况&#xff0c;你有个目录未来会使用到大约 5T 的容量&#xff0c;但是目前你的磁盘仅有 3T&#xff0c;问题是&#xff0c;接下来的两个月你的系统都还不会超过 3T 的容量&#xff0c; 不过你想要让用户知道&#xff0c;就是他最多有 5T 可以使用就是了&#xff01;…

ECharts 折线图使用相关

一、折线图堆叠设置为不堆叠的方法 官网是这样的&#xff0c;但是不需要这种堆叠形式的如下图&#xff1a; 即&#xff1a;第2条数据值 第1条数据值 第2条数据值 第3条数据值 第2条数据值 第3条数据值 需要改成实际值展示&#xff0c;如下图&#xff1a; 只需要修改stack的…

微信小程序 地图map(电子围栏圆形和多边形)

正常情况下是没有手机上画电子围栏的&#xff0c;公共平台上我也没找到&#xff0c;所以走了一个歪点子&#xff0c;就是给地图添加点击事件&#xff0c;记录点的位置&#xff0c;在画到电子围栏上就是添加电子围栏了&#xff0c;如果只是显示电子围栏就简单了 一、多边形电子…

mybatis-flex探索

mybatis古今未来 最近无意之中发现了一个非常棒的持久层框架mybatis-flex&#xff0c;迫不及待研究了一下 发现简直就是我的梦中情框&#xff0c;之前写ibatis&#xff0c;后来写mybatis&#xff0c;接着写mybatis-plus&#xff0c;接着研究mybatis-flex ibatis ibatis是apa…

Markdown和LaTex的学习

下载Typora Typora(免费版) 轻量级Markdown编辑器 - 哔哩哔哩 (bilibili.com) 部分编辑器需要进入设置 中开启特定的 Markdown 语法&#xff0c;例如 Typora 就需要手动开启 高亮 功能 Typora的使用&#xff1a; Typora中各种使用 - lyluoye - 博客园 (cnblogs.com) 标题 #…

MyBatisPlus快速入门

MyBatisPlus概述和快速入门 概述 基础框架 MyBatisSpringSpringMVC 为什么需要学习&#xff1f; MyBatisPlus可以节省我们大量的工作时间&#xff0c;所有的CRUD都可以自动化完成。还有其他框架JPA、tk-mapper。 简介 是什么&#xff1f; Mybatis本来就是简化JDBC操作的…