Linux系统编程 --- 基础IO

news2024/11/13 15:41:00

形成共识原理:

1、文件 = 内容 + 属性

2、文件分为打开的文件和没打开的文件

3、打开的文件:谁打开?进程!--- 本质是研究进程和文件的关系!

文件被打开,必须先被加载到内存!

一个进程可以打开多个文件!操作系统内部,一定存在大量的被打开的文件!--- OS需要管理这些被打开的文件,先描述,再组织 --- 在内核中,一个被打开的文件都必须有自己的文件打开对象,包含文件的很多属性。结构体对象。

4、没打开的文件:在哪里放着呢?在磁盘上,我们最关注什么问题?没有被打开的文件非常多。文件如何被分门别类的放置好 --- 我们要快速的进行 增删查改 --- 快速的找到文件。最终就是谈论如何存储。

一、目标:被打开的文件

1、以C语言为主,先回忆一下C文件接口

 fopen,fclose,fprintf,fscanf,fsprintf,fsscanf,fseek,fgetc,fgets,fputc,fputs,fread,fwrite。

当前路径是什么?当前路径指的是进程的当前路径cwd。可以在ls /proc文件中找到对应的pid,进入后就可以看到。如果我更改了当前进程的cwd,就可以把文件新建到更改后的cwd,可以使用chdir这个函数更改工作目录。

w写之前,都会对文件进行清空处理。

文件重定向也可以写入 >       >>以追加的方式写入。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <string.h>
int main()
{
    //C语言文件操作
    FILE* fd = fopen("log.txt","w");
    if(fd == NULL)
        return 1;
    const char* msg = "hello linux file\n";
    fwrite(msg,strlen(msg),1,fd);
    
    fclose(fd);
    return 0;
}

strlen 不需要 + 1,字符串以‘\0’结尾,是C语言的规定,和文件没有关系。

a 在文件结尾,追加写!

Linux一切皆文件 

C++ cin&&cout&&cerr

C stdin&&stdout&&stderr

C程序默认在启动的时候,会打开三个标准输入输出流文件

stdin 键盘设备,stdout 显示器设备,stderr显示器文件

2、过度到系统,认识文件系统调用

文件其实是磁盘上的,磁盘是外部设备,访问文件其实就是在访问硬件!

计算机系统层次。

用户,

程序 

系统调用

操作系统

硬件驱动

硬件

几乎所有的库只要是访问硬件设备,必定要封装系统调用!

flag参数对应的的值

这些选项都是宏

题外话:比特位方式的标志位传递方式。

0000 0001       0000 0010     0000 0001 | 0000 00010 = 0000 0011

0000 0001       0000 0010

实现C语言W的功能。

代码:

int main()
{
    //C语言文件操作
    // FILE* fd = fopen("log.txt","w");
    // if(fd == NULL)
    //     return 1;
    // const char* msg = "hello linux file\n";
    // fwrite(msg,strlen(msg),1,fd);
    
    // fclose(fd);

    //Linux 系统调用
    int fd = open("log.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    umask(0);
    if(fd < 3)
        return 1;
    //系统调用
    const char* msg = "hello linux file\n";
    write(fd,msg,strlen(msg));

    close(fd);
    return 0;
}

mode参数,是被创建文件的权限。以八进制。

设置umask权限掩码 umask(0)。

写入接口

会覆盖但不会清空。

O_TRUNC 清空选项

3、访问文件的本质

返回值类型的区别和联系,FILE* 和 int fd,也就是访问文件的本质。

返回的是int fd 是一个数组的下标 struct files_struct* files里面的一个文件描述符表里的数组下标。

描述文件的结构体:struct file操作系统内描述一个被打开文件的信息。会包含在磁盘的什么位置,基本属性权限,大小,读写位置,谁打开的……,文件的内核缓冲区信息,struct file* next的指针。用双链表链接。文件描述符是从3开始的。0 1 2 被三个标准 stdin stout sterr 占用。这是操作系统的特性。而不是语言方面的特性。

FILE是一个C库自己封装的结构体!里面必须包含文件描述符

struct file里面会包含引用计数count,关闭一个做count--。

4、重定向&&缓冲区

重定向:

文件描述符的分配规则:从0下标开始,寻找最小的没有被使用的数组位置,它的下标就是新文件的文件描述符

代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <string.h>
#include <unistd.h>
int main()
{
    //C语言文件操作
    // FILE* fd = fopen("log.txt","w");
    // if(fd == NULL)
    //     return 1;
    // const char* msg = "hello linux file\n";
    // fwrite(msg,strlen(msg),1,fd);
    
    // fclose(fd);

    //Linux 系统调用
    close(2);
    int fd = open("log.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    umask(0);
    if(!fd)
        return 1;
    //系统调用
    const char* msg = "hello linux file\n";
    //这里输出应该为2
    printf("fd = %d\n",fd);
    write(fd,msg,strlen(msg));

    close(fd);
    return 0;
}

运行结果:

代码原理:也就是重定向的原理

重定向接口dup2

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <string.h>
#include <unistd.h>
int main()
{
    //C语言文件操作
    // FILE* fd = fopen("log.txt","w");
    // if(fd == NULL)
    //     return 1;
    // const char* msg = "hello linux file\n";
    // fwrite(msg,strlen(msg),1,fd);
    
    // fclose(fd);

    //Linux 系统调用
    // close(2);
    // int fd = open("log.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    // umask(0);
    // if(!fd)
    //     return 1;
    // //系统调用
    // const char* msg = "hello linux file\n";
    // //这里输出应该为2
    // printf("fd = %d\n",fd);
    // write(fd,msg,strlen(msg));

    // close(fd);

    int fd = open("log.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    umask(0);
    if(!fd)
        return 1;
    //系统调用
    const char* msg = "hello linux file\n";
    //把3重定向到stdout也就是1
    dup2(fd,1);
    //结果为3
    printf("fd = %d\n",fd);
    //还是写到了文件上
    write(1,msg,strlen(msg));
    close(fd);
    return 0;
}

read() 

输入重定向和输入重定向原理相同

我们做了重定向工作,后面进行程序替换的时候,难道不影响吗?

这是两个系列的操作,互不影响。进程历史打开的文件与进行的各种重定向关系都和未来进行程序替换无关。

5、其他话题

(1)、stdout和stderr 1 vs 2

        代码:

        只对1重定向

        

        (2)、如何理解Linux下一切皆文件

        

类似于我们的多态。 

二、缓冲区

exit VS _exit

写一段代码:

创建子进程后,重定向到文件里,我们的打印条数变成了

这一定和fork有关系。

缓冲区:去掉/n后我们的打印就不见了这是为什么?

这个缓冲区一定不在操作系统内部!不是系统级别的缓冲区!

(1)缓冲区刷新问题

        a.无缓冲 --- 直接刷新

        b.行缓冲 --- 不刷新,直到碰到\n

        c.全缓冲 --- 缓冲区满了才刷新

fprintf/fwrite,写到C缓冲区调用对应的write接口刷新到我们系统缓冲区

(2)补充问题

        显示器:行缓冲

        文件写入:全缓冲

        进程退出的时候也会刷新。

        为什么会有这个缓冲区

        a.解决效率问题 --- 用户的效率问题

        b.配合格式化输入输出

这个缓冲区在哪里?

文件操作离不开,FILE struct,FILE里面还有对应打开文件的缓冲区字段和维护信息。

这个FILE对象属于用户呢还是操作系统呢?缓冲区是不是属于用户级缓冲区呢?

 FILE对象属于用户,语言都属于用户层。这个缓冲区是用户级缓冲区。在语言层malloc(FILE)

int main()
{
    //printf("hello Linux");
    //close(1);

    //return 0;
    const char *fstr = "hello fwrite\n";
    const char *str = "hello write\n";

    // C
    printf("hello printf\n"); // stdout -> 1
    sleep(2);
    fprintf(stdout, "hello fprintf\n"); // stdout -> 1
    sleep(2);
    fwrite(fstr, strlen(fstr), 1, stdout); // fread, stdout->1
    sleep(2);

    // 操作提供的systemcall
    write(1, str, strlen(str)); // 1

    sleep(5);
    //close(1); // ?
    fork();
    return 0;
}

 

为什么被打印了两次呢?这是因为首先是打印的write函数的这个,他直接写入到了系统缓冲区,所以会先打印出来,在fork之后,程序要退出的时候,子进程要刷新缓冲区,所以就发生了写时拷贝,这也就导致了,在用户缓冲区中的数据子进程打印了一遍,父进程也打印了一遍

重定向以后,向文件打印,刷新方案变成了全缓冲,遇到\n不再刷新

模拟实现一下,理解所有的理论,C文件的标准库。

#ifndef __MYSTDIO_H__
#define __MYSTDIO_H__
#define SIZE 1024
//定义刷新方式
//无刷新
#define FLUSH_NOW 1
//行刷新
#define FLUSH_LINE 2
//完全刷新
#define FLUSH_ALL 4
#include <string.h>
typedef struct IO_FILE{
    int fileno;
    char inbuffer[SIZE];
    //输入缓冲区
    char outbuffer[SIZE];
    int out_pos;
    int flag;
}_FILE;

_FILE* _fopen(const char* filename,const char* flag);
int _fwrite(_FILE* fp,const char* s,int len);
void _fclose(_FILE* fp);
#endif 

#include "myfile.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
//w a r
#define FILE_MODE 0666
_FILE* _fopen(const char* filename,const char* flag)
{
    int f = 0;
    int fd = -1;
    if(strcmp(flag,"w") == 0)
    {
        f = (O_CREAT|O_WRONLY|O_TRUNC);
        fd = open(filename,f,FILE_MODE);
    }
    else if(strcmp(flag,"r") == 0)
    {
        f = (O_RDONLY);
        fd = open(filename,f,FILE_MODE);
    }
    else if(strcmp(flag,"a") == 0)
    {
        f = (O_CREAT|O_WRONLY|O_APPEND);
        fd = open(filename,f,FILE_MODE);
    }
    if(fd == -1) return NULL;
    //创建结构体对象
    _FILE* fp = (_FILE*)malloc(sizeof(_FILE));
    if(fp == NULL) return NULL;

    fp->fileno = fd;
    fp->flag = FLUSH_ALL;
    
    fp->out_pos = 0;
    return fp;

}

int _fwrite(_FILE* fp,const char* s,int len)
{
    memcpy(&fp->outbuffer[fp->out_pos],s,len);
    fp->out_pos += len;

    if(fp->flag & FLUSH_NOW)
    {
        write(fp->fileno,fp->outbuffer,fp->out_pos);
        fp->out_pos = 0;
    }
    else if(fp->flag & FLUSH_ALL)
    {
        if(fp->out_pos == SIZE)
        {
            printf("全刷新\n");
            write(fp->fileno,fp->outbuffer,fp->out_pos);
            fp->out_pos = 0;
        }
    }
    else if(fp->flag & FLUSH_LINE)
    {
        if(fp->outbuffer[fp->out_pos - 1] == '\n')
        {
            write(fp->fileno,fp->outbuffer,fp->out_pos);
            fp->out_pos = 0;
        }
    }

    return len;
}
void _fflush(_FILE* fp)
{
    //进程退出时刷新到缓冲区
    if(fp->out_pos > 0)
    {
        write(fp->fileno,fp->outbuffer,fp->out_pos);
        fp->out_pos = 0;
    }
}
void _fclose(_FILE* fp)
{
    if(fp == NULL) return;
    _fflush(fp);
    close(fp->fileno);

    free(fp);
}

FILE里面的缓冲区的意义是什么,提高效率。

二、文件系统Ext2 

一个打开的文件上面已经说过了!

如果一个文件没有被打开呢,磁盘中进行对应的存储。

1、路径问题

2、存储问题

3、获取的问题 (属性 + 文件内容)

4、效率问题

1、认识硬件,磁盘

文件 = 文件内容 + 属性 ->磁盘上存储文件 = 存文件的内容 + 存文件的属性。

文件的内容 --- 数据块

文件属性 --- inode 128字节

结论 :Linux的文件再磁盘中存储,是将属性和内容分开存储的。

唯一的一个机械设备,也是一个外设

2、对硬件进行抽象理解

盘面,磁道,扇区。磁盘被访问的基本单元是扇区 --- 512字节/4KB,我们可以把磁盘看做由无数个扇区构成的存储介质。要把数据存到磁盘,第一个解决的问题是定位一个扇区:哪一面(定位用哪个磁头),哪一个磁道,哪一个扇区。为了提高效率,在软件设计上,一定要把数据放到一起。

LBA地址(逻辑扇区地址) --->CHS(磁道,磁头,扇区),我们就可以把磁盘看为一个线性结构。 

回归到硬件,不仅仅CPU有“寄存器” ,其他设备,磁盘也有,控制寄存器,状态寄存器。数据寄存器,地址寄存器。

3、文件系统

我们在操作系统层面对磁盘分区,和进程地址空间划分区间的方式相同,同样是在内核中定义一个结构体。

Block group里面有什么?

datablocks:存文件内容的区域!以块的形式呈现,常见的是4KB大小 --- 文件系统的大小!

inode table:单个文件的所有属性,128字节。一般而言,一个文件,一个inode,有很多的inode,inode有唯一的编号。在Linux中,文件的属性中,不包含文件的名称,在Linux系统里面标识文件用的是inode编号。

inode bitmap 比特位的位置和inode的编号映射起来,比特位的内容inode是否是有效的。

block bitmap:比特位的位置和块号映射起来,比特位的内容,标识该块有没有被使用!删一个文件的时候,不用把块的文件内容清空!

group descriptor table: 描述整个分组的使用情况。

super block:文件系统的基本信息。包含的是整个分区的基本使用情况,一共有多少个组,每个组的大小、inode数量,block数量、起始inode、文件系统的类型与名称等!

每一个分区在被使用之前,都必须提前先将部分文件系统的属性信息提前设置进对应的分区中,方便我们后续使用这个分组。

新建一个文件,系统需要做什么?Linux系统中,一个文件,一个inode,每一个inode都有自己的inode编号(inode的设置,是以分区为单位的,不能跨分区)。inode表示文件的所有属性,但是文件名并不是inode内的属性!

删除一个文件,系统需要做什么?删除等于允许被覆盖。

查找一个文件,系统需要做什么?

修改一个文件,系统需要做什么?这些都是对我们的文件系统属性进行操作

那我们怎么知道一个文件的inode编号?使用者从来不关心inode,用的是文件名!接下来我们了解什么是“目录”?目录也是文件,也有自己的inode,目录也要有自己的属性!目录里有内容,目录也有数据块,内容就是该目录下文件的文件名和对应文件的inode的映射关系。

(1)为什么同一个目录下不能有同名的文件,会造成inode冲突。

(2)目录下,没有写权限,我们无法创建文件,写不到目录文件里

(3)目录下,没有读权限,我们无法查看文件,无法读取目录文件。

(4)目录下,没有执行权限,我们无法进入这个目录。

目录是文件,也有inode编号,通过路径递归到根目录通过根目录寻找。dentry缓存会保存使用过的目录。

软硬链接

ln -s file.txt soft-link

软连接是一个独立的文件,具有独立的inode,该如何理解软链接?

有独立的数据块,它的数据块里面保存的是目标文件的路径。相当于windows快捷方式。

ln test.txt hard-link

 硬链接数。任意一个文件无论是目录,还是普通文件都有inode,每一个inode内部都有一个叫做引用计数的计数器,类似于指针,C++里面的share_ptr里面的引用计数。有多少个文件名指向我。删一个文件的时候计数器为0的时候该文件才会被真正的删除。

 硬链接不是一个独立的文件,因为他没有独立的inode。该如何理解硬链接?

所谓的建立硬链接,本质其实就是在特定目录的数据块中新增文件名和指向的文件inode编号的映射关系!

他们的应用场景是:

软链接:就是为了创建快捷方式,使我们可以不带路径执行程序。

硬链接:./   ../ 就是硬链接的方式,通常用来路径定位,采用硬链接可以进行目录间的切换。

Linux系统不允许对目录建立硬链接 --- 为什么 ?会产生环路

目录内部有. / .. 不是目录的硬链接吗?操作系统自己建立的。不是我们用户建立的。系统在搜索时不会对./ ../进行搜索。

补充知识:

1、物理内存也需要进行管理,操作系统会有内存管理模块!物理内存为页框,磁盘为页帧。是磁盘和内存之间交换数据的单位。会存在局部性原理,在正在访问区的附近可能也会被访问,基于局部性原理!预加载机制。减少IO的次数,减少访问外设的次数。

2、操作系统怎么管理内存,操作系统可以看到内存的物理地址的。先描述再组织。

struct page{

        //page页必要的属性信息

}

struct page mem_array[1048576],对内存的管理变成了对数组的管理!我们要访问一个内存,我们只需要先直接找到这个4kb对应的Page,就能在系统中找到对应物理页框,所有申请内存的操作,都是在访问内存page数组!

3、

4、基数树or基树,字典树

这些知识都是在内存管理中的知识。我们通过地址就可以映射到内存的数据块中,定时向磁盘中刷新,刷新会设计到IO子系统。这就导致了大量的IO,操作系统中就会对大量的IO进行管理,六字真言,先描述,再组织。IO子系统方面需要我们在今后的学习中慢慢了解。这里就不展开讲了。

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

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

相关文章

PyTorch 训练自定义功能齐全的神经网络模型的详细教程

在前面的文章中&#xff0c;老牛同学介绍了不少大语言模型的部署、推理和微调&#xff0c;也通过大模型演示了我们的日常的工作需求场景。我们通过大语言模型&#xff0c;实实在在的感受到了它强大的功能&#xff0c;同时也从中受益颇多。 今天&#xff0c;老牛同学想和大家一…

【Android Studiio】default activity 原生安卓和uniapp默认启动分析

文章目录 思路&#xff1a; 一、原生安卓二、uniapp 探究方向&#xff1a;找到Default Activity 思路&#xff1a; 在Android开发中&#xff0c;"default activity"这个概念通常指的是应用启动时默认会加载和显示的那个Activity。AndroidManifest.xml文件是Android…

基于Selenium实现操作网页及操作windows桌面应用

Selenium操作Web页面 Why? 通常情况下&#xff0c;网络安全相关领域&#xff0c;更多是偏重于协议和通信。但是&#xff0c;如果协议通信过程被加密或者无法了解其协议构成&#xff0c;是无法直接通过协议进行处理。此时&#xff0c;可以考虑模拟UI操作&#xff0c;进而实现相…

声音和数据之间的调制解调 —— 电报机和电传打字机如何影响计算机的演变

注&#xff1a;机翻&#xff0c;未校对。 The Squeal of Data The through line between the telegraph and the computer is more direct than you might realize. Its influence can be seen in common technologies, like the modem. 电报和计算机之间的直通线比你想象的要…

基于IOT架构的数据采集监控平台!

LP-SCADA数据采集监控平台是蓝鹏测控推出的一款聚焦于工业领域的自动化数据采集监控系统&#xff0c; 助力数字工厂建设的统一监控平台。 为企业提供从下到上的完整的生产信息采集与集成服务&#xff0c;从而为企业综合自动化、工厂数字化及完整的"管控一体化”的解决方案…

LockSupport详解

文章目录 理解可重入锁LockSupport线程等待唤醒机制&#xff08;wait/notify&#xff09; waitNotify限制awaitSignal限制LockSupport重点说明 理解可重入锁 可重入锁的种类&#xff1a; 隐式锁&#xff08;即synchronized关键字使用的锁&#xff09;默认是可重入锁。 同步代…

站在临床数据科学的角度,药物试验归根结底是这两大假设

在临床数据科学的领域中&#xff0c;药物试验的设计和实施是评估药物效果及其安全性的关键环节。药物试验的基础无外乎两大核心假设&#xff1a;有效性与安全性。这两个假设不仅是药物试验的起点&#xff0c;也是整个研究过程中的重要指导原则。 药物试验的核心主旨在于对待测试…

Python高性能计算:进程、线程、协程、并发、并行、同步、异步

这里写目录标题 进程、线程、协程并发、并行同步、异步I/O密集型任务、CPU密集型任务 进程、线程、协程 进程、线程和协程是计算机程序执行的三种不同方式&#xff0c;它们在资源管理、执行模型和调度机制上有显著的区别。以下是对它们的详细解释和比较&#xff1a; 进程&…

一款有趣的工具,锁定鼠标键盘,绿色免安装

这是一款完全免费的程序&#xff0c;可以实现在不锁定屏幕的情况下锁定鼠标键盘&#xff0c;让鼠标键盘无法操作。比较适合防止误碰鼠标键盘&#xff0c;以及离开电脑时不希望别人操作自己的电脑。 ★★★★★锁定鼠标键盘工具&#xff1a;https://pan.quark.cn/s/e5c518a2165…

路由配置修改(五)

一、默认约定式路由 1、umi 会根据 pages 目录自动生成路由配置。 * name umi 的路由配置* description 只支持 path,component,routes,redirect,wrappers,name,icon 的配置* param path path 只支持两种占位符配置&#xff0c;第一种是动态参数 :id 的形式&#xff0c;第二种…

win11 intel新显卡控制面板无自定义分辨率选项解决

问题 下图是现在的intel显卡控制面板&#xff0c;不知道为啥变得很傻瓜式了&#xff0c;连所有显卡控制面板都有的分辨率自定义也被干掉了。 解决方式 其实解决很简单&#xff0c;因为自定义分辨率对显卡玩游戏来说还是很常用的&#xff0c;intel在beta版又加回来了&#x…

样式与特效(2)——新闻列表

1.盒子模型的边距概念 ) Margin-top 上面 Margin-bottom 底部 Margin-right 右边 Margin-left 左边 Margin : 10px &#xff08;上下左右都是10px&#xff09; Margin &#xff1a;10px,20px (上下边距10px 左右20px) CSS里面最重要的属性之一 将页面理解成…

C++ | Leetcode C++题解之第316题去除重复字母

题目&#xff1a; 题解&#xff1a; class Solution { public:string removeDuplicateLetters(string s) {vector<int> vis(26), num(26);for (char ch : s) {num[ch - a];}string stk;for (char ch : s) {if (!vis[ch - a]) {while (!stk.empty() && stk.back(…

C#值类型和引用类型,类和结构体

1、类class是引用类型&#xff0c;多个引用类型变量的值会互相影响。存储在堆&#xff08;heap&#xff09;上 2、结构体struct是值类型&#xff0c;多个值类型变量的值不会互相影响。存储在栈&#xff08;stack&#xff09;上 using System; using System.Collections.Generi…

PTA题目|象限的判断(python)

题目要求 输入一对坐标&#xff0c;输出它在直角坐标系中的象限。 输入格式: 输入坐标(x,y)&#xff0c;&#xff08;假设输入的x或y坐标值一定不会为0&#xff09;如&#xff1a;(3.5,-2)。 输出格式: 输出对应的象限&#xff0c;如&#xff1a;第四象限 输入样例: 在这…

Python | Leetcode Python题解之第315题计算右侧小于当前元素的个数

题目&#xff1a; 题解&#xff1a; import numpy as np from bisect import bisect_leftclass Solution:max_len 10000c []buckets []def countSmaller(self, nums: List[int]) -> List[int]:self.c [0 for _ in range(len(nums) 5)]counts [0 for _ in range(len(…

Sentinel-1 Level 1数据处理的详细算法定义(五)

《Sentinel-1 Level 1数据处理的详细算法定义》文档定义和描述了Sentinel-1实现的Level 1处理算法和方程,以便生成Level 1产品。这些算法适用于Sentinel-1的Stripmap、Interferometric Wide-swath (IW)、Extra-wide-swath (EW)和Wave模式。 今天介绍的内容如下: Sentinel-1 L…

前端怎么做一个验证码和JWT,使用mockjs模拟后端

流程图 创建一个发起请求 创建一个方法 getCaptchaImg() {this.$axios.get(/captcha).then(res > {console.log(res);this.loginForm.token res.data.data.tokenthis.captchaImg res.data.data.captchaImgconsole.log(this.captchaImg)})}, captchaImg: "", 创…

钡铼技术M12双通道防水分线盒稳定可靠

钡铼技术的DB系列M12双通道防水分线盒是一款专为工业自动化环境设计的高性能产品。其采用耐酸碱腐蚀材料制成的壳体&#xff0c;能够达到IP67防护等级&#xff0c;并通过灌胶工艺进一步提升到IP69K防护等级&#xff0c;确保在恶劣的工业条件下仍然能稳定可靠地运行。 技术特点…

小怡分享之Java的继承和多态

前言&#xff1a; &#x1f308;✨小怡给大家分享了Java的类和对象&#xff0c;今天小怡给大家分享的是继承和多态。 1.继承 1.1 为什么需要继承 Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&…