code:readi - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki

Source

  • 该函数处理了两种情况,普通INODE 和 块设备装载INODE(参看文件系统#装载文件系统)
    • 普通INODE,对块的处理:将 逻辑块号 转化为 物理块号
    • 块设备装载INODE,对块的处理:对于块设备来说,逻辑块号=物理块号
6210

6211 /*

6212  * Read the file corresponding to

6213  * the inode pointed at by the argument.

6214  * the actual read arguments are found

6215  * in the variables:

6216  * u_base core address for destination

6217  * u_offset byte offset in file

6218  * u_count number of bytes to read

6219  * u_segflg read to kernel/user

6220  */

6221 readi(aip)

6222 struct inode *aip;

6223 {

6224     int *bp;

6225     int lbn, bn, on;

6226     register dn, n;

6227     register struct inode *ip;

6228

6229     ip = aip;

6230     if(u.u_count == 0)

6231          return;

  • 欲读取字节数为0,函数直接返回
6232     ip->i_flag =| IACC;
  • 标志 该INODE块已被存取
6233     if((ip->i_mode&IFMT) == IFCHR) {

6234          (*cdevsw[ip->i_addr[0].d_major].d_read)(ip->i_addr[0]);

6235          return;

6236     }

6237

6238     do {

6239          lbn = bn = lshift(u.u_offset, -9);

  • u.u_offset右移9位,相当于u.u_offset/512,计算需要读取的逻辑块号
  • u.u_offset值 不改变
  • lbn,bn 赋值为逻辑块号
6240          on = u.u_offset[1] & 0777;
  • on 赋值为 块内偏移量
6241          n = min(512-on, u.u_count);
  • n 置为 该块内需读取的字节数 (= 512-块内偏移量 与 需读取字节 的最小值)
6242          if((ip->i_mode&IFMT) != IFBLK) {
6243           dn = dpcmp(ip->i_size0&0377, ip->i_size1,

6244                     u.u_offset[0], u.u_offset[1]);

6245           if(dn <= 0)

6246                return;

  • 比较 文件大小 和 文件偏移量(u_offset)
  • 若 文件偏移量 > 文件大小 ,则函数返回
  • 否则,dn = min{ 512 , 文件大小-文件偏移量}
6247           n = min(n, dn);
  • n 置为 文件当前块需读字节(= min(该块内需读取的字节数 , 文件剩余字节数))
6248           if ((bn = bmap(ip, lbn)) == 0)

6249                return;

  • bn 置为 需读取块在物理设备对应的块号
6250           dn = ip->i_dev;
  • dn 置为 需读取块所在的物理设备号
6251          } else {

6252           dn = ip->i_addr[0];

6253           rablock = bn+1;

6254          }

  • 若 ip 为 块设备装载INODE,则
    • 获取 设备号dn (参看文件系统#装载文件系统)
    • bn直接作为物理块号(对于设备,逻辑块号=物理块号,不需转换)
    • 设置rablock
6255          if (ip->i_lastr+1 == lbn)

6256           bp = breada(dn, bn, rablock);

6257          else

6258           bp = bread(dn, bn);

  • 若为顺序读,则用使用预读方式读取块
6259          ip->i_lastr = lbn;
  • 更新INODE最后一个读取的块号
6260          iomove(bp, on, n, B_READ);
  • 从读取的块里读出相应的字节
6261          brelse(bp);

6262     } while(u.u_error==0 && u.u_count!=0);

6263 }

6264 /* ------------------------- */

Ref

Caller

⚠️ **GitHub.com Fallback** ⚠️