●用户段
内核段:
操作系统本质上是一个计算机的管理程序,该程序相关的所有资源,被存放在内核段中。
用户段:
用户段用来存放各个进程的数据和指令。
根据所访问的内存段的不同,CPU会处于不同的态,访问用户段的时候处于用户态,访问内核段的时候处于内核态。
●特权操作
安全性:
I/O 操作通常需要与计算机的外部设备(如磁盘、网络设备等)进行交互,如果允许各个进程自己私自与外部设备进行交互,IO的内存放在各个进程内部,太散了,不是很好进行安全控制,相反,如果将IO的内存放在内核段,就很便于集中管理,可以附加一些安全机制上去。
特权操作:
首先IO指令本身就是特权指令,会让CPU进入内核态,其次进行IO的时候会用到中断信号,也涉及到特权指令,也要求CPU处于内核态,所以如果IO内存是在内核段中,让CPU提前进入内核状态,也避免了后面来回切状态造成的时间浪费。
整个IO在内存中的流转过程如下:
读的时候磁盘拷贝到内核段、内核段拷贝到用户段,
写的时候用户段拷贝到内核段、内核段拷贝到磁盘。
一共四次复制。
特别说明:
我知道其它很多地方这里将图画成了这个样子:
这是因为他描绘的这次IO是从磁盘上读出来然后写到网络上去,网卡和磁盘可以理解为两个不同的IO设备,所以他们在内核段中的IO内存,地址是不同的。但是如果仅仅是对磁盘的一次本地IO,那么进行IO的内核段地址会是同一个,在同一个地址内进行读写。这里为了涵盖多种情况,所以博主没有将它分开,读者悉知。
2.SendFile
2.读取映射:另一种方式是通过内存映射(Memory Mapping)来实现读取操作。通过将文件或设备的数据映射到进程的内存区域中,应用程序可以直接访问内存映射区域中的数据,而无需使用传统的 read() 系统调用。在这种情况下,应用程序可以通过直接读取内存映射区域中的数据来获取文件或设备的内容,避免了中间的数据复制。
特别说明:
还是和上文类似,画图的问题。这里为了涵盖,本地IO和网络IO两种情况,内核段没拆成几个设备的不同地址空间,但是如果是从磁盘中读,然后向网络中写,是跨了IO设备的,所以中间有个内核段地址间的复制过程,如下图:
MappedByteBuffer mappedByteBuffer = new RandomAccessFile(file, "r")
.getChannel()
.map(FileChannel.MapMode.READ_ONLY, 0, len);
SendFile:
sendFile进行网络传输:
FileChannel sourceChannel = new RandomAccessFile(sourceFile, "rw").getChannel();
SocketChannel socketChannel = SocketChannel.open(sa);
sourceChannel.transferTo(0, sourceChannel.size(), socketChannel);
sendFile进行文件拷贝:
try (FileChannel srcChannel = new FileInputStream(src).getChannel();
FileChannel targetChannel = new FileInputStream(target).getChannel()) {
srcChannel.transferTo(0, srcChannel.size(), targetChannel );
} catch (IOException e) {
e.printStackTrace();
}
免责申明:
本文系转载,版权归原作者所有,如若侵权请联系我们进行删除!
《数据治理行业实践白皮书》下载地址:https://fs80.cn/4w2atu
《数栈V6.0产品白皮书》下载地址:https://fs80.cn/cw0iw1
想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=bbs
同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术群」,交流最新开源技术信息,群号码:30537511,项目地址:https://github.com/DTStack