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

文件系统 软硬连接

 🌻个人主页:路飞雪吖~

       🌠专栏:Linux


目录

 

一、理解文件系统

🌠磁盘结构

二、软硬连接

🌟软硬链接

🌠软链接:

🌠硬链接:

🌟理解软硬链接的应用场景

✨软链接

✨硬链接


如若对你有帮助,记得关注、收藏、点赞哦~ 您的支持是我最大的动力🌹🌹🌹🌹!!!

若有误,望各位,在评论区留言或者私信我 指点迷津!!!谢谢 ヾ(≧▽≦*)o  \( •̀ ω •́ )/


一、理解文件系统

🌠磁盘结构

<1> 任何磁盘结构

磁盘由上亿的小磁铁构成【磁铁--南北极 --> 二进制】

(1)  磁盘物理结构:

a. 磁盘在进行摆动旋转【磁头的左右摆动】:可以进行数据的寻址。

b. 磁头悬浮在盘片上【要求在真空环境中】。

(2) 磁盘存储结构:

a. 磁头在摆动的本质:定位磁道(柱面)

b. 磁头定位好一个磁道后,盘面在进行旋转时,就可以把各个不同的扇区,依次放在磁头的正下方,让磁头来确定一个扇区上面的 01 值;

c. 磁盘盘片旋转的本质:定位扇区。

d. 扇区:是磁盘存储数据的基本单位,512字节,块设备;

e. 磁盘,若有3片,就有6面,每一面都有一个磁头【h0~h5】;

f. 读写哪一个磁头,本质是读写哪一个面;

g. 如何定位一个扇区?【CHS地址定位法】

   • 先定位磁头(header)

   • 确定磁头要访问哪一个柱面(磁道)(cylinder)

   • 定位一个扇区(sector)

h. 文件 = 内容 + 属性 这些都是数据,数据无非就是占据哪几个扇区的问题,能定位一个扇区,就能定位多个扇区了。

i. 传动臂上的磁头是共进退的!!!

(3) 磁盘逻辑结构:

磁带上面可以储存数据,我们可以把磁带“拉直”,形成线性结构

磁盘本质上是硬质的,但是逻辑上我们可以把磁盘想象成为卷在一起的磁带,那么磁盘的逻辑存储结构就类似于:

这样每一个扇区,就有了一个线性地址(其实就是数组下标),这种地址叫做LBA

柱面是一个逻辑上的概念,其实就是每一个面上,相同半径的磁道逻辑上构成柱面。所以,磁盘物理上分了很多面,但是在我们看来,逻辑上,磁盘整体是由“柱面”卷起来的。

整盘:

整个磁盘不就是多张二维的扇区数组表(三维数组?)
所有,寻址一个扇区:先找到哪一个柱面(Cylinder),在确定柱面内哪一个磁道(其实就是磁头位置,Head),在确定扇区(Sector),所以就有了CHS。

我们之前学过C/C++的数组,在我们看来,其实全部都是一维数组:

所以,每一个扇区都有一个下标,我们叫做LBA(Logical Block Address)地址,其实就是线性地址。所以怎么计算得到这个LBA地址呢? 

• 扇区的编号从1开始,LBA从0开始【数组下标】。

CHS转成LBA:
• 磁头数*每磁道扇区数 =单个柱面的扇区总数
• LBA = 柱面号C*单个柱面的扇区总数 + 磁头号H*每磁道扇区数 +扇区号S-1
• 即:LBA = 柱面号C*(磁头数*每磁道扇区数) + 磁头号H*每磁道扇区数+扇区号S-1
• 扇区号通常是从1开始的,而在LBA中,地址是从0开始的
• 柱面和磁道都是从0开始编号的
• 总柱面,磁道个数,扇区总数等信息,在磁盘内部会自动维护,上层开机的时候,会获取到这些参数。

LBA转成CHS:
• 柱面号C = LBA //(磁头数*每磁道扇区数)【就是单个柱面的扇区总数
• 磁头号H = (LBA %(磁头数*每磁道扇区数)) // 每磁道扇区数
• 扇区号S = (LBA % 每磁道扇区数)+1
• "//";表示除取整

LBA地址  <--转换--> CHS地址,谁来做?磁盘自己来做!固件(硬件电路、伺服系统)

所以,从此往后,在磁盘使用者看来,根本就不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转换。

所以,从现在开始,磁盘就是一个 元素为扇区 的一维数组,数组的下标就是每一个扇区的LBA地址。OS使用磁盘,就可以用一个数字访问磁盘扇区了。

<2> 理解分区,格式化

OS和磁盘进行IO的时候,以扇区为基本单位,512字节,单次IO的数据量,1KB,2KB,3KB,4KB,8KB等,4KB数据块 ---- 8个扇区。

OS如何管理?分区!--> 分组  【分治思想】

<3> Linux文件系统Ext*系列的文件系统,inode号和inode

Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。政府管理各区的例子;
超级块(Super Block):【表示文件系统,管理整个分区】存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了;
GDT,Group Descriptor Table:块组描述符,描述块组属性信息;
块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用;
inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
i节点表:存放文件属性 如 文件大小,所有者,最近修改时间等;
数据区:存放文件内容 ;

文件系统以分区为单位,一个分区一套文件系统;

分区和分区之间是互相独立的,不同的分区可以用不同的文件系统

🌠小贴士:

• 文件 = 内容 + 属性,文件属性也是数据,

• 在Linux当中会以结构体的方式构建出来【inode】,

• 一个文件只有一个inode,inode是文件属性数据的集合,

一个inode就是一个结构体【struct inode】

• inode的大小一般为128字节【跟系统有关】,一个块组中可能会存在100或1000个文件,就会存在100或1000个inode,文件系统会把当前你要新建的文件,文件的属性节点在内存里面定义出来【struct inode】,把属性值填入,接着把inode节点写入到磁盘当中指定的inode Table里面。

• OS在和磁盘进行IO交互的时,磁盘中一个块有4KB,那一个块就有 4KB/128字节 个inode,都存放在一个组当中的inode Table中,为此 每个文件都要有自己的文件编号【inode值】,inode彼此之间互不重复【有条件】

其中,在Linux系统中,文件名这个属性不在inode中保存!

• inode Table 包含了当前组里面所有的文件属性集。

• data block 用来存放文件的内容,里面全是划分好的4KB大小的块,

Linux下,文件属性和文件内容是分开存储的!

✨如何找文件?

拿到对应的inode,接着在inode Table里面找到inode,inode属性里面还有inode映射表 【int block[NUM]】,数组里面记录了对应inode,所对应的数据在哪。

• inode Bitmap : inode Table有多少个inode,inoed Bitmap就需要有多少个比特位,当inode号为0,inode Bitmap对应的位图比特位就会记录下来【有效】,inode Bitmap会按比特位来检查inode号是否有效,有效才会去inode属性里面获取有效的inode属性。

• 对于inode Bitmap的一次进行修改,修改的原则:哪怕是一个Bite也要把4KB的数据全部放到内存里面,修改完成之后再写回磁盘去;

✨修改位图时

磁盘当中是以扇区为单位的,当要修改时,先把要修改的扇区搬到内存里,以比特位修改位图,修改完成之后,直接写回到磁盘分组的 inode Bitmap 里面的位置。

✨在data block里面很多块号,我们怎么样才能知道哪些被占用/空闲?

black Bitmap也是一个位图,它的二进制位图中表明哪些被占用/空闲,因此在一个组当中,有了Block BItmap、inode Bitmap、inode Table、Data blocks后面这四块,我们就可以对一个分组的内容和属性进行基本的管理了。

有了inode Bitmap、inode Table这两张位图(有开始和结束),我们就可以清楚的知道,这两张位图所对应的区域,即inode Bitmap 和 inode Table 都有自己对应的编号(可以通过位图来得到)

✨过程:

新建一个文件并向这个文件写入"hello world"字符串,

• 新建一个文件,要在inode Table里面先分配一个inode,接着在inode Bitmap里面去查某一个对应的位图有没有被使用,没有被使用就会修改对应的位图【由0-->1】,接着在inode Table里面拿着对应的inode号,初始化节点编号、填写权限、属主、时间、文件大小.....,写入之后统计需要多少个块,就回去Block Bitmap里面查位图,申请所需的块数,申请完之后,把对应的“hello world”字符串写入到对应的块号里面,接着拿着这个块号返回到inode Bitmap找到inode Table里面的数组在里面写入块号(属性), 接着在inode Table中找到对应的data blocks进行数据的写入(内容)。

因此,我们只需要知道文件的inode编号就可以找到这个文件!!

在Linux中,删除的本质是设置inode和block无效!

删一个文件,可以恢复!!我们只需要把这个文件的inode Bitmap对应的【1/0 --置为--> 1】,接着再查找inode Table里面的块【int block[NUM];】所对应的块号,在Block Bitmap里面对应的块号【由0 ---> 1】,这个文件就会被恢复。

不小心删除了数据,不要随便操作,以免被删除的的inode和block被占用/覆盖,就恢复不了了。

✨如何评判当前块组【Block group 0】已经满了/放不下了呢?已经使用了多少/还剩多少?

因此每一个块组都有一个Group Descriptor Table【GDT】块组描述符。

Boot Block跟分组关系不大,【以磁盘硬件为单位】一般是整个磁盘里面最开始的一个小区域,与启动有关,一般保存这个磁盘里面的总容量是多少,【第一个分区开始和结束的扇区】启动信息、分区表、操作系统的内核所在的地址.....(不考虑)。

Super Block 表示的就是文件系统,对整个分区管理的数据结构【包括整个文件系统的文件系统名、什么文件系统】。在整个分区里面,不需要给每个分区里都保存Super Block,整个分区里面也不知是只有一个Super Block。混在组的内部里面,可能会存在两三份,并且里面的数据是完全一样的。【在整个分区里面,不是每个分组里面都有Super Block ,也绝不是只有其中一个分组里面有Super Block 】

为什么不是在整个分区里面保存一个Super Block呢?在一个分区里面,若Super Block挂掉了,整个分区的文件系统就全部都没了!!!分组情况都摸不清了,文件系统里面的整体情况都不知道了。所以会被打散到不同的分组里面,不一定每个分组都有,可能会同时存在两三份,因此一个Super Block坏掉/出现问题了,我们对应的文件系统就可以直接区其他块组里面去找对应的Super Block,把Super Block给覆盖回来,此时就能进行文件系统恢复了。

文件系统以分区为单位,一个分区,一套文件系统,不同的分区,可以写不同的文件系统。

格式化:写入空的文件系统

磁盘分区--->分组---> 在组里面划分好相关区域【inode Bitmap、Block Bitmap全部清零....】,划分的区域是多大... 写入文件信息 

<4> 理解 文件、目录、文件系统

• 在一个块组里面 inode号的个数,block个数都是固定的!【这两个的占比是最多的】

• 存在 inode Table 用完【存的全部都是小文件】, Data Block没用完的情况

✨关于inode:

• inode只能在特定分区下有效,inode以分区为单位,一套inode;

• 在格式化分区的时候,要格式化出很多分组,其中在分组当中,inode在分配的时候,只需要确定起始inode即可;inode不能跨分区;inode里面有分组;每一个组里面的inode编号是固定的;这些值一般保存到GDT组描述符里面只需要记录起始inode即可。

Super Block 和 Group Descriptor Table 是两个固定的数据结构,大小也是固定的

✨关于block:

• 整个分区块号也是统一编号的;【保存到GDT组描述符里面】

✨在一个组里面,我们是如何分配一个inode的?

• 在inode Bitmap一旦确定好开始和结束,起始的inode Bitmap里面是位图,位图里面记录的inode + 组里面分组好的起始inode值 = 新的inode; 这个inode在分区当中具有唯一性;

✨在一个组里面,我们是如何分配一个data block的?

• data block也是一样的,它的块号也是加上分组好的起始的block值,这些值都在GDT里面;

✨inode和data block都是全局建立的;

当块号不够的时候,可以进行跨组建立;

OS如何进行管理文件系统?OS对每个Super Block 和 Group Descriptor Table进行 先描述,再组织 来管理文件系统【内存级操作】;【Super Block 和 Group Descriptor Table的数据结构会被加载到内存里】

✨如何查找一个文件?

在一个分区里通过inode怎么找到对应的文件呢?根据inode,确定文件在哪个组里面,接着拿着inode减去start_inode,再查inode Bitmap,找到之后inode Table就找到inode,找到了inode就找到了文件的属性【inode结构】和 块的映射关系就有了,即就找到了块号,最终找到内容。

✨如何删除一个文件?

前提条件就是查找,找到之后,把inode Bitmap的位图直接【由1--置为-->0】,再找到inode属性和块的映射关系,拿到了块号,把 Block Bitmap的位图直接【由1--置为-->0】,inode就被释放了,GDT里面记录的已使用的inode就得减一,最后再把属性进行更新,就完成了删除。

✨如何修改一个文件?

前提条件就是查找,

修改要么是对属性进行修改,改掉文件对应的创建时间、文件的大小、文件权限...,拿着文件的inode,按照查找方式,找到文件,把inode加载到内存里,改完再写回对应的位置,

要么就是对内容进行修改,找到文件,把磁盘内容Data Block加载到内存里【文件的内核缓冲区】,改完之后写回磁盘,此时对文件的属性和内容就都能进行修改了。

✨如何新增一个文件?

首先要确定在哪一个组里面,操作系统由文件系统自动来进行确定, 遍历GDT去找,根据要新增文件的基本信息【新增文件的大小、文件名称、...】找到了对应的一个组,其中就要分配inode号,首先查位图,找到一个局部性的值【偏移量】,把inode Bitmap、Block Bitmap【由0--置为-->1】,最后给用户返回一个inode,  start_inode + inode Bitmap里面的偏移量,即返回inode号。

✨inode 和 block 究竟是怎么映射的?

✨凭什么拿到inode?我们访问的好像都是文件名!!!【Linux,文件名不在inode中保存】,inode存在哪里?文件类型【文本文件、二进制、普通文件、目录】,存在自己所处的目录的数据块中【数据块存文件名和映射关系】,

✨如何理解目录文件?

目录 = inode + block = 属性 + 内容,内容也要有对应的数据块!目录的数据块里面,存的是文件名和 inode的映射关系,因此我们在查一个文件时,我们只要找到当前目录,根据目录的inode,找到目录的数据块【data block】,再根据文件名,进行inode映射,找到inode就可以找到属性和内容。

文件名 和 inode号 是互为映射的,任何目录不能存在同名文件,文件名 <--映射--> inode ,这就是为什么拿到文件名这个字符串就能找到文件,是因为拿着文件名,【ls命令】操作系统就会在当前目录下,打开当前目录,把当前目录的文件名按字符串查找,找到inode,根据inode号查一个文件,属性和内容就全有了。

🌠重新理解目录权限:rwx

• 当我们对一个目录没有 r 权限时,我们就查不了这个目录里面的内容,没有读权限,对目录没有读权限时,就无法读取目录的data block【内容】,操作系统不让读,就得不到文件名和inode的映射关系,拿不到inode就访问不到文件;

•  目录没有 w 权限,就不能在该目录新建文件,没有写权限就无法把文件名和inode的映射关系的字符串信息、文本信息,写到目录数据块当中。

• 目录没有 x 权限,就进不去,本质是打不开。

🌠文件类型【文本文件、二进制、普通文件、目录】,文件名和映射关系是保存在普通文件里面的,在磁盘级文件系统里面的inode Table、Data block、inode Bitmap、Block Bitmap这个层面上不区分文件是普通文件还是目录,不管是文件还是目录,在底层都叫inode、data block。

🌠在Linux中,找文件要用inode去找呢?文件名不在inode保存,是保存在当前所处的目录,所对应的数据块当中的!!!如果没有inode我们的文件名就存在属性里,这时查找文件时,都是按照文件名【字符串】来查找文件的,字符串可长可短,影响查找的效率,而inode是一个整数,效率更高。

🌠 命令"ls -l",在操作系统底层上干了什么?就会把当前目录在底层上给我们打开,接着遍历该目录对应的文件名和inode映射关系,把所有文件的inode全部拿到,接着把每个文件依次在文件系统当中进行查找,根据inode找到inode的值把属性和文件名进行罗列出来。

🌠 找到文件名,首先要打开当前目录,当前目录,也是文件!!也有文件名 ----> 逆向的路径解析,这就是为什么访问任何一个文件都要有路径,没有路径就根本不可能找到这个文件,文件名和inode的映射关系就建立不起来,必须要有全路径,才能在linux内部进行路径解析,才能找到最终文件名和inode的映射关系。

每一个进程都有一个CWD, 任何目标文件的路径都是进程给的!!在bash里做的任何操作,都是进程操作,所以进程内部保存了任何文件的CWD,保存了你所要找的CWD,不管你怎么访问绝对路径/相对路径,它都能拼成最终的完整路径,最终进行路径解析,方便查找。 

当我们连续对相同路径下的文件进行访问【即就是不断地进行访问磁盘文件系统】,此时Linux系统,需要进行对路径结构进行缓存【内存级缓存】!!

Linux系统,在磁盘上不需要维护任何的路径关系,只需要在数据块里记录这个目录里存的是什么文件和inode的映射关系, 在磁盘上没有路径地概念,只要inode、data block,根本就没有路径,那么此时路径是谁在维护呢?1.由进程提供,2.由对应的每个文件的 data block 给我们提供的映射关系,相当于在data block 构建了一张磁盘级简单的路径关系【多叉树】,跟文件系统没有关系。

Linux要以什么样的数据结构来缓存路径呢?多叉树!!在Linux系统当中,在操作系统加载的时候只需要把根目录挂上,就能找到相应的路径, 构建的路径缓存【占磁盘级文件当中极少,会把用户曾经访问过的目录构建成节点缓存起来,没有访问过的目录就不需要了,所以这个缓存是一个内存级的缓存,这样我们在内存里就有一个对应的多叉树的路径了】,当第一次访问这个文件时,就构建好了路径树,第二次再访问时,不需要再进行访问磁盘了,直接查找缓存结构【树】。

struct dentry,维护的是再Linux当中,帮我们维护一个dentry树,来进行路径缓存。

find /home -name test.txt ---- 在磁盘上找这个文件【根据文件路径去不断进行路径解析,去磁盘当中访问磁盘,从根目录开始】,find首次找会慢一点,第二次会快,第二次访问的时候,路径结构被缓存起来了,dentry会指导我们找到任何一个目录的inode和内容。

在Linux中,每一个文件【目录、普通文件....】都要配一个struct dentry{...},因为要把这个文件挂接在这个目录树里面,方便进行查找。

🌠宏观认识:

磁盘上存有很多的文件系统,Linux系统里,默认会在全局当中找到dentry里的根目录,当想要打开一个文件时,进程就必须给提供一个路径 【/home/zxl/test.txt】,Linux系统,根据根目录开始查dentry,dentry打开后,和路径里的字符串进行比较,找对应的字符串【home ,加载home所对应的属性inode和内容,在home所对应的内容里找zxl,此时就形成了路径/home/zxl,再打开zxl数据块的内容,得到test.txtx的内容和属性,得到test.txtx的文件名和inode的映射关系[1234]】,此时dentry就会根据路径所找到文件的inode,在磁盘指定的分区下找[1234]对应的inode,找到后加载到inode的文件属性里面【磁盘加载到内存】,在内核当中形成dentry结构,构建dentry节点【test.txt】, 最终用dentry构建节点【test.txt】指向inode属性,要打开【test.txtx】这个文件,内核就要创建struct_file,打开struct_file[文件描述符表]---> struct file  ---> struct path f_path ---> struct dentry ---> 找到所对应的inode, 这个inode就指向加载到属性里面的inode,再让struct path里的dentry指向新建的dentry,最后再磁盘上把文件的内容加载到文件内核缓冲区里面【磁盘加载到内存】。

※操作系统内打开一个文件:

• 创建内核数据结构

• 再磁盘当中读取数据加载数据到内存,构建对应的映射关系

• 加载内容、加载文件的inode、添加路径关系到Linux系统内部的路径缓存dentry当中

<5> 做一个小实验

$ dd if=/dev/zero of=./disk.img bs=1M count=5 #制作⼀个⼤的磁盘块,就当做⼀个分区 
$ mkfs.ext4 disk.img # 格式化写⼊⽂件系统 
$ mkdir /mnt/mydisk # 建⽴空⽬录 
$ df -h # 查看可以使⽤的分区 
Filesystem Size Used Avail Use% Mounted on
udev 956M 0 956M 0% /dev
tmpfs 198M 724K 197M 1% /run
/dev/vda1 50G 20G 28G 42% /
tmpfs 986M 0 986M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 986M 0 986M 0% /sys/fs/cgroup
tmpfs 198M 0 198M 0% /run/user/0
tmpfs 198M 0 198M 0% /run/user/1002
$ sudo mount -t ext4 ./disk.img /mnt/mydisk/ # 将分区挂载到指定的⽬录 
$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 956M 0 956M 0% /dev
tmpfs 198M 724K 197M 1% /run
/dev/vda1 50G 20G 28G 42% /
tmpfs 986M 0 986M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 986M 0 986M 0% /sys/fs/cgroup
tmpfs 198M 0 198M 0% /run/user/0
tmpfs 198M 0 198M 0% /run/user/1002
/dev/loop0 4.9M 24K 4.5M 1% /mnt/mydisk
$ sudo umount /mnt/mydisk # 卸载分区 
whb@bite:/mnt$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 956M 0 956M 0% /dev
tmpfs 198M 724K 197M 1% /run
/dev/vda1 50G 20G 28G 42% /
tmpfs 986M 0 986M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 986M 0 986M 0% /sys/fs/cgroup
tmpfs 198M 0 198M 0% /run/user/0
tmpfs 198M 0 198M 0% /run/user/1002

怎么确认在哪一个分区里面?--> 访问任何一个文件都要有路径,路径的前缀就可以指明在哪一个分区上!!

多个分区 --> 一个分区包含/ --> 若干个普通目录 --> /a /b /c /d...

只要分区,该分区无法直接使用,分区必须经过“挂载”到目录上,分区才可以被用通过路径的方式进行访问!

✨任何一个分区,天然就有了基本的路径了!【路径一部分是挂载点提供的,一部分是自己产生的】

二、软硬连接

🌟软硬链接

🌠软链接

• 软连接是一个独立的文件,有独立的 inode,软链接内容上,保存的是目标文件的路径【window上的快捷方式】;

• 在用户层 使用软连接【file-soft.link】 等同于 使用目标文件【file.txt】

 ln -s file.txt file-soft.link 【后者去链接前者】

当我们建立软链接,就是在当前目录下新建一个软链接文件/快捷方式。

🌠硬链接:

• 硬链接不是独立的文件!【没有独立的inode】,硬链接本质就是一组文件名和已经存在的文件的映射关系!

• ln file.txt file-hard.link 【后者去链接前者】

• 当我们建立一个硬链接,就是再当前目录所处的目录内部当中,新增一个新的文件名和inode对应的映射关系,所以硬链接所查到的 inode 和 目标文件的 inode 是一样的。 

• 在当前目录下新建一个普通文件,普通文件的文件名在文件所处目录的内容中保存,硬链接会映射到同一个 inode【inode 特别像一个指针一样的东西】,当我们想使用文件名来找对应文件时,Linux是通过inode去找文件的,硬链接使得两个文件名指向同一个inode文件, 此时这个文件如何才算是删除呢?在整个系统里没有任何文件名字符串和这个文件inode有映射关系时,才算是被删除,我们如何知道有多少个文件名通过和inode号来产生对应的映射关系呢?在inode当中存在一个引用计数【atomic_t d_count;】硬链接数。

• 建立一个普通文件本质上就是在不断地进行建立硬链接【文件名和inode的映射关系只有一份,所以数字就会减一】

🌟理解软硬链接的应用场景

✨软链接

可执行文件在当前目录上,如何不带路径就可以直接执行文件呢?

1> 环境变量:把当前的所处的路径添加到系统环境变量里;

2> 把 .exe可执行文件,拷贝到系统的默认路径下;

3> 给对应的可执行程序重新进行命名,建立软链接:

• 作用:当被执行的可执行程序放在比较深的目录下【路径很长】时,可以在深得路径下,建立软链接,也可以给目录进行软链接,直接一步进入想要进的目录里面。

主要是能让我们快速定位某一个文件,以最简单的方式进入。

一般在一个磁盘分区里面,软链接建在哪里都可以。

• 软链接:快捷方式,可以帮我们快速找到指令和对应的库。

✨硬链接

• “.” [文件名] 所映射的inode编号,和当前所处的【/empty】目录inode编号是一样的,文件名不同【.   empty】但指向的inode是一样的,所以 “.” 就表示当前工作路径,所以在创建一个空目录时,一个是它自己【有一个文件名和inode有映射关系】

.”和 “..”目的是为了路径的快速切换,如何做到的呢?本质就是 文件所指向的inode就是上级路径,因此当 cd  切换路径时,要找到目标路径的inode,方便显式目标路径里面的文件。

• 文件备份!(就可以不用拷贝,也能找到内容)

​​​​​​​

• Linux下不允许对目录新建硬链接!!!【原因:怕进行硬链接之后,形成一些环状路径】

软链接【直接指向文件,里面保存的时路径字符串】,我们在进行查找软链接时,并不会对软链接做任何解析。 

​​​​​​​

相关文章:

文件系统 软硬连接

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;Linux 目录 一、理解文件系统 &#x1f320;磁盘结构 二、软硬连接 &#x1f31f;软硬链接 &#x1f320;软链接&#xff1a; &#x1f320;硬链接&#xff1a; &#x1f31f;理解软硬链接的应…...

Linux环境基础开发工具使用

本节目标&#xff1a; 1. 学习yum工具&#xff0c;进行软件安装 2. 掌握vim编辑器使用&#xff0c;学会vim的简单配置 3. 掌握gcc/g编译器的使用&#xff0c;并了解其过程&#xff0c;原理 4. 掌握简单gdb使用于调试 5. 掌握简单的Makefile编写&#xff0c;了解其运行思想…...

秘密任务 2.0:如何利用 WebSockets + DTOs 设计实时操作

在之前的文章中&#xff0c;我们探讨了为什么 DTO 是提升 API 效率和安全性的秘密武器。现在&#xff0c;我们进入了一个全新的场景——我们将深入探讨如何通过 WebSockets DTOs 实现实时操作&#xff01; Agent X 正在进行一项高风险的卧底任务。突然&#xff0c;总部更新了…...

LeetCode hot 100—括号生成

题目 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;["((()))","(()())","(())()","()(())",&…...

2025.04.17【Dendrogram】生信数据可视化:Dendrogram图表详解

Dendrogram customization Go further with ggraph: edge style, general layout, node features, adding labels, and more. Customized circular dendrogram Learn how to build a circular dendrogram with proper labels. 文章目录 Dendrogram customizationCustomized c…...

SDL基础

SDL SDL&#xff08;Simple DirectMedia Layer&#xff09;是一个开源的跨平台多媒体开发库&#xff0c;主要用于开发需要图形、音频和输入设备支持的应用程序。它使用C语言编写&#xff0c;提供了简单易用的API&#xff0c;**能够帮助开发者快速实现跨平台的多媒体功能。**SD…...

硬件工程师面试常见问题(2)

第六问&#xff1a;你知道那些常用逻辑电平?TTL与COMS电平可以直接互连吗? 逻辑电平&#xff1a;是数字电路中用于表示二进制逻辑状态&#xff08;0 和 1&#xff09;的电压或电流信号范围&#xff0c;是数字系统中器件间信号传输的统一标准。 注&#xff1a;逻辑电…...

Python自学第2天:条件语句,循环语句

条件语句 1.条件判断 score 60 if score > 90:print("优秀") elif score > 60:print("及格") else:print("不及格") 注意&#xff1a; 1、每个条件后面要使用冒号 :&#xff0c;表示接下来是满足条件后要执行的语句块。2、使用缩进来划…...

2025年4月16日华为笔试第一题100分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 01. 博物馆展览规划 问题描述 卢小姐是一家著名博物馆的策展人,她需要从众多展品中选择一些组成新的展览。每件展品可以展示不同的历史文化主题,而博物馆希望通过最少的展品数量覆…...

智能体开发的范式革命:Cangjie Magic全景解读与实践思考

引言&#xff1a;当智能体开发遇见仓颉魔法 在人工智能技术日新月异的今天&#xff0c;智能体(Agent)开发正从实验室走向产业应用的核心舞台。2025年3月&#xff0c;仓颉社区推出的Cangjie Magic开源平台&#xff0c;以其创新的设计理念和技术架构&#xff0c;为这一领域带来了…...

LeetCode hot 100—单词搜索

题目 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或…...

基于flask+vue框架的灯饰安装维修系统u49cf(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,工单人员,服务项目,订单记录,服务记录,评价记录 开题报告内容 基于 FlaskVue 框架的灯饰安装维修系统开题报告 一、选题背景与意义 &#xff08;一&#xff09;选题背景 随着城市化进程的加速与居民生活品质的显著提升&#xf…...

C/C++指针

为什么要使用指针 函数的值传递&#xff0c;无法通过调用函数&#xff0c;来修改函数的实参&#xff1b;被调用函数需要提供更多的“返回值”给调用函数&#xff1b;减少值传递时带来的额外开销&#xff0c;提高代码执行效率 指针定义&#xff1a;指针是什么 int age18; /* …...

Unity编辑器扩展之项目资源查找工具

一、需要实现的效果如下: 二、在项目的Asset目录下新增Editor目录,新增AssetSearchWindow和EditorDefine和EditorTools这三个C#脚本,并复制以下的代码保存好之后,就可以实现上述功能啦。 -------------------------------------------EditorTools脚本Begin----------------…...

什么是分布式锁?

分布式锁是一种在分布式系统中控制资源共享的机制。 一、背景和作用 在单机环境下&#xff0c;当多个线程同时访问共享资源时&#xff0c;可以通过线程锁&#xff08;如 Java 中的 synchronized 关键字、ReentrantLock 等&#xff09;来保证操作的原子性、可见性和有序性&#…...

ESP32- 开发笔记- 硬件设计-ESP32-C3 天线设计-利用嘉立创EDA来设计

这个硬件设计&#xff0c;只是一个随手记录文档。如果中间有什么问题&#xff0c;欢迎大家提出来。 1 板载天线 1.1 背景介绍 PCB&#xff08;Printed Circuit Board&#xff09;板载天线是现代电子设备中用于无线通信的一种关键组件&#xff0c;它直接集成在电路板上&#…...

setTimeoutsetIntervalrequestAnimationFrame

requestAnimationFrame 详解及与 setTimeout/setInterval 的比较 requestAnimationFrame&#xff08;简称 rAF&#xff09;是浏览器提供的专门用于 动画渲染 的 API&#xff0c;相比 setTimeout 和 setInterval&#xff0c;它在性能和流畅度上有显著优势。以下是详细解析和对比…...

Python内置函数---anext()

用于异步迭代器的核心工具&#xff0c;专为处理异步数据流设计。 1. 基本语法 await anext(async_iterator, default) 参数&#xff1a; async_iterator &#xff1a;实现了异步迭代协议的对象&#xff08;如异步生成器、异步迭代器类&#xff09;。 default &#xff08;可选…...

JavaEE——线程安全

目录 前言1.线程安全的定义2.线程安全问题产生的原因2.1 多个线程修改一个变量2.2 修改操作不是原子的2.3 内存可见性引起的线程安全问题 3.解决线程安全问题的方法3.1 通过synchronized关键字加锁3.2 使用volatile关键字 总结 前言 在使用多线程的时候&#xff0c;难免会出现…...

MongoServerError: Authentication failed.处理办法

1停止MongoDB服务&#xff1a; systemctl stop mongod2临时修改MongoDB配置&#xff0c;禁用认证&#xff1a; vim /etc/mongdb.config 在配置文件中找到 security:authorization: disabled # 临时关闭认证3.重启MongoDB服务 # 重启MongoDB服务 sudo systemctl restart mon…...

IOS微信小程序无法显示背景图片

最近线上突然出现了一个问题&#xff0c;就是原来的在线上的小程序无法显示背景图片。而且这个问题只有在IOS上才有。在安卓上是正常的。 然后这里和前端沟通说是&#xff0c;看能不能用苹果手机真机调试。果然也成功复现出来了&#xff0c;部分图片无法显示。 然后在网上找了…...

实验五 8255和LED数码管显示实验

一、实验目的 1&#xff0e;掌握并行接口8255A的工作原理及使用方法。 2&#xff0e;了解七段数码管显示数字的原理。 3&#xff0e;掌握多位数码显示的接口技术。 二、实验电路 三、实验内容 1&#xff0e;静态显示&#xff1a;按图3连接好电路&#xff0…...

秒杀系统解决两个核心问题的思路方法总结:1.库存超卖问题;2.用户重复抢购问题。

秒杀系统解决两个核心问题 秒杀系统解决两个核心问题&#xff1a;一、解决库存超卖的核心逻辑&#xff1a;解释&#xff1a;原子性保证&#xff1a; 二、如何避免重复抢购&#xff1a;使用 Redis 做唯一标识判断优点&#xff1a; 三、流程完整梳理&#xff1a;四、通过数据库建…...

大数吞小数

A-春_牛客练习赛134 double 的有效数字约 15-17 位十进制&#xff0c;因此&#xff1a; 如果两个数的数量级相差超过 15-16 个数量级&#xff0c;较小的数会被吞掉。...

1-9 堆宝塔

堆宝塔游戏是让小朋友根据抓到的彩虹圈的直径大小&#xff0c;按照从大到小的顺序堆起宝塔。但彩虹圈不一定是按照直径的大小顺序抓到的。聪明宝宝采取的策略如下&#xff1a; 首先准备两根柱子&#xff0c;一根 A 柱串宝塔&#xff0c;一根 B 柱用于临时叠放。把第 1 块彩虹圈…...

Java虚拟机(JVM)平台无关?相关?

计算机的概念模型 计算机实际上就是实现了一个图灵机模型。即&#xff0c;输入参数&#xff0c;根据程序计算&#xff0c;输出结果。图灵机模型如图。 Tape是输入数据&#xff0c;Program是针对这些数据进行计算的程序&#xff0c;中间横着的方块表示的是机器的状态。 目前使…...

第七章--查找

查找表 定义 由同一类型的数据元素(或记录)构成的集合。 1&#xff09;特点&#xff1a;数据元素的类型相同&#xff1b;结构松散→先后次序无关紧要&#xff0c;只关心是否在集合内。 2&#xff09;常用操作&#xff1a;查询某个“特定的”数据元素是否在查找表中&#xf…...

photo-sphere-viewer 4.8.1在vue中使用

photo-sphere-viewer 加载单张平面图 import { Viewer } from photo-sphere-viewerthis.viewer new Viewer({panorama: ‘完整的url,也可以是一个base64’,// Containercontainer: document.getElementById(viewer1),navbar: true,// Resize the panoramasize: {width: 100%,…...

vue MarkdownIt标签多出了<p>标签导致高度变丑

​ 效果如下&#xff1a; ​ [点击并拖拽以移动] ​ F12观察后发现多了 标签包裹&#xff0c;所以要解决 标签。 在 markdown-it 中禁用自动包裹 <p> 标签的方法 要让 markdown-it 渲染的 Markdown 内容不自动包裹 <p> 标签&#xff0c;你可以使用以下两种方…...

《Java 并发编程实践》阅读笔记(一):线程重要性

文章目录 一. 并发历史二. 线程优势三. 线程带来的风险1. 安全性问题2. 活跃性问题3. 性能问题 四. 线程无处不在示例1: Timer示例2: 远程方法调用(Remote Method Invocation, RMI)示例3: GUI 程序 一. 并发历史 操作系统的出现 大型机时代, 没有操作系统, 一台主机只能执行一…...

算法思想之分治-归并

欢迎拜访&#xff1a;雾里看山-CSDN博客 本篇主题&#xff1a;算法思想之分治-归并 发布时间&#xff1a;2025.4.17 隶属专栏&#xff1a;算法 目录 算法介绍核心思想与步骤时空复杂度分析C代码实现关键特性与优化 例题排序数组题目链接题目描述算法思路代码实现 交易逆序对的总…...

Vue基础(5)_事件修饰符

事件修饰符 Vue中的事件修饰符&#xff1a; 1、prevent&#xff1a;阻止默认事件(常用)。 2、stop&#xff1a;阻止事件冒泡(常用)。 3、once&#xff1a;事件只触发一次(常用)。 4、capture&#xff1a;使用事件的捕获模式。 5、self&#xff1a;只有event.target是当前操作的…...

网络编程 - 1

目录 为什么需要网络编程&#xff1f; —— 丰富的网络资源 什么是网络编程 网络编程中的基本概念 发送端和接收端 请求和相应 客户端和服务端 常见的客户端服务端模型 Socket 套接字 概念 分类 解释 有连接 / 无连接 可靠传输 / 不可靠传输 面向字节流 / 面向数…...

github | 仓库权限管理 | 开权限

省流版总结&#xff1a; github 给别人开权限&#xff1a;仓库 -> Setting -> Cllaborate -> Add people GitHub中 将公开仓库改为私有&#xff1a;仓库 -> Setting -> Danger Zone&#xff08;危险区&#xff09; ->Change repository visibility( 更改仓…...

【系统搭建】DPDK关键概念与l2fwd源码解析

DPDK&#xff08;Data Plane Development Kit&#xff09;是一套用于高性能网络数据面处理的开发框架&#xff0c;其核心设计在于绕过内核协议栈&#xff0c;它提供了一个用户空间下的高效数据包处理库函数&#xff0c;可以用于快速开发高性能的网络应用程序&#xff0c;如网络…...

【Qt】初识Qt(一)

目录 一、Qt的背景二、认识Qt项目 一、Qt的背景 关于客户端开发&#xff1a; 客户端开发的重要任务&#xff0c;是编写和用户交互的界面&#xff0c;和用户交互的界面有两种风格&#xff1a; TUI&#xff1a;命令行界面&#xff0c;也叫终端界面GUI&#xff1a;图形化界面 Q…...

Django REST framework 并结合 `mixin` 的示例

下面为你提供一个使用 Django REST framework 并结合 mixin 的示例,该示例将实现一个简单的图书管理 API。 项目需求 我们要创建一个图书管理系统的 API,支持对图书信息的创建、读取、更新和删除操作。 实现步骤 1. 项目初始化 首先,确保你已经安装了 Django 和 Django…...

《前端性能优化秘籍:打造极致用户体验》

在当下&#xff0c;网站和应用的性能表现直接关乎用户去留。快速加载、流畅交互的页面能让用户沉浸其中&#xff0c;反之&#xff0c;缓慢的响应速度则会让他们毫不犹豫地离开。对于前端开发者而言&#xff0c;性能优化不仅是技术追求&#xff0c;更是提升用户体验、增强产品竞…...

数据结构与算法学习导航

目录 指导思想资料总结代码随想录hello-algoOI-WIKI 一名麻瓜的刷leetcode的简单概述。 在这里对过去的自己说: 如果你相信算法有用你就刷刷leetcode&#xff0c;如果不相信面试会让你相信。 当然&#xff0c;现在我确实认为算法和数据结构有用&#xff0c;leetcode也有用。 …...

【Python】用Python写一个俄罗斯方块玩玩

【Python】用Python写一个俄罗斯方块玩玩 一、引言1.成品效果展示 二、思考准备1.思考设计2.代码设计2.1 游戏页面2.2 控件设计2.2.1 方块生成2.2.2 方块碰撞2.2.3 方块消融2.2.4 游戏主循环2.2.5 游戏窗口 三、游戏完整版 一、引言 今日看到侄子在玩游戏&#xff0c;凑近一看…...

nginx中的代理缓存

1.缓存存放路径 对key取哈希值之后&#xff0c;设置cache内容&#xff0c;然后得到的哈希值的倒数第一位作为第一个子目录&#xff0c;倒数第三位和倒数第二位组成的字符串作为第二个子目录&#xff0c;如图。 proxy_cache_path /xxxx/ levels1:2 2.文件名哈希值...

【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; Yaoyao2024往期回顾&#xff1a;【深度学习】你真的理解张量了吗&#xff1f;|标量、向量、矩阵、张量的秩|01每日一言&#x1f33c;: “脑袋想不明白的&#xff0c;就用脚想”…...

20.3 使用技巧3

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的 20.3.5 禁止追加行与禁止删除行 通常情况下DataGridView最末一行是空白行&#xff0c;在此行单元格输入数据就可以追加新行。如果需要…...

使用代理IP提取数据的步骤是什么?代理IP如何提高爬虫采集效率?

在当今大数据时代&#xff0c;网络爬虫已成为获取互联网信息的重要手段。然而&#xff0c;许多网站为了防止数据被过度抓取&#xff0c;会设置反爬机制&#xff0c;如IP封禁、访问频率限制等。这时&#xff0c;使用代理IP就成为了一种有效的解决方案。本文将详细介绍使用代理IP…...

探索关系型数据库 MySQL

目录 引言 一.SQL的基本操作 1.数据库是什么? 什么是SQL&#xff1f; 1.1.OLTP 1.2.OLAP 1.3.SQL 1.4.DQL 1.5.DML 1.6.DDL 1.7.DCL 1.8.TCL 1.9.数据库术语 2.MySQL体系结构 2.1.连接者 2.2.MySQL 内部连接池 2.3.管理服务和工具组件 2.4.SQL接口 …...

Redis--事务

目录 一、事务介绍 二、事务操作 2.1 MULTI 2.2 EXEC 2.3 DISCARD 2.4 WATCH 2.5 UNWATCH 一、事务介绍 Redis 的事务和 MySQL 的事务概念上是类似的. 都是把一系列操作绑定成⼀组. 让这⼀组能够批量执行. 但是注意体会 Redis 的事务和 MySQL 事务的区别: 1.弱化的原子性…...

【Windows上配置Git环境】

在Windows上配置Git环境可以按照以下步骤进行&#xff1a; 1. 下载Git 打开浏览器&#xff0c;访问Git官方网站https://git-scm.com/downloads。在下载页面中&#xff0c;找到适用于Windows的下载链接&#xff0c;根据你的系统是32位还是64位选择相应的安装包进行下载 。 2.…...

揭秘大数据 | 23、软件定义网络

软件定义网络将网络的边缘从硬件交换机推进到了服务器里面&#xff0c;将服务器和虚拟机的所有部署、管理的职能从原来的系统管理员网络管理员的模式变成了纯系统管理员的模式&#xff0c;让服务器的业务部署变得简单&#xff0c;不再依赖于形态和功能各异的硬件交换机&#xf…...

前端api(请求后端)简易template

微信小程序 API 模块模板 基本 API 模块结构 /*** 示例API模块*/ const api require(../api); const config require(../../config/index);// 示例API对象 const exampleApi {// API方法定义... };// 导出模块 module.exports exampleApi;标准 RESTful 请求方法 获取列表…...

【力扣】重排链表

重排链表 代码 class Solution { public:void reorderList(ListNode* head) {//当链表只有一个节点或两个节点时直接返回空,不用重排if (head->next NULL || head->next->next NULL) return;//1. 进行分割链表ListNode* fast head, *slow head;ListNode* end1 N…...