zoukankan      html  css  js  c++  java
  • 20191323王予涵第十二章学习笔记

    20191323王予涵第十二章学习笔记

    一、知识点归纳和总结

    块设备I/O和缓冲区管理

    • 当进程试图读取(dev,blk)标识的磁盘块时,它首先在缓冲区缓存中搜索分配给磁盘块的缓冲区。若缓冲区存在并且包含有效数据,只需从缓冲区中读取数据,无需再次从磁盘中读取数据块;若缓冲区不存在,则为磁盘块分配相应缓冲区,将数据从磁盘读入缓冲区,然后从缓冲区中读数据。
    • 当某个块被读入时,该缓冲区将被保存在缓冲区缓存中,以供任意进程对同一个块的下一次读/写请求使用;当进程写入磁盘块时,会将数据写入缓冲区,将缓冲区标记为脏,以延迟写入,并将其释放至缓冲区缓存中。
    • 脏缓冲区只有在重新分配到不同的块时才会写入磁盘

    从磁盘块中读:

    BUFFER *bread(dev,blk){
        BUFFER *bp = getblk(dev,blk);  
        if (bp data valid)             
        return bp;                    
        bp->opcode = READ;             
        strat_io(bp);                   
        wait for I/O completion;
        return bp;
    }
    

    写入磁盘块:

    write_block(dev, blk, data){
        BUFFER *bp = bread(dev,blk);
        write data to bp;
        (synchronous write)? bwrite(bp):dwrite(bp);   
    }
    
    同步写入bwrite(bp):

    同步写入等待写操作完成,用于顺序块或可移动设备

    bwrite (BUFFER *bp){
    	bp->opcode = WRITE;
    	start_io(bp);
    	wait for I/O completion;
    	brelse(bp);
    }
    
    延迟写入dwrite(bp):

    延迟写入无写操作,用于随机访问设备

    dwrite(BUFFER *bp){
    	mark bp dirty for delay_write;
        brelse(bp);                       
    }
    

    脏缓冲区写入操作:

    • 脏缓冲区只用在重新分配到不同的磁盘块时才会被写入磁盘
    • awrite()会调用start_io()在缓冲区开始I/O操作,但不会等待操作完成
    • 当异步ASYNC完成后,磁盘中断处理程序将释放缓冲区
    awrite(BUFFER *bp){
    	bp -> opcode = ASYNC;
    	start_io(bp);
    }
    

    物理块设备I/O:

    I/O队列中保存着等待I/O的缓冲区

    start_io(BUFFER *bp){
        enter bp into device I/O queue;
        if (bp is first buffer in I/O queue)
        issue I/O command for bp to device;
    }
    

    缓冲区管理算法

    缓冲区结构体:

    typdef struct buf{
        struct buf *next_free;
        struct buf *next_dev;
        int dev,blk;
        int opcode;
        int dirty;
      	int async;
      	int valid;
      	int busy;
      	int wanted;
      	struct semaphore lock = 1;
      	struct semaphore iodone = 0;
      	char buf[BLKSIZE];
    }BUFFER;
    BUFFER buf[NBUF], *freelist;
    

    设备表:

    struct devtab{
      	u16 dev;
      	BUFFER *dev_list;
      	BUFFER *io_queue;
    }devtab[NDEV];
    
    1. 缓冲区初始化:系统启动时,所有I/O缓冲区都在空闲列表中,所有设备列表和I/O队列均为空

    2. 缓冲区列表:

      1. 缓冲区分配给(dev,blk)时,会被插入设备表的dev_list中

        • 缓冲区正在使用:标记为busy并从空闲列表中删除
      2. 通过使用相同的next_free来维护设备I/O序列

      3. 缓冲区不在繁忙时,释放回空闲列表,保留在dev_list中,以便重用

    信号量缓冲区管理算法(PV)

    具备优点:

    • 数据一致性
    • 良好的缓存效果
    • 高效率:没有重试循环,没有不必要的唤醒
    • 无死锁和饥饿

    信号量定义

    BUFFER buf[NBUF];
    SEMAPHORE free = NBUF;
    SEMAPHORE buf[i].sem = 1;
    

    算法伪代码

    BUFFER *getblk(dev,blk)
    {
        while(1){
      (1).      p(free);                              
      (2).      if (bp in dev_list){                  
      (3).          if (bp not BUSY){                 
                        remove from freelist;         
                        P(bp);                        
                        return bp;
                     }
                //bp in cache but BUSY
                    V(free);                          
      (4).          P(bp);                            
                    return bp;
               }
                //bp not in cache, try to create a bp=(dev.blk)
      (5).     bp = first buffer taken out of freelist;
               P(bp);                             
      (6).     if (bp dirty){                    
                  awrite(bp);                     
                  continue;
               }
      (7).     reassign bp to (dev,blk);          
               return bp;
          }
    }
    brelse (BUFFER *bp)
    {
      (8).if (bp queue has waiter) {V(bp); return; }
      (9).if (bp dirty && freee queue has waiter){ awrite(bp); return;}
      (10).enter bp into (tail of) freelist; V(bp); V(free);
    }
    
  • 相关阅读:
    检测mysq组复制的脚本
    centos7安装NFS
    mysql组复制安装
    springboot+VUE(一)
    redis集群配置
    codevs 3139 栈练习3
    codevs 3138 栈练习2
    codevs 2622 数字序列
    codevs 1054 电梯
    codevs 1507 酒厂选址
  • 原文地址:https://www.cnblogs.com/WANGYUHAN/p/15581974.html
Copyright © 2011-2022 走看看