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

Linux入门——06 基础IO

1.什么是当前路径

exe -> /home/lin/Desktop/Linux_learn/fork_learn/test

当前进程执行是磁盘路径下的哪一个程序

cwd -> /home/lin/Desktop/Linux_learn/fork_learn

当前进程的工作目录------》当前进程

1.1当前路径这个地址能改吗?

可以,使用函数chdir()

chdir("/home/lin");//这个路径一定要存在

2.重谈文件

1.空文件也要占磁盘空间

2.文件的内容加属性

3.文件操作=对内容+对属性or内容和属性

4.标定一个文件的时候,必须使用文件路径+文家名(唯一性)

5.如果没有指定文件路径,默认时在当前路径下(进程当前路径),进行文件访问。

6.当我们把fopen,fclose,fread,fwrite等接口写完之后,代码编译之后,形成的二进制程序之后,但是没有运行,文件对应的操作做了没有?没有------》对文件的操作是进程对文件的操作。

7.一个文件没有被打开,可以直接进行文件访问吗?不可以。一个文件要被访问,一定要被打开(并不是所有文件都被打开)。-------》用户+进程+OS

所以文件分类:1.被打开的文件 2.没被打开的文件

结论:文件操作的本质是:进程和被打开文件的关系

文件在磁盘上(硬件),只有OS有资格访问文件-------->所有人访问文件都绕不过OS---->使用OS提供的接口-------->提供文件级别的系统调用接口--------》可以操作系统的只有一个。=====》所以,1.上层高级语言如何变化,库函数底层 必须 调用系统接口 2.库函数可以千变万化,但底层不变!!----》如何降低学习成本呢?学习不变的东西。

3.重谈文件操作

3.1C语言上的文件操作

文件使用方式 含义 如果指定文件不存在

“r”(只读) 为了输入数据,打开一个已经存在的文本文件 出错

“w”(只写) 为了输出数据,打开一个文本文件 建立一个新的文件

“a”(追加) 向文本文件尾添加数据 建立一个新的文件

“rb”(只读) 为了输入数据,打开一个二进制文件 出错

“wb”(只写) 为了输出数据,打开一个二进制文件 建立一个新的文件

“ab”(追加) 向一个二进制文件尾添加数据 建立一个新的文件

“r+”(读写) 为了读和写,打开一个文本文件 出错

“w+”(读写) 为了读和写,建议一个新的文件 建立一个新的文件

“a+”(读写) 打开一个文件,在文件尾进行读写 建立一个新的文件

“rb+”(读写) 为了读和写打开一个二进制文件 出错

“wb+”(读写) 为了读和写,新建一个新的二进制文件 建立一个新的文件

“ab+”(读写) 打开一个二进制文件,在文件尾进行读和写 建立一个新的文件

3.2hello.c写文件


#include <string.h>
#include <stdio.h>
int main()
{FILE *fp = fopen("myfile", "w");if(!fp){printf("fopen error!\n");}const char *msg = "hello bit!\n";int count = 5;while(count--){fwrite(msg, strlen(msg), 1, fp);}fclose(fp);return 0;
}

3.3hello.c读文件

#include <stdio.h>
#include <string.h>
int main()
{FILE *fp = fopen("myfile", "r");if(!fp){printf("fopen error!\n");}char buf[1024];const char *msg = "hello bit!\n";while(1){//注意返回值和参数,此处有坑,仔细查看man手册关于该函数的说明size_t s = fread(buf, 1, strlen(msg), fp);if(s > 0){buf[s] = 0;printf("%s", buf);}if(feof(fp)){break;}}fclose(fp);return 0;
}

4.系统调用文件接口

4.0open

返回值文件描述符(整数)或-1

参数:mode就是权限

flags选项:全大写(宏)

在C语言中我们会给函数中传一个标记位,C90没有bool类型,用标记位表示某一个事情发生了,或者将标记位作为返回值,把结果拿出去。C传标记位,一个int----》只传一个标记位====》当要传多个呢,一个int有32个bit位,这样我们就可以使用比特位来传递选项。

O_TRUNC选项对文件作清空,O_APPEND追加

int fd = open(FILE_NAME,O_WRONLY | O_CREAT | O_TRUNC ,0666);//对应c语言的w

int fd = open(FILE_NAME,O_WRONLY | O_CREAT | O_APPEND ,0666);//对应c语言的a

int fd = open(FILE_NAME,O_RDONLY); //对应c语言的r

pathname: 要打开或创建的目标文件

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。

参数:

O_RDONLY: 只读打开

O_WRONLY: 只写打开

O_RDWR: 读,写打开

O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限

O_APPEND: 追加写

返回值:

成功:新打开的文件描述符

失败:-1

mode_t理解:直接 man 手册

4.1如何使用比特位传递选项?

//标记位,每一个宏标记的数值,只有一个比特位,且是1,彼此位置不重叠
//好的写法是#define ONE (1<<0) 
#define ONE 0X1  //0001
#define TWO 0X2  //0010
#define THREE 0X4 // 0100
#define EIGHT 0x8 //1000void show(int flags)
{if(flags&ONE) {printf("one\n");}if(flags&TWO) {printf("two\n");}if(flags&THREE) {printf("three\n");}if(flags&EIGHT) {printf("eight\n");}
}int main()
{//像打谁传谁show(ONE);show(ONE | TWO);show(ONE | TWO | THREE);show(TWO);}

 我们再回头卡看这个open函数的标记位

int open(const char *pathname, int flags);

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

//没有该文件的时候,用下面这个函数,这个文件权限0666

O_RDONLY(只读), O_WRONLY(只写), or O_CRAT(没有创建).这就是宏,对应着标志位。

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#define FILE_NAME "log.txt"
int main()
{int fd = open(FILE_NAME,O_WRONLY | O_CREAT ,0666);if(fd < 0){perror("open");}(void)fd;close(fd);return 0;
}

当我们不想用系统给的umask创建文件的时候,权限由我们设置

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#define FILE_NAME "log.txt"
int main()
{umask(0);//改的是子进程的umaskint fd = open(FILE_NAME,O_WRONLY | O_CREAT ,0666);if(fd < 0){perror("open");}(void)fd;close(fd);return 0;
}

0666的文件权限

4.2文件描述符

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#define FILE_NAME "log.txt"
int main()
{umask(0);//改的是子进程的umaskint fd = open(FILE_NAME,O_WRONLY | O_CREAT ,0666);if(fd < 0){perror("open");}printf("%d\n",fd);(void)fd;close(fd);return 0;
}

从3开始,为什么从3开始,0,1,2呢?

printf("stdin->fd:%d\n",stdin->_fileno);

printf("stdout->fd:%d\n",stdout->_fileno);

printf("stderr->fd:%d\n",stderr->_fileno);

三个标准输入输出流

  • stdin=====键盘
  • stdout====显示器
  • stderr====显示器

FILE *fp = fopen()

FILE是啥?

是一个结构体----------》底层系统调用管理文件的是文件描述符------》所以这个结构体必定有一个字段(文件描述符)

文件描述符的本质是啥?

地址下标

文件描述符的分配规则

先关闭0和2文件,再分配两个文件就是0和2,close(0),close(2);

 

文件log.txt在磁盘中存储,当加载到内存时,OS为了管理,为其创建结构体struct file结构体,包含了文件的属性。这时进程为了管理这些文件,就会创建一个struct files_struct *file的多文件管理结构体指针,他通过指向多文件管理结构体struct files_struct,来找到要管理的文件,在这个struct files_struct结构体中有一个结构体数组struct file* fd_arry[],这个结构体数组就存储着struct file,对内存中的文件进行管理。这样进程与被打开的文件就关联了起来。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcnt.h>
int main()
{close(1);int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC, 0666);if(fd < 0){perror("open");return 1;}printf("%d\n",fd);fflaush(stdout); //加上刷新close(fd);return 0;
}

当0关闭的时候,这时候从文件描述符表的表里面找一个位置放,按从小到大,按照顺序,找到最小的且没有被占用的fd-----------这就是文件描述符的分配规则

关闭0和2的时候没有问题,这时候如果关闭1,printf("%d",fd)就会出现不显示输出了,因为1为比标准输出,当1被关闭的时候,就不会有输出了。

printf就是向stdout打的,stdout是向显示器fd1中打的,所以现在的fd1为文件log.txt,最终的printf("%d",fd)就会输出到文件中。但是文件没有,这是因为,向显示器打印的缓冲区的刷新策略和向普通文件打印的缓冲区的刷新策略不一样。

上面的情况,本来应该到显示器上,但是到了文件里,这种现象就称为重定向。(本质:上层的fd不变,内核更改fd对应的struct file* 的地址)

  • >   输出重定向
  • >> 追加重定向
  • <   输入重定向

系统给我们做了关于重定向的接口

4.3dup重定向函数系统接口(dup2)

 

int dup2(int oldfd, int newfd);//newfd是oldfd的拷贝。newfd必须和oldfd一样。

在两个文件描述符之间的拷贝。把file * fd_arry[]数组对应的file*对应文件的内容进行拷贝。fd为文件的标识符,1为显示器文件的标识符,要想把内容输出到文件中,就要把fd的内容拷贝的1。让1为fd的文件标识符。也就是把fd的内容拷贝到1。

这时fd的内容和1的内容都以fd为主了。这时候fd就是oldfd,1就是newfd。

这样上面的代码,我们就可以写成

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcnt.h>int main()
{int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC, 0666);if(fd < 0){perror("open");return 1;}dup2(fd,1);  //fd为oldfd,1就是newfd。printf("%d\n",fd);fflush(stdout);close(fd);return 0;
}
  • >输出重定向

int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC, 0666);

dup2(fd,1); //fd为oldfd,1就是newfd。

  • >>追加重定向

int fd = open("log.txt",O_WRONLY | O_CREAT | O_APPEND, 0666);

dup2(fd,1); //fd为oldfd,1就是newfd。

const char*msg = "hello world";

write(1,msg,strlen(msg));

  • <输入重定向

int fd = open("log.txt",O_RDONLY);

char line[64];

du2p(fd,0); //输入重定向 //fd-->0,从文件中输入。

while(1)

{

printf(">");

if(gets(line,sizeof(line),stdin) == NULL),break;

printf("%s",line);

}

dup2(fd,1); //fd为oldfd,1就是newfd。

4.4 write文件写入(向文件描述符中写入)

ssize_t write(int fd, const void *buf, size_t count);

参数: fd:文件描述符

buf:对应缓冲区数据在哪?(void*)

count:缓冲区字节个数

返回值: 写了几个字节

文件读写分类(C语言提供的)

  • ASCLL类(文本类)
  • 二进制类

这里用的是const void *buf,void*操作系统看来,都是二进制。

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>#define FILE_NAME "log.txt"int main()
{umask(0);int fd = open(FILE_NAME,O_WRONLY | O_CREAT ,0666);if(fd < 0){perror("open");}char outBuffer[64];int cnt = 5;while(cnt);{sprintf(outBuffer,"%s:%d\n","hello lin",cnt--);//C语言规定\0结尾,跟系统没有关系write(fd,outBuffer,strlen(outBuffer));//所以向文件中写入字符串,不用加1,除非你就想把\0写进去}//printf("%d\n",fd);//(void)fd;close(fd);return 0;
}

 

4.5read文件读取(向文件描述符中读取)

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>#define FILE_NAME "log.txt"int main()
{int fd = open(FILE_NAME,O_RDONLY);if(fd < 0){perror("open");return 1;}char RBuffer[1024];ssize_t num = read(fd,RBuffer,sizeof(RBuffer)-1);if(num>0){RBuffer[num] = 0;  // 0,\0,NULL--->0printf("%s",RBuffer);}(void)fd;close(fd);return 0;
}

4.6lseek

#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

  • fd: 文件描述符,指向已经打开的文件。
  • offset: 要设置的偏移量,根据 whence 参数来解释。
  • whence: 指定偏移量的基准位置,取值如下:
    • SEEK_SET: 文件开头。
    • SEEK_CUR: 当前文件位置。
    • SEEK_END: 文件末尾。

返回值:

  • 返回新的文件偏移量(以字节为单位)。
  • 如果失败,返回 -1,并设置 errno 以指示错误原因。

5.库函数接口与系统调用接口

库函数接口(封装了系统调用的接口)

fopen/fclose/fwrite/fread/fseek

系统调用接口

open/close/write/read/lseek

6.被打开的文件与进程

文件操作的本质:进程和被打文件的关系。

进程可以打开多个文件-------》系统中一定存在大量被打开的文件-------》被打开的文件要被OS管理起来------》先描述再组织------》操作系统为了管理对应的文件,必定要位文件创建相应的内核结构标识文件------》struct_file{}------>包含了文件的大部分的属性。

文件log.txt在磁盘中存储,当加载到内存时,OS为了管理,为其创建结构体struct file结构体,包含了文件的属性。这时进程为了管理这些文件,就会创建一个struct files_struct file的多文件管理结构体指针,他通过指向多文件管理结构体struct files_struct,来找到要管理的文件,在这个struct files_struct结构体中有一个结构体数组struct file fd_arry[],这个结构体数组就存储着struct file,对内存中的文件进行管理。这样进程与被打开的文件就关联了起来。

6.1Linux系统下一切皆文件

每一个硬件都有对应的结构体。

键盘有对应的struct keyboard{}

显示器有对应的struct tty{}

键盘有对应的struct disk{}

网卡有对应的struct netcard{}

这些都有对应的IO函数。

例如键盘

int keyboardRead(){} //向键盘中读

int keyboardWrite(){NULL} //向键盘中写,有,但是方法为空

显示器

int ttyRead(){NULL} //显示器中读,有,但是方法为空

int ttyWrite(){} //向显示器中写

其中这些读写程序都应该在自己的驱动程序里面。

并且每种硬件,他的访问方法他是不一样的。

6.2缓冲区

  • 缓冲区本质:就是一段内存,谁申请的?属于谁?为啥要有它。

当我们要将北京的快递发到四川。四川就相当于内存,北京相当于磁盘,写文件就相当于进程,快递就相当于数据,你要把数据直接给你朋友,就相当于你自己从四川到北京,太消耗时加了,外设的传速(IO)太慢,太消耗时间。缓冲区就相当于快递,可以直接将数据交给缓冲,那么缓冲区的意义为:节省进程数据IO 的时间。

但我们没有看到数据拷贝到缓冲区呀。我们使用的是fwrite--------》与其理解fwrite为写入函数,不如理解fwrite为拷贝函数!!!!!!将数据从进程,拷贝到“缓冲区”或者外设中!!

  • 缓冲区刷新策略

就像快递点,发快递一样,不可能一个一个发,这样消耗会增加,一般都是固定频率的来取。

如果有一块数据,一次写入到外设(效率高) VS 如果有一块数据,多次少批量的写入到外设

        a.立即刷新   ------ 无缓冲(一般不考虑)
        b.行刷新  ----- 行缓存 ----- 显示器(进度条小程序) ------- 给人看的(提高效率的同时,提高使用性)
        c.缓冲区满 ------ 全缓存 -------磁盘文件()
        d.用户强制刷新-------(fflush)
        e.进程退出

  • 缓冲区在那里?
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{//C接口printf("hello printf\n");fprintf(stdout,"hello fprintf\n");fputs("hello fputs\n",stdout);//系统接口const char * s = "hello write\n";write(1,s,strlen(s));fork();return 0;}

当从定向到log2.txt会出现(./buffer > log2.txt)

会发现这里的C接口函数被打印了两次,系统调用接口被打印了一次,why?

跟fork有关,当我们的数据被写道显示器上,就不属于父进程了,但数据没有显示到显示器上,此时的数据依旧属于父进程,调完了C接口,数据还在缓存区。

上面的现象可以看出,缓冲区一定不在内核中。因为如果在内核中,write也要被打印两次。

我们之前谈到缓冲区都是在用户级语言给我们提供的缓冲区!!!!

这个缓冲区在stdout,stdin,stderr----->FILE*----->FILE结构体 ----------》fd&&还包括了一个缓冲区!!!!!

所以我们自己强制刷新,fflush(文件指针),close(文件指针) ,为啥有文件指针,因为里面包含了缓冲区。

C语言上的操作,printf,fprintf,fgets.....所有的这些消息,会被写进fp(我们所定义的FILE* fp = fopen())对应的结构体内部的缓冲区里。因为缓冲区里面封装了fd(文件标识符),所以我们的C语言,他会在合适的时候,将我们的数据,刷新到缓冲区里面。

解释上面C接口出现打印两个

1.如果我们没有>(重定向),我们看到了四条消息。

stdout----->默认使用的是行刷新,在进程fork之前,三条C函数,已经将消息打印输出到显示器上了,进程内部已经不存在对应的数据了。

2.如果我们进行>(重定向),写入文件不再是显示器,而是普通的文件(磁盘文件),刷新策略使用的是全缓冲。虽然数据带了"\n”,但是不足以写满stdout缓冲区,数据并没有刷新!!!

再进行fork时,stdout属于父进程,创建子进程的时候,紧接着就是进程退出。谁先退出,就会刷新缓冲区域。刷新,就相当于修改,这时发生写时拷贝。另一个进程退出的时候,就会接着刷新,重新写一份。

3.write没有写两次,是因为,write没有FILE,而用的是文件描述符,就没有缓冲区。

6.3文件写入磁盘的过程

在我们自己写的程序中,hello bit\n实际上,并不是直接他通过我们的刷新策略,写道磁盘上的,而是先通过struct file结构体中的内核缓冲区,内核缓冲区的数据,由操作系统决定刷新,跟我们写的刷新策略没有关系。

如果我们在写数据的时候电脑突然宕机了,但我们是对数据丢失0容忍的,这是就有了fsync函数,可以立即将内核缓冲区的数据写到磁盘上。

7.文件系统

进程与被打开的文件,我们已经了解,那如果是没有被打开的文件呢?

没被打开的文件只能在磁盘上。磁盘上有大量的文件,这些文件也是要被管理起来的,方便我们随时打开!

文件被管理就是文件系统!

1.磁盘的物理结构

固态磁盘(SSD)和机械磁盘,机械磁盘是我们计算机中唯一的一个机械结构,还是个外设,访问很慢(ms),企业主要的存储结构,便宜。

SSD,存储效率高,造价高,性价比不高,读写次数限制,数据丢失,不能恢复。

两面都可以存数据,磁盘表面磁化来保存数据,磁化就相当于,磁面上有一些小的磁铁,通过南北极掉转,来进行磁化。

7.1.磁盘的储存结构

 

磁盘的盘面被分为一个一个磁道,每一个磁道又被分为一个个扇区。每一个扇区的存储量为512bite(字节),磁盘在寻址的时候,基本单位是bit,也不是byte,而是扇面。

为啥 周长不一样,但是数据量是一样的?因为byte(字节)密度是不一样的。

7.1.1在磁面上是如何确定扇面?

1. 先确定磁道(柱面),再确定扇区。

2.磁头通过电机的旋转,来回摆动,就可以确定在那一个磁道上,然后磁片通过电机的转动,让磁头确定扇区的位置。

柱面就是多个盘面的同一磁道组成的,其本质等价与磁道。柱面 的产生是因为,多个盘面的组合,多个磁头的组合,多个磁头是共进退的。

7.1.2CHS定位法

  1. 先确定磁道(柱面)          cylinder
  2. 再定位磁头(定位盘面)   head
  3. 再确定扇区。                     sector

7.1.3LBA访问磁盘

下面我们假设一个磁盘,利用LBA方法进行访问,再将LBA与CHS,进行映射(物理结构抽象成逻辑结构)

盘面:4

磁道/面:10

扇区/磁道:100

扇区:512字节

那么该磁盘的总容量为: 4*10*100*512 byte = 2 * 1024 * 1024 = 2MB

那么对应每个扇区的编号就有4*10*100,每个面的扇区有10*100

要找到123号扇区,就是

确定扇面:123 / 10*100 = 0面H

确定磁道:123 / 100 = 1磁道C

确定扇面:123 % 100 = 23扇面 S

为什么OS要进行逻辑抽象呢?直接用CHS不行吗?

  • 便于管理
  • 不想让OS的代码与硬件强耦合。
  • 不管你磁盘是如何存储的,我操作系统就是认为你是LBA存储,你不管怎么变,我都能使用

磁盘对应的基本单位扇区为512byte,每次访问依旧是很小,如何解决?

每一次IO,等磁盘找, 线程要等(sleep状态 ),操作系统得到数据了(加载到内存了 )。 线程唤醒,   这时候才吧文件加载进来。

虽然对应的磁盘的访问的基本单位是512字节,但是依旧很小!!OS内的文件系统定制的进行多个扇区的读取–〉 1KB,2KB,4KB为基本单位!!

你哪怕指向读取/修改1bit,必须将4KB load内存,进行读取或者修改,如果必要,在写回磁盘!!

解决办法

采用局部性原理========多加载一些,减少IO次数,提高效率。提高数据命中的效率=========用空间换时间

局部性原理!内存是被划分成为了4KB大小的空间–页框〈——磁盘中的文件尤其是可执行文件―--按照4KB大小划分好的块--页帧

7.2分而治之的磁盘

先分区,再分组

(一个分区的第一小块)Boot Block是启动块,计算机加电的时候,首先进行加电自检, 通过硬件的方式,来检测硬件的状态。当识别到盘符,会进行读取,从C盘(根目录), 盘面0号柱面的一号扇区,它上面加载的是我们的分区表,和操作系统所在的位置,跳转到操作系统所在分区,加载操作体统代码,然后加载图形化界面和命令行解释器。操作系统开机的所有信息都在这个区域。

每个分组都有一个Supper Block分组,多个SuperBlock,就以为着备份,分组中有SuperBlock,这就是分区中有多个,就以为着备份,防止数据丢失

Inodes块,利用ls -li可以查看文件的inode,查看一个文件的时候,统一使用的是:inode的编号,这个编号是按区进行编号的,拿到编号很容易找在那个分区的。

inode table在分区的时候就已经被创建了,每一个inode是固定大小256字节或128字节,保存在他里面。

在创建文件的时候就要在inodetable里面,找一个inode,把文件所有属性,存操里面。inode数据结构中有对应的Dateblock信息。

Dateblock放的是文件的内容,每一个文件占用一个或多个块,那些块是属于哪一个文件的,可以标识它。

GroupDescriptorTable:inode一个共多少个,被用多少,Dateblock被用了多少。

写创建文件的过程

1. 存储属性 内核先找到一个空闲的inode节点(这里是2xxxx)。内核把文件信息记录到其中。

2. 存储数据 该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第一块数据复制到300,下一块复制到500,以此类推。

3. 记录分配情况 文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。

4. 添加文件名到目录

新的文件名abc。linux如何在当前的目录中记录这个文件?内核将入口(263466,abc)添加到目录文件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。

删除过程

直接将文件Inodemap,由1致0,就直接删除了,文件删除时可以恢复的

可是我们用的都是文件名呀,没用过inode呀。

任何一个文件都在一个目录下,目录也是文件,目录有属性,也有内容,有自己的inode,和数据块

目录的数据块放的是当前目录下的文件名与inode的映射关系

这也就是我们在创建文件目录的时候,必须要有写的权限

当新增内容的时候必须要向数据块写inde与文件名的映射关系

必须罗列一下当前目录下面的文件名

必须要有读权限

要根据文件名找到inode,才能读取到文件所有属性

相关文章:

Linux入门——06 基础IO

1.什么是当前路径 exe -> /home/lin/Desktop/Linux_learn/fork_learn/test 当前进程执行是磁盘路径下的哪一个程序 cwd -> /home/lin/Desktop/Linux_learn/fork_learn 当前进程的工作目录------》当前进程 1.1当前路径这个地址能改吗&#xff1f; 可以&#xff0c;使…...

未来城市的科技展望

未来城市&#xff0c;‌将是科技与人文深度融合的产物&#xff0c;‌展现出一个全方位智能化、‌绿色生态且可持续发展的全新面貌。‌随着物联网、‌人工智能等技术的飞速发展&#xff0c;‌未来城市的轮廓逐渐清晰&#xff0c;‌它将为我们带来前所未有的生活体验。‌ 在未来…...

DevOps安全性的重要性体现在哪?

DevOps的安全性&#xff0c;也称为DevSecOps&#xff0c;是DevOps领域中的一个重要方面&#xff0c;它强调将安全实践集成到DevOps流程中&#xff0c;以提高代码发布的质量和速度&#xff0c;并降低安全漏洞的风险。 DevOps安全性的重要性&#xff1a; 提高代码质量和速度&…...

【tip】数量级大小

大于1 量级英文名称中文名称yotta尧zetta泽exa艾peta拍tera太giga吉mega兆kilo千hecto百deca十 小于1 量级英文名称中文名称deci分centi厘milli毫micro微nano纳pico皮femto飞atto阿zepto仄yocto幺...

Java基础——自学习使用(static关键字)

一、static关键字是什么&#xff1f; static修饰的代码属于类&#xff0c;定义的变量存储在方法区的静态常量池当中 二、static可以修饰什么 1.static修饰变量 static修饰的变量叫做类变量&#xff0c;被所有该类产生的对象所共享&#xff0c;存储在方法区的静态常量池中 2…...

安装docker+docker远程连接

docker Docker 是⼀个开源的应⽤容器引擎&#xff0c;可以实现虚拟化&#xff0c;完全采⽤“沙盒”机制&#xff0c;容器之间不会存在任何接⼝。 docker架构 docker核心概念 1. 镜像&#xff08;images&#xff09;&#xff1a;⼀个⾯向 docker 容器引擎的只读模板&#xff0c;…...

2080. 邻接点

代码 #include<bits/stdc.h> using namespace std; int main() {int n,e,i,j,x,y;cin>>n >> e;vector<vector<int>> adj(n1);for(i0;i<e;i){cin>>x>>y;adj[x].push_back(y);}for(i1;i<n;i)sort(adj[i].begin(),adj[i].end())…...

《计算机操作系统》(第4版)第7章 文件管理 复习笔记

第7章 文件管理 一、文件和文件系统 1. 数据项、记录和文件 数据组成可分为数据项、记录和文件三级&#xff0c;它们之间的层次关系如图7-1所示。 图7-1 文件、记录和数据项之间的层次关系 (1)数据项 在文件系统中&#xff0c;数据项是最低级的数据组织形式&#xff0c;可以分为…...

uniapp 修复使用 uni.saveImageToPhotosAlbum 方法在部分安卓手机上保存失败

场景&#xff1a;使用 uni.saveImageToPhotosAlbum 保存图片&#xff0c;其他手机都是可以的&#xff0c;但在鸿蒙系统的手机上出现了bug&#xff0c;报错Object {errMsg:"savelmageToPhotosAlbum:fai..errMsg:savelmageToPhotosAlbum:fail invalid filetype"} 原因&…...

电脑无法新建 Word Excle PPT 这些文件是咋回事

咦 我的电脑怎么没有 Excel文件 Word文件 和 PPT选项嘞 &#xff01;&#xff01; 今天突然要写个材料&#xff0c;发现自己新建文件竟然没有excel文档 word和ppt幻灯片这些选项。哦 原来是我自己上次把电脑从win7升级win10系统之后还没有安装wps这些所以不能使用。如果你的电…...

CANoe.DiVa的应用——生成TP层测试用例过程流程详解(二)

🙋‍♂️【Vector CANdelastudio配置CDD】文章合集💁‍♂️点击跳转 ——————————————————————————————————–—— 从0开始学习CANoe使用 从0开始学习车载测试 相信时间的力量 星光不负赶路者,时光不负有心人。 目录 一.概述2.经典CAN T…...

java设计模式--组合模式、适配器模式

组合模式 组合模式&#xff08;Composite Pattern&#xff09;允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式让客户端可以统一地处理单个对象和组合对象。在这个模式中&#xff0c;组合对象&#xff08;Composite&#xff09;和叶子对象&#xff08;Lea…...

保姆级-C#与Halcon的窗体界面展示阈值分割图像教程(机器视觉保姆级教程)

经历上一篇《零基础小白实现C#调用halcon dll的过程&#xff0c;并测试程序证明C#halcon联合开发成功》的发布已经过去三天啦&#xff0c; 零基础小白实现C#调用halcon dll的过程&#xff0c;并测试程序证明C#halcon联合开发成功_添加halcondotnet.dll-CSDN博客 在友友的催更下…...

Kotlin学习-01创建kotlin学习环境

安装idea https://www.jetbrains.com/zh-cn/ 创建项目 选择kotlin 修改Main.kt fun main() {print("Hello World!") }运行...

NGINX 之 location 匹配优先级

章节 1 NGINX 的源码安装 2 NGINX 核心配置详解 3 NGINX 之 location 匹配优先级 4 NGINX 基础参数与功能 目录 1 location 基础语法 1.1 location 语法说明表 1.2 URI部分简单介绍 2 location 匹配优先级 2.1 URI匹配的规则与顺序 2.2 精确匹配(location /1.txt) 2.3 区…...

算法_字符串专题---持续更新

文章目录 前言最长公共前缀题目要求题目解析代码如下 最长回文子串题目要求题目解析代码如下 二进制求和题目要求题目解析 字符串相乘题目要求题目解析代码如下 前言 本文将会向你介绍有关字符串的相关题目&#xff1a;最长公共前缀、最长回文子串、二进制求和、字符串相乘。本…...

Anaconda与conda、pip与conda的区别

Anaconda与conda、pip与conda的区别 1. 引言1.1 背景介绍1.2 文章目的 2. 什么是Anaconda&#xff1f;2.1 Anaconda简介2.2 Anaconda的优势2.3 Anaconda的安装与配置 3. 什么是Conda&#xff1f;3.1 Conda简介3.2 Conda的功能和用途3.3 Conda与Anaconda的关系 4. 什么是Pip&…...

odoo Request Entity Too Large

在数据库恢复中&#xff0c;文件有256M大小&#xff0c;无法正常恢复下。显示如下&#xff1a; 解决办法&#xff1a; 修改http.py文件里面的 DEFAULT_MAX_CONTENT_LENGTH参数&#xff0c; odoo\http.py DEFAULT_MAX_CONTENT_LENGTH 128 * 1024 * 1024 # 128MiB 修改为300M,即…...

【C++ 面试 - 面向对象】每日 3 题(六)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…...

基于tcp c/s的网络通信

TCP&#xff08;即传输控制协议&#xff09;&#xff1a;是一种面向连接的传输层协议&#xff0c;它能提供高可靠性通信(即数 据无误、数据无丢失、数据无失序、数据无重复到达的通信) tcp协议特点: 1. 面向连接 //类似打电话通话之前 &#xff0c;必须先打通 2. 可靠传输 …...

论文翻译:Universal and Transferable Adversarial Attacks on Aligned Language Models

Universal and Transferable Adversarial Attacks on Aligned Language Models https://arxiv.org/pdf/2307.15043v2 通用且可转移的对抗性攻击对齐语言模型 文章目录 通用且可转移的对抗性攻击对齐语言模型摘要1 引言2 一个针对LLMs的通用攻击2.1 产生肯定回应2.2 贪婪坐标梯…...

Axure RP 9高手速成秘籍:解锁终极快捷键,设计效率飙升10倍!

Axure RP 9作为一款功能强大的原型设计工具&#xff0c;提供了丰富的快捷键来加速设计流程。以下是一份详尽的Axure RP 9快捷键大全&#xff0c;旨在帮助用户更高效地完成设计工作。 一、文件操作 新建&#xff1a;Ctrl N&#xff08;Windows&#xff09;/ Command N&#…...

Springcloud从零开始--Eureka(一)

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等&#xff0c;都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有…...

[数据集][目标检测]agvs仓储机器人检测数据集VOC+YOLO格式967张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;967 标注数量(xml文件个数)&#xff1a;967 标注数量(txt文件个数)&#xff1a;967 标注类别…...

(八)Flink Join 连接

在分布式数据处理中,JOIN 是一个非常重要的操作。Flink 的 JOIN 是用于将两个数据流按照一定的条件进行连接,生成新的数据流。Flink 双流 JOIN 主要分为两大类:一类是基于窗口的 JOIN 操作,另一类是基于原生 State 的 Connect 算子操作。其中基于窗口的 JOIN 可细分为 Wind…...

你也想转行成为一名程序员吗?作为过来人的我希望你想清楚这几个问题再做决定

1 有个朋友突然找我&#xff1a;“现在的工作不想干了&#xff0c;我现在转行搞IT能不能行&#xff1f;学哪个编程语言比较有前景&#xff1f;现在去搞网络安全应该没问题吧&#xff1f;”我相信&#xff0c;很多人出于各种原因都在考虑要不要进行职业转换&#xff0c;迷茫又焦…...

Linux文件属性和打包压缩详解

1、文件属性体系 1.1 文件系统概述 [rootyunwei /]# ls -lhi 总用量 72K3505 lrwxrwxrwx. 1 root root 7 3月 7 2019 bin -> usr/bin 262152 dr-xr-xr-x. 5 root root 4.0K 12月 19 16:00 boot 399635 drwxr-xr-x 2 root root 4.0K 11月 5 2019 data1026 drw…...

微服务注册到nacos时,注册失败报错解决

微服务注册到nacos时&#xff0c;注册失败报错解决 微服务注册nacos时报错nacos报错alipay-jraft.log日志报错原因排查 微服务注册nacos时报错 NacosException: failed to req API:/nacos/v1/ns/instance/list after all servers([127.0.0.1:28100]) tried: ErrCode:503, ErrM…...

基于Sringboot+Vue个人驾校预约管理系统--论文pf

TOC springboot503基于SringbootVue个人驾校预约管理系统--论文pf 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。…...

python-逆序数(赛氪OJ)

[题目描述] 在一个排列中&#xff0c;如果一对数的前后位置与大小顺序相反&#xff0c;即前面的数大于后面的数&#xff0c;那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。比如一个元素个数为 4 的数列&#xff0c;其元素为 2,4,3,1&#xff0c;则 (2,…...