葡京娱乐百家乐
读取硬盘数据到内存中,是操作系统的一个基础功能。
读取硬盘需要有块斥地驱动法子,而以文献的款式来读取则还有要再上头包一层文献系统。
皇冠博彩平台最近更新多款博彩游戏赛事直播,包括、欧洲杯、NBA、CBA、斯诺克,您博彩游戏中享受乐趣收益。提供博彩攻略技巧分享,您博彩游戏中信心。平台安全稳定,操作简便,充值提款便捷,您打造最佳博彩体验最高博彩收益。把读出来的数据放到内存,就触及到内存中缓冲区的措置。
上头说的每一件事,王人是一个至极稠密的体系,咱们今天的著述一个王人不张开讲,哈哈。
咱们就讲讲,读取块斥地与内存缓冲区之间的桥梁,块斥地请求项的运行化责任。
咱们以 Linux 0.11 源码为例,发现干与内核的 main 函数后不久,有这么一滑代码。
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; } }
这也太肤浅了吧?
即是给 request 这个数组的前 32 个元素的两个变量 dev 和 next 附上值,看这俩值 -1 和 NULL 也不错省略猜出,这是莫得任何作用时的运行化值。
皇冠客服飞机:@seo3687咱们看下 request 结构体。
皇冠体育直播/* * 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; };
扫视也附上了。
哎哟,这就有点头大了,刚刚的函数天然很短,但看到这个结构体咱们知说念了,要点在这呢。
这也侧面泄露了,学习操作系统,其实把遭受的遑急数据结构谨记心中,就还是得胜一半了。比如主内存措置结构 mem_map,知说念它的数据结构是什么样貌,其功能也基本就懂了。
收,链接说这个 request 结构,这个结构就代表了一次读盘请求,其中:
dev 默示斥地号,-1 就默示优游。
cmd 默示敕令,其实即是 READ 照旧 WRITE,也就默示本次操作是读照旧写。
errors 默示操作时产生的空幻次数。
俄罗斯央行还表示,将继续以每天23亿卢布的额度出售与国家福利基金资金有关的外汇,以便将其投资到被允许的金融资产中。
8月10日,A股缩量反弹,成交额不足7000亿元,券商板块走高提振市场人气。与此同时,9日上市的次新股集体大跌,高位追涨的投资者或深度被套。10日晚间,沪深交易所同时发布公告,拟出台交易新规,调整主板股票、基金买入规则。
sector 默示肇端扇区。
nr_sectors 默示扇区数。
博彩心理buffer 默示数据缓冲区,也即是读盘之后的数据放在内存中的什么位置。
waiting 是个 task_struct 结构,这不错默示一个程度,也就默示是哪个程度发起了这个请求。
bh 是缓冲区头指针,这个后头讲完缓冲区就懂了,因为这个 request 是需要与缓冲区挂钩的。
next 指向了下一个请求项。
这里有的变量看不懂不枢纽。
不外咱们倒是不错基于现存的要点参数臆想一下,比如读请求时,欧博线上代理cmd 即是 READ,sector 和 nr_sectors 这俩就定位了所要读取的块斥地(不错肤浅先意会为硬盘)的哪几个扇区,buffer 就定位了这些数据读完之后放在内存的什么位置。
这就够啦,思思看,这四个参数是不是就能齐全形容了一个读取硬盘的需求了?而且填塞莫得歧义,就像底下这么。
香港六合彩现金网而其他的参数,详情是为了更好地调和操作系统进行读写块斥地操作嘛,为了把多个读写块斥地请求很好地组织起来。这个组织不但要有这个数据结构中 hb 和 next 等变量的调和,还要有后头的电梯调遣算法的调和,仅此汉典,先点到为止。
总之,咱们这里就先赫然,这个 request 结构不错齐全形容一个读盘操作。然后阿谁 request 数组即是把它们王人放在沿途,况兼它们又通过 next 指针串成链表。
好,本文报告的两行代码,其实就完成了上图所示的责任汉典。
但讲到这就终了的话,好多同学可能会不太宁愿,那我就肤浅瞻望一下,后头读盘的全经过中,是奈何用到刚刚运行化的这个 request[32] 结构的。
皇冠客服不回消息读操作的系统调用函数是 sys_read,源代码很长,我给简化一下,只是保留读取世俗文献的分支,即是如下的样貌。
博彩开奖int sys_read(unsigned int fd,char * buf,int count) { struct file * file = current->filp[fd]; struct m_inode * inode = file->f_inode; // 校验 buf 区域的内存截止 verify_area(buf,count); // 仅关防备录文献或世俗文献 return file_read(inode,file,buf,count); }
看,入参 fd 是文献形容符,通过它不错找到一个文献的 inode,进而找到这个文献在硬盘中的位置。
另两个入参 buf 即是要复制到的内存中的位置,count 即是要复制若干个字节,很好意会。
钻到 file_read 函数里链接看。
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; }
合座看,即是一个 while 轮回,每次读入一个块的数据,直到入参所条目的大小全部读完为止。
平直看 bread 那一滑。
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; }
其中 getblk 先肯求了一个内存中的缓冲块,然后 ll_rw_block 正经把数据读入这个缓冲块,进去链接看。
iba娱乐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); }
看,这里就用到了刚刚说的结构咯。
具体说来,即是该函数会往刚刚的斥地的请求项链表 request[32] 中添加一个请求项,唯有 request[32] 中有未处理的请求项存在,王人会不竭地被处理,直到斥地的请求项链表是空为止。
火狐体育手机网页版具体奈何读盘,即是与硬盘 IO 端口进行交互的过程了,不错链接往里跟,直到看到一个 hd_out 函数为止,本讲不张开了。
具体读盘操作,后头会有详备的章节张动身擢,本讲你只需要知说念,咱们在 main 函数的 init 系列函数中,通过 blk_dev_init 为后头的块斥地探访,提前开发了一个数据结构,行动探访块斥地和内存缓冲区之间的桥梁,就不错了。