《LINUX教程:快速記住Linux內(nèi)核的基本概念》要點(diǎn):
本文介紹了LINUX教程:快速記住Linux內(nèi)核的基本概念,希望對(duì)您有用。如果有疑問,可以聯(lián)系我們。
打算給我們部門弄個(gè)內(nèi)部分享.發(fā)現(xiàn)大家對(duì)一些底層知識(shí)的認(rèn)知停留在一句一句的,好比聽說JVM使用-XX:-UseBiasedLocking取消偏向鎖可以提高性能,因?yàn)樗贿m用于非多線程高并發(fā)應(yīng)用.使用數(shù)字對(duì)象的緩存-XX:AutoBoxCacheMax=20000比默認(rèn)緩存-128~127要提高性能.對(duì)于JVM和Linux內(nèi)核,操作系統(tǒng)沒有系統(tǒng)的概念,遇到實(shí)際問題往往沒有思路.所以我的內(nèi)部分享,主要分為L(zhǎng)inux部分,jvm部分和redis部分.這篇是Linux篇.學(xué)習(xí)思路為主,知識(shí)為輔.我也是菜鳥一枚~~不過是個(gè)鉆石心的菜鳥,不怕別人知道我有多菜.
先說為什么我要去學(xué)習(xí)Linux內(nèi)核.我在上家公司負(fù)責(zé)整個(gè)公司的搜索引擎.有一次很純熟的在一臺(tái)虛擬機(jī)上新搭建了一套,壓測(cè)到8000,額,報(bào)了一個(gè)NIO異常,說是:too many open files.當(dāng)時(shí)查了一下,那臺(tái)機(jī)器太破,和很多服務(wù)公用,內(nèi)存快滿了.所以換了臺(tái)好點(diǎn)的機(jī)器就沒有這個(gè)問題了.但是句柄超限到底是個(gè)什么東西呢?先來(lái)看看Linux內(nèi)核的一些基本概念.
大局觀嘛,先來(lái)看看unix的體系布局.
簡(jiǎn)單解釋一下:任何計(jì)算機(jī)系統(tǒng)都包括一個(gè)基本的程序集合,它控制計(jì)算機(jī)硬件資源,提供程序運(yùn)行環(huán)境.稱為操作系統(tǒng).在這個(gè)集合里,最重要的程序被稱為內(nèi)核,在系統(tǒng)啟動(dòng)時(shí)被裝載.因?yàn)樗鄬?duì)較小,而且位于環(huán)境的核心.內(nèi)核的接口被稱為系統(tǒng)調(diào)用(system call).公用函數(shù)庫(kù)構(gòu)建在系統(tǒng)調(diào)用接口之上,也可使用系統(tǒng)調(diào)用.shell是一個(gè)特殊的應(yīng)用程序,為運(yùn)行其他應(yīng)用程序提供一個(gè)接口.
一些操作系統(tǒng)允許所有的用戶程序直接與硬件部分進(jìn)行交互,如MS-DOS.但是類Unix操作系統(tǒng)在胡勇應(yīng)用程序前把與計(jì)算機(jī)物理組織相關(guān)的所有底層細(xì)節(jié)隱藏了.當(dāng)程序想使用硬件資源時(shí),必須向操作系統(tǒng)發(fā)出一個(gè)哀求,內(nèi)核對(duì)這個(gè)哀求進(jìn)行評(píng)估,如果允許使用這個(gè)資源,內(nèi)核代表應(yīng)用程序與相關(guān)的硬件部分進(jìn)行交互.為了實(shí)施這種機(jī)制,現(xiàn)代操作系統(tǒng)依靠特殊的硬件特性來(lái)禁止用戶程序直接與底層硬件部分打交道,或者直接訪問任意的物理地址.硬件為CPU引入了至少兩種不同的執(zhí)行模式:用戶程序的非特權(quán)模式和內(nèi)核的特權(quán)模式.Unix把他們分別稱為用戶態(tài)(User Mode)和內(nèi)核態(tài)(Kernel Model).
我們平時(shí)敲的一些Linux命令,實(shí)際上都是對(duì)應(yīng)的內(nèi)核的C語(yǔ)言函數(shù).比如cat xxx | grep 'x'.這里面兩個(gè)命令用|連接起來(lái),這個(gè)叫做“管道”.先用男孩紙慣用的職業(yè)一點(diǎn)的語(yǔ)言介紹一下:管道是一個(gè)廣泛應(yīng)用的進(jìn)程間通信手段.其作用是在具有親緣關(guān)系的進(jìn)程之間傳遞消息,所謂有親緣關(guān)系,是指有同一個(gè)祖先.可以是父子,兄弟或者祖孫等等.反正只要共同的祖先調(diào)用了pipe函數(shù),打開的管道文件會(huì)在fork之后,被各個(gè)后代所共享.其本色是內(nèi)核維護(hù)了一塊緩沖區(qū)與管道文件相關(guān)聯(lián),對(duì)管道文件的操作,被內(nèi)核轉(zhuǎn)換成對(duì)這塊緩沖區(qū)內(nèi)存的操作.分為匿名管道和命名管道.
這里面包括了一些概念.進(jìn)程的概念大家都應(yīng)該很清楚:程序的執(zhí)行實(shí)例被稱為進(jìn)程.UNIX系統(tǒng)確保每個(gè)進(jìn)程都有一個(gè)唯一的數(shù)字表示符,稱為進(jìn)程ID(process ID),它是一個(gè)非負(fù)數(shù).Linux很多命令都會(huì)將其顯示出來(lái).有3個(gè)用于進(jìn)程控制的主要函數(shù):fork,exec和waitpid.其中fork函數(shù)用來(lái)創(chuàng)建一個(gè)新進(jìn)程,此進(jìn)程是調(diào)用進(jìn)程的一個(gè)副本,稱為子進(jìn)程.fork對(duì)父進(jìn)程返回新的子進(jìn)程的進(jìn)程ID(一個(gè)非負(fù)整數(shù)),對(duì)子進(jìn)程則返回0.因?yàn)閒ork創(chuàng)建一個(gè)新進(jìn)程,所以說它被調(diào)用一次,但返回兩次.
一個(gè)進(jìn)程內(nèi)的所有線程共享同一地址空間,文件描述符,棧以及進(jìn)程相關(guān)的屬性.因?yàn)樗鼈兡馨菰L同一存儲(chǔ)區(qū),所以各線程在拜訪共享數(shù)據(jù)時(shí)需要采取同步措施以避免不一致性.說到這里大家都應(yīng)該多少有些概念了:為什么進(jìn)程開銷大,線程涉及鎖.
匿名管道是一個(gè)未命名的,單向管道,通過父進(jìn)程和一個(gè)子進(jìn)程之間傳輸數(shù)據(jù).只能實(shí)現(xiàn)當(dāng)?shù)貦C(jī)器上兩個(gè)進(jìn)程之間的通信,而不能實(shí)現(xiàn)跨網(wǎng)絡(luò)的通信.常用的比如Linux命令.
定名管道是進(jìn)程間單向或雙向管道,建立時(shí)指定一個(gè)名字,任何進(jìn)程都可以通過該名字打開管道的另一端,可跨網(wǎng)絡(luò)通信.
這是一個(gè)jvisualvm調(diào)試的截圖,藍(lán)框部門就相當(dāng)于一個(gè)命名管道.
好,現(xiàn)在來(lái)答復(fù)一個(gè)問題:用戶進(jìn)程間通信主要哪幾種方式?
剛才說的匿名管道和命名管道都算一種.除此之外,還有:信號(hào),消息隊(duì)列,共享內(nèi)存,信號(hào)量和套接字.不消頭疼,看到最后你很可能會(huì)有豁然開朗的感覺,學(xué)的東西終于可以串在一起了.
信號(hào)(signal):其實(shí)是軟中斷信號(hào)的簡(jiǎn)稱.用來(lái)通知進(jìn)程發(fā)生了異步事件.在軟件層次上是對(duì)中斷機(jī)制的一種模擬,在原理上,一個(gè)進(jìn)程收到一個(gè)信號(hào)與處理器收到一個(gè)中斷哀求是一樣的.信號(hào)是進(jìn)程間通信機(jī)制中唯一的異步通信機(jī)制,一個(gè)進(jìn)程不必通過任何操作來(lái)等待信號(hào)的到達(dá).
收到信號(hào)的進(jìn)程對(duì)各種信號(hào)有不同的處理辦法,主要是三類:
1>類似中斷的處理程序,對(duì)于必要處理的信號(hào),進(jìn)程可以指定處理函數(shù),由該函數(shù)來(lái)處理.
2>忽略某個(gè)信號(hào),對(duì)該信號(hào)不做任何處置.
3>對(duì)該信號(hào)的處理保存系統(tǒng)的默認(rèn)值,這種缺省操作,對(duì)大部分的信號(hào)的缺省操作是讓進(jìn)程終止.進(jìn)程通過系統(tǒng)調(diào)用signal來(lái)指定進(jìn)程對(duì)某個(gè)信號(hào)的處理行為.
下面是window的旌旗燈號(hào)列表
Linux也是用kill -l敕令:
1) SIGHUP? ? ? 2) SIGINT? ? ? 3) SIGQUIT? ? ? 4) SIGILL
?5) SIGTRAP? ? ? 6) SIGABRT? ? ? 7) SIGBUS? ? ? 8) SIGFPE
?9) SIGKILL? ? 10) SIGUSR1? ? 11) SIGSEGV? ? 12) SIGUSR2
13) SIGPIPE? ? 14) SIGALRM? ? 15) SIGTERM? ? 17) SIGCHLD
18) SIGCONT? ? 19) SIGSTOP? ? 20) SIGTSTP? ? 21) SIGTTIN
22) SIGTTOU? ? 23) SIGURG? ? ? 24) SIGXCPU? ? 25) SIGXFSZ
26) SIGVTALRM? 27) SIGPROF? ? 28) SIGWINCH? ? 29) SIGIO
30) SIGPWR? ? ? 31) SIGSYS? ? ? 34) SIGRTMIN? ? 35) SIGRTMIN+1
36) SIGRTMIN+2? 37) SIGRTMIN+3? 38) SIGRTMIN+4? 39) SIGRTMIN+5
40) SIGRTMIN+6? 41) SIGRTMIN+7? 42) SIGRTMIN+8? 43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8? 57) SIGRTMAX-7? 58) SIGRTMAX-6? 59) SIGRTMAX-5
60) SIGRTMAX-4? 61) SIGRTMAX-3? 62) SIGRTMAX-2? 63) SIGRTMAX-1
64) SIGRTMAX
我在用gdb命令運(yùn)行調(diào)試C語(yǔ)言程序的時(shí)候常常可以看到這些信號(hào)量.
再來(lái)看消息隊(duì)列.消息隊(duì)列提供了一種從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送一個(gè)數(shù)據(jù)塊的辦法.每個(gè)數(shù)據(jù)塊都被認(rèn)為含有一個(gè)類型,接收進(jìn)程可以獨(dú)立的接收含有不同類型的數(shù)據(jù)結(jié)構(gòu).可以通過發(fā)送消息來(lái)避免命名管道的同步和阻塞問題.但是消息隊(duì)列和命名管道一樣,每個(gè)數(shù)據(jù)塊都有一個(gè)最大長(zhǎng)度的限制.
共享內(nèi)存就是允許兩個(gè)不相關(guān)的進(jìn)程訪問同一個(gè)邏輯內(nèi)存.共享內(nèi)存是在兩個(gè)正在運(yùn)行的進(jìn)程之間共享和傳遞數(shù)據(jù)的一種非常有效的方式.不同進(jìn)程之間共享的內(nèi)存通常支配為同一段物理內(nèi)存.進(jìn)程可以將同一段共享內(nèi)存連接到他們自己的地址空間中,所有進(jìn)程都可以訪問共享內(nèi)存中的地址.
信號(hào)量:為了防止出現(xiàn)因多個(gè)程序同時(shí)拜訪一個(gè)共享資源而引發(fā)的一系列問題,我們需要一種方法,它可以通過生成并使用令牌來(lái)授權(quán),在任一時(shí)刻只能有一個(gè)執(zhí)行線程拜訪代碼的臨界區(qū)域.臨界區(qū)域是指執(zhí)行數(shù)據(jù)更新的代碼需要獨(dú)占式的執(zhí)行.而信號(hào)量就可以提供這樣的一種拜訪機(jī)制.讓一個(gè)臨界區(qū)同一時(shí)間只有一個(gè)線程在拜訪它,也就是說信號(hào)量是用來(lái)協(xié)調(diào)對(duì)共享資源拜訪的.
套接字:這種通信機(jī)制使得客戶端/服務(wù)器的開發(fā)工作既可以在當(dāng)?shù)貑螜C(jī)上進(jìn)行,也可以跨網(wǎng)絡(luò)進(jìn)行.它的特性有三個(gè)屬性確定:域(domain),類型(type)和協(xié)議(protocol).簡(jiǎn)單的說:源IP地址和目的IP地址以及源端口號(hào)和目的端口號(hào)的組合成為套接字.
下面介紹一下通信過程,里面涉及一些C語(yǔ)言的函數(shù),不消怕,眼熟即可.如果你學(xué)習(xí)過nio,你會(huì)發(fā)現(xiàn)這些是很常接觸的.
要想使不同主機(jī)的進(jìn)程通信,就必需使用套接字,套接字是用socket()函數(shù)創(chuàng)建,如果需要C/S模式,則需要把server的套接字與地址和端口綁定起來(lái),使用bind(),當(dāng)上述操作完成后,便可使用listen()來(lái)監(jiān)聽這個(gè)端口,如果有其他程序來(lái)connect,那么server將會(huì)調(diào)用accept()來(lái)接受這個(gè)申請(qǐng)并為其服務(wù).client是調(diào)用connect()來(lái)建立與server之間的連接,這時(shí)會(huì)使用三次握手來(lái)建立一條數(shù)據(jù)鏈接.當(dāng)連接被建立后,server與client便可以通信了,通信可以使用read()/write(),send()/recv(),sendto()/recvfrom()等函數(shù)來(lái)實(shí)現(xiàn),但是不同的函數(shù)作用和使用位置是不同的.當(dāng)數(shù)據(jù)傳送完后,可以調(diào)用close()來(lái)關(guān)閉server與client之間的鏈接.
到此,本篇文章的主要內(nèi)容就沒有了,基本就在介紹一個(gè)東西:linux內(nèi)核的進(jìn)程通信.這是學(xué)習(xí)任何高級(jí)編程語(yǔ)言nio部門的基礎(chǔ).下面引入一些輔助理解的概念.
文件句柄:在文件I/O中,要從一個(gè)文件讀取數(shù)據(jù),應(yīng)用程序首先要調(diào)用操作系統(tǒng)函數(shù)并傳送文件名,并選一個(gè)到該文件的路徑來(lái)打開文件.該函數(shù)取回一個(gè)順序號(hào),即文件句柄(file handle),該文件句柄對(duì)于打開的文件是唯一的識(shí)別依據(jù).一個(gè)句柄就是你給一個(gè)文件,設(shè)備,套接字(socket)或者管道的一個(gè)名字,以便幫助你記住你證處理的名字,并暗藏某些緩存等的復(fù)雜性.說白了就是文件指針啦.
文件描述符:內(nèi)核利用文件描述符來(lái)拜訪文件.打開現(xiàn)存文件或新建文件時(shí),內(nèi)核會(huì)返回一個(gè)文件描述符.讀寫文件也需要使用文件描???符來(lái)指定待讀寫的文件.文件描述符形式上是非負(fù)整數(shù),實(shí)際上它是一個(gè)索引值,指向內(nèi)核為每一個(gè)進(jìn)程所維護(hù)的該進(jìn)程打開文件的記錄表.當(dāng)程序打開一個(gè)現(xiàn)有文件或者創(chuàng)建一個(gè)新文件時(shí),內(nèi)核向進(jìn)程返回一個(gè)文件描述符.在程序設(shè)計(jì)中,一些涉及底層的程序編寫往往會(huì)圍繞著文件描述符展開.但是文件描述符往往值適用于unix,linux這樣的操作系統(tǒng).習(xí)慣上,標(biāo)準(zhǔn)輸入的文件描述符是0,標(biāo)準(zhǔn)輸出是1,標(biāo)準(zhǔn)錯(cuò)誤是2.
`/letv/apps/jdk/bin/java -DappPort=4 $JAVA_OPTS -cp $PHOME/conf:$PHOME/lib/* com.letv.mms.transmission.http.VideoFullServerBootstrap $1 $3 > /dev/null 2>&1 &`
本身部署過java后臺(tái)程序的話,對(duì)上面的shell命令應(yīng)該都能理解. /dev/null 2>&1 這里面的2就是文件描述符,這個(gè)是將錯(cuò)誤輸出到文件.
這兩個(gè)概念比較繞,不用過多區(qū)分,可以當(dāng)成一回事來(lái)理解.打開文件(open files)包含文件句柄但不僅限于文件句柄,由于lnux所有的事務(wù)都以文件的形式存在,要使用諸如共享內(nèi)存,信號(hào)量,消息隊(duì)列,內(nèi)存映射等都會(huì)打開文件,但這些不會(huì)占用文件句柄.查看進(jìn)程允許打開的最大文件句柄數(shù)的linux命令:ulimit -n
好了,本日的概念都介紹完了,回到最初的問題:too many open files. 當(dāng)時(shí)的機(jī)器破,內(nèi)存快滿了.所以搜索引擎走的是索引文件,有很多的IO操作,共享內(nèi)存和內(nèi)存映射這塊的文件肯定是供不上的,報(bào)錯(cuò)了.縈繞在心頭兩年的問題稍微有點(diǎn)認(rèn)知了.
本文永遠(yuǎn)更新鏈接地址:
歡迎參與《LINUX教程:快速記住Linux內(nèi)核的基本概念》討論,分享您的想法,維易PHP學(xué)院為您提供專業(yè)教程。
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.snjht.com/jiaocheng/9034.html