zoukankan      html  css  js  c++  java
  • Kafka实现涉及的一些基础概念

     

    顺序io

    每次访问磁盘的一个块时,磁臂就需移动到正确的磁道上(这段时间为寻址时间),然后盘片就需旋转到正确的扇区上(这叫旋转时延)。这套动作需要时间。

    那下一个磁盘块又是如何呢?如果它在磁盘的某个地方,访问它会有同样的寻道和旋转时延,我们就把这种方式的IO叫做随机IO;但是如果它刚好就在你刚才访问的那一个磁盘块的后面,磁头就能立刻遇到,不需等待,这种IO就叫顺序IO

    内存映射文件(Memary mapped files)

    内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件。 

    有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问。这种解决办法能大大简化修改文件的代码。

    虚拟内存

    零复制(ZeroCopy)

    进程缓存区和用户缓存区

    缓冲区的出现是为了减少频繁的系统调用,由于系统调用需要保存之前的进程数据和状态等信息,而结束调用之后回来还需要回复之前的信息,为了减少这种耗时耗性能的调用于是出现了缓冲区。在linux系统中,每个进程有自己独立的缓冲区,叫做进程缓冲区,而系统内核也有个缓冲区叫做内核缓冲区。

     

    当进程需要指定的磁盘数据的时候,进程先到内核缓冲区去看看数据是否在内核缓冲区,如果没有,内核把读取磁盘中此数据的请求添加到内核的请求队列,然后挂起此进程,等解决了别的进程的问题之后,磁盘中的数据也读取到了内核缓冲区,然后复制数据到进程缓冲区,接着唤醒这个被挂起的进程,进程从自己的进程缓冲区中拿到数据,然后继续工作。

     

    但是一般的操作系统在存储数据的时候也并不是立即存储的,这个是磁盘文件系统设计的问题,有些UNIX操作系统除外,相对数据安全,但是IO不可避免的会降低。操作系统使用read函数把数据从内核缓冲区复制到进程缓冲区,write把数据从进程缓冲区 复制到内核缓冲区中。至于什么时候读取和存储则由内核来决定,内核缓冲区满则存储到磁盘,读取的时候内核缓冲区空则从磁盘读取到内核缓冲区中,当然,在写入的时候如果系统突然关闭则会造成内核缓冲区的数据无法存储到磁盘的事情发生。

    资料来源:https://blog.csdn.net/u010590568/article/details/54848646

    从磁盘文件中读取并且通过Socket写出的过程,对应的系统调用如下:

    read(file, tmp_buf, len);

    write(socket, tmp_buf, len);

    a)         程序使用read()系统调用,系统由用户态转换为内核态,磁盘中的数据由DMA(Direct memory access)的方式读取到内核读缓冲区(kernel buffer)。DMA过程中CPU不需要参与数据的读写,而是DMA处理器直接将硬盘数据通过总线传输到内存中。

    b)         系统由内核态转为用户态,当程序要读的数据已经完全存入内核读缓冲区以后,程序会将数据由内核读缓冲区,写入到用户缓冲区,这个过程需要CPU参与数据的读写。

    c)         程序使用write()系统调用,系统由用户态切换到内核态,数据从用户缓冲区写入到网络缓冲区(Socket Buffer),这个过程需要CPU参与数据的读写。

    d)         系统由内核态切换到用户态,网络缓冲区的数据通过DMA的方式传输到网卡的驱动(存储缓冲区)中(protocol engine)

    内存映射方式I/O

    tmp_buf = mmap(file, len);

    write(socket, tmp_buf, len);

    这是使用的系统调用方法,这种方式的I/O原理就是将用户缓冲区(user buffer)的内存地址和内核缓冲区(kernel buffer)的内存地址做一个映射,也就是说系统在用户态可以直接读取并操作内核空间的数据。

        mmap()系统调用首先会使用DMA的方式将磁盘数据读取到内核缓冲区,然后通过内存映射的方式,使用户缓冲区和内核读缓冲区的内存地址为同一内存地址,也就是说不需要CPU再讲数据从内核读缓冲区复制到用户缓冲区。

        当使用write()系统调用的时候,cpu将内核缓冲区(等同于用户缓冲区)的数据直接写入到网络发送缓冲区(socket buffer),然后通过DMA的方式将数据传入到网卡驱动程序中准备发送。

     

    可以看到这种内存映射的方式减少了CPU的读写次数,但是用户态到内核态的切换(上下文切换)依旧有四次,同时需要注意在进行这种内存映射的时候,有可能会出现并发线程操作同一块内存区域而导致的严重的数据不一致问题,所以需要进行合理的并发编程来解决这些问题。

    ---------------------

    作者:CringKong

    来源:CSDN

    原文:https://blog.csdn.net/cringkong/article/details/80274148

    接下来可以通过以下文章来了解:https://blog.csdn.net/z69183787/article/details/80323581

  • 相关阅读:
    LeetCode 79. 单词搜索
    LeetCode 1143. 最长公共子序列
    LeetCode 55. 跳跃游戏
    LeetCode 48. 旋转图像
    LeetCode 93. 复原 IP 地址
    LeetCode 456. 132模式
    LeetCode 341. 扁平化嵌套列表迭代器
    LeetCode 73. 矩阵置零
    LeetCode 47. 全排列 II
    LeetCode 46. 全排列
  • 原文地址:https://www.cnblogs.com/cai-cai777/p/10212907.html
Copyright © 2011-2022 走看看