目录
block_dev.c 文件的作用
int block_write(int dev, long * pos, char * buf, int count)
block_dev.c 文件的作用
block_dev.c 文件的作用
block_dev.c 文件就包含两个函数,分别是block_read和block_write函数,提供给read和write系统调用
块读写数据是操作指针图
int block_write(int dev, long * pos, char * buf, int count)
代码首先根据位置指针将其右移 BLOCK_SIZE_BITS 位,得到块号(block),然后使用与运算将其与 (BLOCK_SIZE-1) 进行按位与操作,以获取在块内的偏移量(offset)。
进入循环,只要还有待写入的字节数(count>0),就执行以下步骤:
将 chars 设置为当前块剩余的字符数(BLOCK_SIZE - offset)。如果 chars 大于 count,则将 chars 设置为 count,以确保不会写入超过指定字节数的数据。
根据 chars 的值选择不同的读取策略:
如果 chars 等于块大小(BLOCK_SIZE),则调用 getblk 函数从设备上获取单个块,并将返回的缓冲头结构体赋给 bh。
如果 chars 不等于块大小,则调用 breada 函数异步地读取多个块,并将返回的缓冲头结构体赋给 bh。
增加块号的值,将 p 设置为偏移量加上缓冲区数据的地址,并将偏移量 offset 重置为 0。
更新位置指针(*pos)的值,增加已写入的字节数(written),减少待写入的字节数(count)。
使用 get_fs_byte 函数从用户空间的缓冲区(buf)逐个字符地读取数据,并将其写入内核空间的缓冲区(p)。循环会自减 chars 直到为 0。
将缓冲头结构体(bh)的 b_dirt 标志设置为 1,表示该块已被修改。
调用 brelse 函数释放之前获取的缓冲头结构体(bh)。
最后,函数返回已写入的总字节数(written)
int block_write(int dev, long * pos, char * buf, int count)
{
int block = *pos >> BLOCK_SIZE_BITS;//右移10bit获取获取block号
int offset = *pos & (BLOCK_SIZE-1);//与运算获取块内偏移量
int chars;
int written = 0;
struct buffer_head * bh;
register char * p;
while (count>0) {
chars = BLOCK_SIZE - offset;
if (chars > count)
chars=count;
if (chars == BLOCK_SIZE)
bh = getblk(dev,block);//完整的块
else
bh = breada(dev,block,block+1,block+2,-1);//读取设备上的多个块,预读后续几个block提高性能,并返回缓冲头结构体
block++;
if (!bh)
return written?written:-EIO;
p = offset + bh->b_data;
offset = 0;
*pos += chars;
written += chars;
count -= chars;
while (chars-->0)
*(p++) = get_fs_byte(buf++);
bh->b_dirt = 1;
brelse(bh);
}
return written;
}
block_dev.c 文件的作用
首先将位置指针右移 BLOCK_SIZE_BITS 位,以获取块号(block),然后使用与运算获取在块内的偏移量(offset)。
进入循环,只要还有待读取的字节数(count>0),就会执行以下步骤:
将 chars 设置为当前块剩余的字符数(BLOCK_SIZE - offset),如果此值大于 count,则将其设置为 count。
调用 breada 函数以异步地读取设备上的多个块,并将返回的缓冲头结构体赋给 bh。如果读取失败,则根据 read 的值判断是否已经读取过数据,如果是则返回 read,否则返回 -EIO 表示 I/O 错误。
增加 block 的值,将 p 指向缓冲区起始位置加上偏移量(offset)的地址,并将 offset 重置为 0。
更新位置指针(*pos)的值,增加已读取的字节数(read),减少待读取的字节数(count)。
使用 put_fs_byte 函数将内核空间的字符复制到用户空间的缓冲区(buf)。这个过程会逐个字符地从 p 指向的地址复制到 buf 指向的地址,并同时自增 p 和 buf 的指针。循环将重复执行 chars 次。
调用 brelse 函数释放之前获取的缓冲头结构体(bh)。
最后,函数返回已读取的总字节数(read)。
int block_read(int dev, unsigned long * pos, char * buf, int count)
{
int block = *pos >> BLOCK_SIZE_BITS;
int offset = *pos & (BLOCK_SIZE-1);
int chars;
int read = 0;
struct buffer_head * bh;
register char * p;
while (count>0) {
chars = BLOCK_SIZE-offset;
if (chars > 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;
}