linux下的基础io(代码片段)

两片空白 两片空白     2022-12-25     659

关键词:

目录

一.C语言文件IO操作(库函数)

1.打开文件fopen

 2.写入二进制文件fwrite和读取二进制文件fread

3.关闭文件fclose

 二.系统文件IO(系统调用接口)

1.打开文件open系统调用

2.读文件read和写文件write

3. 关闭文件close 

 三.文件描述符

1.系统管理文件的原理

 2.文件描述符是什么

3.文件描述符的分配规则

四.如何理解Linux下一切皆文件

五.总结,进程如何操作一个文件

 六.重定向

1.重定向原理

 2.使用dup2系统调用

 七.理解FILE

1.发现问题


一.C语言文件IO操作(库函数)

文件分为文本文件和二进制文件。

文本文件:在内存中什么样,保存在硬盘时需要转化,需要转化成字符,这个操作需要程序员做。

二进制文件:在内存中什么样,在硬盘就什么样。

1.打开文件fopen

fopen打开文件失败返回NULL,打开成功返回一个C语言的文件指针FILE*。

fopen参数:

        path:打开文件的路径,默认当前路径。当前路径是指可执行程序所在的路径。但是在VS中为源文件所在的路径,可执行程序在debug目录下。

        mode:为打开文件的方式。

文件打开方式含义如果指定文件不存在
"r"(只读)打开一个已经存在的文本文件,读取文件内容出错
"w"(只写)打开一个文本文件,往该文件中写入数据。会建立一个新文件
"a"(追加)打开一个文本文件,在文件最后添加数据。出错
"rb"(只读)打开一个已经存在的二进制文件,读取文件内容出错
"wb"(只写)打开一个二进制文件,往该文件中写入数据。建立一个新文件
"ab"(追加)打开一个二进制文件,在文件最后添加数据。出错
"r+"(读写)打开一个文本文件,可对该文件读和写出错
"w+"(读写)打开一个文本文件,可对该文件读和写建立一个新文件
"a+"(读写)打开一个文本文件,可在该文件末尾读和写建立一个新文件
"rb+"(读写)打开一个已经存在的二进制文件,可对该文件读写出错
"wb+"(读写)打开一个二进制文件,可对该文件读写建立一个新文件
"ab+"(读写)打开一个已经存在的二进制文件,可在该文件末尾读和写建立一个新文件

总结:r是读文件,w是写文件,a是追加文件,带+号为可读可写。带b为对二进制文件操作,不带b是对文件文件操作。打开文件为w方式时,文件不存在会建立新文件。

 2.写入二进制文件fwrite和读取二进制文件fread

 后面有代码演示。

3.关闭文件fclose

  1 #include<stdio.h>
  2 #include<string.h>
  3 
  4 int main()
  5   FILE* fp=fopen("log.txt","w");
  6   if(NULL==fp)
  7     perror("fopen fail");
  8     return 1;
  9   
 10   const char *str="hello linux\\n";                                                                                                                       
 11   fwrite(str,strlen(str),1,fp);
 12   fclose(fp);
 13 
 14 
 15   return 0;
 16 

    1 #include<stdio.h>
    2 #include<string.h>
    3 
    4 int main()
    5   FILE* fp=fopen("log.txt","r");
    6   if(NULL==fp)
    7     perror("fopen fail");
    8     return 1;
    9   
   10   char *buf[1024];
   11   fread(buf,1024,1,fp);
W> 12   printf("%s",buf);                                                                                                                                    
   13   //const char *str="hello linux\\n";
   14   //fwrite(str,strlen(str),1,fp);
   15   fclose(fp);
   16 
   17 
   18   return 0;
   19 

 二.系统文件IO(系统调用接口)

1.打开文件open系统调用

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

 flags:打开文件的方式。

        O_RDONLY:只读打开

        O_WRONLY:只写打开

        O_RDWR:读写打开

        这三个常量,必须指定一个,并且只能指定一个。

        O_CREAT:若文件不存在,则创建该文件。需要使用mode选项来指明创建文件的权限。即需要用到上面的第二个有三个参数的open函数。

        O_APPEND:追加写

        O_TRUNC:将文件内容清空。

        flags参数类型是一个整形,上面的各种方式其实都是宏定义。每一个宏代表的数化成二进制后,都只有特定的一位为1.不同的位代表不同的功能。即可以将上面个方式按位或,实现不同的功能呢在一起。

mode:为创建新文件的权限,为8进制。但是一般输入4位,在最开始输入0。否则,C语言会将其看作10进制。

返回值:打开成功:新打开文件的文件描述符。

                打开失败:返回-1。 

2.读文件read和写文件write

3. 关闭文件close 

  2 #include<string.h>
  3 #include<sys/types.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<unistd.h>
  7 
  8 int main()
  9   int fd=open("log.txt",O_WRONLY|O_CREAT,0644);
 10   if(-1==fd)
 11     perror("open fail");
 12     return 1;
 13   
 14   const char *str="hello world\\n";
 15   write(fd,str,strlen(str));
      close(fd)
 16   return 0;                                                                                                                                              
 17  
    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 
    8 int main()
    9   int fd=open("log.txt",O_RDONLY|O_CREAT,0644);
   10   if(-1==fd)
   11     perror("open fail");
   12     return 1;
   13 
   14   
   15   char *buf[1024];
   16   read(fd,buf,1024);
W> 17   printf("%s",buf);                                                                                                                                    
   18   //const char *str="hello world\\n";
   19   //write(fd,str,strlen(str));
        close(fd);
   20   return 0;
   21 

总结:

        上面的fopen,fclose,fread,fwrite都是C标准库中的库函数。

        而,open,close,read,write属于系统提供的接口,为系统调用接口。

        库函数与系统调用的关系,可以认为时一种上下级关系。即大多数库函数都是系统调用的封装。 

 三.文件描述符

1.系统管理文件的原理

        我们如果想了解文件描述符的含义,首先我们得知道系统时如何管理文件的。

  • 系统为什么要管理文件?

文件是由进程打开的,一个进程可以打开多个文件。理论上来说,多个进程可以打开一个文件,但是这样会导致文件内容混乱,一般不这样做。所以我们可以理解进程和文件的关系为1对多的关系。

系统中会有很多进程,也可能会打开很多的文件,为了使文件不会再系统中出现混乱,所以需要系统管理文件。

  • 系统如何管理文件?

先描述和组织。

描述文件:Linux操作系统是由C语言编写的,所以操作系统描述文件是通过结构体来描述文件的。这个结构体名字为struct_file

组织文件:系统用一种数据结构,将描述的文件链接起来。用链表,将每一个struct_file连接起来。

这样的管理方式就像系统对进程的管理方式一样。

  • 文件与进程的关系?

文件是由进程打开的,并且一个进程可以打开多个文件。所以这个进程要与文件组织的链表要产生关联或者说有一种映射关系。由于进程和文件是一对多的关系,所以进程是用数组与文件组织的链表进行关联的。

所以我们得到了一张图:

 2.文件描述符是什么

结论:文件描述符实际就是files_struct里数组的下标。

  •  为什么上面代码会等于3。

因为Linux系统默认情况下会默认打开三个文件,标准输入,标准输出,标准错误。这三个文件一斤在数组中分配好了下标,分别是0,1,2。

3.文件描述符的分配规则

 关闭文件描述符为0的文件时,再立马打开一个文件,我们发现,此时新打开文件的文件描述符为0。 

文件描述符的分配规则:

对于进程来讲,默认的文件描述符从3开始分配。因为0,1,2默认分配给了标准输入,标准输出,标准错误。

但是,文件描述符分配时从最小的没有使用过的数组下标开始分配的。

四.如何理解Linux下一切皆文件

  • 每一个硬件最主要的操作是读和写。但是每一个硬件实现读和写的实现方法不一样,例如:访问网卡和访问硬盘的方法不一样。
  • Linux下一切皆文件,每一个硬件都可以用一个文件来描述,然后组织管理。

  • 为什么说Linux下一切皆文件?

每一个硬件都会对应一个struct_file,都会有对应不同访问的方法。 OS看到的时虚拟层,都是一个个的文件(struct_file)。

 五.总结,进程如何操作一个文件

  • 进程打开一个文件

OS会在创建一个struct_file描述这个文件,再将该文件连接到系统管理文件的链表中。找到进程PCB指针file指向的files_struct里的数组。根据文件描述符的分配规则,往数组中填入struct_file的地址。

注意:并不是文件不存在,创建文件时才创建struct_file,而是打开文件时创建,因为之前没有打开过该文件。打开文件是将硬盘中的文件加载到内存。磁盘有自己的文件系统。

  • 进程往文件写入数据

open系统调用:找到该进程,通过PCB找到files_struct,得到文件描述符fd。

write系统调用:通过文件描述符fd,找到该文件的结构体,即找到该文件。要写入数据,就是调用该文件的写入数据的函数指针,调用写入函数。

 六.重定向

重定向符号">"。

1.重定向原理

printf是C语言的库函数,是往文件描述符为1的文件中打印数据。

重定向原理">":

内核将标准输出(stdout)文件描述符为1的文件关闭再用O_WRONLY | O_CREAT | O_TRUNC 打开方式打开一个文件。按照文件描述符的分配规则,是从数组下标最小并且未使用的下标分配,将文件描述符1分配给了新打开的文件。但是这个操作是操作系统做的,在应用层并不知道标准输出被替换了,还会继续往文件描述符为1的文件打印。 

追加重定向原理">>":

和重定向原理相同,只是打开文件的方式不同,使用的是O_WRONLY | O_CREAT | O_APPEND方式打开的文件。

输入重定向"<":

内核关闭文件描述符为0的文件,将标准输入关闭。用O_RDONLY 方式打开文件。 按照文件描述符的分配规则,将文件描述符0分配给了新打开的文件。然后会读取文件描述符为0文件的内容。

重定向原理示意图: 

 2.使用dup2系统调用

实现重定向需要想将文件描述符为1的文件关闭,再打开一个文件。

使用dup2系统调用,不需要先关闭文件描述符为1的文件。

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 #include<unistd.h>
  6 
  7 int main()
  8   //close(1);
  9   int fd=open("log.txt",O_WRONLY|O_CREAT,0644);
 10 
 11   if(-1==fd)
 12     perror("open fail");
 13     return 1;
 14   
 15   dup2(fd,1);//将数组下标为fd位置内容拷贝给数组下标1处
 16   close(fd); //防止文件描述符泄漏                                                                                                                                            
 17   printf("%d\\n",fd);
 18   fflush(stdout);
 19   close(fd);
 20 
 21   return 0;
 22 

 七.理解FILE

FILE是C标准库里的,表示文件的一种类型。本质是一个结构体。

C语言中的标准输入,标准输出,标准错误为

  • FILE* stdin
  • FILE* stdout
  • FILE* stderr

他们的类型都是FILE*的。

1.发现问题

 重定向后: 

为什么往stdout打印重定向后也往文件了打印?

  •  打开文件实质上都需要通过文件描述符来打开文件,所以FILE结构体中一定含有文件描述符。
  • printf时往stdout打印。
  • 实际上stdin,stdout,stderr的FILE结构体中的文件描述符为0,1,2。当发生重定向时,stdout里的文件描述符还是1,但是1指向的文件发生了改变。

 为什么重定向后,printf和fprintf(库函数)后输出了两次,但是write只输出了一次?

  • 我们知道在C语言中将数据写入文件需要经过缓冲区,一般C库函数写入文件时是全缓冲方式的,写入显示器是行缓冲方式的。
  • 一开始是将数据写到显示器上,为行缓冲方式,当重定向到普通文件后,缓冲方式变成了全缓冲。
  • 当执行到fork前,printf和fprintf数据保存在缓冲区里。保存在缓冲区里的数据还是父进程的数据。
  • 执行fork时,创建子进程,子进程会将父进程的数据发生写时拷贝再刷新数据后,父子进程都将各自缓冲区的数据刷新出来了。
  • write没有打印两份,说明,write并没有自己的缓冲区,已经将数据打印了。

没有重定向只输出一次是因为,行缓冲已经将数据冲缓冲区刷新出去了。创建子进程时,已经没有这个数据了。

上面结论还说明:缓冲区并不是操作系统提供的,而是语言提供的。如printf和fprintf缓冲区时有C语言提供的。

FILE库函数代码:

linux/unix系统下的线程安全io(代码片段)

SIOPackages(Signal-SafeIO)/**************************************************************TheSio(Signal-safeI/O)package-simplereentrantoutput*functionsthataresafeforsignalhandlers.********************* 查看详情

linux/unix系统下的线程安全io(代码片段)

SIOPackages(Signal-SafeIO)/**************************************************************TheSio(Signal-safeI/O)package-simplereentrantoutput*functionsthataresafeforsignalhandlers.********************* 查看详情

linux下的网络i/o——转载(代码片段)

转载于——腾讯技术工程文章目录网络IO的发展网络的两个阶段堵塞IO和非堵塞IO的区别同步IO和异步IO的区别堵塞IO非堵塞IOIO多路复用select/pollselectpollselect/pollIO多路复用epoll异步IOreactor模型1.单reactor模型2.单reactor多线程模型3.multi-... 查看详情

linux下的网络i/o——转载(代码片段)

转载于——腾讯技术工程文章目录网络IO的发展网络的两个阶段堵塞IO和非堵塞IO的区别同步IO和异步IO的区别堵塞IO非堵塞IOIO多路复用select/pollselectpollselect/pollIO多路复用epoll异步IOreactor模型1.单reactor模型2.单reactor多线程模型3.multi-... 查看详情

linux下的io重定向与管道相关的知识简析(代码片段)

一、bash重定向部分简单翻译1.1、bash手册关于重定向短短的注解(因为过于经典,所以摘录出来)我的翻译要开始毁经典啦...参考:https://blog.csdn.net/spch2008/article/details/51433353/https://www.cnblogs.com/lqminn/archive/2013/05/30/3108283.htmlhttps://bash.... 查看详情

linux基础io-io接口,文件描述符,重定向(代码片段)

【Linux】基础IO文章目录【Linux】基础IO一、C语言中文件IO操作1.C语言中的开关读写文件1.1.fopen()1.2.fclose()1.3.fwrite()1.4.fread()2.stdin&&stdout&&stderr3.三个标准流和IO接口二、系统文件IO1.系统级别的开关读写文件1.1.open()1.2.close... 查看详情

linux基础io(代码片段)

愿所有梦见远方的人,心有惊雷,生似静湖。基础IO前言一、C语言中文件的IO操作fopen函数打开文件fread函数读文件fwrite函数写文件stdin&stdout&stderr二、系统I/O操作open函数open的第一个形参open的第二个形参open的第三个... 查看详情

[转帖]linux下的cpu内存io网络的压力测试(代码片段)

  https://www.cnblogs.com/zhuochong/p/10185881.html 一、对CPU进行简单测试:1、通过bc命令计算特别函数例:计算圆周率echo"scale=5000;4*a(1)"|bc-l-qMATH LIBRARY        If&n 查看详情

linux入门基础io(代码片段)

基础IO✔回顾C文件的接口✔系统文件I/O✔文件描述符文件描述符的分配规则重定向✔FILE缓冲区fclose和close✔dup2系统调用✔理解文件系统inode硬链接软链接文件的三个时间✔回顾C文件的接口在学习C语言时我们了解了一些C语言的对... 查看详情

linux入门基础io(代码片段)

基础IO✔回顾C文件的接口✔系统文件I/O✔文件描述符文件描述符的分配规则重定向✔FILE缓冲区fclose和close✔dup2系统调用✔理解文件系统inode硬链接软链接文件的三个时间✔回顾C文件的接口在学习C语言时我们了解了一些C语言的对... 查看详情

linux:基础io(代码片段)

...述符三,静态库和动态库总结前言本文将为大家介绍基础IO的相关知识,让我一起来学习吧。一,复习C语言当中学习的文件接口操作FILE*fopen(constchar*path,constchar*mode); path:待要打开的文件 mode:以何种方式打开 r:可读方... 查看详情

linux:基础io(代码片段)

...述符三,静态库和动态库总结前言本文将为大家介绍基础IO的相关知识,让我一起来学习吧。一,复习C语言当中学习的文件接口操作FILE*fopen(constchar*path,constchar*mode); path:待要打开的文件 mode:以何种方式打开 r:可读方... 查看详情

linux基础io(代码片段)

文章目录一.C文件IO相关操作二.系统文件IOopen函数返回值重定向使用dup2系统调用给简易shell中增加重定向功能理解文件系统理解软硬链接三.动态库和静态库制作动静态库一.C文件IO相关操作只有文件名但不带路径的话,默认在... 查看详情

linux基础io(代码片段)

文章目录一.C文件IO相关操作二.系统文件IOopen函数返回值重定向使用dup2系统调用给简易shell中增加重定向功能理解文件系统理解软硬链接三.动态库和静态库制作动静态库一.C文件IO相关操作只有文件名但不带路径的话,默认在... 查看详情

linux基础io(代码片段)

目录系统文件IOopenwritereadclose文件描述符fdFILE重定向使用dup2系统调用文件系统磁盘磁盘和内存交互磁盘的分区与格式化Ext2文件系统的存储方案inode软硬链接软连接硬链接文件的三个时间系统文件IOopenopen接口的作用是打开文件。... 查看详情

linux基础io(代码片段)

目录系统文件IOopenwritereadclose文件描述符fdFILE重定向使用dup2系统调用文件系统磁盘磁盘和内存交互磁盘的分区与格式化Ext2文件系统的存储方案inode软硬链接软连接硬链接文件的三个时间系统文件IOopenopen接口的作用是打开文件。... 查看详情

linux基础io(代码片段)

文章目录C语言文件IOC语言文件接口汇总什么是当前路径?默认打开的三个流系统文件I/Oopenopen的第一个参数open的第二个参数open的第三个参数open的返回值closewriteread文件描述符fd文件描述符的分配规则重定向重定向的原理dup2... 查看详情

沃趣科技漫游linux块io(代码片段)

...简化为两种场景——计算密集型和IO密集型。这两种场景下的表现,决定这一个计算机系统的能力。数据库作为一个典型的基础软件,它的所有业务逻辑同样可以抽象为这两种场景的混合。因此,一个数据库系统性能... 查看详情