【Linux IO】文件描述符、重定向、缓冲区

news2024/9/21 14:28:58

1.open函数

1.1第二个参数的解释;

O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
         上面三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
open("test.txt",O_WRONLY|O_CREAT,0644/*八进制给初始值*/);

1.2open的返回值(重点)

  • 返回值是struct file*指针数组的下标

  • 0:标准输入1:标准输出2:标准错误

#include<iostream>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
using namespace std;

int main()
{
    int fd1=open("test.txt",O_WRONLY|O_CREAT,0644/*°???????*/);
    int fd2=open("test.txt1",O_WRONLY|O_CREAT,0644/*°???????*/);
    int fd3=open("test.txt2",O_WRONLY|O_CREAT,0644/*°???????*/);
    int fd4=open("test.txt3",O_WRONLY|O_CREAT,0644/*°???????*/);
    printf("%d %d %d %d\n",fd1,fd2,fd3,fd4);
    return 0;
}

执行结果:

原理:

2.文件描述符fd

2.1文件描述符的分配规则

上面说了,进程PCB中有一个指向files_struct的指针,这个结构体中又包含一个struct file的指针数组,打开文件就会在指针数组依次添加

那么关闭默认打开的标准输入、标准输出、标准错误文件,会发生什么结果呢?

关闭标准输入,那么新打开文件的文件描述符就是0了

#include<iostream>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
using namespace std;

int main()
{
    close(0);
    int fd1=open("test.txt",O_WRONLY|O_CREAT,0644);
    if(fd1<0)
    {
        cerr<<"open fail";
        return 1;
    }
    cout<<"fd1:"<<fd1<<endl;
    return 0;
}

有上述可以得出文件描述符的分配规则:在files_struct指针数组当中,找到当前没有被使用的 最小的一个下标,作为新的文件描述符。

2.2输入输出重定向

把标准输出关闭在打开一个新文件,再打印就会发现不会打印在显示器,创建的文件中有我们打印的内容,出现了一个输出重定向

#include<iostream>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
using namespace std;

int main()
{
    close(1);
    int fd1=open("test.txt",O_WRONLY|O_CREAT,0644);
    if(fd1<0)
    {
        cerr<<"open fail";
        return 1;
    }
    cout<<"fd1:"<<fd1<<endl;
    return 0;
}

输出重定向原理:

追加重定向只是在打开文件时加一个O_APPEND

#include<iostream>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
using namespace std;

int main()
{
    close(1);
    int fd1=open("test.txt",O_WRONLY|O_CREAT|O_APPEND/*这里修改了*/,0644);
    if(fd1<0)
    {
        cerr<<"open fail";
        return 1;
    }
    cout<<"fd1:"<<fd1<<endl;
    return 0;
}

我前面执行了几次

输入重定向

#include<iostream>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
using namespace std;
int main()
{
    close(0);
    int fd=open("./test.txt",O_RDONLY);
    if(fd<0)
    {
        cerr<<"open fail";
        return(1);
    }
    char s[50];
    while(fgets(s,sizeof(s)-1,stdin))
        cout<<s;
    return 0;
}

2.3dup2

需要重定向是就关闭文件是不是有些麻烦了,使用dup2函数也可以做到一样的效果;

原理:将oldfd拷贝newfd(标准输入、标准输出、标准错误)

#include<iostream>
#include<unistd.h>
using namespace std;
int main()
{
    int fd=open("test.txt",O_WRONLY|O_TRUNC|O_CREAT);
    if(fd<0)
    {
        cerr<<"opne fail";
        return 1;
    }
    dup2(fd,1);
    cout<<"hello wrold"<<endl;
    cout<<"hello IO"<<endl;
    return 0;
}

2.4提出一些问题

Q:如果程序替换文件描述符会改变吗?

A:不会,因为指向文件结构体的指针保存在PCB中的指向的files_struct结构体中的指针数组内,文件描述符是这个指针数组的下标,程序替换替换的是代码和数据;

Q:创建子进程,子进程文件描述符会怎么初始化和文件会新增吗?

A:子进程的PCB是使用父进程的PCB来初始化的,子进程创建PCB,文件描述符使用父进程初始化所以相同,文件当然不会新增,文件在磁盘中只有一份;

3.缓冲区

进程退出时,会将FILE内部的数据刷新到系统缓冲区,再调用系统接口,用户->OS

三种刷新策略:

1.不缓存(直接刷新)

2.行缓冲\n,endl,例:输出到显示器

3.全缓冲(把缓冲区填满就刷新到内核缓冲区),例:写入磁盘文件

#include<stdio.h>
#include<iostream>
#include<unistd.h>
using namespace std;
int main()
{
    const char* s1="hello buffer\n";
    write(1,s1,strlen(s1));
    printf("hello world\n");
    fprintf(stdout,"hello world\n");

    close(1);
    return 0;
}

执行结果:原本打印显示器重定向写到磁盘文件,刷新策略由行刷新变为了全刷新,在函数结束前关闭了磁盘文件,保存在FILE的字符串生命周期结束,write是系统调用接口所以在写入的磁盘文件中;

3.1缓冲区属于PCB、代码、数据哪一个?

#include<stdio.h>
#include<iostream>
#include<unistd.h>
using namespace std;
int main()
{
    const char* s1="hello buffer\n";
    write(1,s1,strlen(s1));
    printf("hello world\n");
    fprintf(stdout,"hello world\n");
    fork();
    return 0;
}

执行结果:缓冲区的数据属于数据,所以遵守写实拷贝的规则,父子进程谁先刷新谁就写实拷贝

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

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

相关文章

MyBatis 连接数据库与增删改查

❤️作者主页&#xff1a;微凉秋意 ✅作者简介&#xff1a;后端领域优质创作者&#x1f3c6;&#xff0c;CSDN内容合伙人&#x1f3c6;&#xff0c;阿里云专家博主&#x1f3c6; ✨精品专栏&#xff1a;数据结构与课程设计 &#x1f525;系列专栏&#xff1a;javaweb 文章目录前…

C++设计模式(8)——命令模式

命令模式 亦称&#xff1a;动作、事务、Action、Transaction、Command 意图 命令模式是一种行为设计模式&#xff0c; 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中&#xff0c; 且能…

linux基本功系列之-lsattr命令实战

文章目录一. lsattr命令实战二. 语法格式及常用选项三. 参考案例3.1 查看指定文件上的隐藏属性&#xff1a;3.2 查看目录的隐藏属性3.3 查看目录中全部文件的隐藏属性总结前言&#x1f680;&#x1f680;&#x1f680; 想要学好Linux&#xff0c;命令是基本功&#xff0c;企业中…

英语学习打卡day4

2023.1.24 1.out of curiosity 出于好奇 out of necessity 出于必要 out of interest 出于利益 out of sympathy 出于同情 out of respect 出于尊敬 out of’ fear 出于害怕 out of desperation 出于不得已/绝望 2.ashore adv.向(或在)岸上;上岸 a在… …的 shore岸- >在…

Java 23种设计模式(5.结构型模式-代理模式)

结构型模式 代理模式 结构型模式描述如何将类或对象按某种布局组成更大的结构。 它分为类结构型模式和对象结构型模式&#xff0c;前者采用继承机制来组织接口和类&#xff0c;后者釆用组合或聚合来组合对象。 由于组合关系或聚合关系比继承关系耦合度低&#xff0c;满足“合成…

分享127个ASP源码,总有一款适合您

ASP源码 分享127个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 127个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1JpOFmxkovbScxmz0_MhUWg?pwd758t 提取码&#x…

算法:一维与二维最大连续子序列和(子矩阵和,c++实现 动态规划)

文章目录一维最大连续子序列和代码示例二维最大连续子序列和、代码示例一维最大连续子序列和 给你一个序列 【-1&#xff0c;-2&#xff0c;3&#xff0c;6&#xff0c;4&#xff0c;-9】的最大的连续的子序列和的值。 什么是最大连续子序列和&#xff0c;首先要满足两个条件…

Java基础 Stream流方法引用异常

Stream流 引例 需求&#xff1a;按照下面要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素 1. 把所有以“曹”开头的元素存储到新集合中 2. 把曹开头&#xff0c;长度为3的元素存储到新集合中 List<String> list List.of("曹操", "…

19.2、Javaweb案例_Servlet代码抽取优化分页数据redis缓存优化分页数据展示

优化Servlet 目的 减少Servlet的数量&#xff0c;现在是一个功能一个Servlet&#xff0c;将其优化为一个模块一个Servlet&#xff0c;相当于在数据库中一张表对应一个Servlet&#xff0c;在Servlet中提供不同的方法&#xff0c;完成用户的请求。 Idea控制台中文乱码解决&…

线性代数复习——行列式

文章目录第一章 行列式1.1 克拉默法则1.2 n阶行列式1.3 特殊行列式1.4 行列式的性质和推论1.5 余子式和代数余子式1.6 范德蒙德行列式第一章 行列式 1.1 克拉默法则 举例&#xff1a; 对于三元线性方程组 {a11x1a12x2a13x3b1a21x1a22x2a23x3b2a31x1a32x2a33x3b3(1)\begin{cas…

Allegro如何自动导弧操作指导

Allegro如何自动导弧操作指导 在做PCB设计的时候,经常会需要给信号线导弧,如果有大量的走线,导弧线是个比较费时间的工作,Allegro可以自动给信号线导弧,如下图 具体操作如下 选择Route选择Unsupported Prototypes

金融帝国实验室(Capitalism Lab)官方正版游戏『优惠活动政策』

「金融帝国实验室」&#xff08;Capitalism Lab&#xff09;Enlight 官方正版游戏「2023春节特卖」 ■时间&#xff1a;2023.01.21&#xff5e;2023.02.28 ■游戏开发商&#xff1a;Enlight Software Ltd. 请您认准以下官方正版游戏购买链接&#xff1a;支持“支付宝&a…

使用ebpf 监控mysqld 内核

一、开发思路分析 我们使用ebpf 监控mysql的话有两个思路去做这件事情 1、kprobe -> hook 掉tcp_sendmsg 和 tcp_recvmsg 一类的内核函数去分析网络协议 2、uprobe -> hook 掉 mysqld 的api函数&#xff0c;然后在此基础上进行统计 我使用的是uprobe 去hook 掉mysql内…

24. 面向对象的思想

1. 面向对象 类似于c/c#/java等高级语言&#xff0c;python从设计之初就已经是一门面向对象的语言&#xff0c;正因为如此&#xff0c;在python中创建一个类和对象是很容易的。关于面向对象的思想及基础&#xff0c;此处不再赘述。 2. 类对象 (1) 类变量&#xff1a;类变量在…

计算机毕业设计选题推荐基于nodejs+Vue360学生宿舍系统

管理员&#xff1b;首页、个人中心、宿舍信息管理、学生管理、宿舍报修管理、访客信息管理、水电费管理、管理员管理、交流论坛、系统管理&#xff0c;学生&#xff1b;首页、个人中心、宿舍报修管理、水电费管理&#xff0c; 前台首页&#xff1b;首页、交流论坛、通知公告、个…

STM32之HAL源码阅读(GPIO章节)

前言 说明 本文只针对于软件层面的阅读&#xff0c;详细操作请查阅对应的手册,使用过标准库的朋友更好的能理解本文针对的是STM32F10x系列&#xff0c;其他的类似 参考资料 STM32F10x中文参考手册 工具 stm32cubemx6.5clion最新版 HAL源码之GPIO的阅读 步骤一&#xff…

Cesium:Indexed 3D Scene Layers (I3S)加载

点击此处,查看完整的OGC标准列表项。Indexed 3D Scene Layers(I3S)标准官网介绍地址为:I3S,相关的GitHub主页地址为:Esri/i3s-spec,其详细介绍文档地址可点击此处查阅。我们的核心点在于介绍如何通过Cesium.js开发框架加载I3S三维场景服务。 目录 Cesium.js:I3S支持情…

JUC面试(九)——Synchronized和Lock的区别

Synchronized和Lock的区别 前言 对象锁&#xff08;synchronized method{}&#xff09;和类锁&#xff08;static sychronized method{}的区别 对象锁也叫实例锁&#xff0c;对应synchronized关键字&#xff0c;当多个线程访问多个实例时&#xff0c;它们互不干扰&#xff0…

基于蜣螂优化的BP神经网络(分类应用) - 附代码

基于蜣螂优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录基于蜣螂优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.蜣螂优化BP神经网络3.1 BP神经网络参数设置3.2 蜣螂算法应用4.测试结果&#xff1a;5.Mat…

Ubuntu16.04安装N卡驱动

最近碰到个实验&#xff0c;需要用pytorch0.4和python2.7的环境&#xff0c;因为环境比较老&#xff0c;所以新显卡可能不能装。紧急联系朋友搞了张1660ti想来跑实验&#xff0c;结果光是驱动就碰了一鼻子灰&#xff0c;这里简单做下总结&#xff0c;引以为戒。首先是系统版本&…