/*
* linux/fs/block_dev.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/system.h>
//是以“块”为单位读写的
int block_write(int dev, long * pos, char * buf, int count)// 数据块写函数 - 从高速缓冲区向指定设备(块设备,如硬盘)从给定偏移处写入指定长度字节数据
{//参数:dev - 设备号;pos - 设备文件中偏移量指针;buf - 用户地址空间中缓冲区地址,count - 要传送的字节数
//
*pos (32bit) 的组成是 低10位是。这是因为 BLOCK_SIZE=1024=0x400 所以 BLOCK_SIZE-1=1023=0x3FF,所以
int offset = *pos & (BLOCK_SIZE-1);
所以offset = *pos & 0x3FF, 相当于取 *pos的低10位。
而*pos的高 22 位则是块序号
int block = *pos >> BLOCK_SIZE_BITS; 就是将 *pos右移10位,那么就只剩高22位了,所以说高22位是块序号,低10位是在块内的.
int block = *pos >> BLOCK_SIZE_BITS;//pos 所在文件数据块号
int offset = *pos & (BLOCK_SIZE-1);//pos在数据块中的偏移值
int chars;
int written = 0;
struct buffer_head * bh; //缓冲区头数据结构
register char * p; //register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度。
while (count>0) {// 针对要写入的字节数count,循环执行以下操作,直到全部写入
chars = BLOCK_SIZE - offset;// 计算在该块中可写入的字节数。
if (chars > count)//如果需要写入的字节数填不满一块
chars=count;
if (chars == BLOCK_SIZE)//如果正好要写1 块数据,则直接申请1 块高速缓冲块
bh = getblk(dev,block);
else//否则需要读入将被写入的数据块,并预读下两块数据块,然后将块号递增1
bh = breada(dev,block,block+1,block+2,-1);
block++;
if (!bh)// 如果缓冲块操作失败,则返回已写字节数,如果没有写入任何字节,则返回出错号
return written?written:-EIO;
p = offset + bh->b_data;//在这一块中指定要写入的位置
offset = 0;//写数据是按块写入的,如果要写入 的数据大于1块,则第2次循环从下一块的开始写入,所以offset置0
*pos += chars;//更新文件的当前指针,它的值直接反映到被调用函数sys_write中来,pos变量是按“址”传递参数的
written += chars;//记录写的个数
count -= chars;//更新还有多少数据没有写
while (chars-->0)//写入数据
*(p++) = get_fs_byte(buf++);
bh->b_dirt = 1;// 置该缓冲区块已修改标志
brelse(bh);//并释放该缓冲区
}
return written;
}
int block_read(int dev, unsigned long * pos, char * buf, int count)// 数据块读函数 - 从指定设备和位置读入指定字节数的数据到高速缓冲中
{
int block = *pos >> BLOCK_SIZE_BITS;//pos 所在文件数据块号,记住这种方法
int offset = *pos & (BLOCK_SIZE-1);//pos在数据块中的偏移值,记住这种方法
int chars;
int read = 0;
struct buffer_head * bh;
register char * p;
while (count>0) {
chars = BLOCK_SIZE-offset;// 计算在该块中要读出的的字节数。
if (chars > count)//如果需要读出的字节数不满一块,则只需读count 字节
chars = count;
if (!(bh = breada(dev,block,block+1,block+2,-1)))// 读出需要的数据块,并预读下两块数据
return read?read:-EIO;
block++;
p = offset + bh->b_data;//在这一块中指定要读出的位置
offset = 0;
*pos += chars;//同前
read += chars;//同前
count -= chars;//同前
while (chars-->0)//同前
put_fs_byte(*(p++),buf++);
brelse(bh);//同前
}
return read;
}
阅读(1575) | 评论(0) | 转发(0) |