void main(void) {
...
blk_dev_init();
...
}
void blk_dev_init(void) {
int i;
for (i=0; i<32; i++) {
request[i].dev = -1;
request[i].next = NULL;
}
}
/*
* Ok, this is an expanded form so that we can use the same
* request for paging requests when that is implemented. In
* paging, 'bh' is NULL, and 'waiting' is used to wait for
* read/write completion.
*/
struct request {
int dev; /* -1 if no request */
int cmd; /* READ or WRITE */
int errors;
unsigned long sector;
unsigned long nr_sectors;
char * buffer;
struct task_struct * waiting;
struct buffer_head * bh;
struct request * next;
};
dev 表示設(shè)備號,-1 就表示空閑。
cmd 表示命令,其實就是 READ 還是 WRITE,也就表示本次操作是讀還是寫。
errors 表示操作時產(chǎn)生的錯誤次數(shù)。
sector 表示起始扇區(qū)。
nr_sectors 表示扇區(qū)數(shù)。
buffer 表示數(shù)據(jù)緩沖區(qū),也就是讀盤之后的數(shù)據(jù)放在內(nèi)存中的什么位置。
waiting 是個 task_struct 結(jié)構(gòu),這可以表示一個進程,也就表示是哪個進程發(fā)起了這個請求。
bh 是緩沖區(qū)頭指針,這個后面講完緩沖區(qū)就懂了,因為這個 request 是需要與緩沖區(qū)掛鉤的。
next 指向了下一個請求項。
int sys_read(unsigned int fd,char * buf,int count) {
struct file * file = current->filp[fd];
struct m_inode * inode = file->f_inode;
// 校驗 buf 區(qū)域的內(nèi)存限制
verify_area(buf,count);
// 僅關(guān)注目錄文件或普通文件
return file_read(inode,file,buf,count);
}
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) {
int left,chars,nr;
struct buffer_head * bh;
left = count;
while (left) {
if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {
if (!(bh=bread(inode->i_dev,nr)))
break;
} else
bh = NULL;
nr = filp->f_pos % BLOCK_SIZE;
chars = MIN( BLOCK_SIZE-nr , left );
filp->f_pos += chars;
left -= chars;
if (bh) {
char * p = nr + bh->b_data;
while (chars-->0)
put_fs_byte(*(p++),buf++);
brelse(bh);
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
}
inode->i_atime = CURRENT_TIME;
return (count-left)?(count-left):-ERROR;
}
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) {
...
while (left) {
...
if (!(bh=bread(inode->i_dev,nr)))
}
}
struct buffer_head * bread(int dev,int block) {
struct buffer_head * bh = getblk(dev,block);
if (bh->b_uptodate)
return bh;
ll_rw_block(READ,bh);
wait_on_buffer(bh);
if (bh->b_uptodate)
return bh;
brelse(bh);
return NULL;
}
void ll_rw_block(int rw, struct buffer_head * bh) {
...
make_request(major,rw,bh);
}
static void make_request(int major,int rw, struct buffer_head * bh) {
...
if (rw == READ)
req = request+NR_REQUEST;
else
req = request+((NR_REQUEST*2)/3);
/* find an empty request */
while (--req >= request)
if (req->dev<0)
break;
...
/* fill up the request-info, and add it to the queue */
req->dev = bh->b_dev;
req->cmd = rw;
req->errors=0;
req->sector = bh->b_blocknr<<1;
req->nr_sectors = 2;
req->buffer = bh->b_data;
req->waiting = NULL;
req->bh = bh;
req->next = NULL;
add_request(major+blk_dev,req);
}