code:writei - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki
6265
- 该函数处理了两种情况,普通INODE 和 块设备装载INODE(参看文件系统#装载文件系统)
- 普通INODE,对块的处理:将 逻辑块号 转化为 物理块号
- 块设备装载INODE,对块的处理:对于块设备来说,逻辑块号=物理块号,不需转换
6266 /*
6267 * Write the file corresponding to
6268 * the inode pointed at by the argument.
6269 * the actual read arguments are found
6270 * in the variables:core address for source
6271 * u_base core address for source
6272 * u_offset byte offset in file
6273 * u_count number of bytes to write
6274 * u_segflg write to kernel/user
6275 */
6276 writei(aip)
6277 struct inode *aip;
6278 {
6279 int *bp;
6280 int lbn, bn, on;
6281 register dn, n;
6282 register struct inode *ip;
6283
6284 ip=aip;
6285 ip->i_flag =| IACC|IUPD;
6286 if((ip->i_mode&IFMT) == IFCHR) {
- 标志 该INODE块已被修改与存取
6287 (*cdevsw[ip->i_addr[0].d_major].d_write)(ip->i_addr[0]);
6288 return;
- 处理 字符文件
6289 }
6290 if (u.u_count == 0)
6291 return;
6292
6293 do{
6294 bn = lshift(u.u_offset, -9);
6295 on = u.u_offset[1] & 0777;
- u.u_offset右移9位,相当于u.u_offset/512,计算需要读取的逻辑块号
- u.u_offset值 不改变
- bn 赋值为逻辑块号
6296 n = min(512-on, u.u_count);
- on 赋值为 块内偏移量
6297 if((ip->i_mode&IFMT) != IFBLK) {
- n 置为 该块内需写入的字节数 (= 512-块内偏移量 与 需读取字节 的最小值)
6298 if ((bn = bmap(ip, bn)) == 0)
- 若 INODE 不为 特殊块文件,...
6299 return;
- bn 置为 需写入块在物理设备对应的块号
6300 dn = ip->i_dev;
6301 } else
- dn 置为 需写入块的对应物理设备号
6302 dn = ip->i_addr[0];
6303 if(n == 512)bn直接作为物理块号(对于设备,逻辑块号=物理块号,不需转换)
- 若 ip 为 块设备装载INODE,则
- 获取 设备号dn (参看文件系统#装载文件系统)
6304 bp = getblk(dn, bn); else
6305 bp = bread(dn, bn);
6306 iomove(bp, on, n, B_WRITE);
6307 if(u.u_error != 0)
- 若需写入的字节数为512(即整个块都要写入)
- 直接分配一个缓存块,从 指定地址空间 将一整块读入该缓存块
- 若欲写入的字节数不到一整块
- 则将磁盘上该块文件的内容读入一个缓存块
- 然后从 指定地址空间 读入相应字节的内容 到该缓存块的相应位置(即只更新部分内容)
6308 brelse(bp); else
6309 if ((u.u_offset[1]&0777)==0)
6310 bawrite(bp); else
6311 bdwrite(bp);
6312 if(dpcmp(ip->i_size0&0377, ip->i_size1,
- 若文件块已经被全部改写
- 直接将缓存块异步写回磁盘
- 若文件块没有被全部改写
- 采用延迟写策略
6313 u.u_offset[0], u.u_offset[1]) < 0 &&
6314 (ip->i_mode&(IFBLK&IFCHR)) == 0) {
6315 ip->i_size0 = u.u_offset[0];
6316 ip->i_size1 = u.u_offset[1];
6317 }
6318 ip->i_flag =| IUPD;
- 若文件小于当前偏移量,表明文件需要扩充,将文件大小改为当前偏移量的值
6319 } while(u.u_error==0 && u.u_count!=0);
- 标志 该INODE块已被存取
6320 }
- 每次循环判断是否出错或者是否写完
- 若没有写完则继续循环,直到写完为止
6321 /* -------------------------*/