【Linux】六、Linux 基础IO(一)|重谈文件|C语言文件操作|操作系统文件操作(系统文件I/O)|文件描述符

news2024/11/18 16:37:36

目录

一、重谈文件

二、C语言文件操作

2.1 重谈C语言文件操作

2.2 补充细节

三、操作系统文件操作(系统文件I/O)

3.1 文件相关系统调用:close 

3.2 文件相关系统调用:open

3.2.1 open 的第二个参数 flags

3.2.2 open 的第三个参数 mode

3.2.3 open 的返回值

3.3 文件相关系统调用:write

3.4 文件相关系统调用:read

四、文件描述符

4.1 如何理解文件

4.2 什么是文件描述符

4.3 文件描述符的分配规则


一、重谈文件

文件的基本知识:

  1. 文件由文件内容和文件属性两部分构成
  2. 空文件只是文件内容为空,但文件依旧存在属性,所以空文件也要占用磁盘空间
  3. 因为文件由内容和属性构成,所以对文件的操作 = 对内容操作 + 对属性操作 or 对内容和属性操作
  4. 标识一个文件:文件路径 + 文件名(唯一性)
  5. 如果没有指明路径,默认在当前路径下进行文件访问,当前路径是指当前进程的工作路径
  6. 在C语言中,对包含 fopen、fclose、fwrite、fread 等函数接口的程序进行编译链接形成可执行程序之后,如果不运行该可执行程序,相应的文件接口就没有被调用,则对应的文件操作也不会被执行。所以对文件的操作只有进程运行了才会对文件进行操作,运行起来的程序就是一个进程,所以对文件的操作本质上就是进程对文件的操作
  7. 一个文件没有打开,不能直接对文件进行访问;一个文件要被访问,就必须先被打开。怎么打开?用户进程 + OS(操作系统),进程负责调用文件接口,OS 负责打开相应的文件
  8. 一个文件被打开,并不是磁盘上所有的这些文件都被打开了,只是打开了相应的文件。所以磁盘上的文件分为 被打开的文件 + 未打开的文件。所以,文件操作的本质:进程 和 被打开的文件 的关系
  9. 而 没有被打开的文件 与文件系统相关,文件系统也是 基础IO 重点学的对象

二、C语言文件操作

2.1 重谈C语言文件操作

在学习文件操作之前,我们先来回顾一下C语言的文件操作

C语言文件操作部分接口

C语言文件操作函数功能
fopen打开文件
fclose关闭文件
fputc写入一个字符
fgetc读取一个字符
fputs写入一个字符串
fgets读取一个字符串
fprintf格式化写入数据
fscanf格式化读取数据
fwrite向二进制文件写入数据
fread从二进制文件读取数据
fseek设置文件指针的位置
ftell计算当前文件指针相对于起始位置的偏移量
rewind设置文件指针到文件的起始位置
ferror判断文件操作过程中是否发生错误
feof判断文件指针是否读取到文件末尾

C语言文件打开的几种方式(部分)

文件打开方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件
“a”(追加)向文本文件尾添加数据建立一个新的文件
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建议一个新的文件建立一个新的文件
“a+”(读写)打开一个文件,在文件尾进行读写建立一个新的文件
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据出错

C语言文件操作的例子在 C语言专栏的文件操作里面,这里不再演示

        默认打开的三个流,任何进程在运行的时候都会默认打开三个输入输出流,即标准输入流、标准输出流以及标准错误流,对应到C语言当中就是 stdin、stdout 以及 stderr

        随着我们的不断学习,接触的语言逐渐增多,比如面向过程语言C、面向对象语言 C++/java、静态编译语言 go、解释型语言 python 等等语言,它们的都有文件操作,并且接口都不一样,学习成本高。

        但是它们底层调用的接口都一样。因为文件是在磁盘上,磁盘归 OS 管理,而所有人想访问磁盘都绕不开操作系统,想访问磁盘就必须使用 OS 提供的接口,所以想要访问文件,OS 就必须提供相关文件级别的系统接口,所以想访问文件就必须直接或间接使用操作系统提供的接口

        所以无论上层的语言(C/C++/Java..)怎么变化,库函数的底层必须调用系统接口。库函数可以千变万化,但是底层是不变的,要降低学习成本,我们只要学习不变的东西即可!!

        所以我们学习文件操作只需要学习操作系统系统调用有关文件操作方面的接口即可,以后我们再学习语言的文件操作时只需要学习一些新的特性即可,总体层面上是不变的(因为底层接口都一致),大大降低了学习成本

2.2 补充细节

测试代码

#include<stdio.h>      
      
#define FILE_NAME "log.txt"      
      
int main()      
{      
   FILE* fp = fopen(FILE_NAME, "w");                                                                                                                                       
   if(fp == NULL)      
   {      
       perror("fopen");      
       return 1;      
   }      
          
   int cnt = 5;      
   while(cnt)      
   {      
       fprintf(fp, "%s, %d\n", "hello", cnt--);      
   }      
      
   fclose(fp);      
      
    return 0;      
}      

运行结果

        log.txt 文件创建出来的权限为 664,普通文件的默认权限为0666,Linux 下普通用户默认的 umask 为 0002,而文件最终权限等于默认权限 & ~umask,所以 log.txt 的权限为 0664

        C语言以 “w” 方式打开文件时,无论是否写入新数据,都会清空之前文件中的数据 

三、操作系统文件操作(系统文件I/O)

3.1 文件相关系统调用:close 

close:关闭一个文件

man 2 close 进行查看

3.2 文件相关系统调用:open

open:打开或者创建一个文件 

man 2 open 进行查看

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

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

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

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags
参数:
    O_RDONLY: 只读打开
    O_WRONLY: 只写打开
    O_RDWR : 读,写打开
        这三个常量,必须指定一个且只能指定一个
    O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
    O_APPEND: 追加写

mode: 指定创建新文件时文件的默认权限(文件最终权限还要受umask的影响)

返回值:
    成功:新打开的文件描述符
    失败:-1

3.2.1 open 的第二个参数 flags

        open函数的第二个参数是 flags,表示打开文件的方式

        系统接口 open的第二个参数flags是整型,有 32比特位,若将一个比特位作为一个标志位,则理论上 flags 可以传递32种不同的标志位。实际上传入 flags 的每一个选项在系统当中都是以宏的方式进行定义的

参数选项:

 上述这些宏表示不同的文件打开方式,其原理是 通过比特位传递选项

什么是比特位传递选项?

#include<stdio.h>    
    
//每一个宏只占用一个比特位,该比特位为1说明该选项成立,且各个宏的位置不重叠    
#define ONE (1<<0)    
#define TWO (1<<1)    
#define THREE (1<<2)    
#define FOUR (1<<3)    
    
void show(int flags)    
{    
    //flags与上面哪个选项匹配,就执行对应的操作    
    if(flags & ONE) printf("one\n");    
    if(flags & TWO) printf("two\n");    
    if(flags & THREE) printf("three\n");    
    if(flags & FOUR) printf("four\n");    
}    
    
int main()                                                                                                                                                                 
{    
    //主函数中通过传递不同选项来达到不同效果    
    show(ONE);    
    printf("--------------\n");    
    show(ONE | TWO);    
    printf("--------------\n");    
    show(ONE | TWO | THREE);    
    printf("--------------\n");    
    show(ONE | TWO | THREE | FOUR);    
    
    return 0;    
}    

 运行结果

下面进行测试使用

  #include<stdio.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<fcntl.h>    
  #include<unistd.h>                                                                                                                                                       
                                            
  #define FILE_NAME "log.txt"               
                                            
  int main()                                
  {                                                          
      int fp = open(FILE_NAME, O_WRONLY);//以写的形式打开    
      if(fp < 0)                            
      {                                     
          perror("open");                   
          return 1;                         
      }                                     
                                            
      close(fp);                                                                                                                                    
                                                                                                                                                    
      return 0;                                                                                                                                     
  }                                                

运行结果

        文件没有创建成功是因为 没有传创建参数 O_CREAT,系统接口默认是不会自动创建的,必须传创建参数

修改一下代码

运行结果,文件创建成功了

但是,这个文件有点不对劲,它的权限是乱码?这就跟第三个参数有关了

3.2.2 open 的第三个参数 mode

        open函数的第三个参数是mode,表示创建文件的默认权限

        但实际上创建出来文件的权限值还会受到 umask(文件默认掩码)的影响,实际创建出来文件的权限为:mode&(~umask)。umask的默认值普通用户为 0002,当我们设置 mode 值为 0666 时实际创建出来文件的权限为 0664 

再次修改代码

运行结果,文件就可以正常创建了

3.2.3 open 的返回值

        open函数的返回值是新打开文件的 文件描述符

文件描述符下面讲解 

3.3 文件相关系统调用:write

        write 系统接口的作用是向文件写入信息

man 2 write 查看

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

        使用 write 系统调用,将 buf 位置开始向后 count 字节的数据写入文件描述符为 fd 的文件当中

  • 如果数据写入成功,实际写入数据的字节个数被返回。
  • 如果数据写入失败,-1被返回

测试代码

 #include<stdio.h>                                                                                                                                     
  #include<sys/types.h>                                                                                                                                 
  #include<sys/stat.h>                                                                                                                                  
  #include<fcntl.h>                                                                                                                                     
  #include<unistd.h>                                                                                                                                    
  #include<string.h>                                                                                                                                    
                                                                                                                                                        
  #define FILE_NAME "log.txt"                                                                                                                           
                                                                                                                                                        
  int main()                                                                                                                                            
  {                                                                                                                                                     
      int fp = open(FILE_NAME, O_WRONLY|O_CREAT, 0666);//以写的形式打开,不存在创建,权限设置为 0666                                                    
      if(fp < 0)                                                                                                                                        
      {                                                                                                                                                 
          perror("open");                                                                                                                               
          return 1;                                                                                                                                     
      }                                                                                                                                                 
                                                                                                                                                        
      int cnt = 5;                                                                                                                                      
      char outBuffer[64];                                                                                                                               
      while(cnt)                                                                                                                                        
      {                                                                                                                                                 
          sprintf(outBuffer, "%s:%d\n", "hello", cnt--);                                                                                                
          write(fp, outBuffer, strlen(outBuffer));//strlen 之后不用+1,系统接口是以有效数据结尾,不是C语言,C语言 strlen+1代表添加'\0',因为C语言的字符串是以'\0'结尾       
      }                                                                                                                                
                                                                                                                                       
      close(fp);                                                                                                                       
                                                                                                                                       
      return 0;                                                                                                                        
  }                                    

运行结果

修改一下写入文件的内容

   

再次运行,cat 查看文件内容

文件里面怎么有上一次的内容?怎么没有清理干净??

这是因为我们没有传清空文件内容的参数 O_TRUNC,修改代码

再次运行,cat 查看,上一次的内容就被清空了

        C语言的 ‘w’  则是自动清空上一次文件的数据,当你C语言在以 ‘w’ 的方式写入时,实际上操作系统在底层给你传了 O_WRONLY|O_CREAT|O_TRUNC, 0666,这就是系统接口与库函数的区别

3.4 文件相关系统调用:read

        read 系统接口的作用是从文件读取信息

man 2 read 进行查看

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

 使用read函数,从文件描述符为fd的文件读取count字节的数据到buf位置当中

  • 如果数据读取成功,实际读取数据的字节个数被返回
  • 如果数据读取失败,-1被返回

测试代码

 #include<stdio.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<fcntl.h>    
  #include<unistd.h>    
  #include<string.h>    
      
  #define FILE_NAME "log.txt"    
      
  int main()    
  {    
      int fp = open(FILE_NAME, O_RDWR);//O_RDWR读    
      if(fp < 0)    
      {    
          perror("open");    
          return 1;    
      }    
      
      char buffer[512];    
      ssize_t num = read(fp, buffer, sizeof(buffer)-1);    
      if(num>0)    
      {    
          buffer[num] = 0;//C语言的字符串以'\0'结尾    
      }    
      printf("%s", buffer);                                                                                                                                                
      
      close(fp);    
      
      return 0;    
  }    

运行结果

        由于C语言字符串以 ‘\0’ 结尾,而文件中的字符串数据并不包含 ‘\0’,所以这里我们需要预留一个位置,便于在数据量大于等于512字节情况下 buf 中仍有空间来放置 ‘\0’ 

总结

        C语言的库函数接口 fwrite fread fclose fopen ..,类比系统调用接口 write read close open ...,实际上就是 C语言对系统调用接口进行封装形成库函数

四、文件描述符

4.1 如何理解文件

上面已经说过

        文件操作本质上是 进程 与 被打开文件 之间的关系

        一个进程可以打开多个文件,且操作系统同时运行着许多个进程,那么操作系统中就一定存在着大量被打开的文件 

那这些被打开的文件要不要被操作系统管理起来呢?肯定要的

怎么管理?

        先描述,在组织

        操作系统为了管理被打开的文件,必定要为文件创建对应的 内核数据结构用于标识文件,在 Linux 中,这个数据结构是 struct file {}这个结构体包含了文件的大部分属性(这个结构体与C语言的 FILE 没有任何关系)

4.2 什么是文件描述符

        open 系统调用的返回值是新打开文件的 文件描述符 

测试代码

C语言 # 在宏当中的作用 – 将参数插入到字符串中 

#include<stdio.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<fcntl.h>    
  #include<unistd.h>    
  #include<string.h>    
      
  #define FILE_NAME(number) "log.txt"#number    
      
  int main()    
  {    
      
      int fd0 = open(FILE_NAME(1), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      int fd1 = open(FILE_NAME(2), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      int fd2 = open(FILE_NAME(3), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      int fd3 = open(FILE_NAME(4), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      int fd4 = open(FILE_NAME(5), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      
      printf("fd0:%d\n", fd0);    
      printf("fd1:%d\n", fd1);    
      printf("fd2:%d\n", fd2);    
      printf("fd3:%d\n", fd3);    
      printf("fd4:%d\n", fd4);    
      
      close(fd0);    
      close(fd1);                                                                                                                                                          
      close(fd2);    
      close(fd3);    
      close(fd4);    
      
      return 0;    
}

运行结果

        从运行结果可以看到,文件描述符是连续分配且依次增大的,这也很合理,因为文件描述符本质上是数组下标,而连续增长正好是数组下标的特性;但是这里有一个很奇怪的地方 – 文件描述符是从3开始的,但是0、1、2 呢? 

        这是由三个默认打开的标准流引起的:标准输入stdin、标准输出流stdout 与 标准错误流stderr

man stdin 查看,这三个流都是 FILE* 的指针,FILE 结构体里面就一定会封装一个变量来表示文件描述,这个这个变量是 _fileno

         在C语言中,打开一个文件:FILE* fp = open(),这个 FILE 实际上也是一个结构体,它底层封装采用的是系统调用,所以必定有一个字段叫做:文件描述符

所以,我们进行打印一下这三个值

  #include<stdio.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<fcntl.h>                                                                                                                                                        
  #include<unistd.h>    
  #include<string.h>    
      
  #define FILE_NAME(number) "log.txt"#number    
      
  int main()    
  {    
      printf("stdin->fd:%d\n", stdin->_fileno);    
      printf("stdout->fd:%d\n", stdout->_fileno);    
      printf("stderr->fd:%d\n", stderr->_fileno);    
      
      int fd0 = open(FILE_NAME(1), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      int fd1 = open(FILE_NAME(2), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      int fd2 = open(FILE_NAME(3), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      int fd3 = open(FILE_NAME(4), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      int fd4 = open(FILE_NAME(5), O_WRONLY|O_CREAT|O_TRUNC, 0666);    
      
      printf("fd0:%d\n", fd0);    
      printf("fd1:%d\n", fd1);    
      printf("fd2:%d\n", fd2);    
      printf("fd3:%d\n", fd3);    
      printf("fd4:%d\n", fd4);    
      

      close(fd0);
      close(fd1);
      close(fd2);
      close(fd3);
      close(fd4);
  
      return 0;
  }

 运行结果

        从运行结果就可以知道, 因为三个标准流是默认打开的,所以 0、1、2 是默认被占用的,所以文件描述符默认是从 3 开始的

        而现在知道,文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体,表示一个已经打开的文件对象

        而进程执行 open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!

        所以,本质上,文件描述符就是该数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件

4.3 文件描述符的分配规则

测试代码

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

运行结果,是3,没毛病,0、1、2 默认被占用

 

若我们先关闭文件描述符为0的文件,此后文件描述符的分配又会是怎样的呢? 

修改一下代码

再次运行,可以看到,打开的文件获取到的文件描述符变成了0 

  

再次修改代码

  #include<stdio.h>                                                                                                                  
  #include<sys/types.h>                                                                                                              
  #include<sys/stat.h>                                                                                                               
  #include<fcntl.h>                                                                                                                  
  #include<unistd.h>                                                                                                                                                                                                                                 
                                                                                                                                     
  int main()                                                                                                                         
  {                                                                                                                                  
      close(0);//关闭文件描述符0                                                                                                     
      close(2);                                                                                                                      
                                                                                                                                     
      int fd1 = open("log.txt1", O_WRONLY|O_CREAT|O_TRUNC, 0666);                                                                    
      int fd2 = open("log.txt2", O_WRONLY|O_CREAT|O_TRUNC, 0666);                                                                    
      int fd3 = open("log.txt3", O_WRONLY|O_CREAT|O_TRUNC, 0666);                                                                                                          
                             
      printf("open fd1: %d\n", fd1);    
      printf("open fd2: %d\n", fd2);    
      printf("open fd3: %d\n", fd3);    
                                                                                                                                                        
      close(fd1);                                                                                                                                       
      close(fd2);                                                                                                                                       
      close(fd3);                                                                                                                                       
                                                                                                                                                        
      return 0;                                                                                                                                         
  }                               

 运行结果

  

可以看到,当 0 和 2 文件描述符被关闭以后,系统将其分配给了新打开的文件

        close 关闭文件并不是将 fd 指向的文件对象释放掉,而仅仅是让当前进程文件描述符表中的对应下标不再指向该文件对象,因为同一个文件可能会被多个进程访问

        其底层采用 count “引用计数” 的方式来实现,即当有指向该文件的进程关闭时文件计数减1,有指向该文件的进程打开时文件计数加1,当 ount 为 0 时操作系统才释放该文件的内核数据结构,即真正意义上的关闭文件

        所以,文件描述符的分配规则是:在 files_struct 数组当中,从小到大依次搜寻,找到当前没有被使用的最小的一个下标,作为新的文件描述符

----------------我是分割线---------------

文章到这里就结束了,下一篇即将更新

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

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

相关文章

解决跨微服务调用token共享问题

场景描述 使用jeecg搭建SpringCloud微服务系统模块&#xff0c;各个系统模块单独创建了拦截器进行权限校验。结果发现跨微服务调用存在鉴权失败问题。不能正常跨微服务调用。 原因描述 单个微服务鉴权拦截器。 package org.jeecg.modules.taxation.inerceptor;import org.s…

【MySQL】MySQL单表操作

序号系列文章2【MySQL】MySQL基本操作详解3【MySQL】MySQL基本数据类型4【MySQL】MySQL表的七大约束5【MySQL】字符集与校对集详解文章目录MySQL单表操作1&#xff0c;数据操作1.1&#xff0c;复制表结构和数据1.2&#xff0c;解决主键冲突1.3&#xff0c;清空数据1.4&#xff…

二叉树详解(概念+遍历实现)

一、基本概念 1.最左孩子结点&#xff1a;一个结点的孩子结点中位于最左边的孩子结点。例如&#xff0c;A——B&#xff0c;B——E&#xff1b; 2.树的高度&#xff1a;树的最高层数&#xff1b; 3.路径长度&#xff1a;树中的任意两个顶点之间都存在唯一的一条路径。一条路径所…

我们这样做容器分层性能测试

前言目前闲鱼不少业务正在从H5/Weex升级到Kun&#xff08;基于W3C标准&Flutter打造的混合高性能终端容器&#xff09;&#xff0c;从测试角度来看&#xff0c;我们希望这种升级迭代对于用户体验是正向的&#xff0c;所以用好性能测试这把标准尺就显得格外重要。早期做性能保…

有什么比较好用的低代码开发平台?

国内有特色的低代码快速开发平台产品有哪些&#xff1f;这篇就来介绍下目前市面上主要的几家零代码开发平台&#xff01; 简道云、明道云、IVX这几家目前是无代码赛道的明星选手&#xff0c;在市场综合表现上名列前茅。宜创、红圈营销虽也极具潜力&#xff0c;但在市场表现力上…

Java开发技术之成为高级java工程师必须学习的三个技术

所谓的Java高级程序员往往是经验和能力的结合&#xff0c;并不是说掌握了哪几个技术就是高级程序员了&#xff0c;能否把掌握的知识运用到实际的项目中&#xff0c;并且解决了具体的问题&#xff0c;这个才是衡量一个Java程序员的标准。 那么对于一名Java程序员来说&#xff0…

Java项目:房屋租赁系统设计和实现(java+ssm+mysql+spring+jsp)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 主要功能描述&#xff1a; 1.登录管理&#xff1a;主要有管理员登录和租客登录 2.房源列表以及添加房源功能&#xff1a; 3.租赁合同管理以及在租房源和已退租房源信息管理: 4.看房申请和退租申请管理&a…

【 java 集合】HashMap源码分析

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

python基础篇之列表(增删改查)

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a;lqj_本人的博客_CSDN博客-微信小程序,前端,vue领域博主lqj_本人擅长微信小程序,前端,vue,等方面的知识https://blog.csdn.net/lbcyllqj?spm1000.2115.3001.5343 哔哩哔哩欢迎关注&…

excel数据统计:三个公式提高统计工作效率

善于在工作中使用函数、公式可以提高工作效率&#xff0c;结合近期学员们遇到的问题&#xff0c;老菜鸟总结了三个非常实用的公式&#xff0c;每个公式都可以解决一类问题。学会这三个公式套路&#xff0c;就能解决日常遇到的很多麻烦事。第一类问题&#xff1a;对指定时间段的…

通过nvm 控制node的常见命令

通过nvm 控制node查看本电脑安装的node版本号切换到对应的node版本号可以查看nvm的全部命令查看node可安装的全部版本号下载对应node的版本查看本电脑安装的node版本号 nvm ls 查看本电脑安装的node版本号 切换到对应的node版本号 nvm use 版本号 切换到对应的node版本号 注意…

基于Python + Django 的密码自助平台项目(完整代码)

场景说明&#xff1a;因为本公司 AD 是早期已经在用&#xff0c;用户的个人信息不是十分全面&#xff0c;例如:用户手机号。 钉钉是后来才开始使用&#xff0c;钉钉默认是使用手机号登录。 用户自行重置密码时如果通过手机号来进行钉钉与 AD 之间的验证就行不通了。逻辑&#x…

Linux驱动开发基础_在设备树中指定中断以及在代码中获得中断

目录 1 设备树里中断节点的语法 1.1 设备树里的中断控制器 1.2 设备树里使用中断 2 设备树里中断节点的示例 3 在代码中获得中断 3.1 对于 platform_device 3.2 对于 I2C 设备、SPI 设备 3.3 调用 of_irq_get 获得中断号 3.4 对于 GPIO 1 设备树里中断节点的语法…

OVN实验----L3互通

概述 物理拓扑 如上一个实验OVN实验----L2互通 逻辑拓扑 按照上个实验OVN实验----L2互通 的操作方式&#xff0c;再配置一组容器blue&#xff0c;网段192.168.2.0/24 配置完成后可以在central上ovn-sbctl show看到如下4个绑定接口 此时&#xff0c;red和blue两个网段内是可…

EasyTrans,一个注解搞定数据翻译,减少30%SQL代码量

介绍easy trans适用于3种场景1 有userId/idCardNo(身份证号码-唯一键场景) 需要 userName&#xff0c;无需联表查询。2 有gender code 0 需要 男。3 枚举指定属性给前端亮点1 缓存支持2 跨微服务翻译支持(User和Order 是2个不同微服务&#xff0c;order里面有userId 需要userNa…

strapi系列--如何自定义非界面化的接口,定制化自己的业务逻辑

为什么要进行后端定制呢&#xff1f; 在实际开发过程中&#xff0c;项目中有些需求是不需要创建界面化接口的&#xff0c;需要我们定制化自己的业务逻辑&#xff0c;那么我们该如何处理这个需求呢&#xff1f;本文以图文并茂的形式&#xff0c;定制一个我们自己的业务逻辑接口…

blender 应用物体变换的作用

编辑模式和物体模式操作的区别 旋转 在物体模式下旋转时物体旋转值会发生变换** 在编辑模式下旋转时物体不会发生变化** 缩放 在物体模式下缩放会导致缩放尺寸发生变化 在编辑模式下缩放时&#xff0c;缩放属性不会发生变化 应用物体变换 把物体模式下的缩放旋转变换应…

Android---TabLayout

目录 TabLayout TabItem ​编辑 演示效果的xml TabLayout TabLayout 在开发中一般作为选项卡使用&#xff0c;常与 ViewPager2 和 Fragment 结合起来使用。 常用属性&#xff1a; app:tabBackground 设置 TabLayout 的背景色&#xff0c;改变整个TabLayout 的颜色&#xf…

绪论的习题

刘佳瑜*&#xff0c;王越 *, 黄扬* , 张钊* (淮北师范大学计算机科学与技术学院&#xff0c;安徽 淮北) *These authors contributed to the work equllly and should be regarded as co-first authors. &#x1f31e;欢迎来到机器学习的世界 &#x1f308;博客主页&#xff1…

idea调试常用的快捷键

一、F7 步入调试&#xff0c;进入当前函数内部。 说明&#xff1a; 如果步入的是自己编的函数&#xff0c;可读性会好很多。 如果是系统函数&#xff0c;我个人目前水平&#xff0c;觉得很难读。而且idea系统已编写好的函数&#xff0c;除非是研究源码&#xff0c;否则感觉…