IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux详解 --- 系统文件IO操作与文件描述符 -> 正文阅读

[系统运维]Linux详解 --- 系统文件IO操作与文件描述符


?接下来我将介绍Linux当中与IO有关的知识,下面是本章节的思维导图,接下来的几篇博客我将按照思维导图的划分进行讲解。
在这里插入图片描述
思维导图获取
提取码: m9cz
?

IO操作

语言级IO操作

??在介绍系统级别的IO操作之前,我们先来回顾一下语言级别的IO操作。这里就以C语言中的IO操作为例了。
??在C语言中,我们首先需要打开一个文件,使用的函数就是fopen,fopen可以指定以何种方式去打开文件,如: 以只读的方式、以只写的方式、以追加的方式等。
??在打开文件之后,我们就可以写入或读取这个文件了。C语言中,文件的写入操作有fputs、fwrite、fprintf等。文件的读取操作有fgets、fread、fscanf等。下面给出一个C语言中常用的文件操作函数的接口及其功能的解释。

C语言文件操作函数接口功能
fopen打开文件
可以指定打开的方式
fputc向文件中写入一个字符
fputs向文件中写入一个字符串
fwrite向文件中写入指定数量的全部字符
fprintf以格式化的方式输入到文件中
fgetc从文件中读取一个字符
fgets从文件中读取n个字符(会读取\n)
fread从文件中读取指定数量的全部字符
fscanf以格式化的方式读取文件中的数据
fseek将文件指针移动到 特定的偏移量的位置
ftell返回文件指针相对于起始的偏移量
rewind让文件指针回到起始的位置
fclose关闭文件

?
问题:为什么我们可以直接 printf 和 scanf?
?任何进程在运行的时候,都会默认打开的3个输入/输出流
stdin ( 键盘 ) ????:标准输入
stdout ( 显示器 ) ?:标准输出
stderror ( 显示器 ) :标准错误
??他们三个流的类型都是FILE*类型的文件指针,就和我们打开文件一样,我们往往使用一个FILE *的指针去接收fopen函数的返回值。
?
?

系统级IO操作

??为什么我要在前面讲C语言的文件操作接口呢?因为接下来的系统级的IO接口和C语言中的接口非常相似,相似到只要你知道函数名你几乎它是干什么的了。

open

	int open(const char* pathname, int flags);            
    int open(const char* pathname, int flags, mode_t mode);
	//包含于:<sys/types.h>    <sys/stat.h>    <fcntl.h>

参数:
????pathname:要打开或创建的 目标文件??//支持相对路径和绝对路径
????flag:传参标志位
???????flag参数有以下几种,可以传1个或多个。使用多个时,用“|”或运算符连结。
??????? O_RDONLY:只读打开
??????? O_WRONLY:只写打开
??????? O_RDWR :读、写 打开
??????? O_CREAT :若文件不存在,则创建它。使用该选项时,必须要用mode选项指定新文件的权限
??????? O_APPEND :追加 写
????mode:当创建新文件时,对权限的设置。如:0666 (注意,该权限还需要与umask进行运算)
返回值:
????成功:返回新打开文件的文件描述符?(我下面会详细讲,类似C语言中的文件指针,但是它是个int)
????失败:-1
?
演示:

	umask(0004);
	int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);
	//创建一个文件并以只写的方式打开,文件的权限设置为0666 (还需要与umask值进行运算)

close

	int close(int fd);	//关闭指定的文件描述符fd

write

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

参数:
????fd:文件描述符
????buf:要写入的字符串
????count:要写入的字符个数

read

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

参数:
????fd:文件描述符
????buf:从文件中读取的字符所存放的空间
????count:传入你要读取的字符个数
?

函数使用演示

//测试write
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;

int main()
{
	umask(002);
	int fd = open("log.txt", O_WRONLY | O_CREAT, 0666); 
  	char buff[64] = "write some buffer to log.txt\n";
	write(fd, buff, sizeof(buff));
                                                                                                 
 	close(fd);
 	return 0;
}

在这里插入图片描述
?

//测试read
#include <iostream>
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
using namespace std;    

int main()
{
  int fd = open("log.txt", O_RDONLY);
  char buffer[64];
  read(fd, buffer, sizeof(buffer));
  
  cout << buffer; //这里没有加换行哦!
  close(fd);
  return 0;    
} 

在这里插入图片描述

?
?

文件描述符

??从刚才的open函数的返回值开始就一直在提到文件描述符了,文件描述符到底是个什么东西呢?
??我们可以从open的返回值入手,在C语言中,我们使用fopen函数得到的返回值是一个FILE *的指针,我们每次在进行读写函数调用的时候都要再传入这个指针去指定是哪个目标文件。而这里的文件描述符其实和FILE *是很类似的!它也是用来标识我们打开的是哪个文件的,实际上在底层,FILE *指针中也必然是包含了文件描述符的,FILE *指针是语言级别的,它是对系统调用的一个封装。
??说了这么多,我们该透彻的分析一下了。文件描述符的本质是:数组下标,它是什么数组的下标呢?看下图!
在这里插入图片描述
??结合这个图,我们可以从左上角的进程task_struct结构体出发,在task_struct中存在一个指向files_struct结构体的指针。而files_struct结构体中存有一个数组struct file *fd_array,这个数组也被叫做“文件描述符表”,因为它是个数组,所以我们可以通过数组下标去访问数组中的元素,而这里的数组下标就被称为“文件描述符”。数组中的每个元素都是一个指向file结构体的指针,而这里的file结构体则对应一个被打开的文件,它用来描述文件的相关信息。而在file结构体中存有一个指针file_operations,它指向了一个结构体,结构体中存着一堆函数指针,每次我们要对文件进行读写操作的时候,本质都是去使用了这里的函数指针从而进行函数调用的!
?

文件描述符的分配规则

结论:
??在files_struct结构体中的fd_array[]指针数组中,会优先找到当前没有被使用最小下标,将其作为的文件描述符。
举🌰应用:
??比如:当我们close(0)后,也就是把 输入(键盘) 文件关闭了,那么你再新创建一个文件时,该文件的fd文件描述符就会优先使用 0 这个位置!

实验演示

#include <iostream>    
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>  
#include <string.h> 
using namespace std;    
    
int main()    
{    
  close(1);		//默认情况下,1号文件描述符对应显示器,这里把显示器关闭了
  umask(0);    
  int fd = open("log.txt", O_WRONLY | O_CREAT, 0666); //我们新打开的文件就会使用1号文件描述符
  
  //我们正常向显示器输出的内容也会被打印到文件中(类似重定向)
  cout << "fd:" << fd << endl;	
  
  const char* buffer = "Put words to log.txt\n";
  //向1号文件描述符所对应的文件中写入字符串
  write(1, buffer, strlen(buffer));	
    
  close(fd);    
  return 0;                                                                                         
}  

在这里插入图片描述

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-01-12 00:27:51  更:2022-01-12 00:28:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 7:02:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码