在進(jìn)行Linux內(nèi)核配置時(shí)有下述工具可以使用:
make config:該工具會(huì)逐一便利所有配置項(xiàng)蝶溶,要求用戶進(jìn)行選擇昧谊,過程用時(shí)巨大
make menuconfig:基于ncurse庫的圖形界面工具
make gconfig:基于gtk+的圖形工具
對(duì)輸出進(jìn)行重定向 make > ../detritus
將輸出拋棄 make > /dev/null
同時(shí)進(jìn)行多個(gè)作業(yè):make -jn 淑际,n為作業(yè)數(shù)目晨缴,正常狀態(tài)下每個(gè)處理器可以衍生一個(gè)或兩個(gè)作業(yè)
在16核處理器中可以輸入 make -j32
塊I/O層
1.I/O設(shè)備
設(shè)備類型大體上可以分為塊設(shè)備(block device)和字符設(shè)備(character device)
塊設(shè)備和字符設(shè)備關(guān)鍵的區(qū)別在于數(shù)據(jù)訪問的方式:
- 塊設(shè)備:數(shù)據(jù)訪問的方式為隨機(jī)訪問,可以在塊設(shè)備的不同位置進(jìn)行跳轉(zhuǎn)做祝,隨機(jī)訪問數(shù)據(jù)近尚,并不需要遵循一定的順序蠕啄。(常見塊設(shè)備包括:hard disk(最普遍)、floppy drivers戈锻、Blu-ray reader歼跟、flash memory)
- 字符設(shè)備:數(shù)據(jù)訪問的方式為數(shù)據(jù)流却嗡,拿鍵盤來說,如果鍵入“wolf”嘹承,驅(qū)動(dòng)會(huì)嚴(yán)格按照字符串順序返回字符流窗价,如果亂序讀取這個(gè)字符流,或者讀取字符流中其它位置的字符叹卷,都會(huì)產(chǎn)生歧義撼港。(常見字符設(shè)備包括:serial ports、keyboards)
因此骤竹,管理塊設(shè)備通常會(huì)更復(fù)雜帝牡。因?yàn)樽址O(shè)備只需要記錄當(dāng)前讀取數(shù)據(jù)的位置就行了,而塊設(shè)備在任何位置支持向前或者向后訪問蒙揣。加上塊設(shè)備對(duì)性能十分敏感靶溜,因此內(nèi)核為塊設(shè)備單獨(dú)提供了一個(gè)子系統(tǒng)(塊I/O層 block I/O layer)進(jìn)行管理
2.扇區(qū)(sector)
塊設(shè)備的最小可尋址單元。最常見大小是512B(也有其它大小懒震,如很多CD-ROM discs 的扇區(qū)為2KB)罩息。盡管很多塊設(shè)備能一次對(duì)多個(gè)扇區(qū)進(jìn)行管理,但是無法對(duì)比塊更小的單元進(jìn)行尋找/操作
3.塊(block)
塊是文件系統(tǒng)層面的一個(gè)抽象个扰。盡管塊設(shè)備以扇區(qū)為單元進(jìn)行尋址瓷炮,但是文件系統(tǒng)操作的數(shù)據(jù)以塊為單位。內(nèi)核要求塊不能小于扇區(qū)递宅,不能大于頁(page)娘香。一般是2^k
個(gè)扇區(qū)大小,常見大小為512B办龄,1KB烘绽,4KB
扇區(qū)和塊的關(guān)系下圖:
4.buffer_head結(jié)構(gòu)
如果一個(gè)塊被存進(jìn)內(nèi)存,那么就是說這個(gè)塊存入了一個(gè)buffer俐填。每一個(gè)buffer和一個(gè)具體的塊對(duì)應(yīng)安接。可以說玷禽,一個(gè)buffer是一個(gè)塊的內(nèi)存表示
由于塊不能比page大赫段,因此在內(nèi)存中,一個(gè)page能容納一個(gè)或多個(gè)塊矢赁。內(nèi)核需要一些控制信息(buffer對(duì)應(yīng)哪個(gè)設(shè)備的哪個(gè)塊)來管理buffer,因此設(shè)計(jì)了名為buffer_head
的描述符贬丛。定義在<linux/buffer_head.h>
中:
struct buffer_head {
unsigned long b_state; /* buffer的狀態(tài)位圖 */
struct buffer_head *b_this_page; /* 該頁buffer的循環(huán)鏈表 */
struct page *b_page; /* 該buffer_head映射到的page */
sector_t b_blocknr; /* 起始?jí)K號(hào) */
size_t b_size; /* size of mapping */
char *b_data; /* pointer to data within the page */
struct block_device *b_bdev;
bh_end_io_t *b_end_io; /* I/O completion */
void *b_private; /* reserved for b_end_io */
struct list_head b_assoc_buffers; /* associated with another mapping */
struct address_space *b_assoc_map; /* mapping this buffer is
associated with */
atomic_t b_count; /* 引用計(jì)數(shù) */
};
-
b_state
:buffer的狀態(tài)撩银。可能是下表中的值 -
b_count
:buffer的使用計(jì)數(shù)豺憔。這個(gè)值通過兩個(gè)內(nèi)聯(lián)函數(shù)進(jìn)行增加和減小额获,它們定義在<linux/buffer_head.h>
中
在操作一個(gè)buffer前够庙,需要調(diào)用static inline void get_bh(struct buffer_head *bh) { atomic_inc(&bh->b_count); } static inline void put_bh(struct buffer_head *bh) { atomic_dec(&bh->b_count); }
get_bh()
增加這個(gè)buffer的使用計(jì)數(shù),確保buffer不會(huì)意外釋放抄邀。當(dāng)操作完成后耘眨,調(diào)用put_bh()
函數(shù)減小使用計(jì)數(shù) -
b_bdev
:buffer對(duì)應(yīng)的塊設(shè)備 -
b_blocknr
:buffer對(duì)應(yīng)塊的邏輯塊號(hào) -
b_page
:指向buffer對(duì)應(yīng)的page -
b_data
:直接指向具體的塊(buffer對(duì)應(yīng)的塊位于內(nèi)存b_data
到b_data+b_size
范圍內(nèi)) -
b_size
:塊的大小
標(biāo)志值 | 描述 |
---|---|
BH_Uptodate | Buffer contains valid data |
BH_Dirty | Buffer is dirty |
BH_Lock | Buffer is undergoing disk I/O and is locked to prevent concurrent access |
BH_Req | Buffer is involved in an I/O request |
BH_Mapped | Buffer is a valid buffer mapped to an on-disk block |
BH_New | Buffer is newly mapped via get_block() and not yet accessed |
BH_Async_Read | Buffer is undergoing asynchronous read I/O via end_buffer_async_read() |
BH_Async_Write | Buffer is undergoing asynchronous write I/O via end_buffer_async_write() |
BH_Delay | Buffer does not yet have an associated on-disk block (delayed allocation) |
BH_Boundary | Buffer forms the boundary of contiguous blocks—the next block is discontinuous |
BH_Write_EIO | Buffer incurred an I/O error on write |
BH_Ordered | Ordered write |
BH_Eopnotsupp | Buffer incurred a “not supported” error |
BH_Unwritten | Space for the buffer has been allocated on disk but the actual data has not yet been written out |
BH_Quiet | Suppress errors for this buffer |
總的來說,buffer_head
包含內(nèi)核操作buffer需要用到控制信息境肾,它描繪了內(nèi)存中buffer和磁盤塊之間的映射關(guān)系
5.bio結(jié)構(gòu)
bio
結(jié)構(gòu)是內(nèi)核中塊I/O的基本容器剔难,定義在<linux/bio.h>
中。它代表一個(gè)活動(dòng)的塊I/O操作
這個(gè)塊I/O操作的對(duì)象是以片段(segement)組織的鏈表奥喻。片段(segement)是一個(gè)buffer在內(nèi)存中連續(xù)的一塊數(shù)據(jù)偶宫,用bio_vec
結(jié)構(gòu)表示,因此环鲤,單個(gè)buffer不一定要在內(nèi)存中連續(xù)(意思就是纯趋,可以由分散在內(nèi)存中的多個(gè)連續(xù)的數(shù)據(jù)區(qū)——片段,組成一個(gè)buffer)冷离。即使單個(gè)buffer的數(shù)據(jù)可能分散在內(nèi)存中的多個(gè)位置吵冒,bio結(jié)構(gòu)也提供了對(duì)這個(gè)buffer操作的能力(scatter-gather I/O)
struct bio {
sector_t bi_sector; /* device address in 512 byte
sectors */
struct bio *bi_next; /* request queue link */
struct block_device *bi_bdev;
unsigned long bi_flags; /* status, command, etc */
unsigned long bi_rw; /* bottom bits READ/WRITE,
* top bits priority
*/
unsigned short bi_vcnt; /* how many bio_vec's */
unsigned short bi_idx; /* current index into bvl_vec */
/* Number of segments in this BIO after
* physical address coalescing is performed.
*/
unsigned short bi_phys_segments;
/* Number of segments after physical and DMA remapping
* hardware coalescing is performed.
*/
unsigned short bi_hw_segments;
unsigned int bi_size; /* residual I/O count */
/*
* To keep track of the max hw size, we account for the
* sizes of the first and last virtually mergeable segments
* in this bio
*/
unsigned int bi_hw_front_size;
unsigned int bi_hw_back_size;
unsigned int bi_max_vecs; /* max bvl_vecs we can hold */
struct bio_vec *bi_io_vec; /* the actual vec list */
bio_end_io_t *bi_end_io;
atomic_t bi_cnt; /* pin count */
void *bi_private;
bio_destructor_t *bi_destructor; /* destructor */
};
-
bi_io_vec
:指向片段組織的鏈表。每一個(gè)bio_vec
()表示一個(gè)片段西剥,被看作是一個(gè)<page,offset,len>形式的矢量(vector)桦锄。bio_vec
結(jié)構(gòu)定義在<linux/bio.h>
中:struct bio_vec { struct page *bv_page; unsigned int bv_len; unsigned int bv_offset; };
-
bi_vcnt
:鏈表的大小 -
bi_cnt
:這個(gè)bio的使用計(jì)數(shù)。當(dāng)bi_cnt=0
時(shí)蔫耽,這個(gè)bio結(jié)構(gòu)會(huì)被銷毀结耀,釋放。在對(duì)bio進(jìn)行操作前匙铡,需要調(diào)用bio_get增加使用計(jì)數(shù)图甜,操作完成后,需要調(diào)用bio_put減小使用計(jì)數(shù)鳖眼。下面兩個(gè)功能用來更新bi_cnt
的值:void bio_get(struct bio *bio) //增加使用計(jì)數(shù) void bio_put(struct bio *bio) //減小使用計(jì)數(shù)
-
bi_private
域記錄這個(gè)bio擁有者的私有信息黑毅,擁有者為分配這個(gè)bio結(jié)構(gòu)的人
下圖描繪了bio、bio_vec钦讳、page三者間的關(guān)系:
<div align="center"> <img src="../pic/kernel-blockio-2.png"/> </div>
總之矿瘦,每個(gè)塊I/O請(qǐng)求用一個(gè)bio結(jié)構(gòu)表示,每個(gè)請(qǐng)求由一個(gè)或多個(gè)塊組成(對(duì)應(yīng)一個(gè)或多個(gè)buffer)愿卒,這些塊通過bi_io_vec指向的bio_vec鏈表串連起來缚去。隨著塊I/O層提交片段,bi_idx域被更新指向當(dāng)前段琼开。
6.I/O請(qǐng)求隊(duì)列與I/O請(qǐng)求
塊設(shè)備維護(hù)一個(gè)請(qǐng)求隊(duì)列來存放待處理的塊I/O請(qǐng)求易结。這個(gè)請(qǐng)求隊(duì)列由request_queue
結(jié)構(gòu)表示,定義在<linux/blkdev.h>
中。請(qǐng)求隊(duì)列包含了:
- 一個(gè)由請(qǐng)求組成的雙鏈表
- 還有一些相關(guān)的控制信息
請(qǐng)求在內(nèi)核上層(如文件系統(tǒng)層)被加入到隊(duì)列搞动。只要請(qǐng)求隊(duì)列非空躏精,塊設(shè)備驅(qū)動(dòng)就從隊(duì)列頭部提取I/O請(qǐng)求,然后提交到對(duì)應(yīng)的塊設(shè)備
每個(gè)I/O請(qǐng)求用request
結(jié)構(gòu)表示鹦肿。定義在<linux/blkdev.h>
中矗烛。每個(gè)I/O請(qǐng)求可以由不止一個(gè)bio結(jié)構(gòu)組成,因?yàn)閱蝹€(gè)請(qǐng)求可以操作多個(gè)磁盤上連續(xù)的塊
7.調(diào)度算法
調(diào)度算法就是控制I/O請(qǐng)求隊(duì)列中I/O請(qǐng)求的合并方式與調(diào)用時(shí)機(jī)
如果只是簡單的按I/O請(qǐng)求插入請(qǐng)求隊(duì)列的順序?qū)/O請(qǐng)求提交到對(duì)應(yīng)的塊設(shè)備箩溃,會(huì)導(dǎo)致非常差的性能瞭吃。磁盤尋道是當(dāng)今計(jì)算機(jī)最慢的操作之一。因此最小化尋道時(shí)間對(duì)于提升系統(tǒng)性能來說至關(guān)重要
為了最小化尋道時(shí)間碾篡,內(nèi)核并不按I/O請(qǐng)求插入隊(duì)列的順序提交I/O請(qǐng)求虱而。它們會(huì)對(duì)I/O請(qǐng)求進(jìn)行合并和排序來提高系統(tǒng)的總體性能。內(nèi)核實(shí)現(xiàn)這兩個(gè)操作的子系統(tǒng)就是調(diào)度算法
通過合并和排序开泽,I/O調(diào)度器在待處理的I/O請(qǐng)求之間劃分磁盤I/O資源
- 合并:就是將多個(gè)請(qǐng)求合并成一個(gè)請(qǐng)求牡拇,舉例來說,如果一個(gè)讀取文件中一大塊數(shù)據(jù)的請(qǐng)求被插入到請(qǐng)求隊(duì)列穆律,如果此時(shí)請(qǐng)求隊(duì)列中已經(jīng)存在一個(gè)讀取磁盤中相鄰扇區(qū)的請(qǐng)求惠呼。那么則兩個(gè)請(qǐng)求能被合并成一個(gè)。這樣的合并使得只需要提交一個(gè)命令到塊設(shè)備就能完成多個(gè)請(qǐng)求的I/O操作峦耘,極大節(jié)省了尋道時(shí)間
- 排序:即使沒有找到合適的請(qǐng)求進(jìn)行合并剔蹋,也不會(huì)簡單的將新請(qǐng)求插入到隊(duì)尾。而是按訪問扇區(qū)的位置插入新請(qǐng)求辅髓。這樣可以在磁頭從一端移動(dòng)到另一端的過程中泣崩,處理這條路徑上的所以請(qǐng)求(就像電梯)。這樣設(shè)計(jì)的目的是為了最小化總尋道時(shí)間洛口,并不是最小化每一個(gè)請(qǐng)求的尋道時(shí)間(想一下矫付,對(duì)于電梯最高層的人來說,如果電梯上升過程中有另外的人要上電梯——即有新請(qǐng)求要插隊(duì)第焰,那么肯定會(huì)延長電梯到達(dá)最高層的時(shí)間)
1)Elevator(電梯)
內(nèi)核2.4的默認(rèn)調(diào)度算法买优;內(nèi)核2.6中,被換成了deadline調(diào)度算法挺举;但是由于這個(gè)算法更簡單杀赢,并且在功能上有很多相似的地方,因此是個(gè)很好的入門
Linux Elevator調(diào)度算法包括合并和排序操作
當(dāng)有請(qǐng)求入隊(duì)時(shí):
- 檢索是否有可以合并的候選者湘纵。包括向前合并(front merging)和向后合并(back merging)
- 如果新請(qǐng)求被合并到相鄰請(qǐng)求前面脂崔,則是向前合并(由于文件的布局方式(按扇區(qū)號(hào)增加的方向布局)以及一種典型負(fù)載的I/O操作特點(diǎn)(通常讀文件從起始讀到結(jié)尾,而不是反過來讀)瞻佛,向前合并相比于向后合并來說極少發(fā)生脱篙。但是盡管如此娇钱,Linux Elevator還是會(huì)對(duì)兩種合并進(jìn)行檢查)
- 如果新請(qǐng)求被合并到鄰近請(qǐng)求的后面伤柄,則是向后合并
- 如果新請(qǐng)求沒有合并绊困,則在隊(duì)列中尋找一個(gè)合適的位置插入新請(qǐng)求,未找到則將新請(qǐng)求插入隊(duì)尾
- 此外适刀,如果在隊(duì)列中存在駐留時(shí)間過長的請(qǐng)求(超過一個(gè)預(yù)定的閾值)秤朗,那么即使有適合新請(qǐng)求插入的位置,新請(qǐng)求也會(huì)被插入隊(duì)尾笔喉。這是為了防止磁盤上鄰近的大量請(qǐng)求饑餓其它位置的請(qǐng)求取视。但是這種時(shí)間檢測并沒有為駐留時(shí)間過長的請(qǐng)求提供服務(wù),而是停止新請(qǐng)求的有序插入常挚。雖然改善了延遲作谭,但是仍然有可能導(dǎo)致饑餓。這是內(nèi)核2.4的I/O調(diào)度算法必須修改的一點(diǎn)
總的來說奄毡,當(dāng)一個(gè)被添加到隊(duì)列時(shí)折欠,可能會(huì)執(zhí)行下列4個(gè)操作:
- 如果有合適的請(qǐng)求合并,則執(zhí)行請(qǐng)求合并操作吼过;
- 如果隊(duì)列中存在駐留時(shí)間過長的請(qǐng)求锐秦,則將新請(qǐng)求插入隊(duì)尾;
- 如果在隊(duì)列中找到合適的插入位置盗忱,則將新請(qǐng)求插入該位置(使得所有請(qǐng)求按磁盤中的物理位置排序)酱床;
- 如果沒找到合適的位置插入,則將新請(qǐng)求插入隊(duì)尾趟佃;
2)Deadline(截止日期)
這個(gè)調(diào)度算法嘗試解決Linus Elevator中的饑餓問題扇谣。為了最小化尋道時(shí)間,相同位置的請(qǐng)求會(huì)插入請(qǐng)求隊(duì)列闲昭,饑餓其它位置的請(qǐng)求
更壞的是罐寨,這個(gè)饑餓問題帶來了一個(gè)特例:寫?zhàn)囸I讀。寫操作經(jīng)常在內(nèi)核空閑時(shí)被提交到磁盤汤纸,它和提交它(寫操作)的程序完全異步執(zhí)行衩茸。而讀操作完全不同。一般情況下贮泞,當(dāng)一個(gè)應(yīng)用提交一個(gè)讀請(qǐng)求后楞慈,它會(huì)被阻塞,直到讀請(qǐng)求被滿足啃擦。也就是說囊蓝,讀請(qǐng)求和提交它的程序同步執(zhí)行。雖然寫延遲和應(yīng)用性能沒有多大關(guān)系令蛉,但是對(duì)于讀操作來說聚霜,應(yīng)用必須等待讀操作完成狡恬。因此,讀延遲對(duì)系統(tǒng)性能來說十分重要
除此之外蝎宇,讀請(qǐng)求往往互相依賴弟劲。考慮讀取一個(gè)大文件姥芥,如果前面一塊數(shù)據(jù)沒有讀完兔乞,后面數(shù)據(jù)塊的讀取也無法執(zhí)行。更糟的是凉唐,讀和寫操作都要求讀取元素?fù)?jù)(如inode)庸追。這使得I/O更加串行化。因此台囱,如果讀請(qǐng)求饑餓淡溯,整個(gè)串行化累積起來的延遲將會(huì)異常巨大
需要注意的是,減少請(qǐng)求饑餓必須以全局吞吐量為代價(jià)簿训。deadline調(diào)度算法非常努力地嘗試在限制饑餓發(fā)生的同時(shí)咱娶,提供良好的全局吞吐量。但是不要搞錯(cuò):要保證請(qǐng)求公平性的同時(shí)煎楣,最大化全局吞吐量仍然非常困難
在deadline調(diào)度算法中豺总,每個(gè)請(qǐng)求有一個(gè)到期時(shí)間(expiration time),默認(rèn)為500ms(對(duì)于讀請(qǐng)求)和5s(對(duì)于寫請(qǐng)求)
- 和linux elevator類似择懂,它有一個(gè)名為sorted queue的有序隊(duì)列喻喳。這個(gè)隊(duì)列按請(qǐng)求數(shù)據(jù)的物理磁盤位置對(duì)請(qǐng)求排序。當(dāng)請(qǐng)求被提交到sorted queue時(shí)困曙,deadline按照linus elevator的方式執(zhí)行合并和插入操作
- 此外表伦,它還根據(jù)請(qǐng)求的類型將讀請(qǐng)求和寫請(qǐng)求分別插入到read FIFO queue和write FIFO queue。雖然sorted queue是按照物理磁盤訪問順序?qū)φ?qǐng)求進(jìn)行排序慷丽,但是read FIFO queue和write FIFO queue嚴(yán)格保持先進(jìn)先出的順序蹦哼。正常情況下,deadline從sorted queue頭部取出一個(gè)請(qǐng)求要糊,提交到分發(fā)隊(duì)列(dispatch queue)纲熏,分發(fā)隊(duì)列進(jìn)一步將請(qǐng)求提交給磁盤。這保證了最小化尋道時(shí)間
- 如果read FIFO queue或者write FIFO queue中的頭部請(qǐng)求到期(也就是說锄俄,當(dāng)前時(shí)間超過了請(qǐng)求的到期時(shí)間)局劲,則deadline轉(zhuǎn)為服務(wù)FIFO隊(duì)列。這確保了不會(huì)有請(qǐng)求超過到期時(shí)間太多才完成
<div align="center"> <img src="../pic/kernel-blockio-3.png"/> </div>
deadline并不保證請(qǐng)求的完成時(shí)間奶赠,它只保證在到期時(shí)間來臨之前或者在到期時(shí)間來臨時(shí)提交請(qǐng)求鱼填。這能夠防止饑餓發(fā)生。同時(shí)毅戈,由于讀請(qǐng)求的到期時(shí)間遠(yuǎn)小于寫請(qǐng)求的到期時(shí)間苹丸,它也能防止寫?zhàn)囸I讀愤惰。對(duì)讀請(qǐng)求的照顧確保了最小化的讀延遲
3)Anticipatory(預(yù)測)
deadline調(diào)度算法還是在全局吞吐量上做出了犧牲,考慮這種負(fù)載:一個(gè)應(yīng)用在執(zhí)行大量順序?qū)懖僮髯咐怼T跊]有請(qǐng)求到期之前宦言,按順序滿足這些順序?qū)懻?qǐng)求。假設(shè)現(xiàn)在每隔一段時(shí)間有一個(gè)讀請(qǐng)求到達(dá)感憾,在讀請(qǐng)求到期時(shí)間之前蜡励,會(huì)繼續(xù)執(zhí)行寫請(qǐng)求令花。當(dāng)讀請(qǐng)求到期時(shí)阻桅,轉(zhuǎn)而調(diào)度讀請(qǐng)求。這里引入了磁盤尋道時(shí)間兼都。在處理完讀請(qǐng)求后嫂沉,又回來出來順序?qū)懀@里又引入了尋道開銷扮碧。然后一段時(shí)間后下一個(gè)讀請(qǐng)求到達(dá)趟章,如此反復(fù),每個(gè)讀請(qǐng)求到來時(shí)慎王,都會(huì)引入一定的尋道時(shí)間蚓土。導(dǎo)致全局吞吐量下降。因此赖淤,anticipatory調(diào)度算法試圖保持讀請(qǐng)求低延遲的同時(shí)蜀漆,優(yōu)化全局吞吐量
首先,anticipatory調(diào)度算法按照deadline的方式進(jìn)行調(diào)度咱旱,它也有3個(gè)隊(duì)列确丢,每個(gè)請(qǐng)求都有一個(gè)到期時(shí)間。主要改變是它引入了一個(gè)啟發(fā)式預(yù)測
繼續(xù)用之前的例子說明吐限。當(dāng)一個(gè)讀請(qǐng)求到達(dá)時(shí)鲜侥,在到達(dá)日期來臨前,會(huì)按照之前的方式進(jìn)行處理诸典。當(dāng)這個(gè)讀請(qǐng)求被提交后移层,anticipatory不會(huì)馬上轉(zhuǎn)回去處理順序?qū)懻?qǐng)求,而是會(huì)等待一小段時(shí)間(可以設(shè)置檩咱,默認(rèn)是6ms)万细。如果在這段時(shí)間內(nèi)還有其它讀請(qǐng)求到來,就可以較少來回尋道次數(shù)脑奠,提高吞吐量
當(dāng)然基公,如果在等待時(shí)間內(nèi)沒有任何事發(fā)生,那么這段等待時(shí)間就浪費(fèi)了宋欺。anticipatory調(diào)度算法的性能取決于能否準(zhǔn)確預(yù)測等待時(shí)間內(nèi)系統(tǒng)的I/O活動(dòng)轰豆。這通過一系列統(tǒng)計(jì)以及啟發(fā)式來完成胰伍。anticipatory跟蹤并統(tǒng)計(jì)每個(gè)進(jìn)程的塊I/O操作行為
這個(gè)調(diào)度算法在大多數(shù)負(fù)載下都表現(xiàn)良好。對(duì)于服務(wù)器來說是個(gè)比較理想的算法酸休,但是在一些不常見但是負(fù)載嚴(yán)格的場景中(包括 seek-happy databases)表現(xiàn)不好
4)CFQ(完全公平隊(duì)列)
這個(gè)調(diào)度算法是為特定負(fù)載設(shè)計(jì)的骂租,但是實(shí)際上在很多負(fù)載下它都能提供不錯(cuò)的性能。它和之前提到的算法有本質(zhì)上的區(qū)別
cfq為每個(gè)進(jìn)程維護(hù)一個(gè)I/O隊(duì)列斑司,新的I/O請(qǐng)求會(huì)插入到發(fā)起這個(gè)請(qǐng)求的進(jìn)程的I/O隊(duì)列中渗饮。在每個(gè)隊(duì)列中,請(qǐng)求進(jìn)行合并以及排序操作
cfq以輪詢的方式服務(wù)每一個(gè)隊(duì)列宿刮,每次從一個(gè)隊(duì)列中選擇一定數(shù)目的(默認(rèn)4互站,可以設(shè)置)請(qǐng)求服務(wù)。因此提供了進(jìn)程之間的公平性僵缺。確保每個(gè)進(jìn)程得到公平的帶寬胡桃。這個(gè)算法主要是為多媒體負(fù)載設(shè)計(jì),實(shí)際上能在很多場景下工作良好磕潮。它被推薦用于桌面負(fù)載
5)Noop
noop調(diào)度算法僅僅只對(duì)新請(qǐng)求執(zhí)行合并操作翠胰,除此之外它什么也不做。僅僅只是以near-FIFO的順序維護(hù)一個(gè)請(qǐng)求隊(duì)列
這種算法這樣設(shè)計(jì)并不是沒有原因的自脯,它是考慮到如ssd這類在尋道上只有很小開銷或者沒有開銷的設(shè)備之景,對(duì)于這些設(shè)備來說,不需要擔(dān)心尋道延遲膏潮,因此也就不需要對(duì)請(qǐng)求進(jìn)行排序锻狗。因此對(duì)于這類設(shè)備來說,noop是個(gè)理想的候選者
6)查看與選擇可用的調(diào)度算法
可用通過如下命令查看linux中支持和當(dāng)前使用的調(diào)度算法:
cat /sys/block/設(shè)備名/queue/scheduler
noop [deadline] cfq #當(dāng)前使用的調(diào)度算法為"deadline"
如果要切換調(diào)度算法戏罢,可用使用命令:
echo 算法名 >> /sys/block/設(shè)備名/queue/scheduler