【linux】基础IO+系统文件IO+文件描述符分配规则

news2025/1/18 20:10:05

基础IO+系统文件IO+文件描述符+文件描述符分配规则

  • 1.重新谈论文件
  • 2.重谈文件操作(C语言)
    • 2.1C文件接口
  • 3.系统文件IO
    • 3.1open
    • 3.2close
    • 3.3write
    • 3.4read
    • 3.5lseek
    • 3.6总结
  • 4.如何理解文件
  • 5.文件描述符(fd)分配规则

自我名言只有努力,才能追逐梦想,只有努力,才不会欺骗自己。在这里插入图片描述
喜欢的点赞,收藏,关注一下把!在这里插入图片描述

1.重新谈论文件

根据前面所学知识,我们也了解一些文件的相关知识:

1.空文件,也要在磁盘占据空间
2.文件=文件内容+文件属性
3.文件操作=对内容+对属性 or 对内容和属性
4.标定一个文件,必须使用:文件路径+文件名【唯一性】
5.如果没有指定对应的文件路径,默认是在当前路径(进程当前的路径),进行访问

6.当我们把fopen,fclose,fwrite,fread接口写完之后,代码编码之后,形成一个二进制可执行程序之后,但是没有运行,文件对应的操作有没有被执行?

其实并没有,对文件的操作,本质:进程对文件的操作!

7.一个文件如果没有被打开,可以直接进行文件访问吗?

不能,一个文件要被访问,必须先被打开。 那么被谁打开呢?

对文件的操作,是在进程中进行的,因此首先是用户进程,其次对文件操作的C接口是封装了系统调用接口,这部分是由OS操作的。

因此是由用户进程+OS共同进行的。

是不是所有文件都被打开呢?

不是,这里文件分成两类
a.被打开的文件
b.没有被打开的文件

上述这么多知识都是为了阐明一点:
文件操作的本质:进程+被打开文件的关系

2.重谈文件操作(C语言)

1.C,C++,Java,python…shell都有对文件操作的接口,但是接口都不一样

根据目前掌握的知识,了解文件在磁盘里,而磁盘是一个硬件OS能访问硬件,因此所有人想访问磁盘都绕不过OS使用的是OS提供的接口,想访问的是磁盘上的文件,因此使用的是OS提供文件级别的系统调用接口所有语言访问文件接口五花八门,但是操作系统只有一个。

所以上层语言无论如何变化
a.库函数底层都必须调用系统调用接口
b.库函数可以千变万化,但是底层不变

为了降低学习成本------->学习不变的东西

2.1C文件接口

2.文件的操作(C语言)

在C的时候学过文件相关操作知识,这里不再详细说,对这块知识记得不清的可以参考这篇博客超详细C语言文件操作,学完对文件了解更进一步。

在这里插入图片描述
fopen打开文件,必须要提供打开的方式。这里总结一下

r(读),w(写),
r+(读写,文件不存在报错),w+(读写,文件不存在创建),
a(append,追加),a+(在文件尾读写,文件不存在创建),
rb(读(二进制)),wb(写(二进制)),
rb+(读写(二进制),报错),wb+(读写(二进制),创建)
ab(二进制文件尾追加),ab+(二进制文件尾读写,创建)

在这里插入图片描述

   1 #include<stdio.h>
  2 
  3 int main()
  4 {
  5     //打开
  6     FILE* fp=fopen("log.txt","w");
  7     if(fp == NULL)
  8     {
  9         perror("fopen");
 10         return 1;
 11     }
 12 
 13     //写
 14     int cnt=5;
 15     while(cnt)
 16     {
 17         fprintf(fp,"%s:%d\n","hello linux",cnt--);
 18     }
 19 
 20     //关闭                                                                                                                                                       
 21     fclose(fp);          
 22     return 0;            
 23 }  

在这里插入图片描述

  1 #include<stdio.h>
  2 #include<string.h>
  3 
  4 int main()
  5 {
  6     //打开
  7    // FILE* fp=fopen("log.txt","w");
  8     FILE* fp=fopen("log.txt","r");
  9     if(fp == NULL)
 10     {
 11         perror("fopen");
 12         return 1;
 13     }
 14 
 15    // //写
 16    // int cnt=5;
 17    // while(cnt)
 18    // {
 19    //     fprintf(fp,"%s:%d\n","hello linux",cnt--);
 20    // }
 21 
 22    //读
 23     char buffer[64];
 24     while(fgets(buffer,sizeof(buffer)-1,fp) !=  NULL)
 25     {
 26         buffer[strlen(buffer)-1]=0;
 27         puts(buffer);                                                                                                                                            
 28     }
 29 
 30     //关闭
 31     fclose(fp);
 32     return 0;
 33 }

在这里插入图片描述
追加

  1 #include<stdio.h>
  2 #include<string.h>
  3 
  4 int main()
  5 {
  6     //打开
  7    // FILE* fp=fopen("log.txt","w");
  8    // FILE* fp=fopen("log.txt","r");
  9     FILE* fp=fopen("log.txt","a");
 10     if(fp == NULL)
 11     {
 12         perror("fopen");
 13         return 1;
 14     }
 15 
 16    //写                                                                                                                                                          
 17    int cnt=5;
 18    while(cnt)
 19    {
 20        fprintf(fp,"%s:%d\n","hello linux",cnt--);
 21    }
 22 
 23   // //读
 24   //  char buffer[64];
 25   //  while(fgets(buffer,sizeof(buffer)-1,fp) !=  NULL)
 26   //  {
 27   //      buffer[strlen(buffer)-1]=0;
 28   //      puts(buffer);
 29   //  }
 30 
 31     //关闭
 32     fclose(fp);
 33     return 0;
 34 }

在这里插入图片描述
以w方式单词的打开文件,C会自动清空内部数据

  1 #include<stdio.h>
  2 #include<string.h>
  3 
  4 int main()
  5 {
  6     //打开
  7     FILE* fp=fopen("log.txt","w");
  8    // FILE* fp=fopen("log.txt","r");
  9    // FILE* fp=fopen("log.txt","a");
 10     if(fp == NULL)
 11     {
 12         perror("fopen");
 13         return 1;
 14     }                  
 15                        
 16  //  //写
 17  //  int cnt=5;        
 18  //  while(cnt)        
 19  //  {                                                                                                                                                           
 20  //      fprintf(fp,"%s:%d\n","hello linux",cnt--);  
 21  //  }                 
 22                        
 23   // //读              
 24   //  char buffer[64];  
 25   //  while(fgets(buffer,sizeof(buffer)-1,fp) !=  NULL)  
 26   //  {                
 27   //      buffer[strlen(buffer)-1]=0;  
 28   //      puts(buffer);  
 29   //  }               
 30                       
 31     //关闭          
 32     fclose(fp);     
 33     return 0;       
 34 } 

在这里插入图片描述

这些都是C语言给我提供的一些对文件操作的接口。现在来看看OS给我们提供的关于对文件操作的系统调用的接口。

3.系统文件IO

3.1open

在这里插入图片描述
open有两个接口,首先来讲第二个接口
在这里插入图片描述

第一个参数:文件名
第三个参数:权限(如果创建一个文件,告诉系统该文件的权限是什么)

在这里插入图片描述

第二个参数:flags(是一个标记位,告诉系统以什么方式打开文件)

在这里插入图片描述

O_RDONLY(只读),O_WRONLY(只写),O_RDWR(读写)

flags有很多选项,这些选项是大写的,在我们印象中这样写都是宏。

C传标记位,一个int表示一个标记位,如果想传多个标记位怎么办呢?难道要传多个int吗?
显然这样处理不好。
正确解决方法:一个整数---->32个比特位---->通过比特位传递选项(一个比特位,一个选项,比特位位置不能重复)。

  1 #include<stdio.h>
  2 #include<string.h>
  3 
  4 //每一个宏,对应的数值,只有一个比特位是1,彼此位置不能重叠
  5 #define ONE (1<<0)
  6 #define TWO (1<<1)
  7 #define THERE (1<<2)
  8 #define FOUR (1<<3)
  9 
 10 void show(int flags)
 11 {
 12     if(flags & ONE) printf("one\n");
 13     if(flags & TWO) printf("two\n");
 14     if(flags & THERE) printf("there\n");
 15     if(flags & FOUR) printf("four\n");
 16 }
 17 
 18 int main()
 19 {
 20 
 21     show(ONE);
 22     printf("------------------\n");
 23     show(ONE|TWO);
 24     printf("------------------\n");
 25     show(ONE|TWO|THERE);
 26     printf("------------------\n");
 27     show(ONE|TWO|THERE|FOUR);
 28     printf("------------------\n");
 29  
 30     return 0;
 31 }   

在这里插入图片描述

返回值:文件描述符(成功),-1(失败)

在这里插入图片描述

  #include<stdio.h>    
  #include<string.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<fcntl.h>    
     
  int main()    
  {    
      
      //打开    
      int fd=open("log.txt",O_WRONLY);    
      if(fd<0)    
      {    
          perror("open");    
          return 1;    
      }    
      
      //关闭                                                                                                                                                         
	  close(fd);   
	  return 0}

在这里插入图片描述
文件不存在,并不会自动创建。

这是因为我们调用C接口,是对底层的封装,然后让底层帮我们创建,但是现在我们直接用的就是底层,如果不给具体选项,是不会帮我们自动创建的。

 #include<stdio.h>    
  #include<string.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<fcntl.h>    
     
  int main()    
  {    
      
      //打开    
      //O_CREAT 创建
      int fd=open("log.txt",O_WRONLY|O_CREAT);    
      if(fd<0)    
      {    
          perror("open");    
          return 1;    
      }    

      //关闭                                                                                                                                                         
	  close(fd);   
	  return 0}

在这里插入图片描述
虽然成功创建了文件,但是这个文件权限和我们用C接口创建文件的权限是不一样的,这个是上面所说的原因一样,现在用的是系统调用接口,需要直接告诉这个文件权限是什么。

 #include<stdio.h>    
  #include<string.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<fcntl.h>    
     
  int main()    
  {    
      
      //打开    
      int fd=open("log.txt",O_WRONLY|O_CREAT,0666);    
      if(fd<0)    
      {    
          perror("open");    
          return 1;    
      }    
      
      //关闭                                                                                                                                                         
	  close(fd);   
	  return 0}

在这里插入图片描述

在这里插入图片描述
文件不存在,用的是有第三个参数的接口。
文件存在(已经有了权限),用的是没有第三个参数的接口。

这里可能有个疑问。我给新创建的文件权限设置是0666,为什么新创建的文件权限权限是0664呢?

文件最终权限=起始权限(0666)&(~umask(普通用户0002))

所以新创建的文件权限是0664

那我们就想新创建的文件权限就是我们设置的权限怎么办呢?

umask(0)

清掉系统默认的umask

 #include<stdio.h>    
  #include<string.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<fcntl.h>    
     
  int main()    
  {    
      umask(0);
      //打开    
      int fd=open("log.txt",O_WRONLY|O_CREAT,0666);    
      if(fd<0)    
      {    
          perror("open");    
          return 1;    
      }    
      
      //关闭                                                                                                                                                         
	  close(fd);   
	  return 0}

在这里插入图片描述
我们手动清楚了系统默认的umask,为什么这里还是0002呢?
在这里插入图片描述
注意,我们改掉的是子进程的权限,并不影响shell(还是0002)。

3.2close

在这里插入图片描述
关闭文件。
参数就是文件描述符。

3.3write

在这里插入图片描述

第一个参数:向那个文件里写
第二个参数:想写对应的缓冲区数据在哪里

为什么第二个参数用的是void呢?
语言层面把文件类型分为:1,文本文件 。2,二进制文件。
但是操作系统一律认为都是二进制文件,所以是void

第三个参数:缓冲区字节个数

返回值:成功时,写入内容的字节个数会被返回,失败时返回-1。

在这里插入图片描述

 #include<stdio.h>
  #include<string.h>
  #include<sys/types.h>
  #include<sys/stat.h>
  #include<fcntl.h>
  #include<unistd.h>
  #include<stdlib.h>
  
  int main()    
  {    
      umask(0);    
      //打开    
      int fd=open("log.txt",O_WRONLY|O_CREAT,0666);    
      if(fd<0)    
      {    
          perror("open");    
          return 1;    
      }                                                                                                                                                              
      
      //写    
	  const char* buffer="hello linux\n"; 
      ssize_t num= write(fd,buffer,strlen(buffer)); //向文件中写入string,strlen(buffer)+1 需要加1吗?  
      //你以\0作为字符串的结尾,是C语言的规定,和我文件有什么关系呢?     
	  if(num<0)    
      {
          perror("write");
          exit(2);
      }
      
      //关闭
      close(fd);
      return 0;
}

在这里插入图片描述

 #include<stdio.h>
  #include<string.h>
  #include<sys/types.h>
  #include<sys/stat.h>
  #include<fcntl.h>
  #include<unistd.h>
  #include<stdlib.h>
  
  int main()    
  {    
      umask(0);    
      //打开    
      int fd=open("log.txt",O_WRONLY|O_CREAT,0666);    
      if(fd<0)    
      {    
          perror("open");    
          return 1;    
      }                                                                                                                                                              
      
      //写    
	  //const char* buffer="hello linux\n";    
	  const char* buffer="aaaaaa\n";   
      ssize_t num= write(fd,buffer,strlen(buffer));      
	  if(num<0)    
      {
          perror("write");
          exit(2);
      }
      
      //关闭
      close(fd);
      return 0;
}

在这里插入图片描述
为什么是这样的结果呢?

C语言以w方式打开文件,会先清空文件内容再写。
但是open(“log.txt”,O_WRONLY|O_CREAT,0666);只是直接覆盖,并不会清理。
这是因为我们少传一个参数O_TRUNC。

 #include<stdio.h>
  #include<string.h>
  #include<sys/types.h>
  #include<sys/stat.h>
  #include<fcntl.h>
  #include<unistd.h>
  #include<stdlib.h>
  
  int main()    
  {    
      umask(0);    
      //打开    
      int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);    
      if(fd<0)    
      {    
          perror("open");    
          return 1;    
      }                                                                                                                                                              
      
      //写    
	  //const char* buffer="hello linux\n";    
	  const char* buffer="aaaaaa\n";   
      ssize_t num= write(fd,buffer,strlen(buffer));      
	  if(num<0)    
      {
          perror("write");
          exit(2);
      }
      
      //关闭
      close(fd);
      return 0;
}

在这里插入图片描述

以前我们C接口,fopen,以w/a方法打开文件,就是库里直接帮我们把下面工作做好了。
在这里插入图片描述

3.4read

在这里插入图片描述

第一个参数:从那个文件中读
第二个参数:读到那个缓冲区
第三个参数:读多少个字节
返回值:成功返回读取字节的个数,失败返回-1

在这里插入图片描述

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


int main()        
{                 
    umask(0);     
    //打开        
   //bin int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);    
    int fd=open("log.txt",O_RDONLY);    
    if(fd<0)      
    {             
        perror("open");                                                                                                                                    
        return 1;                                                                                                                                          
    }                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                            
    //读                                                                                                                                                   
   char buffer[1024];
   ssize_t num=read(fd,buffer,sizeof(buffer)-1);                                                                                                    
   if(num > 0) buffer[num-1]=0; //0,\0,NULL--->0,,系统调用接口不管读的是什么类型文件,都会当作二进制处理,这里我们想读的是字符串,因此结尾加个\0      
   puts(buffer);
   //关闭
   close(fd);
   return 0;
}

在这里插入图片描述

3.5lseek

重新定位读写文件的偏移量
在这里插入图片描述
这个函数和fseek类似,这里不再演示。

3.6总结

在这里插入图片描述

4.如何理解文件

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

进程可以打开多个文件吗?—>可以—>系统中一定会存在大量的被打开的文件 —>被打开打开的文件,要不要被OS管理起来呢?—>要 —> 如何管理?—> 先描述,在组织 —> 操作系统为了管理对应打开的文件,必定要为文件创建对应的内核数据结构标识文件 —>struct _file{ } —>包含了文件大部分属性。

  #include<stdio.h>
  #include<string.h>
  #include<sys/types.h>
  #include<sys/stat.h>
  #include<fcntl.h>
  #include<unistd.h>
  #include<stdlib.h>
  #define FILE_NAME(number) "log.txt"#number

  int main()
  {
      umask(0);
      //打开
     //int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
     // int fd=open("log.txt",O_RDONLY);
     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;
}

在这里插入图片描述
文件创建成功,并且返回各自对应的文件描述符。
但是奇怪的是:

a.为什么从3开始呢?0,1,2去哪里了?
b.为什么是连续的小整数呢?—>什么会是连续的小整数呢?—> 猜测可能和数组有关

这里就不得不提到,C程序默认会打开三个标准输入,标准输出,标准错误。
在这里插入图片描述
FILE* fp=fopen();问FILE是什么呢?
int fd=open(); int 是文件描述符

我们知道C:fopen…是对底层系统调用接口的封装,而底层用的是文件描述符。

FILE是一个结构体 ----> 必须有一个字段存放文件描述

C调用文件函数的接口不仅对系统调用接口的封装,与此同时C语言FILE结构体也封装了操作系统内的文件描述符。

在这里插入图片描述

 #include<stdio.h>
  #include<string.h>
  #include<sys/types.h>
  #include<sys/stat.h>
  #include<fcntl.h>
  #include<unistd.h>
  #include<stdlib.h>
  #define FILE_NAME(number) "log.txt"#number

  int main()
  {
     umask(0);
     printf("stdin->fd:%d\n",stdin->_fileno);  
     printf("stdout->fd:%d\n",stdout->_fileno);  
     printf("stderr->fd:%d\n",stderr->_fileno);      
      //打开
     //int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
     // int fd=open("log.txt",O_RDONLY);
     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;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
文件描述符的本质:就是数组的下标。

进程与文件直之间对应的关系:进程通过文件描述符来指向文件的。

5.文件描述符(fd)分配规则

  1 #include<stdio.h>  
  2 #include<string.h>  
  3 #include<sys/types.h>  
  4 #include<sys/stat.h>  
  5 #include<fcntl.h>  
  6 #include<unistd.h>  
  7 #include<stdlib.h>  
  8   
  9 int main()  
 10 {  
 11     umask(0);  
 12     int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);  
 13     if(fd == -1)
 14     {
 15         perror("open");
 16         exit(1);                                                                                                                                                 
 17     }                                                                                                
 18     printf("fd:%d\n",fd);                                                                            
 19                                                                                                      
 20     close(fd);                                                                                       
 21                                                                                                      
 22     return 0;                                                                                        
 23 }       

在这里插入图片描述

   1 #include<stdio.h>
  2 #include<string.h>
  3 #include<sys/types.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<unistd.h>
  7 #include<stdlib.h>
  8 
  9 int main()
 10 {
 11     close(0);                                                                                                                                                    
 12     umask(0);
 13     int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
 14     if(fd == -1)
 15     {
 16         perror("open");
 17         exit(1);
 18     }
 19     printf("fd:%d\n",fd);
 20 
 21     close(fd);
 22 
 23     return 0;
 24 }

在这里插入图片描述

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<sys/types.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<unistd.h>
  7 #include<stdlib.h>
  8 
  9 int main()
 10 {
 11     close(2);                                                                                                                                                    
 12     umask(0);
 13     int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
 14     if(fd == -1)
 15     {
 16         perror("open");
 17         exit(1);
 18     }
 19     printf("fd:%d\n",fd);
 20 
 21     close(fd);
 22 
 23     return 0;
 24 }

在这里插入图片描述
对比三次运行结果,发现每次创建新文件fd都不同,在仔细发现这是由于close(fd)关闭文件,所导致的结果。

由图来解释上述原因

在这里插入图片描述
当我们关闭fd为0的文件,重新打开一个文件的时候,进程扫描文件描述符表:从小到大,按照循序寻找最小的且没有被占用的fd。(fd的分配规则)

 1 #include<stdio.h>
  2 #include<string.h>
  3 #include<sys/types.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<unistd.h>
  7 #include<stdlib.h>
  8 
  9 int main()
 10 {
 11    // close(0);
 12    // close(2);
 13     close(1);                                                                                                                                                    
 14     umask(0);                                                         
 15     int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);             
 16     if(fd == -1)                                                      
 17     {                                                                 
 18         perror("open");                                               
 19         exit(1);                                                      
 20     }                                                                 
 21     printf("fd:%d\n",fd);                                             
 22                                                                       
 23     close(fd);                                                        
 24                                                                       
 25     return 0;                                                         
 26 }  

在这里插入图片描述

close(1),为什么没有打印新建文件fd呢?

printf(“%d\n”,fd); printf会把内容打印到stdout文件中。
但是close(1)关闭标准输出stdout—>显示器,int fd=open();新打开的文件fd是1。
stdout–>fd–>1,虽然我们手动关闭了stdout,但是系统并不知道,还以为fd为1的位置是stdout,但是这个位置现在已经被新打开的文件占用了,所以打印到了新打开的文件里。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<sys/types.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<unistd.h>
  7 #include<stdlib.h>
  8 
  9 int main()
 10 {
 11    // close(0);
 12    // close(2);
 13     close(1);
 14     umask(0);
 15     int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
 16     if(fd == -1)
 17     {
 18         perror("open");
 19         exit(1);
 20     }
 21     printf("fd:%d\n",fd);
 22     
 23     //这里必须刷新一下,不然log.txt里面没有内容,这里和缓冲区有关,下面讲                                                                                                                  
 24     fflush(stdout);      
 25     close(fd);           
 26                          
 27     return 0;            
 28 } 

在这里插入图片描述

本来应该打印到显示器文件中,但是确写到文件里了。------>重定向

有关重定向问题,下篇博文解释!

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

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

相关文章

【LeetCode刷题(数据结构与算法)】:数据结构中的常用排序实现数组的升序排列

现在我先将各大排序的动图和思路以及代码呈现给大家 插入排序 直接插入排序是一种简单的插入排序法&#xff0c;其基本思想是&#xff1a; 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为 止&#xff0c;得到一个…

“第四十三天”

这个是我自己写的&#xff0c;下面那个是看的别人的&#xff0c;其实大致都是一样的&#xff0c;通过四次循环&#xff0c;挨个求和比较&#xff0c;都很麻烦&#xff0c;但重点在于&#xff0c;对于已知变量的运用&#xff0c;当我需要在最内层循环用变量确定a数组组元时&…

数据库备份与恢复(实战mysqldump+bin-log)

一、为什么要进行数据库备份&#xff1f; 常见数据库备份的应用场景如下&#xff1a; 数据丢失应用场景&#xff1a; 人为操作失误造成某些数据被误操作 软件 BUG 造成部分数据或全部数据丢失 硬件故障造成数据库部分数据或全部数据丢失 安全漏洞被入侵数据恶意破坏 非数据丢…

基于骑手优化优化的BP神经网络(分类应用) - 附代码

基于骑手优化优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于骑手优化优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.骑手优化优化BP神经网络3.1 BP神经网络参数设置3.2 骑手优化算法应用 4.测试结果…

【STM32】---存储器,电源核时钟体系

一、STM32的存储器映像 1 文中的缩写 2 系统构架&#xff08;原理图&#xff09; 3. 存储器映像 &#xff08;1&#xff09;STM32是32位CPU&#xff0c;数据总线是32位的 &#xff08;2&#xff09;STM232的地址总线是32位的。&#xff08;其实地址总线是32位不是由数据总线是…

MultiPlayerShoot----C++学习记录02人物

获取人物和动画 可以再Mixamo下载你想要的人物&#xff0c;将文件全部导入&#xff08;不做更改&#xff09; 再在网站里选到动画&#xff0c;下载一些动画左转&#xff0c;右转&#xff0c;起跳&#xff0c;跳中&#xff0c;落下 导入动画&#xff0c;此时不用选择导入骨骼&a…

【机器学习】聚类算法Kmeans

文章目录 聚类Kmeans时间复杂度 sklearn.cluster.KMeansn_clusters模型评估指标轮廓系数卡林斯基-哈拉巴斯指数 init & random_state & n_init&#xff1a;初始质心max_iter & tolk_means函数 聚类 聚类就是按照某个特定标准(如距离准则)把一个数据集分割成不同的类…

PhotoShop批量压缩图片

打开photoshop&#xff0c;在顶部的菜单栏选择文件》脚本》图像处理器。 选择合适的参数&#xff0c;运行即可。

【Linux】:权限

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux的基础知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

【excel】列转行

列转行 工作中有一些数据是列表&#xff0c;现在需要转行 选表格内容&#xff1a;在excel表格中选中表格数据区域。点击复制&#xff1a;在选中表格区域处右击点击复制。点击选择性粘贴&#xff1a;在表格中鼠标右击点击选择性粘贴。勾选转置&#xff1a;在选择性粘勾选转置选…

OSI网络分层模型

OSI英文全文是Open System Interconnection Reference Model&#xff0c;翻译成中文就是开放式系统互联通信参考模型。 OSI模型分成了七层&#xff0c;部分层次与 TCP/IP 很像&#xff0c;从下到上分别是&#xff1a; 第一层&#xff1a;物理层&#xff0c;网络的物理形式&…

通讯协议学习之路:IIC协议理论

通讯协议之路主要分为两部分&#xff0c;第一部分从理论上面讲解各类协议的通讯原理以及通讯格式&#xff0c;第二部分从具体运用上讲解各类通讯协议的具体应用方法。 后续文章会同时发表在个人博客(jason1016.club)、CSDN&#xff1b;视频会发布在bilibili(UID:399951374) 序&…

PyCharm运行python测试,报错“没有发现测试”/“空套件”

问题描述&#xff1a;没有发现测试/空套件 当时没截图&#xff0c;可惜了&#xff01; 解决办法 把python测试文件的文件名改为非test开头的&#xff01; &#xff08;虽然pytest的官方说要以test开头&#xff0c;但是他这样会有错误&#xff0c;就很…

节流防抖

节流&#xff1a;wait时间内只能执行一次func 防抖&#xff1a;触发后延迟wait秒调用func 代码对比&#xff1a;&#xff08;建议自己手敲一遍&#xff0c;不要养成直接cv的坏习惯&#xff09; 节流&#xff1a; 其中的apply函数是 apply() 是 JavaScript 函数的一个方法…

Python 编程基础 | 第六章-包与模块管理 | 1、包与模块简介

一、模块 在程序开发过程中&#xff0c;文件代码越来越长&#xff0c;维护越来越不容易。可以把很多不同的功能编写成函数&#xff0c;放到不同的文件里&#xff0c;方便管理和调用。在Python中&#xff0c;一个.py文件就称之为一个模块&#xff08;Module&#xff09;。 1、简…

Acwing 3306.装珠饰(十一届蓝桥java/py组J题)

分析&#xff1a; 6件装备作为一个整体去看待&#xff01;&#xff01;&#xff01;加的效果是看总的装备数目 分组背包的一个特点&#xff1a;每一个组里面只能取出一个物品&#xff0c;这里是把抽象成不同的方案数(有点多重背包的二进制处理方法的感觉。) 代码实现&#xff1…

vue-cli脚手架创建项目时报错Error: command failed: npm install --loglevel error

项目背景 环境&#xff1a;vue-cli 5.x 在工程文件中&#xff0c;后端模块wms已经创建完成&#xff0c;现在想新建一个名为vue-web的前端模块 执行命令vue create vue-web时&#xff0c; 报错Error: command failed: npm install --loglevel error 问题分析及解决 排查过程…

2023各版本JDK下载链接

Java Archive | Oracle Java Archive | Oraclehttps://www.oracle.com/java/technologies/downloads/archive/

音乐播放器蜂鸣器AX301开发板verilog,视频/代码

名称&#xff1a;音乐播放器蜂鸣器播放音乐按键切歌 软件&#xff1a;Quartus 语言&#xff1a;Verilog 代码功能&#xff1a; 设计一个音乐播放器&#xff0c;使用板子上的蜂鸣器播放歌曲&#xff0c;可以播放三首歌&#xff08;歌曲任选&#xff09;&#xff0c;通过按键控…

ESP RainMaker 客户案例 #2|PitPat

PitPat 是美国领先的健身品牌&#xff0c;致力于通过游戏化的方式改变人们的锻炼习惯&#xff0c;增强健康。该品牌通过智能设备和相关的移动应用程序为从事家庭锻炼的个人提供虚拟跑步体验。目前&#xff0c;PitPat 针对不同受众群体&#xff0c;开发了Superun&#xff0c;Dee…