zoukankan      html  css  js  c++  java
  • Linux IO乱序

    原创翻译,转载请注明出处。

    在一些平台,所谓的内存映射I/O在保序执行这方面是没有保障的。在这些平台,驱动写入器负责保证I/O写操作按照预期的顺序写到设备内存映射地址。

    代表性的做法是通过读取一个安全的设备或桥接寄存器,该寄存器可以导致I/O芯片在任何读操作发生前刷新所有带处理的写操作到设备上。

    驱动通常在一退出由自旋锁保护的临界区代码时就使用这种技术。这就可以保证后发生的写操作只能在之前已有的写操作的后面执行,这个类似只对I/O操作使用一个内存屏障操作,mb()。

    下面举一个具体例子,假设一个设备驱动:

            ...
    CPU A:  spin_lock_irqsave(&dev_lock, flags)
    CPU A:  val = readl(my_status);
    CPU A:  ...
    CPU A:  writel(newval, ring_ptr);
    CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
            ...
    CPU B:  spin_lock_irqsave(&dev_lock, flags)
    CPU B:  val = readl(my_status);
    CPU B:  ...
    CPU B:  writel(newval2, ring_ptr);
    CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
            ...


    以上例子会发生设备可能接收到newval2在newval之前,这样就会引起问题,需要如下修改才能正常:

            ...
    CPU A:  spin_lock_irqsave(&dev_lock, flags)
    CPU A:  val = readl(my_status);
    CPU A:  ...
    CPU A:  writel(newval, ring_ptr);
    CPU A:  (void)readl(safe_register); /* maybe a config register? */
    CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
            ...
    CPU B:  spin_lock_irqsave(&dev_lock, flags)
    CPU B:  val = readl(my_status);
    CPU B:  ...
    CPU B:  writel(newval2, ring_ptr);
    CPU B:  (void)readl(safe_register); /* maybe a config register? */
    CPU B:  spin_unlock_irqrestore(&dev_lock, flags)


    这样,想safe_register读取就会让I/O芯片在收到读操作之前刷新之前的未处理的写操作,从而防止数据污染。

  • 相关阅读:
    Laxcus集群操作系统的分布计算模型
    LAXCUS集群操作系统能不能防止DDOS攻击
    elasticsearch安装启动过程遇到的问题
    Centos7安装snort可视化IDS平台
    网络与信息安全 -国际学术会议和期刊目录
    包的概念、导入与可见性---Go
    Encrypted Traffic Analytics 加密流量分析功能
    商务谈判技巧
    东南大学《数字图像处理》课程作业 8
    东南大学《数字图像处理》课程作业 7
  • 原文地址:https://www.cnblogs.com/danxi/p/6647425.html
Copyright © 2011-2022 走看看