草庐IT

【Linux】基础IO

ζ◇十点半就睡觉 2023-05-14 原文

文章目录

基础IO

1. 系统文件I/O

操作文件,除了C接口外,我们还可以采用系统接口来进行文件访问,我们来看看如下代码:

读文件

1.1 接口介绍

open man open

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

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

pathname: 要打开或者创建的目标文件
flags:打开文件时,可以传入多个参数选项,用下面的一个或者多个进行“或”运算,构成flags
参数:
    O_RDONLY:只读打开
    O_WRONLY:只写打开
    O_RDWR:读,写打开
    		这三个常量必须指定,并且只能指定一个
    O_CREAT:若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
    O_APPEND:追加写
    
返回值:
    成功:新打开的文件描述符
    失败:-1

open函数具体使用那个,和具体的应用场景有关,如果目标文件不存在,需open创建,第三个参数表示创建文件的默认权限。

1.2 open函数返回值

认识一下两个概念:系统调用和库函数

  • fopen fclose fread fwrite都是C语言标准库中的函数,我们称之为库函数
  • open close read write lseek 都属于系统提供的接口,称为系统调用接口

之前的博客中用到的一张图:

系统调用接口和库函数的关系一目了然

1.3 文件描述符

我们知道了文件描述符就是一个小小的整数

在计算机操作系统中,文件描述符是用于访问文件和I/O设备的一个抽象概念。它是一个非负整数,用来标识一个已经打开的文件或I/O设备。在Unix、Linux和其他类Unix系统中,文件描述符是一种非常常见的概念。

文件描述符通常被用于在程序中访问打开的文件或设备,如磁盘文件、标准输入、标准输出等。它们是一种轻量级的机制,能够提供高效、灵活的I/O操作,因为它们可以被用来表示任何类型的I/O流,包括文件、管道、套接字等。

文件描述符通常是通过调用系统调用(如open、close、read、write等)返回的,操作系统会维护一个表格来跟踪打开的文件和设备以及相应的文件描述符。在使用文件描述符时,程序需要保证文件描述符的唯一性,因为文件描述符是在系统范围内唯一的。

一般来说,标准输入、标准输出和标准错误输出的文件描述符分别是0、1、2。其他文件描述符的值通常是由操作系统分配的,通常是一个递增的整数。例如,打开一个文件会返回一个新的、当前未使用的文件描述符。关闭文件时,该文件描述符会被释放,并可以被其他打开的文件或设备使用。

1.4 0 & 1 & 2

  • Linux默认情况下会有3个缺省打开的文件描述符,分别是标准输入0,标准输出1,标准错误2
  • 0,1,2对应的物理设备一般是:键盘,显示器,显示器

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

现在我们知道,文件描述符就是从0开始的整数。当我们打开文件的时候,操作系统要创建相应的数据结构来描述目标文件,于是就有了file结构体。表示已经打开的文件对象。而执行open系统调用,所以必须要让进程和文件关联起来。每个进程都有一个*files指针,指向一张表files_struct,这个表最重要的部分就是包含了一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是这个数组的下标。所以,只要拿着文件描述符就可以找到对应的文件

1.5 文件描述符的分配规则

我们可以查看如下代码:

输出查看我们发现是:3

关闭0或者2重新查看:

我们可以发现这个规律:文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符

1.6 重定向

如果我们关闭1会发生怎么的事情呢?我们看如下代码:


此时我们发现本该在显示器上显示的内容,输出到了文件当中。这种现象叫做重定向

2. 使用dup2系统调用

函数原型是这样:

#include <unistd.h>

int dup2(int oldfd, int newfd);

printf是C库当中的一个IO函数,一般往stdout中输出,但是stdout访问底层文件的时候还是找的是fd : 1,但是fd1已经变成了myfile的地址,不在是显示器文件的地址,所以输出的任何消息都是往文件中写入,进而完成输出重定向。

3. FILE

  • 因为IO相关的函数与系统调用接口对应,并且库函数封装系统调用,所以本质上访问文件都是通过fd访问的
  • C库的FILE内部,必定封装了fd

以上的代码运行结果是:

但是我们如果对进程实现输出重定向会怎么样?.test > myfile,我们发现结果是这样:

我们发现printffwrite都输出了两次,但是write只输出了一次(系统调用)这是为什么?

  • 一般C库函数写入文件是全缓冲,但是写入显示器是行缓冲
  • printffwrite自带缓冲区,当发生重定向到普通文件的时候,数据的缓冲方式变成了全缓冲
  • 而我们放在缓冲区的数据就不会立即刷新,甚至fork之后
  • 但是进程退出之后,会统一刷新,写入到文件当中
  • fork的时候父子进程数据会发生写时拷贝,所以当父进程准备刷新的时候,子进程也有了同样的数据,随机产生两份数据
  • write没有所谓的缓冲

所以我们可以发现:printffwrite库函数自带缓冲区,而write系统调用没有带缓冲区,另外这里的缓冲区都是用户级缓冲区

有关【Linux】基础IO的更多相关文章

  1. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  2. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  3. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  4. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  5. 软件测试基础 - 2

    Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功

  6. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  7. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  8. 【网络】-- 网络基础 - 2

    (本文是网络的宏观的概念铺垫)目录计算机网络背景网络发展认识"协议"网络协议初识协议分层OSI七层模型TCP/IP五层(或四层)模型报头以太网碰撞路由器IP地址和MAC地址IP地址与MAC地址总结IP地址MAC地址计算机网络背景网络发展        是最开始先有的计算机,计算机后来因为多项技术的水平升高,逐渐的计算机变的小型化、高效化。后来因为计算机其本身的计算能力比较的快速:独立模式:计算机之间相互独立。    如:有三个人,每个人做的不同的事物,但是是需要协作的完成。    而这三个人所做的事是需要进行协作的,然而刚开始因为每一台计算机之间都是互相独立的。所以前面的人处理完了就需要将数据

  9. 【Linux操作系统】——网络配置与SSH远程 - 2

    Linux操作系统——网络配置与SSH远程安装完VMware与系统后,需要进行网络配置。第一个目标为进行SSH连接,可以从本机到VMware进行文件传送,首先需要进行网络配置。1.下载远程软件首先需要先下载安装一款远程软件:FinalShell或者xhell7FinalShellxhell7FinalShell下载:Windows下载http://www.hostbuf.com/downloads/finalshell_install.exemacOS下载http://www.hostbuf.com/downloads/finalshell_install.pkg2.配置CentOS网络安装好

  10. Linux磁盘分区中物理卷(PV)、卷组(VG)、逻辑卷(LV)创建和(LVM)管理 - 2

    文章目录一基础定义二创建逻辑卷2-1准备物理设备2-2创建物理卷2-3创建卷组2-4创建逻辑卷2-5创建文件系统并挂载文件三扩展卷组和缩减卷组3-1准备物理设备3-2创建物理卷3-3扩展卷组3-4查看卷组的详细信息以验证3-5缩减卷组四扩展逻辑卷4-1检查卷组是否有可用的空间4-2扩展逻辑卷4-3扩展文件系统五删除逻辑卷5-1备份数据5-2卸载文件系统5-3删除逻辑卷5-4删除卷组5-5删除物理卷六LVM逻辑卷缩容6-1缩容注意事项6-2标准缩容步骤一基础定义LVM,LogicalVolumeManger,逻辑卷管理,Linux磁盘分区管理的一种机制,建立在硬盘和分区上的一个逻辑层,提高磁盘分

随机推荐