您好,登錄后才能下訂單哦!
這一塊操作系統(tǒng)主要分為兩個(gè)部分,一個(gè)部分是書(shū)本上操作系統(tǒng)的知識(shí),還有一部門(mén)是linux的相關(guān)知識(shí):
linux相關(guān)知識(shí)
###(1) Linux中同步異步、阻塞非阻塞的區(qū)別(超級(jí)重要)
首先是同步異步、阻塞非阻塞的區(qū)別:
同步:所謂同步,就是在發(fā)出一個(gè)功能調(diào)用時(shí),在沒(méi)有得到結(jié)果之前,該調(diào)用就不返回。也就是必須一件一件事做,等前一件做完了才能做下一件事。
例如普通B/S模式(同步):提交請(qǐng)求->等待服務(wù)器處理->處理完畢返回 這個(gè)期間客戶(hù)端瀏覽器不能干任何事
異步:異步的概念和同步相對(duì)。當(dāng)一個(gè)異步過(guò)程調(diào)用發(fā)出后,調(diào)用者不能立刻得到結(jié)果。實(shí)際處理這個(gè)調(diào)用的部件在完成后,通過(guò)狀態(tài)、通知和回調(diào)來(lái)通知調(diào)用者。
例如 ajax請(qǐng)求(異步): 請(qǐng)求通過(guò)事件觸發(fā)->服務(wù)器處理(這是瀏覽器仍然可以作其他事情)->處理完畢
阻塞:阻塞調(diào)用是指調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起(線程進(jìn)入非可執(zhí)行狀態(tài),在這個(gè)狀態(tài)下,cpu不會(huì)給線程分配時(shí)間片,即線程暫停運(yùn)行)。函數(shù)只有在得到結(jié)果之后才會(huì)返回。
有人也許會(huì)把阻塞調(diào)用和同步調(diào)用等同起來(lái),實(shí)際上他是不同的。對(duì)于同步調(diào)用來(lái)說(shuō),很多時(shí)候當(dāng)前線程還是激活的,只是從邏輯上當(dāng)前函數(shù)沒(méi)有返回,它還會(huì)搶占cpu去執(zhí)行其他邏輯,也會(huì)主動(dòng)檢測(cè)io是否準(zhǔn)備好。
非阻塞:非阻塞和阻塞的概念相對(duì)應(yīng),指在不能立刻得到結(jié)果之前,該函數(shù)不會(huì)阻塞當(dāng)前線程,而會(huì)立刻返回。
再簡(jiǎn)單點(diǎn)理解就是:
1. 同步,就是我調(diào)用一個(gè)功能,該功能沒(méi)有結(jié)束前,我死等結(jié)果。
2. 異步,就是我調(diào)用一個(gè)功能,不需要知道該功能結(jié)果,該功能有結(jié)果后通知我(回調(diào)通知)
3. 阻塞,就是調(diào)用我(函數(shù)),我(函數(shù))沒(méi)有接收完數(shù)據(jù)或者沒(méi)有得到結(jié)果之前,我不會(huì)返回。
4. 非阻塞,就是調(diào)用我(函數(shù)),我(函數(shù))立即返回,通過(guò)select通知調(diào)用者
同步IO和異步IO的區(qū)別就在于:數(shù)據(jù)拷貝的時(shí)候進(jìn)程是否阻塞
阻塞IO和非阻塞IO的區(qū)別就在于:應(yīng)用程序的調(diào)用是否立即返回
綜上可知,同步和異步,阻塞和非阻塞,有些混用,其實(shí)它們完全不是一回事,而且它們修飾的對(duì)象也不相同。
linux中五種IO模型:
阻塞I/O(blocking I/O)
非阻塞I/O (nonblocking I/O)
I/O復(fù)用(select 和poll) (I/O multiplexing)
信號(hào)驅(qū)動(dòng)I/O (signal driven I/O (SIGIO))
異步I/O (asynchronous I/O (the POSIX aio_functions))
*其中前4種都是同步,最后一種才是異步。
1. 阻塞I/O:
應(yīng)用程序調(diào)用一個(gè)IO函數(shù),導(dǎo)致應(yīng)用程序阻塞,等待數(shù)據(jù)準(zhǔn)備好。 如果數(shù)據(jù)沒(méi)有準(zhǔn)備好,一直等待….數(shù)據(jù)準(zhǔn)備好了,從內(nèi)核拷貝到用戶(hù)空間,IO函數(shù)返回成功指示。
阻塞I/O模型圖:在調(diào)用recv()/recvfrom()函數(shù)時(shí),發(fā)生在內(nèi)核中等待數(shù)據(jù)和復(fù)制數(shù)據(jù)的過(guò)程。
當(dāng)調(diào)用recv()函數(shù)時(shí),系統(tǒng)首先查是否有準(zhǔn)備好的數(shù)據(jù)。如果數(shù)據(jù)沒(méi)有準(zhǔn)備好,那么系統(tǒng)就處于等待狀態(tài)。當(dāng)數(shù)據(jù)準(zhǔn)備好后,將數(shù)據(jù)從系統(tǒng)緩沖區(qū)復(fù)制到用戶(hù)空間,然后該函數(shù)返回。在套接應(yīng)用程序中,當(dāng)調(diào)用recv()函數(shù)時(shí),未必用戶(hù)空間就已經(jīng)存在數(shù)據(jù),那么此時(shí)recv()函數(shù)就會(huì)處于等待狀態(tài)。
2. 非阻塞I/O
非阻塞IO通過(guò)進(jìn)程反復(fù)調(diào)用IO函數(shù)(多次系統(tǒng)調(diào)用,并馬上返回);在數(shù)據(jù)拷貝的過(guò)程中,進(jìn)程是阻塞的
我們把一個(gè)SOCKET接口設(shè)置為非阻塞就是告訴內(nèi)核,當(dāng)所請(qǐng)求的I/O操作無(wú)法完成時(shí),不要將進(jìn)程睡眠,而是返回一個(gè)錯(cuò)誤。這樣我們的I/O操作函數(shù)將不斷的測(cè)試數(shù)據(jù)是否已經(jīng)準(zhǔn)備好,如果沒(méi)有準(zhǔn)備好,繼續(xù)測(cè)試,直到數(shù)據(jù)準(zhǔn)備好為止。在這個(gè)不斷測(cè)試的過(guò)程中,會(huì)大量的占用CPU的時(shí)間。
3. IO復(fù)用
主要是select和epoll;對(duì)一個(gè)IO端口,兩次調(diào)用,兩次返回,比阻塞IO并沒(méi)有什么優(yōu)越性;關(guān)鍵是能實(shí)現(xiàn)同時(shí)對(duì)多個(gè)IO端口進(jìn)行監(jiān)聽(tīng); I/O復(fù)用模型會(huì)用到select、poll、epoll函數(shù),這幾個(gè)函數(shù)也會(huì)使進(jìn)程阻塞,但是和阻塞I/O所不同的的,這兩個(gè)函數(shù)可以同時(shí)阻塞多個(gè)I/O操作。而且可以同時(shí)對(duì)多個(gè)讀操作,多個(gè)寫(xiě)操作的I/O函數(shù)進(jìn)行檢測(cè),直到有數(shù)據(jù)可讀或可寫(xiě)時(shí),才真正調(diào)用I/O操作函數(shù)。
IO復(fù)用模型會(huì)用到select、poll、epoll函數(shù),這幾個(gè)函數(shù)也會(huì)使進(jìn)程阻塞,但是和阻塞I/O所不同的是,這兩個(gè)函數(shù)可以同時(shí)阻塞多個(gè)I/O操作。而且可以同時(shí)對(duì)多個(gè)讀操作、多個(gè)寫(xiě)操作的I/O函數(shù)進(jìn)行檢測(cè),直到有數(shù)據(jù)可讀或者可寫(xiě)時(shí)(注意不是全部數(shù)據(jù)可讀或者可寫(xiě)),才真正的調(diào)用I/O操作函數(shù)。
4. 信號(hào)驅(qū)動(dòng)IO
首先我們?cè)试S套接口進(jìn)行信號(hào)驅(qū)動(dòng)I/O,并安裝一個(gè)信號(hào)處理函數(shù),進(jìn)程繼續(xù)運(yùn)行并不阻塞。當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),進(jìn)程會(huì)收到一個(gè)SIGIO信號(hào),可以在信號(hào)處理函數(shù)中調(diào)用I/O操作函數(shù)處理數(shù)據(jù)。
5. 異步IO
當(dāng)一個(gè)異步過(guò)程調(diào)用發(fā)出后,調(diào)用者不能立刻得到結(jié)果。實(shí)際處理這個(gè)調(diào)用的部件在完成后,通過(guò)狀態(tài)、通知和回調(diào)來(lái)通知調(diào)用者的輸入輸出操作
6. 總結(jié)比較下五種IO模型:
(2) 文件系統(tǒng)的理解(EXT4,XFS,BTRFS)
1.Ext4 文件系統(tǒng)
ext4 還有一些明顯的限制。最大文件大小是 16 tebibytes(大概是 17.6 terabytes),這比普通用戶(hù)當(dāng)前能買(mǎi)到的硬盤(pán)還要大的多。使用 ext4 能創(chuàng)建的最大卷/分區(qū)是 1 exbibyte(大概是 1,152,921.5 terabytes)。通過(guò)使用多種技巧, ext4 比 ext3 有很大的速度提升。類(lèi)似一些最先進(jìn)的文件系統(tǒng),它是一個(gè)日志文件系統(tǒng),意味著它會(huì)對(duì)文件在磁盤(pán)中的位置以及任何其它對(duì)磁盤(pán)的更改做記錄。縱觀它的所有功能,它還不支持透明壓縮、重復(fù)數(shù)據(jù)刪除或者透明加密。技術(shù)上支持了快照,但該功能還處于實(shí)驗(yàn)性階段。
2.XFS 文件系統(tǒng)
XFS 文件系統(tǒng)是擴(kuò)展文件系統(tǒng)(extent file system)的一個(gè)擴(kuò)展。XFS 是 64 位高性能日志文件系統(tǒng)。對(duì) XFS 的支持大概在 2002 年合并到了 Linux 內(nèi)核,到了 2009 年,紅帽企業(yè)版 Linux 5.4 也支持了 XFS 文件系統(tǒng)。對(duì)于 64 位文件系統(tǒng),XFS 支持最大文件系統(tǒng)大小為 8 exbibytes。XFS 文件系統(tǒng)有一些缺陷,例如它不能壓縮,刪除大量文件時(shí)性能低下。目前RHEL 7.0 文件系統(tǒng)默認(rèn)使用 XFS。
3.trfs 文件系統(tǒng)
btrfs 有很多不同的叫法,例如 Better FS、Butter FS 或者 B-Tree FS。它是一個(gè)幾乎完全從頭開(kāi)發(fā)的文件系統(tǒng)。btrfs 出現(xiàn)的原因是它的開(kāi)發(fā)者起初希望擴(kuò)展文件系統(tǒng)的功能使得它包括快照、池化(pooling)、校驗(yàn)以及其它一些功能。雖然和 ext4 無(wú)關(guān),它也希望能保留 ext4 中能使消費(fèi)者和企業(yè)受益的功能,并整合額外的能使每個(gè)人,尤其是企業(yè)受益的功能。對(duì)于使用大型軟件以及大規(guī)模數(shù)據(jù)庫(kù)的企業(yè),讓多種不同的硬盤(pán)看起來(lái)一致的文件系統(tǒng)能使他們受益并且使數(shù)據(jù)整合變得更加簡(jiǎn)單。刪除重復(fù)數(shù)據(jù)能降低數(shù)據(jù)實(shí)際使用的空間,當(dāng)需要鏡像一個(gè)單一而巨大的文件系統(tǒng)時(shí)使用 btrfs 也能使數(shù)據(jù)鏡像變得簡(jiǎn)單。
用戶(hù)當(dāng)然可以繼續(xù)選擇創(chuàng)建多個(gè)分區(qū)從而無(wú)需鏡像任何東西。考慮到這種情況,btrfs 能橫跨多種硬盤(pán),和 ext4 相比,它能支持 16 倍以上的磁盤(pán)空間。btrfs 文件系統(tǒng)一個(gè)分區(qū)最大是 16 exbibytes,最大的文件大小也是 16 exbibytes。
(3) 文件處理grep,awk,sed這三個(gè)命令必知必會(huì)
1.grep、sed和awk都是文本處理工具,雖然都是文本處理工具單卻都有各自的優(yōu)缺點(diǎn),一種文本處理命令是不能被另一個(gè)完全替換的,否則也不會(huì)出現(xiàn)三個(gè)文本處理命令了。只不過(guò),相比較而言,sed和awk功能更強(qiáng)大而已,且已獨(dú)立成一種語(yǔ)言來(lái)介紹。
2.grep:文本過(guò)濾器,如果僅僅是過(guò)濾文本,可使用grep,其效率要比其他的高很多;
3.sed:Stream EDitor,流編輯器,默認(rèn)只處理模式空間,不處理原數(shù)據(jù),如果你處理的數(shù)據(jù)是針對(duì)行進(jìn)行處理的,可以使用sed;
4.awk:報(bào)告生成器,格式化以后顯示。如果對(duì)處理的數(shù)據(jù)需要生成報(bào)告之類(lèi)的信息,或者你處理的數(shù)據(jù)是按列進(jìn)行處理的,最好使用awk。
(4) IO復(fù)用的三種方法(select,poll,epoll)深入理解,包括三者區(qū)別,內(nèi)部原理實(shí)現(xiàn)?
1. IO復(fù)用的了解:
select,poll,epoll都是IO多路復(fù)用的機(jī)制。I/O多路復(fù)用就通過(guò)一種機(jī)制,可以監(jiān)視多個(gè)描述符,一旦某個(gè)描述符就緒(一般是讀就緒或者寫(xiě)就緒),能夠通知程序進(jìn)行相應(yīng)的讀寫(xiě)操作。但select,poll,epoll本質(zhì)上都是同步I/O,因?yàn)樗麄兌夹枰谧x寫(xiě)事件就緒后自己負(fù)責(zé)進(jìn)行讀寫(xiě),也就是說(shuō)這個(gè)讀寫(xiě)過(guò)程是阻塞的,而異步I/O則無(wú)需自己負(fù)責(zé)進(jìn)行讀寫(xiě),異步I/O的實(shí)現(xiàn)會(huì)負(fù)責(zé)把數(shù)據(jù)從內(nèi)核拷貝到用戶(hù)空間。
此時(shí)需知道兩個(gè)概念:
所謂阻塞方式block,顧名思義,就是進(jìn)程或是線程執(zhí)行到這些函數(shù)時(shí)必須等待某個(gè)事件的發(fā)生,如果事件沒(méi)有發(fā)生,進(jìn)程或線程就被阻塞,函數(shù)不能立即返回。
所謂非阻塞方式non-block,就是進(jìn)程或線程執(zhí)行此函數(shù)時(shí)不必非要等待事件的發(fā)生,一旦執(zhí)行肯定返回,以返回值的不同來(lái)反映函數(shù)的執(zhí)行情況,如果事件發(fā)生則與阻塞方式相同,若事件沒(méi)有發(fā)生,則返回一個(gè)代碼來(lái)告知事件未發(fā)生,而進(jìn)程或線程繼續(xù)執(zhí)行,所以效率較高。
2. select 分析
select()的機(jī)制中提供一fd_set的數(shù)據(jù)結(jié)構(gòu),實(shí)際上是一long類(lèi)型的數(shù)組, 每一個(gè)數(shù)組元素都能與一打開(kāi)的文件句柄(不管是Socket句柄,還是其他 文件或命名管道或設(shè)備句柄)建立聯(lián)系,建立聯(lián)系的工作由程序員完成, 當(dāng)調(diào)用select()時(shí),由內(nèi)核根據(jù)IO狀態(tài)修改fd_set的內(nèi)容,由此來(lái)通知執(zhí)行了select()的進(jìn)程哪一Socket或文件可讀或可寫(xiě)。主要用于Socket通信當(dāng)中。
select使用:它能夠監(jiān)視我們需要監(jiān)視的文件描述符的變化情況——讀寫(xiě)或是異常。準(zhǔn)備就緒的描述符數(shù),若超時(shí)則返回0,若出錯(cuò)則返回-1。
1.如果一個(gè)發(fā)現(xiàn)I/O有輸入,讀取的過(guò)程中,另外一個(gè)也有了輸入,這時(shí)候不會(huì)產(chǎn)生任何反應(yīng).這就需要你的程序語(yǔ)句去用到select函數(shù)的時(shí)候才知道有數(shù)據(jù)輸入。
2.程序去select的時(shí)候,如果沒(méi)有數(shù)據(jù)輸入,程序會(huì)一直等待(阻塞時(shí)),直到有數(shù)據(jù)為止,也就是程序中無(wú)需循環(huán)和sleep。
函數(shù)分析:
#include <sys/types.h>
#include <sys/times.h>
#include <sys/select.h>
int select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout)
1
2
3
4
函數(shù)返回結(jié)果:當(dāng)readfds或writefds中映象的文件可讀或可寫(xiě)或超時(shí),本次select()就結(jié)束返回。程序員利用一組系統(tǒng)提供的宏在select()結(jié)束時(shí)便可判斷哪一文件可讀或可寫(xiě),對(duì)Socket編程特別有用的就是readfds。
注:不同的timeval設(shè)置使select()表現(xiàn)出超時(shí)結(jié)束、無(wú)超時(shí)阻塞和輪詢(xún)?nèi)N特性(timeval可精確至百萬(wàn)分之一秒)。
select詳細(xì)執(zhí)行步驟:
(1)使用copy_from_user從用戶(hù)空間拷貝fd_set到內(nèi)核空間
(2)注冊(cè)回調(diào)函數(shù)__pollwait
(3)遍歷所有fd,調(diào)用其對(duì)應(yīng)的poll方法(對(duì)于socket,這個(gè)poll方法是sock_poll,sock_poll根據(jù)情況會(huì)調(diào)用到tcp_poll,udp_poll或者datagram_poll)
(4)以tcp_poll為例,其核心實(shí)現(xiàn)就是__pollwait,也就是上面注冊(cè)的回調(diào)函數(shù)。
(5)__pollwait的主要工作就是把current(當(dāng)前進(jìn)程)掛到設(shè)備的等待隊(duì)列中,不同的設(shè)備有不同的等待隊(duì)列,對(duì)于tcp_poll來(lái)說(shuō),其等待隊(duì)列是sk->sk_sleep(注意把進(jìn)程掛到等待隊(duì)列中并不代表進(jìn)程已經(jīng)睡眠了)。在設(shè)備收到一條消息(網(wǎng)絡(luò)設(shè)備)或填寫(xiě)完文件數(shù)據(jù)(磁盤(pán)設(shè)備)后,會(huì)喚醒設(shè)備等待隊(duì)列上睡眠的進(jìn)程,這時(shí)current便被喚醒了。
(6)poll方法返回時(shí)會(huì)返回一個(gè)描述讀寫(xiě)操作是否就緒的mask掩碼,根據(jù)這個(gè)mask掩碼給fd_set賦值。
(7)如果遍歷完所有的fd,還沒(méi)有返回一個(gè)可讀寫(xiě)的mask掩碼,則會(huì)調(diào)用schedule_timeout是調(diào)用select的進(jìn)程(也就是current)進(jìn)入睡眠。當(dāng)設(shè)備驅(qū)動(dòng)發(fā)生自身資源可讀寫(xiě)后,會(huì)喚醒其等待隊(duì)列上睡眠的進(jìn)程。如果超過(guò)一定的超時(shí)時(shí)間(schedule_timeout指定),還是沒(méi)人喚醒,則調(diào)用select的進(jìn)程會(huì)重新被喚醒獲得CPU,進(jìn)而重新遍歷fd,判斷有沒(méi)有就緒的fd。
(8)把fd_set從內(nèi)核空間拷貝到用戶(hù)空間。
從以上工作流程可得到select特點(diǎn):
a.所監(jiān)視的每種事件描述符個(gè)數(shù)有上限;
printf("%d\n",sizeof(fd_set));
1
我的linux系統(tǒng)所能關(guān)心事件應(yīng)為128字節(jié)*8=1024個(gè)描述符
b.調(diào)用前后輪詢(xún);
使用select函數(shù),必須使用輔助數(shù)組保存關(guān)心的描述符,因?yàn)閟elect函數(shù)中描述符集是輸入輸出型參數(shù),故在調(diào)用前應(yīng)輪詢(xún)數(shù)組重置描述符集,調(diào)用后得輪詢(xún)描述符集判斷關(guān)心事件是否就緒。
c.系統(tǒng)與用戶(hù)數(shù)據(jù)拷貝:使用copy_from_user從用戶(hù)空間拷貝fd_set到內(nèi)核空間。
d.調(diào)用前需重置(描述符集是輸入輸出型參數(shù))。
3. poll分析
poll的實(shí)現(xiàn)和select非常相似,只是描述fd集合的方式不同,poll使用pollfd結(jié)構(gòu)而不是select的fd_set結(jié)構(gòu),其他的都差不多。
#include <poll.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
1
2
監(jiān)視描述符事件選項(xiàng):
fds:是一個(gè)struct pollfd結(jié)構(gòu)類(lèi)型的數(shù)組,用于存放需要檢測(cè)其狀態(tài)的Socket描述符;每當(dāng)調(diào)用這個(gè)函數(shù)之后,系統(tǒng)不會(huì)清空這個(gè)數(shù)組,操作起來(lái)比較方便;特別是對(duì)于socket連接比較多的情況下,在一定程度上可以提高處理的效率;這一點(diǎn)與select()函數(shù)不同,調(diào)用select()函數(shù)之后,select()函數(shù)會(huì)清空它所檢測(cè)的socket描述符集合,導(dǎo)致每次調(diào)用select()之前都必須把socket描述符重新加入到待檢測(cè)的集合中;因此,select()函數(shù)適合于只檢測(cè)一個(gè)socket描述符的情況,而poll()函數(shù)適合于大量socket描述符的情況;與select()十分相似,當(dāng)返回正值時(shí),代表滿(mǎn)足響應(yīng)事件的文件描述符的個(gè)數(shù),如果返回0則代表在規(guī)定時(shí)間內(nèi)沒(méi)有事件發(fā)生。如發(fā)現(xiàn)返回為負(fù)則應(yīng)該立即查看 errno,因?yàn)檫@代表有錯(cuò)誤發(fā)生。
注:如果沒(méi)有事件發(fā)生,revents會(huì)被清空。
poll特點(diǎn):
監(jiān)視描述符個(gè)數(shù)無(wú)上限;最大描述符+1,個(gè)數(shù)由fds數(shù)組決定。
2.監(jiān)視事件與返回后事件狀態(tài)反生分離,調(diào)用前后不需重置。
3.調(diào)用后輪詢(xún)檢測(cè)監(jiān)視事件是否發(fā)生。
4.系統(tǒng)與用戶(hù)數(shù)據(jù)拷貝:使用copy_from_user從用戶(hù)空間拷貝fds到內(nèi)核空間
4. epoll分析
epoll是linux內(nèi)核為處理大批量文件描述符而作了改進(jìn)的poll,是Linux下多路復(fù)用IO接口select/poll的增強(qiáng)版本,它能顯著提高程序在大量并發(fā)連接中中只有少量活躍的情況下的系統(tǒng)CPU利用率。另一點(diǎn)原因就是獲取事件的時(shí)候,它無(wú)須遍歷整個(gè)被偵聽(tīng)的描述符集,只要遍歷那些被內(nèi)核IO事件異步喚醒而加入Ready隊(duì)列的描述符集合就行了。epoll除了提供select/poll那種IO事件的水平觸發(fā)(Level Triggered)外,還提供了邊緣觸發(fā)(Edge Triggered),這就使得用戶(hù)空間程序有可能緩存IO狀態(tài),減少epoll_wait/epoll_pwait的調(diào)用,提高應(yīng)用程序效率。
epoll特點(diǎn):
1.epoll和select和poll的調(diào)用接口上的不同。
select和poll都只提供了一個(gè)函數(shù)——select或者poll函數(shù)。而epoll提供了三個(gè)函數(shù),epoll_create,epoll_ctl和epoll_wait,epoll_create是創(chuàng)建一個(gè)epoll句柄;epoll_ctl是注冊(cè)要監(jiān)聽(tīng)的事件類(lèi)型;epoll_wait則是等待事件的產(chǎn)生。
2.使用mmap加速內(nèi)核與用戶(hù)空間的消息傳遞。
對(duì)于select和poll函數(shù)的系統(tǒng)與內(nèi)核每次調(diào)用時(shí)的數(shù)據(jù)拷貝:epoll是通過(guò)內(nèi)核與用戶(hù)空間mmap同一塊內(nèi)存實(shí)現(xiàn)的,在epoll_ctl函數(shù)中:每次注冊(cè)新的事件到epoll句柄中時(shí)(在epoll_ctl中指定EPOLL_CTL_ADD),會(huì)把所有的fd拷貝進(jìn)內(nèi)核,而不是在epoll_wait的時(shí)候重復(fù)拷貝。epoll保證了每個(gè)fd在整個(gè)過(guò)程中只會(huì)拷貝一次。
3.調(diào)用后不需輪詢(xún)判斷描述符事件是否就緒。
對(duì)于select和poll函數(shù)每次調(diào)用后輪詢(xún)檢測(cè)事件是否發(fā)生:epoll的解決方案不像select或poll一樣每次都把current輪流加入fd對(duì)應(yīng)的設(shè)備等待隊(duì)列中,而只在epoll_ctl時(shí)把current掛一遍(這一遍必不可少)并為每個(gè)fd指定一個(gè)回調(diào)函數(shù),當(dāng)設(shè)備就緒,喚醒等待隊(duì)列上的等待者時(shí),就會(huì)調(diào)用這個(gè)回調(diào)函數(shù),而這個(gè)回調(diào)函數(shù)會(huì)把就緒的fd加入一個(gè)就緒鏈表)。epoll_wait的工作實(shí)際上就是在這個(gè)就緒鏈表中查看有沒(méi)有就緒的fd(利用schedule_timeout()實(shí)現(xiàn)睡一會(huì),判斷一會(huì)的效果)。
4.監(jiān)視描述符沒(méi)有個(gè)數(shù)上限。
epoll沒(méi)有這個(gè)限制,它所支持的FD上限是最大可以打開(kāi)文件的數(shù)目,這個(gè)數(shù)字一般遠(yuǎn)大于2048,注:在1GB內(nèi)存的機(jī)器上大約是10萬(wàn)左右,具體數(shù)目可以cat /proc/sys/fs/file-max察看,一般來(lái)說(shuō)這個(gè)數(shù)目和系統(tǒng)內(nèi)存關(guān)系很大。
5.IO效率不隨FD數(shù)目增加而線性下降。
傳統(tǒng)的select/poll另一個(gè)致命弱點(diǎn)就是當(dāng)你擁有一個(gè)很大的socket集合,不過(guò)由于網(wǎng)絡(luò)延時(shí),任一時(shí)間只有部分的socket是“活躍”的,但是select/poll每次調(diào)用都會(huì)線性掃描全部的集合,導(dǎo)致效率呈現(xiàn)線性下降。但是epoll不存在這個(gè)問(wèn)題,它只會(huì)對(duì)“活躍”的socket進(jìn)行操作—這是因?yàn)樵趦?nèi)核實(shí)現(xiàn)中epoll是根據(jù)每個(gè)fd上面的callback函數(shù)實(shí)現(xiàn)的。只有“活躍”的socket才會(huì)主動(dòng)的去調(diào)用 callback函數(shù),其他idle狀態(tài)socket則不會(huì)。
拓展:系統(tǒng)維護(hù)一顆紅黑樹(shù)(平衡搜索二叉樹(shù):穩(wěn)定)存儲(chǔ)監(jiān)視描述符,和一張鏈表存儲(chǔ)就緒的描述符。當(dāng)每次注冊(cè)或修改,刪除新的文件描述符到epoll句柄中時(shí),就會(huì)增加一個(gè)描述符到這課紅黑樹(shù)中(增刪改查簡(jiǎn)單),當(dāng)返回時(shí)檢測(cè)鏈表上是否有節(jié)點(diǎn),有節(jié)點(diǎn)則拷貝到用戶(hù)傳給它的那個(gè)描述符數(shù)組中。
epoll對(duì)于select和poll相比,顯著優(yōu)點(diǎn)是:
(1)select,poll實(shí)現(xiàn)需要自己不斷輪詢(xún)所有fd集合,直到設(shè)備就緒,期間可能要睡眠和喚醒多次交替。而epoll其實(shí)也需要調(diào)用epoll_wait不斷輪詢(xún)就緒鏈表,期間也可能多次睡眠和喚醒交替,但是它是設(shè)備就緒時(shí),調(diào)用回調(diào)函數(shù),把就緒fd放入就緒鏈表中,并喚醒在epoll_wait中進(jìn)入睡眠的進(jìn)程。雖然都要睡眠和交替,但是select和poll在“醒著”的時(shí)候要遍歷整個(gè)fd集合,而epoll在“醒著”的時(shí)候只要判斷一下就緒鏈表是否為空就行了,這節(jié)省了大量的CPU時(shí)間。這就是回調(diào)機(jī)制帶來(lái)的性能提升。
(2)select,poll每次調(diào)用都要把fd集合從用戶(hù)態(tài)往內(nèi)核態(tài)拷貝一次,并且要把current往設(shè)備等待隊(duì)列中掛一次,而epoll只要一次拷貝,而且把current往等待隊(duì)列上掛也只掛一次(在epoll_wait的開(kāi)始,注意這里的等待隊(duì)列并不是設(shè)備等待隊(duì)列,只是一個(gè)epoll內(nèi)部定義的等待隊(duì)列)。這也能節(jié)省不少的開(kāi)銷(xiāo)。
####5. 總結(jié):
poll和epoll適用于關(guān)心描述符個(gè)數(shù)多的應(yīng)用程序。其中epoll對(duì)于每次只有很少描述符就緒很有優(yōu)勢(shì)(采用回調(diào)機(jī)制監(jiān)測(cè)描述符就緒)。
綜上:epoll是上面三個(gè)函數(shù)中效率最高的。
(5) Epoll的ET模式和LT模式(ET的非阻塞)
LT(level triggered)是缺省的工作方式,并且同時(shí)支持block和no-block socket.在這種做法中,內(nèi)核告訴你一個(gè)文件描述符是否就緒了,然后你可以對(duì)這個(gè)就緒的fd進(jìn)行IO操作。如果你不作任何操作,內(nèi)核還是會(huì)繼續(xù)通知你的,所以,這種模式編程出錯(cuò)誤可能性要小一點(diǎn)。傳統(tǒng)的select/poll都是這種模型的代表.
ET(edge-triggered)是高速工作方式,只支持no-block socket。在這種模式下,當(dāng)描述符從未就緒變?yōu)榫途w時(shí),內(nèi)核通過(guò)epoll告訴你。然后它會(huì)假設(shè)你知道文件描述符已經(jīng)就緒,并且不會(huì)再為那個(gè)文件描述符發(fā)送更多的就緒通知,直到你做了某些操作導(dǎo)致那個(gè)文件描述符不再為就緒狀態(tài)了(比如,你在發(fā)送,接收或者接收請(qǐng)求,或者發(fā)送接收的數(shù)據(jù)少于一定量時(shí)導(dǎo)致了一個(gè)EWOULDBLOCK 錯(cuò)誤)。
(6) 查詢(xún)進(jìn)程占用CPU的命令(注意要了解到used,buf,cache代表意義)
很常見(jiàn)TOP命令,里面的參數(shù)分析如下:
used:已經(jīng)使用物理內(nèi)存的大小
total:總的物理內(nèi)存
free:空閑的物理內(nèi)存
buffers:用于內(nèi)核緩存的內(nèi)存大小
cache:緩沖的交換空間的大小
buffers于cached區(qū)別:buffers指的是塊設(shè)備的讀寫(xiě)緩沖區(qū),cached指的是文件系統(tǒng)本身的頁(yè)面緩存。他們都是Linux系統(tǒng)底層的機(jī)制,為了加速對(duì)磁盤(pán)的訪問(wèn)。
(7) linux的其他常見(jiàn)命令(kill,find,cp等等)
kill命令用來(lái)刪除執(zhí)行中的程序或工作。kill可將指定的信息送至程序
kill 3268
1
find命令用來(lái)在指定目錄下查找文件。任何位于參數(shù)之前的字符串都將被視為欲查找的目錄名。如果使用該命令時(shí),不設(shè)置任何參數(shù),則find命令將在當(dāng)前目錄下查找子目錄與文件。并且將查找到的子目錄和文件全部進(jìn)行顯示。
find /home -name "*.txt"
1
cp命令用來(lái)將一個(gè)或多個(gè)源文件或者目錄復(fù)制到指定的目的文件或目錄。它可以將單個(gè)源文件復(fù)制成一個(gè)指定文件名的具體的文件或一個(gè)已經(jīng)存在的目錄下。cp命令還支持同時(shí)復(fù)制多個(gè)文件,當(dāng)一次復(fù)制多個(gè)文件時(shí),目標(biāo)文件參數(shù)必須是一個(gè)已經(jīng)存在的目錄,否則將出現(xiàn)錯(cuò)誤。
cp file /usr/men/tmp/file1
1
(8) shell腳本用法
Shell是一種腳本語(yǔ)言,那么,就必須有解釋器來(lái)執(zhí)行這些腳本。linux中最常見(jiàn)的解釋器就是bash。
腳本語(yǔ)言是不需要編譯的,是一種解釋型語(yǔ)言,可以直接通過(guò)解釋器解釋運(yùn)行。
(9) 硬連接和軟連接的區(qū)別
硬連接指通過(guò)索引節(jié)點(diǎn)來(lái)進(jìn)行連接。在Linux的文件系統(tǒng)中,保存在磁盤(pán)分區(qū)中的文件不管是什么類(lèi)型都給它分配一個(gè)編號(hào),稱(chēng)為索引節(jié)點(diǎn)號(hào)(Inode Index)。在Linux中,多個(gè)文件名指向同一索引節(jié)點(diǎn)是存在的。比如:A是B的硬鏈接(A和B都是文件名),則A的目錄項(xiàng)中的inode節(jié)點(diǎn)號(hào)與B的目錄項(xiàng)中的inode節(jié)點(diǎn)號(hào)相同,即一個(gè)inode節(jié)點(diǎn)對(duì)應(yīng)兩個(gè)不同的文件名,兩個(gè)文件名指向同一個(gè)文件,A和B對(duì)文件系統(tǒng)來(lái)說(shuō)是完全平等的。刪除其中任何一個(gè)都不會(huì)影響另外一個(gè)的訪問(wèn)。
另外一種連接稱(chēng)之為符號(hào)連接(Symbolic Link),也叫軟連接。軟鏈接文件有類(lèi)似于Windows的快捷方式。它實(shí)際上是一個(gè)特殊的文件。在符號(hào)連接中,文件實(shí)際上是一個(gè)文本文件,其中包含的有另一文件的位置信息。比如:A是B的軟鏈接(A和B都是文件名),A的目錄項(xiàng)中的inode節(jié)點(diǎn)號(hào)與B的目錄項(xiàng)中的inode節(jié)點(diǎn)號(hào)不相同,A和B指向的是兩個(gè)不同的inode,繼而指向兩塊不同的數(shù)據(jù)塊。但是A的數(shù)據(jù)塊中存放的只是B的路徑名(可以根據(jù)這個(gè)找到B的目錄項(xiàng))。A和B之間是“主從”關(guān)系,如果B被刪除了,A仍然存在(因?yàn)閮蓚€(gè)是不同的文件),但指向的是一個(gè)無(wú)效的鏈接。
(10) 文件權(quán)限怎么看(rwx)
r:表示的是讀,4
w:表示的是寫(xiě),2,
x:表示的是執(zhí)行,1
組合:通過(guò)4、2、1的組合,得到以下幾種權(quán)限: 0(沒(méi)有權(quán)限) 4(讀取權(quán)限) 5(4+1 | 讀取+執(zhí)行) 6(4+2 | 讀取+寫(xiě)入) 7(4+2+1 | 讀取+寫(xiě)入+執(zhí)行)
從左至右:
1-3位數(shù)字代表文件所有者的權(quán)限
4-6位數(shù)字代表同組用戶(hù)的權(quán)限
7-9數(shù)字代表其他用戶(hù)的權(quán)限
例如chmod 777 a,
(11) 文件的三種時(shí)間(mtime, atime,ctime),分別在什么時(shí)候會(huì)改變
一個(gè)文件也有三種時(shí)間,分別是:訪問(wèn)時(shí)間atime、修改時(shí)間mtime、狀態(tài)時(shí)間ctime,分別為Access time、Modify time、Change time
訪問(wèn)時(shí)間:對(duì)文件進(jìn)行一次讀操作,它的訪問(wèn)時(shí)間就會(huì)改變。例如像:cat、more等操作,但是像之前的state還有l(wèi)s命令對(duì)atime是不會(huì)有影響的;
修改時(shí)間:文件的內(nèi)容被最后一次修改的時(shí)間,我們經(jīng)常用的ls -l命令顯示出來(lái)的文件時(shí)間就是這個(gè)時(shí)間,當(dāng)用vim對(duì)文件進(jìn)行編輯之后保存,它的mtime就會(huì)相應(yīng)的改變;
狀態(tài)時(shí)間:當(dāng)文件的狀態(tài)被改變的時(shí)候,狀態(tài)時(shí)間就會(huì)隨之改變,例如當(dāng)使用chmod、chown等改變文件屬性的操作是會(huì)改變文件的ctime的。
(12) Linux監(jiān)控網(wǎng)絡(luò)帶寬的命令,查看特定進(jìn)程的占用網(wǎng)絡(luò)資源情況命令
監(jiān)控總體帶寬使用――nload、bmon、slurm、bwm-ng、cbm、speedometer和netload
監(jiān)控總體帶寬使用(批量式輸出)――vnstat、ifstat、dstat和collectl
每個(gè)套接字連接的帶寬使用――iftop、iptraf、tcptrack、pktstat、netwatch和trafshow
每個(gè)進(jìn)程的帶寬使用――nethogs
————————————————
版權(quán)聲明:本文為CSDN博主「祚兒瘋」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u012414189/article/details/83830848
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。