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

linux篇【8】:基础IO—<后序>

目录

一.myshell中实现重定向

1.myshell中实现重定向

二.标准输出与标准错误

小知识点:linux下的c++后置——.cpp / .cc / .cxx

1. 示例解释

./a. out > stdout. txt 解释:

 ./a.out 1> stdout. txt 2>stderr. txt 解释:

 ./a.out 1> stdout. txt 2>stderr. txt的意义:

 ./a. out > all. txt 2>&1:

2.perror和模拟实现

三.文件系统

1. 磁盘的物理结构

2.磁盘的存储结构

3.磁盘的逻辑抽象结构

(1)LBA地址转换为CHS地址( 磁柱(Cylinder),磁面(Head),扇区(Sector) )


一.myshell中实现重定向

1.myshell中实现重定向

ChangeDir

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

#define SEP " "
#define NUM 1024
#define SIZE 128

//跳过 //ls -a -l>>  log.txt 的>>和log.txt之间空格操作:
#define DROP_SPACE(s) do { while(isspace(*s)) s++; }while(0)

char command_line[NUM];
char *command_args[SIZE];

char env_buffer[NUM]; //for test

#define NONE_REDIR  -1
#define INPUT_REDIR  0
#define OUTPUT_REDIR 1
#define APPEND_REDIR 2

int g_redir_flag = NONE_REDIR;
char *g_redir_filename = NULL;

extern char**environ;

//对应上层的内建命令
int ChangeDir(const char * new_path)
{
    chdir(new_path);

    return 0; // 调用成功
}

void PutEnvInMyShell(char * new_env)
{
    putenv(new_env);
}

void CheckDir(char *commands)
{
    assert(commands);
    //[start, end)
    char *start = commands;
    char *end = commands + strlen(commands);
    // ls -a -l
    while(start < end)
    {
        if(*start == '>')
        {
            if(*(start+1) == '>')
            {
                //ls -a -l>>  log.txt --追加
                *start = '\0';
                start += 2;
                g_redir_flag = APPEND_REDIR;
                DROP_SPACE(start);
                g_redir_filename = start;
                break;
            }
            else{
                //ls -a -l > log.txt -- 输出重定向
                *start = '\0';
                start++;
                DROP_SPACE(start);
                g_redir_flag = OUTPUT_REDIR;
                g_redir_filename = start;
                break;
            }
        }
        else if(*start == '<')
        {
            // 输入重定向
            *start = '\0';
            start++;
            DROP_SPACE(start);
            g_redir_flag = INPUT_REDIR;
            g_redir_filename = start;
            break;
        }
        else 
        {
            start++;
        }
    }
}

int main()
{
    //shell 本质上就是一个死循环
    while(1)
    {
        g_redir_flag = NONE_REDIR;
        g_redir_filename = NULL;

        //不关心获取这些属性的接口, 搜索一下
        //1. 显示提示符
        printf("[张三@我的主机名 当前目录]# ");
        fflush(stdout);

        //2. 获取用户输入
        memset(command_line, '\0', sizeof(command_line)*sizeof(char));
        fgets(command_line, NUM, stdin); //键盘,标准输入,stdin, 获取到的是c风格的字符串, '\0'
        command_line[strlen(command_line) - 1] = '\0';// 清空\n

        //2.1 ls -a -l>log.txt or cat<file.txt or ls -a -l>>log.txt or ls -a -l
        // ls -a -l>log.txt -> ls -a -l\0log.txt
        CheckDir(command_line);

        //3. "ls -a -l -i" -> "ls" "-a" "-l" "-i" 字符串切分
        command_args[0] = strtok(command_line, SEP);
        int index = 1;
        // 给ls命令添加颜色
        if(strcmp(command_args[0]/*程序名*/, "ls") == 0 ) 
            command_args[index++] = (char*)"--color=auto";
        // = 是故意这么写的
        // strtok 截取成功,返回字符串其实地址
        // 截取失败,返回NULL
        while(command_args[index++] = strtok(NULL, SEP));

        //for debug
        //for(int i = 0 ; i < index; i++)
        //{
        //    printf("%d : %s\n", i, command_args[i]);
        //}
    
        // 4. TODO, 编写后面的逻辑, 内建命令
        if(strcmp(command_args[0], "cd") == 0 && command_args[1] != NULL)
        {
            ChangeDir(command_args[1]); //让调用方进行路径切换, 父进程
            continue;
        }
        if(strcmp(command_args[0], "export") == 0 && command_args[1] != NULL)
        {
            // 目前,环境变量信息在command_line,会被清空
            // 此处我们需要自己保存一下环境变量内容
            strcpy(env_buffer, command_args[1]);
            PutEnvInMyShell(env_buffer); //export myval=100, BUG?
            continue;
        }

        // 5. 创建进程,执行
        pid_t id = fork();
        if(id == 0)
        {
            int fd = -1;
            switch(g_redir_flag)
            {
                case NONE_REDIR:
                    break;
                case INPUT_REDIR:
                    fd = open(g_redir_filename, O_RDONLY);
                    dup2(fd, 0);
                    break;
                case OUTPUT_REDIR:
                    fd = open(g_redir_filename, O_WRONLY | O_CREAT | O_TRUNC);
                    dup2(fd, 1);
                    break;
                case APPEND_REDIR:
                    fd = open(g_redir_filename, O_WRONLY | O_CREAT | O_APPEND);
                    dup2(fd, 1);
                    break;
                default:
                    printf("Bug?\n");
                    break;
            }
            //child
            // 6. 程序替换, 会影响曾经子进程打开的文件吗?不影响
            //exec*?
            execvp(command_args[0]/*不就是保存的是我们要执行的程序名字吗?*/, command_args);
            exit(1); //执行到这里,子进程一定替换失败
        }
        int status = 0;
        pid_t ret = waitpid(id, &status, 0);
        if(ret > 0)
        {
            printf("等待子进程成功: sig: %d, code: %d\n", status&0x7F, (status>>8)&0xFF);
        }
    }// end while
}

二.标准输出与标准错误

小知识点:linux下的c++后置——.cpp / .cc / .cxx

1. 示例解释

./a. out > stdout. txt 解释:

默认只能重定向标准输出

 ./a.out 1> stdout. txt 2>stderr. txt 解释:

1> stdout. txt:stdout的内容重定向;2>stderr. txt stderr的内容重定向

 ./a.out 1> stdout. txt 2>stderr. txt的意义:

可以区分哪些是程序日常输出哪些是错误!——日至等级

 

 ./a. out > all. txt 2>&1:

把标准输出和标准错误混着输到一个文件

 

解释:./a.out > all.txt 是普通的把标准输出重定向——把[1]指向了文件all.txt,2>&1是把[1]拷贝给[2],使得标准错误重定向——把[2]也指向了文件all.txt

2.perror和模拟实现

 

errno:C语言有一个全局变量,记录最近一次C库函数调用失败的原因!

三.文件系统

上面我们学到的所有的东西,全部都是在内存中,但是不是所有的文件都被打开了——大量的文件就在磁盘上 静静的躺着,这批文件非常多,杂,乱
磁盘基本的文件管理,本质工作和快递点的老板做的工作是一样的。磁盘基本的文件管理就叫文件系统。
所以我们要把视角从内存中移开,迁移到磁盘上!

1. 磁盘的物理结构

磁盘是我们电脑上的唯一的一个机械设备,目前,同学们笔记本上,可能已经不用磁盘了。而是SSD
你的文件数据,就在这个盘面上。

磁盘图片:

一个面,一个磁头!
机械式+外设 = 磁盘一定是很慢的(CPU,内存)
磁盘存储数据:电子分NS极,磁盘的一面有很多个类似电子的单元,通过磁头改变电子的NS几来改变01。
磁性:N,S极
改变NS极——>就是改变了01

2.磁盘的存储结构

磁盘上存储的基本单位是扇区512字节
读写磁盘的时候,磁头找的是某一个面某一个磁道某一个扇区

哪一个面由哪一个磁头决定;哪个磁道——>要知道是哪一个柱面的——>距离圆心的半径——>也是由哪一个磁头决定;哪一个扇区——>磁道上的一段——>由盘面旋转决定的

 

 柱面:

文件系统:什么文件,对应了几个磁盘块!
物理上查找某一个扇区的寻址方式叫 CHS地址(对应下图        磁柱(Cylinder),磁面(Head),扇区(Sector)):只要我们能找到磁盘上的盘面,柱面(磁道),扇区找到一个存储单元。用同样的方法,我们可以找到所有的基本单元! !

 

3.磁盘的逻辑抽象结构

类比磁带,把磁盘抽象成一个数组。假设有10000000个扇区,每个扇区是512字节,类型是sector

对磁盘的管理,转化成为了对数组空间的管理! !定位一个sector,只要找到下标就行了!这里的下标叫做 LBA(logic block address 逻辑块地址)

(1)LBA地址转换为CHS地址( 磁柱(Cylinder),磁面(Head),扇区(Sector) 

假如要找第3234个扇区,假如有4个磁盘面,4个磁盘面放在一个数组,一面假设是1000个扇区,3234/1000=3,第一面是0~1000,第二面是1000~2000,第三面是2000~3000,第四面是3000~4000。所以3234这个扇区在第4面,磁面H=4,假设一个磁盘面上有20个磁道,3234%1000=234,234/20=11,磁柱C=11,234%20=14,扇区S=14,即可得到CHS地址的三个值

 

相关文章:

  • Vue复刻华为官网 (二)
  • SQL每日一练(牛客新题库)——第15天:汇总数据
  • 【ArchSummit】Web3.0去中心化预言机网络技术剖析
  • TI单芯片毫米波雷达代码走读(二十六)—— 角度维(3D)处理之 DFT
  • Python提取pdf中的表格数据(附实战案例)
  • YOLOv5、v7改进之三十七:结合CVPR2022新作ConvNeXt网络
  • [SpringBoot] AOP-AspectJ 切面技术
  • Prometheus + Grafana 监控SpringBoot项目
  • [C]编译和预处理详解
  • C++入门(正在更新)
  • 风控大佬的一天从这两张报表开始(搬砖)了
  • 【SpringBoot】72、SpringBoot中集成Graylog分布式日志框架
  • STM32CubeMX学习笔记(44)——USB接口使用(HID按键)
  • ElasticSearch 学习(一)-- 概念
  • 用户登录权限校验 JWT【详解】
  • 【译】JS基础算法脚本:字符串结尾
  • 【知识碎片】第三方登录弹窗效果
  • es6--symbol
  • HTML5新特性总结
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • OSS Web直传 (文件图片)
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Python利用正则抓取网页内容保存到本地
  • Redis字符串类型内部编码剖析
  • Sublime text 3 3103 注册码
  • Travix是如何部署应用程序到Kubernetes上的
  • V4L2视频输入框架概述
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 深度学习入门:10门免费线上课程推荐
  • 十年未变!安全,谁之责?(下)
  • 微信小程序:实现悬浮返回和分享按钮
  • 中文输入法与React文本输入框的问题与解决方案
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • ionic异常记录
  • #AngularJS#$sce.trustAsResourceUrl
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #pragma pack(1)
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (06)Hive——正则表达式
  • (175)FPGA门控时钟技术
  • (2)空速传感器
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (function(){})()的分步解析
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (多级缓存)缓存同步
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (过滤器)Filter和(监听器)listener
  • (一)基于IDEA的JAVA基础12
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)visual stdio 书签功能介绍
  • (转)为C# Windows服务添加安装程序
  • **CI中自动类加载的用法总结
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?