• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-5  評論-33  文章-0  trackbacks-0

             

                《Linux內(nèi)核情景分析》這本書讀過了一遍,不想繼續(xù)讀第二遍了.
                《Linux Kernel Development》這本書前后讀了3遍,寫得實(shí)在是好,正所謂"布衣暖,菜根香,好書滋味長".
            去書城買來,飽讀之后置于書架之上,扮作有學(xué)問之人:) 本想買英文影印版,未能尋到,就買本中文的湊合著看,
            看完之后發(fā)現(xiàn)有幾處明顯的翻譯錯(cuò)誤(好在有英文CHM作為對照).技術(shù)類書籍一直都是讀的英文CHM或PDF,這一本是例外.
                《Understanding the Linux Kernel》這本巨作正在拜讀之中,這次不再去買中文版了,還是直接讀英文原版比較好.             
                下面是在閱讀《Linux Kernel Development》的過程中自認(rèn)為值得記錄的部分,五筆輸入的過程中選詞時(shí)可能會有輸入錯(cuò)誤,敬請指正!            

                    -------------------------------------------- 華麗的分割線 -----------------------------------------------------
             
            chapter 1
            1.當(dāng)應(yīng)用程序向內(nèi)核請求調(diào)用一個(gè)系統(tǒng)調(diào)用時(shí),我們說內(nèi)核正在代其執(zhí)行,如果進(jìn)一步解釋,在這種情況下,應(yīng)用程序被稱為通過系統(tǒng)調(diào)用在內(nèi)核空間運(yùn)行;而內(nèi)核則被稱為運(yùn)行在進(jìn)程上下文中.
            2.硬件與內(nèi)核的交互:當(dāng)硬件設(shè)備想和系統(tǒng)進(jìn)行交互時(shí),它首先要向CPU發(fā)送一個(gè)異步的中斷信號,然后由CPU去打斷內(nèi)核當(dāng)前正在執(zhí)行的工作,中斷通常對應(yīng)著一個(gè)中斷號,內(nèi)核通過這個(gè)中斷號來查找對應(yīng)的中斷處理程序,并調(diào)用這個(gè)找到的中斷處理程序來處理中斷.為了保證同步,內(nèi)核可以停用中斷,也就是忽略某個(gè)中斷,既可以停止所有的中斷處理程序,也可以有選擇性地停止某些中斷處理程序。許多操作系統(tǒng)的中斷處理程序都不在進(jìn)程上下文中,而是在一個(gè)單獨(dú)的與所有的進(jìn)程都無關(guān)的中斷上下文中執(zhí)行,這樣做是為了保證中斷處理程序在第一時(shí)間響應(yīng)和處理中斷信號,并快速退出.
            3.任一時(shí)刻,CPU的活動范圍為以下三者之一:
             a.運(yùn)行于內(nèi)核空間,處理進(jìn)程上下文,代表某個(gè)特定的進(jìn)程執(zhí)行.
             b.運(yùn)行于內(nèi)核空間,處理中斷上下文,與任何進(jìn)程無關(guān),處理某個(gè)特定的中斷信號.
             c.運(yùn)行于用戶空間,執(zhí)行用戶程序.
            4.單內(nèi)核與多內(nèi)核:操作系統(tǒng)的內(nèi)核設(shè)計(jì)分為兩大陣營:單內(nèi)核和微內(nèi)核(以及在科研中的外內(nèi)核)
             單內(nèi)核:就是把內(nèi)核在整體上做為一個(gè)單獨(dú)的大過程來實(shí)現(xiàn),并同時(shí)運(yùn)行在一個(gè)單獨(dú)的地址空間中。因此這樣的內(nèi)核通常以單個(gè)靜態(tài)的二進(jìn)制文件的形式存儲于磁盤,所有內(nèi)核服務(wù)都在這樣一個(gè)大的內(nèi)核空間中運(yùn)行,內(nèi)核之間的通信是微不足道的,因?yàn)榇蠹叶歼\(yùn)行在內(nèi)核態(tài),并處于同一地址空間,內(nèi)核可以直接調(diào)用函數(shù)(其它的內(nèi)核服務(wù)中的功能函數(shù)),這與用戶空間沒有什么區(qū)別,這種模式的好處在于:簡單和高性能。
            大部分的UNIX和Linux是單內(nèi)核系統(tǒng).Linux同時(shí)也吸收了微內(nèi)核的優(yōu)點(diǎn):內(nèi)核模塊化設(shè)計(jì),搶占式內(nèi)核,支持內(nèi)核線程,以及動態(tài)內(nèi)核模塊加載和卸載.
             微內(nèi)核:微內(nèi)核并不將內(nèi)核作為一個(gè)單獨(dú)的大過程來實(shí)現(xiàn),相反,微內(nèi)核的功能被劃分為獨(dú)立的過程,每個(gè)過程叫做一個(gè)服務(wù)。理想情況下,只有強(qiáng)烈請求特權(quán)服務(wù)的服務(wù)器運(yùn)行在特權(quán)模式下,其它的服務(wù)都運(yùn)行在用戶空間.不過所有的服務(wù)都保持獨(dú)立并運(yùn)行在各自的地址空間,因此就不能像單內(nèi)核那樣直接調(diào)用函數(shù),而是通過消息傳遞處理微內(nèi)核服務(wù)之間的通信:系統(tǒng)采用進(jìn)程間通信(IPC)機(jī)制,各種服務(wù)器之間通過IPC機(jī)制互通消息,互換服務(wù).服務(wù)器的各自獨(dú)立有效地避免了一個(gè)服務(wù)器的失效禍及另一個(gè).Windows和Max OS X 都是微內(nèi)核.Windows NT內(nèi)核和Mac OS 的內(nèi)核都將所有的內(nèi)核服務(wù)程序運(yùn)行于內(nèi)核特權(quán)模式下,這一點(diǎn)違背了微內(nèi)核的設(shè)計(jì)思想,但是減少了內(nèi)核服務(wù)之間的通信之間的消息機(jī)制產(chǎn)生的開銷.
            5.Linux內(nèi)核并不區(qū)分進(jìn)程和線程,對于內(nèi)核來說,只有進(jìn)程,而且所有的進(jìn)程都一樣,只不過是有的進(jìn)程共享一些資源而已.
            6.Linux內(nèi)核的版本號:x.y.z
             x:是主版本號;y:從版本號;z:修訂版本號
             z:如果為偶數(shù),那么它是一個(gè)穩(wěn)定的版本;如果為奇數(shù),那么它是一個(gè)開發(fā)版.
             x.y 用于描述內(nèi)核系列.


            chapter 2
            7.內(nèi)核源碼文件結(jié)構(gòu):
             arch:    特定體系結(jié)構(gòu)的源碼
             crypto:   Crypto API
             Documentation: 內(nèi)核源碼文檔
             drivers:  設(shè)備驅(qū)動程序
             fs:    VFS和各種文件系統(tǒng)
             include:   內(nèi)核頭文件
             init:   內(nèi)核引導(dǎo)和初始化
             ipc:   進(jìn)程間通信代碼
             kernel:   內(nèi)核核心子系統(tǒng)
             lib:   通用內(nèi)核函數(shù)
             mm:    內(nèi)存管理子系統(tǒng)和VM
             net:   網(wǎng)絡(luò)子系統(tǒng)
             scripts:   編譯內(nèi)核所用的腳本
             secrity:  Linux安全模塊
             sound:   語音子系統(tǒng)
             usr:   早期用戶空間代碼(所謂的initramfs)

            8.內(nèi)核中的內(nèi)核空間都不分頁,所以,如果內(nèi)核空間使用了一個(gè)字節(jié)的內(nèi)存,那么實(shí)際的可用的物理內(nèi)存就少了一個(gè)字節(jié)。
            9.在內(nèi)核中沒有內(nèi)存保護(hù)機(jī)制.
            10.不要輕易在內(nèi)核中使用浮點(diǎn)數(shù).在用戶空間進(jìn)行浮點(diǎn)數(shù)操作時(shí),內(nèi)核會完成從整數(shù)操作到浮點(diǎn)數(shù)操作的模式轉(zhuǎn)換,在執(zhí)行浮點(diǎn)數(shù)操作時(shí)到底會做些什么,因體系結(jié)構(gòu)的不同,內(nèi)核的選擇也會不同,但是內(nèi)核通常捕獲陷阱并做相應(yīng)的處理.和用戶空間進(jìn)程不同,內(nèi)核并不能完美支持浮點(diǎn)操作,因?yàn)樗旧聿荒芟萑?在內(nèi)核使用浮點(diǎn)數(shù)時(shí),除了要人工保存和恢復(fù)浮點(diǎn)計(jì)數(shù)器,還有其它的一些瑣碎的事情要做.所以:不要在內(nèi)核中使用浮點(diǎn)數(shù).
            11.內(nèi)核開發(fā)中,不能使用內(nèi)核源代碼之外的其它的外部庫文件.
            12.內(nèi)核中沒有printf函數(shù),但是有printk函數(shù)可以用于打印調(diào)試信息.
            13.內(nèi)核的棧空間很小:內(nèi)核棧的準(zhǔn)確大小隨體系結(jié)構(gòu)而變.在X86系統(tǒng)中,棧的大小可以在編譯時(shí)配置,可以是4KB,也可以是8KB.從歷史上說,內(nèi)核棧的大小是兩頁,這也就意味著,在32位系統(tǒng)上內(nèi)核棧是8K,在64位系統(tǒng)上,內(nèi)核棧是16K,這是固定不變的,每個(gè)處理器都有自己的棧.
            14.硬件中斷是異步到來的,由CPU發(fā)送給內(nèi)核,完全不顧及內(nèi)核當(dāng)前的操作.
            15.Linux內(nèi)核中常用的用于解決并發(fā)產(chǎn)生的競爭的辦法是:自旋鎖和信號量.

            chapter 3
            15.進(jìn)程:就是包含各種資源的處于執(zhí)行期的程序.
            16.線程:進(jìn)程中的活動對象.每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器,進(jìn)程棧和一組進(jìn)程寄存器.
            17.內(nèi)核調(diào)度的是線程而不是進(jìn)程.
            18.Linux中,進(jìn)程與線程并不特別進(jìn)行區(qū)分,對于內(nèi)核而言,線程只不過是一種特殊的進(jìn)程而已.
            19.進(jìn)程的5種狀態(tài):
             a. TASK_RUNNING(運(yùn)行狀態(tài))--進(jìn)程是可以執(zhí)行的,它或者正在執(zhí)行,或者在運(yùn)行隊(duì)列中等待執(zhí)行,這是進(jìn)程在用戶空間中執(zhí)行的唯一狀態(tài),也可以應(yīng)用到內(nèi)核空間中正在執(zhí)行的進(jìn)程.
             b. TASK_INTERRUPTIBLE(可中斷)--進(jìn)程正在睡眠(也就是說它被阻塞),等待某些條件的達(dá)成.一旦這些條件達(dá)成,內(nèi)核就會把進(jìn)程設(shè)置為運(yùn)行,處于此狀態(tài)的進(jìn)程也會因?yàn)槭盏叫盘柖崆氨粏拘讯度脒\(yùn)行.
             c. TASK_UNINTERRUPTIBLE(不可中斷)--除了不會因?yàn)榻邮盏叫盘柖粏拘讯度脒\(yùn)行之外,這個(gè)狀態(tài)與TASK_INTERRUPTIBLE(可中斷)狀態(tài)相同.這個(gè)狀態(tài)通常在進(jìn)程正在等待地不受干擾或等待事件很快就會發(fā)生時(shí),由于此狀態(tài)不對信號進(jìn)行響應(yīng),所以,較之TASK_INTERRUPTIBLE(可中斷)使用得比較少.
             d. TASK_ZOMBIE(僵死)--該進(jìn)程已經(jīng)結(jié)束,但是父進(jìn)程還沒有調(diào)用wait4()系統(tǒng)調(diào)用,為了父進(jìn)程能夠獲知它的消息,子進(jìn)程的進(jìn)程描述符仍然被保留著。一旦父進(jìn)程調(diào)用了wait4,該僵死的子進(jìn)程的進(jìn)程描述符就會被釋放.
             e. TASK_STOPPED(停止)--進(jìn)程停止執(zhí)行:進(jìn)程沒有投入運(yùn)行,也不能投入運(yùn)行.通常這種狀態(tài)發(fā)生在接收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU等信號的時(shí)候,此外,在調(diào)試期間接收到的任何信號,都會使進(jìn)程進(jìn)入這種狀態(tài).
            20.UNIX創(chuàng)建進(jìn)程的方式:
             許多其它的操作系統(tǒng)都提供了spawn進(jìn)程的機(jī)制:先在新的地址空間里創(chuàng)建進(jìn)程,讀入可執(zhí)行文件,最后開始執(zhí)行.
             UNIX采用了與眾不同的機(jī)制:把上述步驟分解到兩個(gè)單獨(dú)的函數(shù)中去執(zhí)行(fork和exec)。首先fork通過拷貝當(dāng)前的進(jìn)程創(chuàng)建一個(gè)子進(jìn)程。子進(jìn)程與父進(jìn)程的區(qū)別僅僅在于PID,PPID和某些資源以及統(tǒng)計(jì)量;exec函數(shù)負(fù)責(zé)讀入可執(zhí)行文件并加載到新創(chuàng)建的子進(jìn)程的地址空間并開始運(yùn)行.
            21.Linux的fork系統(tǒng)調(diào)用采用寫時(shí)拷貝(copy-on-write)機(jī)制.寫時(shí)拷貝是一種推遲甚至是免除數(shù)據(jù)拷貝的技術(shù).內(nèi)核并不是復(fù)制整個(gè)進(jìn)程地址空間,而是讓父進(jìn)程和子進(jìn)程以只讀的方式共用一個(gè)拷貝。只在在需要寫入的時(shí)候,數(shù)據(jù)才會被復(fù)制,從而使各個(gè)進(jìn)程擁有各自的拷貝.
            22.fork系統(tǒng)調(diào)用是通過clone系統(tǒng)調(diào)用來實(shí)現(xiàn)的.
            23.fork系統(tǒng)調(diào)用后,系統(tǒng)有意讓子進(jìn)程先執(zhí)行。因?yàn)橐话阕舆M(jìn)程會馬上調(diào)用exec函數(shù),這樣可以避免寫時(shí)拷貝的額外開銷,如果父進(jìn)程先執(zhí)行,有可能會開始向地址空間寫入.
            24.vfork:vfork系統(tǒng)調(diào)用和fork系統(tǒng)調(diào)用的功能類似,除了不拷貝父進(jìn)程的頁表項(xiàng),子進(jìn)程作為父進(jìn)程的一個(gè)單獨(dú)的線程執(zhí)行,父進(jìn)程被阻塞,直到子進(jìn)程退出運(yùn)行,子進(jìn)程不能向地址空間中寫入。
            25.concurrent與parallelism的區(qū)別:
             concurrent是并發(fā),如果在單核的系統(tǒng)上,并不是同時(shí)多個(gè)任何同時(shí)運(yùn)行,只有在多核的系統(tǒng)上,才可能有多個(gè)進(jìn)程同時(shí)并行運(yùn)行,這才是真正意義上的并發(fā),也就是并行.
             parallelism是并行,只針對于多核系統(tǒng)而言,指在任意一個(gè)時(shí)刻,系統(tǒng)上有多個(gè)的任務(wù)在不同的CPU上同時(shí)運(yùn)行.
            26.Linux把所有的線程都當(dāng)作是進(jìn)程來處理.線程僅被視作一個(gè)與其它的進(jìn)程共享一些資源的進(jìn)程
            27.Windows和Sun Solaris則是從內(nèi)核的角度來支持線程.
            28.內(nèi)核線程:獨(dú)立運(yùn)行于內(nèi)核空間的標(biāo)準(zhǔn)進(jìn)程,用于執(zhí)行一些后臺操作.內(nèi)核線程與用戶線程的區(qū)別在于,它們沒有獨(dú)立的地址空間,它們只運(yùn)行于內(nèi)核空間,從來不會切換到用戶空間去運(yùn)行.內(nèi)核線程也可以被調(diào)度和搶占.
            29.孤兒進(jìn)程的處理:在當(dāng)前進(jìn)程的進(jìn)程組內(nèi)找一個(gè)進(jìn)程作為父進(jìn)程,如果不行,那么就讓init做為它們的父進(jìn)程.

            chapter 4
            30.調(diào)度程序:可以看作是在可運(yùn)行態(tài)的進(jìn)程之間分配有限的處理器時(shí)間的內(nèi)核子系統(tǒng).
            31.多任務(wù)系統(tǒng)分為:非搶占式和搶占式多任務(wù)系統(tǒng).
            32.搶占式多任務(wù):由調(diào)度程序來決定什么時(shí)候停止一個(gè)正在運(yùn)行的進(jìn)程而使得其它的進(jìn)程有可執(zhí)行的機(jī)會.
            33.進(jìn)程時(shí)間片:分配給每個(gè)可運(yùn)行進(jìn)程的處理器時(shí)間段.
            34.非搶占式多任務(wù):除非進(jìn)程自已退出運(yùn)行,否則它會一直點(diǎn)用處理器.
            35.進(jìn)程分為:處理器消息耗型和I/O消耗型.
            36.優(yōu)先級高的進(jìn)程所獲得的時(shí)間片也更長,調(diào)度程序總是調(diào)度時(shí)間片未用盡而優(yōu)先級又最高的進(jìn)程運(yùn)行.
            37.調(diào)度程序會提高I/O消耗進(jìn)程的優(yōu)先級,降低處理器消耗進(jìn)程的優(yōu)先級.
            38.Linux內(nèi)核提供兩組獨(dú)立的優(yōu)先級范圍:
             a. nice值,從-20到19,nice級越大,優(yōu)先級越低.
             b. 實(shí)時(shí)優(yōu)先級,其值是可以配置的,默認(rèn)情況下是從0到99,任何實(shí)時(shí)進(jìn)程的優(yōu)先級都高于普通進(jìn)程.
            39.進(jìn)程時(shí)間片:它是一個(gè)整數(shù)值,表示進(jìn)程在被搶占之前可以連續(xù)運(yùn)行的最長的時(shí)間.進(jìn)程的時(shí)間片不需要一次性用盡,可以分多次用完,這樣,一個(gè)進(jìn)程可以被調(diào)度運(yùn)行多次,這對于I/O消耗類型的進(jìn)程非常有利
            40.當(dāng)一個(gè)進(jìn)程的時(shí)間片耗盡時(shí),就認(rèn)為進(jìn)程到期了。沒有時(shí)間處的進(jìn)程不會再次被調(diào)度運(yùn)行,要等到其它的所有的進(jìn)程都耗盡了它們的時(shí)間片,也就是說剩余的時(shí)間片為0,在那個(gè)時(shí)間,所有的進(jìn)程的時(shí)間片會被重新計(jì)算.
            50.每個(gè)處理器都有一個(gè)任務(wù)隊(duì)列,這個(gè)任務(wù)隊(duì)列里面有一個(gè)“可運(yùn)行進(jìn)程優(yōu)先隊(duì)列”和一個(gè)“已過期進(jìn)程優(yōu)先級隊(duì)列”,當(dāng)一個(gè)進(jìn)程的時(shí)間片耗盡時(shí),它會被從“可運(yùn)行隊(duì)列”移動到“已過期隊(duì)列”,在移動在過期隊(duì)列之前,它的新的時(shí)間片會被重新計(jì)算好。當(dāng)“可運(yùn)行隊(duì)列”為空,也即是當(dāng)前的CPU上的可執(zhí)行的進(jìn)程的時(shí)間片都已經(jīng)耗盡時(shí),這個(gè)時(shí)候會交換“可運(yùn)行隊(duì)列”和“過期隊(duì)列”,這樣“過期隊(duì)列”中的所有的“已重新計(jì)算好時(shí)間片”的進(jìn)程已可以重新投入運(yùn)行,這就是Linux內(nèi)核中O(1)調(diào)度程序的核心.
            51.每一個(gè)CPU都有一個(gè)對應(yīng)的schedule調(diào)度函數(shù),用于決定當(dāng)前的CPU上下一個(gè)可以執(zhí)行的進(jìn)程.
            52.對于內(nèi)核而言,如果一個(gè)進(jìn)程的睡眠時(shí)間比運(yùn)行時(shí)間長,那么這個(gè)進(jìn)程是I/O消耗型的;如果一個(gè)進(jìn)程的運(yùn)行時(shí)間比睡眠時(shí)間長,那么這個(gè)進(jìn)程是處理器消耗型的.
            53.當(dāng)一個(gè)新的子進(jìn)程創(chuàng)建時(shí),子進(jìn)程會和父進(jìn)程均分剩余的時(shí)間片,這樣就可以避免用戶通過不停地創(chuàng)建子進(jìn)程來不停地攫取時(shí)間片.
            54.重新計(jì)算進(jìn)程的時(shí)間片時(shí),只依據(jù)進(jìn)程的靜態(tài)優(yōu)先級,這個(gè)優(yōu)先級在進(jìn)程狀態(tài)時(shí)由用戶指定,一旦指定,這個(gè)優(yōu)先級就不會被改變.優(yōu)先級越高,進(jìn)程所獲得的進(jìn)程運(yùn)行時(shí)間片就越長.
            55.內(nèi)核對進(jìn)程“休眠”和“喚醒”的處理:
             當(dāng)進(jìn)程“休眠”時(shí),進(jìn)程將自己標(biāo)識為“休眠”狀態(tài),把自己從“可執(zhí)行隊(duì)列”移動到“等待隊(duì)列”。
             當(dāng)進(jìn)程“喚醒”時(shí),進(jìn)程被設(shè)置為“可執(zhí)行狀態(tài)”,然后被從“等待隊(duì)列”移動到“可執(zhí)行隊(duì)列”.
            56.進(jìn)程的用戶搶占:是指進(jìn)程在內(nèi)核空間返回到用戶空間時(shí)或是從中斷處理程序中返回到用戶空間時(shí),如果進(jìn)程的need_resched標(biāo)志被重新標(biāo)記了,那么進(jìn)程就需要被重新調(diào)度.
            57.在Linux系統(tǒng)中,內(nèi)核進(jìn)程也可以被搶占.只要沒有鎖,內(nèi)核就可以進(jìn)行搶占.
             內(nèi)核搶占發(fā)生的時(shí)間:
             a. 當(dāng)從中斷處理程序正在執(zhí)行,且返回內(nèi)核空間之前.
             b. 當(dāng)內(nèi)核代碼再一次具有可搶占性的時(shí)候.
             c. 如果內(nèi)核中的任務(wù)顯示地高度schedule。
             d. 如果內(nèi)核中的任務(wù)阻塞(這同樣也會導(dǎo)致調(diào)用schedule).


            chapter 5
            58.系統(tǒng)調(diào)用的作用:
             a. 為用戶空間提供了一種硬件的抽象接口.
             b. 系統(tǒng)調(diào)用保證了系統(tǒng)的穩(wěn)定和安全.
             c. 系統(tǒng)調(diào)用是用戶空間訪問內(nèi)核的唯一手段.
            59.UNIX的設(shè)計(jì)原則是:提供機(jī)制而不是策略.換句話說,UNIX系統(tǒng)抽象出了用于完成某種確定目的的函數(shù),至于這些函數(shù)怎么用完全不需要內(nèi)核去關(guān)心.
            60.系統(tǒng)調(diào)用的實(shí)現(xiàn)原理:
             用戶空間無法直接執(zhí)行內(nèi)核代碼,它們不能直接調(diào)用內(nèi)核空間中的函數(shù),因?yàn)閮?nèi)核駐留在受保護(hù)的地址空間上,如果進(jìn)程可以直接在內(nèi)核地址空間上讀寫的話,系統(tǒng)安全就會失敗控制.
             所以,應(yīng)用程序應(yīng)該以某種方式通知系統(tǒng),告訴內(nèi)核自己需要執(zhí)行一個(gè)系統(tǒng)調(diào)用,希望系統(tǒng)切換到內(nèi)核態(tài),這樣內(nèi)核就可以代表應(yīng)用程序來執(zhí)行該系統(tǒng)調(diào)用了.
             通知內(nèi)核的機(jī)制是靠軟中斷:通過引發(fā)一個(gè)異常來促使系統(tǒng)切換到內(nèi)核態(tài)去執(zhí)行異常處理程序。此時(shí)的異常處理程序?qū)嶋H上就是系統(tǒng)調(diào)用處理程序。X86系統(tǒng)上的軟中斷由int 0x80指令產(chǎn)生.這條指令觸發(fā)一個(gè)異常導(dǎo)致系統(tǒng)切換到內(nèi)核態(tài)并執(zhí)行第128號異常處理程序,而該程序是系統(tǒng)調(diào)用處理程序.這個(gè)異常處理程序的名字叫作system_call。最近x86增加了一條叫做sysenter的指令,與int中斷指令相比,這條指令提供了更快,更專業(yè)的陷入內(nèi)核執(zhí)行系統(tǒng)調(diào)用的方式.
            61.當(dāng)內(nèi)核接收一個(gè)用戶空間的指針時(shí),內(nèi)核 必須保證:
             a. 指針指向的內(nèi)存區(qū)域?qū)儆谟脩艨臻g,進(jìn)程決不能哄騙內(nèi)核去讀取內(nèi)核空間的數(shù)據(jù).
             b. 指針指向的內(nèi)存區(qū)域在進(jìn)程的地址空間里,進(jìn)程決不能哄騙內(nèi)核去讀取其它的進(jìn)程空間的數(shù)據(jù).
             c. 如果是讀,該內(nèi)核區(qū)域必須被標(biāo)記為可讀,如果是寫,該內(nèi)存區(qū)域必須被標(biāo)記為可寫。進(jìn)程決不能繞過內(nèi)存訪問控制.
            62.硬件與內(nèi)核通信的機(jī)制是:中斷機(jī)制,當(dāng)硬件需要和系統(tǒng)通信時(shí),硬件向系統(tǒng)發(fā)送一個(gè)中斷請求,中斷在本質(zhì)上是一種特殊的電信號。這個(gè)中斷請求實(shí)際上并不是硬件直接發(fā)送給內(nèi)核的,而是硬件先發(fā)送給CPU,再由CPU向內(nèi)核發(fā)送中斷信號,內(nèi)核再中斷當(dāng)前的工作調(diào)用相應(yīng)的中斷處理程序,從而完成內(nèi)核與硬件的通信.硬件的中斷可以隨時(shí)產(chǎn)生,因此,處理器也需要隨時(shí)響應(yīng)中斷信號.硬件中斷不用考慮與處理器的時(shí)鐘同步問題,但是“異常”需要考慮與處理器的時(shí)鐘同步問題.
            63.每個(gè)中斷信號都有一個(gè)唯一的數(shù)值.這樣內(nèi)核才能區(qū)分中斷信號來自于哪個(gè)硬件,更進(jìn)一步,內(nèi)核才能為對應(yīng)的硬件中斷信號調(diào)用其中斷處理程序.
            64.中斷信號的值被稱為“中斷請求線”(IRQ).
            65."異常"必須考慮與處理器的時(shí)鐘同步問題,因此“異常”也被稱作為“同步中斷”.在處理器遇到編程失誤或是特殊情況而需要由內(nèi)核來處理的時(shí)候,處理器就產(chǎn)生一個(gè)“異常”,因?yàn)樵S多體系結(jié)構(gòu)處理“異常”與處理“中斷”的方式很相似,所以,內(nèi)核對于它們的處理也很相似.
            66.“中斷”必須是由硬件產(chǎn)生的,而“異常”可以是由軟件產(chǎn)生的.
            67.在響應(yīng)一個(gè)中斷的時(shí)候,內(nèi)核會執(zhí)行一個(gè)函數(shù),這個(gè)函數(shù)叫做“中斷處理程序”(interrupt handler)或者是“中斷服務(wù)例程”(interrupt service routine,ISR)。中斷處理程序是和特定的中斷關(guān)聯(lián),而不是和硬件關(guān)聯(lián)的,這樣一來,如果一個(gè)硬件可以產(chǎn)生多種中斷,那么它的設(shè)備驅(qū)動程序就要提供多個(gè)中斷處理程序.
            68.中斷處理程序與其它的內(nèi)核函數(shù)的區(qū)別在于:中斷處理程序是被內(nèi)核用來響應(yīng)中斷的,而且它們只運(yùn)行在我們稱之為“中斷上下文”的特殊上下文中.
            69.中斷處理程序一般被切分為兩部分完成:上半部和下半部.
             a. 上半部用于完成有嚴(yán)格的時(shí)限的工作.
             b. 中斷處理程序中能夠被推遲到稍后完成的工作就被放到下半部中.
            70.設(shè)備驅(qū)動程序:實(shí)際上就是對設(shè)備所產(chǎn)生的中斷進(jìn)行處理的中斷處理程序的集合,所有的這個(gè)硬件設(shè)備的中斷處理程序被一起提供給內(nèi)核用于內(nèi)核完成該硬件設(shè)備的中斷處理.
            71.中斷共享:中斷共享的函數(shù)就是“一個(gè)中斷信號值可以由多個(gè)硬件產(chǎn)生”.
            72.如果某個(gè)中斷信號被屏蔽,那么當(dāng)硬件設(shè)備向處理器發(fā)送對應(yīng)的中斷電信號時(shí),在處理器將這個(gè)中斷通知內(nèi)核時(shí),內(nèi)核就不會去響應(yīng)這個(gè)中斷信號.
            73.Linux中的中斷處理程序是無需重入的.當(dāng)一個(gè)給定的中斷處理程序正在執(zhí)行時(shí),這個(gè)中斷在所有的處理器上都會被屏蔽掉,以防止在同一個(gè)中斷線上接收另一個(gè)新的同樣的中斷信號.通常情況下,所有的其它的中斷都沒有被屏蔽而是打開的,所有這些不同的中斷線上的其它中斷都能夠被響應(yīng),但當(dāng)前的中斷線總是被禁止的.由此可以看出,同一個(gè)中斷處理程序絕對不會被同時(shí)調(diào)用以處理嵌套的中斷,這極大地簡化了中斷處理程序的編寫.
            73.內(nèi)核接收到中斷后,會依次調(diào)用當(dāng)前的中斷線上注冊的每一個(gè)中斷處理程序.
            74.進(jìn)程上下文是針對內(nèi)核而言的,它是指內(nèi)核所處的操作模式,此時(shí)內(nèi)核代表進(jìn)程執(zhí)行.
             中斷上下文.中斷上下文與進(jìn)程沒有瓜葛,因?yàn)闆]有進(jìn)程背景,所有中斷上下文不可以睡眠--否則又怎能被重新調(diào)度呢?因此不能從中斷上下文中調(diào)用某些函數(shù)。如果一個(gè)函數(shù)睡眠,就不能在中斷處理程序中調(diào)用它,這是對什么表函數(shù)可以在中斷上下文中調(diào)用的限制.
             中斷上下文有嚴(yán)格的時(shí)間限制,因?yàn)樗驍嗟钠渌拇a的執(zhí)行.中斷上下文中的代碼應(yīng)當(dāng)快速簡潔,盡量不要使用循環(huán)去處理復(fù)制的工作,有一點(diǎn)非常重要,請永遠(yuǎn)牢記:中斷處理程序打斷了其它的代碼(甚至可能是其它的中斷線上的另一個(gè)中斷處理程序).
            75.中斷處理機(jī)制的實(shí)現(xiàn).
             中斷處理系統(tǒng)在Linux系統(tǒng)中的實(shí)現(xiàn)是依賴于體系結(jié)構(gòu)的,想必你對此不會感到特別驚訝。實(shí)現(xiàn)依賴于處理器,所使用的中斷處理器的類型,體系結(jié)構(gòu)的設(shè)計(jì)及機(jī)器本身.
             設(shè)備產(chǎn)生中斷,通過中斷控制總線把電信號發(fā)送給中斷控制器,如果中斷線是激活的(它們允許被屏蔽),那么中斷控制器就會把中斷發(fā)往處理器.在大多數(shù)的體系結(jié)構(gòu)上,這個(gè)工作就是通過電信號給處理器的特定的管腳發(fā)送一個(gè)電信號。除非在處理器上禁止該中斷,否則,處理器就會停止它正在做的事,關(guān)閉中斷系統(tǒng),然后跑到內(nèi)存中預(yù)定義的位置開始執(zhí)行那里的代碼。這個(gè)預(yù)定義的位置是由內(nèi)核設(shè)置的,是中斷處理程序的入口.
             在內(nèi)核中,中斷的旅程開始于預(yù)定義的入口點(diǎn),這類似于系統(tǒng)調(diào)用通過預(yù)定義的異常句柄進(jìn)入內(nèi)核,對于每條中斷線,處理器都會跳到一個(gè)唯一的位置,這樣,內(nèi)核就可以知道所接收的中斷的IRQ號了,初始入口只是在棧中保存這個(gè)號,并存放當(dāng)前的寄存器的值,然后內(nèi)核調(diào)用do_IRQ.從這里開始,大多數(shù)的中斷處理代碼都是用C寫的.
            76.Linux內(nèi)核提供了一組接口用于操作機(jī)器上的中斷狀態(tài),這些接口為我們提供了能夠禁止當(dāng)前處理器的中斷系統(tǒng),或屏蔽掉整個(gè)機(jī)器的一條中斷線的能力.


            chapter 7
            77.中斷處理流程分為:上半部和下半部兩部分.
             上半部:中斷處理程序.
             下半部:Linux中將響應(yīng)中斷的一部分操作推遲到之后完成的機(jī)制.
            78.上半部和下半部的區(qū)分取決于開發(fā)者自己的判斷,通常的規(guī)則是:
             a. 如果一個(gè)任務(wù)對時(shí)間非常敏感,將其入在中斷處理程序中執(zhí)行.
             b. 如果一個(gè)任務(wù)和硬件相關(guān),將其入在中斷處理程序中執(zhí)行.
             c. 如果一個(gè)任務(wù)要保證不被其它的中斷(特別是相同的中斷)打斷,將其入在中斷處理程序中執(zhí)行.
             d. 其它的任務(wù),考慮放置在下半部中執(zhí)行.
            79. Linux內(nèi)核提供的3種下半部機(jī)制:
             a. 軟中斷:是在編譯時(shí)指定的softirq_action結(jié)構(gòu)體數(shù)組,一般有32項(xiàng).一個(gè)軟中斷不會去搶占另一個(gè)軟中斷,實(shí)際上,唯一可以搶占軟中斷的是中斷處理程序,不過其它的軟中斷,甚至是其它的相同類型的軟中斷,可以在其它的處理器上同時(shí)執(zhí)行.
            執(zhí)行軟中斷:一個(gè)注冊的軟中斷必須在被標(biāo)記為才會執(zhí)行,這被稱作“觸發(fā)軟中斷”,通常中斷處理程序會在返回前標(biāo)記它的軟中斷,使其在稍后執(zhí)行.在以下時(shí)刻,軟中斷會被檢查和執(zhí)行:
             a). 從一個(gè)硬件中斷代碼返回時(shí).
             b). 在ksoftirqd內(nèi)核線程中.
             c). 在那些顯示檢查和執(zhí)行待處理的軟中斷的代碼中,如網(wǎng)絡(luò)子系統(tǒng)中.
            內(nèi)核定時(shí)器和tasklet都是建立在軟中斷的基礎(chǔ)之上的.
             b. tasklet:基于軟中斷實(shí)現(xiàn).
             c. 工作隊(duì)列:可以把中斷處理程序中的后續(xù)工作推遲到后續(xù)去完成,交由一個(gè)內(nèi)核線程去執(zhí)行,這個(gè)下半部在“進(jìn)程上下文”中執(zhí)行.工作隊(duì)列允許重新調(diào)度甚至是睡眠.
             如果推遲的工作可以需要睡眠,那么使用任務(wù)隊(duì)列;如果推遲的工作不能進(jìn)行睡眠,那么使用軟中斷或tasklet.工作隊(duì)列最基本的表現(xiàn)形式就成了把需要推遲執(zhí)行的任務(wù)交給一個(gè)特定的通用線程來處理這樣的一個(gè)接口。默認(rèn)的工作者線程叫做:events/n。這里的n是處理器的編號;每個(gè)處理器一個(gè)對應(yīng)的線程.比如,用于處理工作隊(duì)列的工作者線程可以自行創(chuàng)建,但是有一個(gè)默認(rèn)的工作者線程.


            80.當(dāng)你需要保證工作被推遲到某一個(gè)指定的時(shí)間去執(zhí)行時(shí),那么你需要使用內(nèi)核定時(shí)器機(jī)制.
            81.每個(gè)處理器都有一個(gè)對應(yīng)的“軟中斷輔助處理線程”:ksoftirqd/n。
            82.臨界區(qū):就是訪問和操作共享數(shù)據(jù)的代碼斷.代碼在執(zhí)行完成之前不能夠被打斷.
            83.處理器會保證任何的兩個(gè)處理器原子指令不會同時(shí)執(zhí)行.也就是說:如果有兩個(gè)原子A,B指令要執(zhí)行,那么要么A執(zhí)行完之后再執(zhí)行B,要么B執(zhí)行完后再執(zhí)行A,不可以出現(xiàn)A執(zhí)行一半再執(zhí)行B然后再執(zhí)行A,最后又執(zhí)行B的情況.
            84.內(nèi)核中有可能造成并發(fā)執(zhí)行原因:
             a. 中斷--中斷幾乎可以在任何時(shí)刻發(fā)生,也就是可能打斷當(dāng)前正在執(zhí)行的代碼.
             b. 軟中斷和tasklet--內(nèi)核能在任何時(shí)刻喚醒或調(diào)度軟中斷和tasklet,打斷當(dāng)前正在執(zhí)行的代碼.
             c. 內(nèi)核搶占--因?yàn)閮?nèi)核具有搶占性,所以內(nèi)核中的任務(wù)可能會另外一個(gè)任務(wù)搶占.
             d. 睡眠及與用戶空間的同步--在內(nèi)核執(zhí)行的進(jìn)程可能睡眠,這就會喚醒調(diào)度程序,從而導(dǎo)致調(diào)度一個(gè)新的用戶進(jìn)程執(zhí)行.
            85.對稱多處理器--兩個(gè)或多個(gè)處理器可以同時(shí)執(zhí)行代碼.以及如何安排同步的順序.
            86.并發(fā)開發(fā)的難點(diǎn)就在于找出所有的潛在的可能發(fā)生競爭和數(shù)據(jù)同步的地方.
            87.幾種安全代碼:
             a. 中斷安全代碼:在中斷處理程序中能避免被并發(fā)訪問的代碼.
             b. 對稱多處理器安全代碼:在對稱多處理器中能避免被并發(fā)訪問的代碼.
             c. 搶占安全代碼:在內(nèi)核搶占時(shí)能避免并發(fā)訪問的代碼.
            88.在并發(fā)開發(fā)中:我們實(shí)際上要保護(hù)的是數(shù)據(jù)而不是代碼.
            89.線程中的局部數(shù)據(jù)不需要加鎖,因?yàn)榫€程上的局部數(shù)據(jù)是存儲在線程的棧空間的中的,特定于每一個(gè)線程的棧空間中都有一份自己的線程局部數(shù)據(jù),它們互不影響.一條原則時(shí),如果公有數(shù)據(jù)可能同時(shí)被多個(gè)線程訪問,那么這些公有數(shù)據(jù)需要被訪問.
            90.避免死鎖的方法:
             a.操作公共數(shù)據(jù)的線程都以相同的順序去獲取鎖.
             b. 對鎖的獲取和釋放加上序號.
             c. 不要在一個(gè)線程中重復(fù)請求同一個(gè)鎖.
             d. 以獲取鎖的相反順序來釋放鎖.
             e. 加鎖的精髓在于力求簡單的方案.
            91.原子操作:執(zhí)行過程不會被打斷的操作.
            92.讀寫內(nèi)存中的一個(gè)字的操作是原子操作,也就是說,在對這個(gè)內(nèi)存字的讀的過程中,不會出現(xiàn)對該字的寫的過程,在對該字的寫的過程中,不會出現(xiàn)對該字的讀的過程.
            93.原子性:確保指令執(zhí)行期間不會被其它的操作打斷,也就是說這個(gè)指令一次性完成,在這條指令完成的過程中,不會有其它的指令執(zhí)行.
            94.順序性:兩條或多條指令出現(xiàn)在獨(dú)立的執(zhí)行線程中,甚至獨(dú)立的處理器上,但它們本該執(zhí)行的順序依然要得到保持.
            95.自旋鎖為多處理器機(jī)器上提供了防止并發(fā)訪問的數(shù)據(jù)所需要的鎖保護(hù)機(jī)制.
            96.Linux下的自旋鎖是不可遞歸的.
            97.當(dāng)一個(gè)線程在試圖獲取自旋鎖時(shí),如果這個(gè)鎖已被其它的線程所獲取,那么這個(gè)等待的線程不會因?yàn)榈却@個(gè)自旋鎖而休眠,相反,這個(gè)等待的線程會一直嘗試去獲取這個(gè)自旋鎖。
            98.自旋鎖可以使用在中斷處理程序中(此處不能使用信號量,因?yàn)樗鼈儠?dǎo)致睡眠),在中斷程序中調(diào)用 自旋鎖時(shí),一定要在獲取鎖之前首先禁用本地中斷(在當(dāng)前的處理器上的中斷請求),否則,中斷處理程序可能會打斷正持有鎖的內(nèi)核代碼,有可能會試圖爭用這個(gè)已經(jīng)被持有的自旋鎖,這樣一來,中斷處理程序就會自旋,等待該鎖重新可用,但是鎖的持有者在這個(gè)中斷處理過程處理完成之前不可能運(yùn)行,這正是我們在前一章節(jié)中提到的“雙重請求死鎖”。注意,需要關(guān)閉的只是當(dāng)前的處理器上的中斷,如果中斷發(fā)生在不同的機(jī)器上,即使中斷處理程序在同一鎖上自旋,也不會妨礙鎖的持有者(在不同的處理器上)最終釋放鎖.
            99.要記住一點(diǎn):在任何時(shí)候,我們加鎖是為了鎖住數(shù)據(jù),而不是為了鎖住代碼.
            100.對于自旋鎖和下半部:
             在與下半部配合使用時(shí),必須小心地使用鎖機(jī)制。函數(shù)spin_lock_bh用于獲取指定的鎖,同時(shí)它們禁止所有的下半部的執(zhí)行,相應(yīng)的spin_unlock_bh函數(shù)執(zhí)行相反的操作.
             由于下半部可以搶占進(jìn)程上下文中的代碼,所以,當(dāng)下半部與進(jìn)程上下文共享數(shù)據(jù)時(shí),必須對進(jìn)程上下文中的共享數(shù)據(jù)進(jìn)行保護(hù),所以需要加鎖的同時(shí)還要禁止下半部執(zhí)行(不然下半部又可以會搶占進(jìn)程上下文)。同樣,由于中斷處理程序可以搶占下半部,所以,如果中斷處理程序和下半部共享數(shù)據(jù),那么就必須在獲取恰當(dāng)?shù)逆i的同時(shí)還要禁止中斷.
             同類的tasklet不可能同時(shí)運(yùn)行,所以對于同類的tasklet中的共享數(shù)據(jù)不需要加鎖保護(hù),因?yàn)橥惖膖asklet的任何必定是嚴(yán)格的串行完成,如果同一個(gè)處理器上的同類的tasklet任務(wù)A和B,在A沒有完成之前,B絕對不會開始運(yùn)行,只有在A完全完成之后,B才開始運(yùn)行.但是當(dāng)數(shù)據(jù)被不同類的tasklet共享時(shí),就需要在訪問下半部中的數(shù)據(jù)前先獲得一個(gè)普通的自旋鎖。這里不需要禁止下半部,因?yàn)樵谕粋€(gè)處理器上,決不會有tasklet相互搶占的情況發(fā)生.
             對于軟中斷,無論是否同種類型,如果數(shù)據(jù)被軟中斷共享,那么它必須得到鎖的保護(hù),因?yàn)榧词故峭N類型的兩個(gè)軟中斷也可以同時(shí)運(yùn)行在一個(gè)系統(tǒng)的多個(gè)處理器上,但是,同一處理器上的一個(gè)軟中斷絕不會搶占另一個(gè)軟中斷,因此根本沒有必須搶占軟中斷.
            101.信號量:信號量支持兩個(gè)原子操作P和V,前者叫做測試操作,后者叫做增加操作,后來系統(tǒng)把這兩個(gè)操作分別叫做down和up。down通過對信號量計(jì)數(shù)減1來請示獲得一個(gè)信號量,如果結(jié)果是0或者大于0,那么獲取鎖成功,進(jìn)入到臨界區(qū)中.如果結(jié)果是負(fù)數(shù),那么任務(wù)就會被放入到等待隊(duì)列,對應(yīng)的進(jìn)程也會進(jìn)入休眠.處理器此時(shí)可以執(zhí)行其它的操作.相反,在臨界區(qū)中的操作完成之后,通過up操作來釋放信號量,該操作也被稱作是提升信號量的值,因?yàn)樗鼤黾有盘柫康挠?jì)數(shù),如果在該信號量上的等待隊(duì)列不為空,那么處于隊(duì)列中的等待的任務(wù)就會被喚醒同時(shí)獲得該信號量.
            102.內(nèi)核中的 barrier的作用是保證:一個(gè)操作必須在另一個(gè)操作之前完成這一點(diǎn)不會被編譯器或者是處理器改變.

            chapter 10
            103.系統(tǒng)定時(shí)器:一種可編程的硬件芯片,它能以固定頻率產(chǎn)生中斷,這種中斷就是所謂的“定時(shí)器中斷”.它所對應(yīng)的中斷處理程序負(fù)責(zé)更新系統(tǒng)時(shí)間,還負(fù)責(zé)執(zhí)行需要周期性執(zhí)行的任務(wù).系統(tǒng)定時(shí)器和時(shí)鐘中斷處理程序是Linux系統(tǒng)內(nèi)核管理機(jī)制中的中樞.
            104.動態(tài)定時(shí)器: 一種用來推遲執(zhí)行程序的工具,內(nèi)核可以動態(tài)創(chuàng)建或銷毀動態(tài)定時(shí)器.
            105.系統(tǒng)定時(shí)器以某種固定的頻率自動觸發(fā)時(shí)鐘中斷,這種頻率可以通過編程預(yù)定,稱作節(jié)拍率,當(dāng)時(shí)鐘中斷發(fā)生時(shí),內(nèi)核就通過一種特殊的中斷處理程序?qū)ζ溥M(jìn)行處理.因?yàn)轭A(yù)編的節(jié)拍率對內(nèi)核來說是已知的,所以內(nèi)核知道兩次連接的時(shí)鐘中斷間隔的時(shí)間,這個(gè)間隔時(shí)間就被稱作:節(jié)拍(tick)。它等于節(jié)拍頻率分之一,內(nèi)核就是靠這種時(shí)鐘間隔來計(jì)算墻上時(shí)間和系統(tǒng)時(shí)間.
            106.jiffies:記錄自系統(tǒng)啟動以來的時(shí)鐘節(jié)拍數(shù).
            107.實(shí)時(shí)時(shí)鐘:RTC,是用來持久存放系統(tǒng)時(shí)間的設(shè)備,即使系統(tǒng)關(guān)閉后,它也可以靠主板上的微型電池提供的電力保持系統(tǒng)的計(jì)時(shí),在PC體系結(jié)構(gòu)中,RTC和CMOS集成在一起,而且RTC的運(yùn)行和BIOS的保存設(shè)置都是通過同一個(gè)電池供電的.
            108.實(shí)時(shí)時(shí)鐘的最大作用是在啟動時(shí)初始化xtime變量.
            109.系統(tǒng)定時(shí)器:通過對電子晶振進(jìn)行分頻來實(shí)現(xiàn)系統(tǒng)定時(shí)器.
            110.在X86系統(tǒng)中,主要采用可編程中斷時(shí)鐘(PIT)。在X86系統(tǒng)中還包括本地APIC時(shí)鐘和時(shí)間戳計(jì)數(shù)(TSC)等時(shí)鐘資源.
            111.時(shí)鐘處理程序:時(shí)鐘處理程序可以分為兩部分,體系結(jié)構(gòu)相關(guān)的部分和體系結(jié)構(gòu)無關(guān)的部分。
             與體系結(jié)構(gòu)相關(guān)的部分作為系統(tǒng)定時(shí)器的中斷處理程序而注冊到內(nèi)核中,以便產(chǎn)生時(shí)鐘中斷時(shí),它能夠相應(yīng)地運(yùn)行。
            112.動態(tài)定時(shí)器:它并不周期性地運(yùn)行,它在超時(shí)后就自行銷毀,這也是這種定時(shí)器被稱為動態(tài)定時(shí)器的原因 ,動態(tài)定時(shí)器不斷創(chuàng)建和銷毀,而且它的運(yùn)行次數(shù)也不受限制。
            113.定時(shí)器會在指定的定時(shí)值到達(dá)之后開始運(yùn)行.在運(yùn)行完成之后,這個(gè)定時(shí)器會被刪除,所以如果你想要一個(gè)定時(shí)函數(shù)周期性地運(yùn)行下去,那么你需要在定時(shí)器超時(shí)后重新設(shè)定定時(shí)器,也就是在定時(shí)器處理函數(shù)的最后重新設(shè)定這個(gè)定時(shí)器.
            114.volatile變量可以強(qiáng)制使得編譯器在每次訪問變量時(shí)都重新從主內(nèi)存中獲取而不是通過寄存器中的變量的別名來獲取,這樣就可以保證變量的值永遠(yuǎn)都是最新的.
            115.經(jīng)驗(yàn)表明,不要使用udelay來處理超過1毫秒的延遲,在延遲超過1毫秒的情況下,使用mdelay更為安全.這些函數(shù)的實(shí)現(xiàn)使用基于循環(huán)的忙等待.
            116.MIPS:Million Instruction Per Second。處理器每秒執(zhí)行的百萬條指令數(shù).

            chapter 11
            117.內(nèi)存頁:內(nèi)核把物理內(nèi)存頁作內(nèi)存管理的基本單位,盡管處理器的最小可尋址單位通常是字(甚至字節(jié)),但是,內(nèi)存管理單元(MMU:管理內(nèi)存并把虛擬地址轉(zhuǎn)換為物理地址的硬件)通常以頁為單位來進(jìn)行處理,正因?yàn)槿绱耍琈MU大小為單位來管理系統(tǒng)中的頁表(這也是頁表名的由來),從物理內(nèi)存的CPU角度來看,內(nèi)存的最小單位是字節(jié),但是從虛擬內(nèi)存的角度來看,頁就是最小單位.
            118.在32位機(jī)上,一個(gè)內(nèi)存頁的大小是4K,而在64位機(jī)上,內(nèi)存頁的大小為8K。所以在32位機(jī)上,1G的內(nèi)存會被分成262144個(gè)頁.
            119.內(nèi)存區(qū):內(nèi)核并不是對所有的內(nèi)存頁都一致對待,內(nèi)核使用區(qū)對具有相似特性的頁進(jìn)行分組。
             ZONE_DMA:這個(gè)內(nèi)存區(qū)的內(nèi)存頁可以執(zhí)行DMA(直接內(nèi)存訪問操作).X86上為:0 ~ 16M
             ZONE_NORMAL: 這個(gè)區(qū)包含的正常可尋址的頁.X86上為: 16M ~896M
             ZNOE_HIGHMEM: 這個(gè)區(qū)中的頁并不能永久地映射到內(nèi)核地址空間。X86上為: > 896M
            120.內(nèi)核slab層:slab層把不同的對象劃分為所謂的“調(diào)整緩存”組,其中每個(gè)高速緩存都存放不同類型的對象,每種對象類型對應(yīng)于一個(gè)高速緩存,例如,一個(gè)高速緩存用于存放進(jìn)程描述符,另一個(gè)高速緩存用于存放索引節(jié)點(diǎn).slab由一個(gè)或多個(gè)物理上連續(xù)的頁組成.

             

            chapter 12
            121.虛擬文件系統(tǒng):有時(shí)也稱作虛擬文件交換(VFS),采用面向?qū)ο蟮脑O(shè)計(jì)思路,作為內(nèi)核子系統(tǒng),為用戶空間提供了系統(tǒng)相關(guān)的接口,系統(tǒng)中所有的文件系統(tǒng)不但依賴于VFS共存,而且也依靠VFS系統(tǒng)協(xié)同工作。
            122.UNIX文件系統(tǒng):UNIX使用了4種與文件系統(tǒng)相關(guān)的傳統(tǒng)抽象概念:
             文件:可以看作是一個(gè)有序的字節(jié)串,字節(jié)串中的每一個(gè)字節(jié)是文件的頭,最后一個(gè)字節(jié)是文件的尾。
             目錄項(xiàng):用來容納文件的結(jié)構(gòu).
             索引節(jié)點(diǎn):文件相關(guān)信息,有時(shí)被稱作文件的元數(shù)據(jù)(也就是說文件的相關(guān)的數(shù)據(jù)),被存儲在一個(gè)單獨(dú)的數(shù)據(jù)結(jié)構(gòu)中,這個(gè)結(jié)構(gòu)被稱作索引結(jié)點(diǎn)( inode ).
             安裝點(diǎn):安裝文件系統(tǒng)的特定的安裝點(diǎn).
            123.文件系統(tǒng):從本質(zhì)上講,文件系統(tǒng)是特殊的數(shù)據(jù)分層存儲結(jié)構(gòu),包含文件,目錄和相關(guān)的控制信息。在UNIX系統(tǒng)中,文件系統(tǒng)被安裝在一個(gè)特定的安裝點(diǎn)上,該安裝點(diǎn)在全局層次結(jié)構(gòu)中被稱作命名空間,所有已安裝的文件系統(tǒng)都作為根文件系統(tǒng)樹的枝葉出現(xiàn)在系統(tǒng)中.
            124.UNIX是面向流的文件系統(tǒng),其它的操作系統(tǒng)中有面向記錄的文件系統(tǒng).UNIX將相關(guān)信息和文件本身這兩個(gè)概念加以區(qū)分.
            125.VFS中的4種主要對象:
             a. 超級塊 對象:它代表一個(gè)已安裝的文件系統(tǒng).該對象存儲特定文件系統(tǒng)的信息,通常對應(yīng)于存放在磁盤特定扇區(qū)中的文件系統(tǒng)超級塊或文件系統(tǒng)控制塊.
             b. 索引節(jié)點(diǎn) 對象:它代表一個(gè)文件.包含了內(nèi)核在操作文件或目錄時(shí)所需要的全部的信息.對于UNIX風(fēng)格的文件系統(tǒng)來說,這些信息可以從磁盤的索引節(jié)點(diǎn)中直接讀入.一個(gè)索引節(jié)點(diǎn)代表文件系統(tǒng)中(雖然索引節(jié)點(diǎn)僅當(dāng)文件被訪問時(shí)才在內(nèi)存中被創(chuàng)建)的一個(gè)文件,它也可以是設(shè)備或管道這樣的特殊的文件。
             c. 目錄項(xiàng) 對象:它代表一個(gè)目錄項(xiàng),是路徑的一個(gè)組成部分.路徑中的每一個(gè)組成部分都由一個(gè)索引節(jié)點(diǎn)對象表示。雖然它們可以統(tǒng)一由索引節(jié)點(diǎn)表示。目錄項(xiàng)對象沒有對應(yīng)的磁盤數(shù)據(jù)結(jié)構(gòu),VFS根據(jù)字符串的形式的路徑來現(xiàn)場創(chuàng)建它們。
             d. 文件對象:它代表由進(jìn)程打開的文件.是打開的物理文件在內(nèi)存中的表示.同一個(gè)物理文件如果被多個(gè)進(jìn)程打開,那么就會有多個(gè)對應(yīng)的文件對象.文件對象只在內(nèi)存中存在,并不存儲在磁盤上.
                 VFS中將目錄當(dāng)作一種特殊的文件來看待,所以不存在“目錄對象”

            126.目錄項(xiàng)對象的狀態(tài):被使用,未被使用,負(fù)狀態(tài).
             a. 被使用狀態(tài):一個(gè)使用的目錄項(xiàng)對應(yīng)于一個(gè)有次的索引節(jié)點(diǎn).
             b. 未被使用狀態(tài):未被使用的目錄項(xiàng)對應(yīng)于一個(gè)有效的索引節(jié)點(diǎn),但是應(yīng)指明,當(dāng)前的VFS并沒有使用它,該目錄項(xiàng)對象仍然指向一個(gè)有效對象,而且被保留在緩存中以便需要時(shí)再使用它。由于該目錄項(xiàng)不會過早刪除,所以,在以后需要它時(shí),不必重新創(chuàng)建,從而使用路徑查找更迅速,如果要回收內(nèi)存的話,可以銷毀未使用的目錄項(xiàng).
             c. 負(fù)狀態(tài):目錄項(xiàng)沒有對應(yīng)的有效的索引節(jié)點(diǎn),因?yàn)樗饕?jié)點(diǎn)已被刪除(也即是物理文件被刪除),或路徑不再正確了,但是目錄項(xiàng)仍然保留,以便快速解析以后的路徑查詢。雖然負(fù)狀態(tài)的目錄項(xiàng)有些用處,但是如果需要的話,可以銷毀它。
            127.如果系統(tǒng)中有大量的進(jìn)程都要打開超過32個(gè)文件,為了優(yōu)化性能,管理員可以適當(dāng)增大NR_OPEN_DEFAULT的值.

            chapter 13
            128.Linux系統(tǒng)中的設(shè)置類型分為“塊設(shè)備”和“字符設(shè)備”
            塊設(shè)備:能夠隨機(jī)的訪問固定大小數(shù)據(jù)片的設(shè)備,如果磁盤,軟盤驅(qū)動器,CD-ROM。它們都是以安裝文件系統(tǒng)的方式使用。
            字符設(shè)備:字符設(shè)備按照字符流的方式被訪問,像串口和鍵盤就屬于字符設(shè)備。
            這兩種設(shè)備的本質(zhì)區(qū)別在于是否可以進(jìn)行隨機(jī)訪問.
            129.塊設(shè)備的最小的可尋址單元是扇區(qū),扇區(qū)大小一般是2的倍數(shù),而最常見的大小是512字節(jié),扇區(qū)的大小是設(shè)備的物理屬性,扇區(qū)是所有的塊設(shè)備的基本單元,塊設(shè)備無法對比它還小的單元進(jìn)行尋址和操作,不過許多塊設(shè)備能夠一次就傳輸多個(gè)扇區(qū),雖然大多數(shù)設(shè)備的扇區(qū)的大小都是512字節(jié),不過其它大小的扇區(qū)也是很常見的,比如,CD-ROM的扇區(qū)大小就是2K.
            130.雖然物理磁盤都是按扇區(qū)級進(jìn)行尋址的,但是內(nèi)核卻是基于塊的方式來操作磁盤的,所以塊必須是扇區(qū)大小的整數(shù)倍,而且要小于頁面的大小,所以通常塊的大小是512字節(jié)或是4K.
            131.為了優(yōu)化高度程序,內(nèi)核會在提交I/O請求到磁盤之前所將這些請求進(jìn)行“合并與排序”,從而每次I/O請求所消耗的時(shí)間.

             

            chapter 14
            132.進(jìn)程的地址空間包括:
            a.代碼段:可執(zhí)行文件代碼的內(nèi)存映射
            b.數(shù)據(jù)段:可執(zhí)行文件的已初始化全局變量的內(nèi)存映射.
            c.BSS的零頁:包含未初始化全局變量的內(nèi)存映射.
            d.進(jìn)程用戶棧:不要和進(jìn)程的內(nèi)核棧混淆,進(jìn)程的內(nèi)核棧獨(dú)立存在并由內(nèi)核維護(hù)。
            e.每一個(gè)諸如C庫或動態(tài)連接程序等共享庫的代碼段,數(shù)據(jù)段和bss也會被載入進(jìn)程的地址空間。
            f.任何內(nèi)存映射文件.
            g.任何共享內(nèi)存段.
            h.任何匿名的內(nèi)存映射,比如由malloc分配的內(nèi)存.
            進(jìn)程地址空間中的任何有效地址都只能位于唯一一個(gè)區(qū)域,這些內(nèi)存區(qū)域并不能相互覆蓋,可以看到,在執(zhí)行的地址中,每個(gè)不同的內(nèi)存片段都對應(yīng)一個(gè)獨(dú)立的內(nèi)存區(qū)域:棧,對象代碼,全局變量,被映射的文件等等.
            133.Linux中線程與進(jìn)程的唯一區(qū)別幾乎是:是否共享地址空間.
            134.內(nèi)核線程沒有進(jìn)程地址空間,也沒有相關(guān)的內(nèi)存描述符,所以內(nèi)核線程對應(yīng)的進(jìn)程描述符中的MM域?yàn)榭眨聦?shí)上,這也正是內(nèi)核線程的真實(shí)含義--它們沒有用戶上下文。
            135.平坦地址空間:描述的是地址空間范圍是一個(gè)獨(dú)立的連續(xù)空間(比如從0擴(kuò)展到429496729的32位地址空間)。
            136.進(jìn)程的地址空間之間互不相干.兩個(gè)不同的進(jìn)程可以在相同的地址空間上存放相同的數(shù)據(jù),但是進(jìn)程之間也可以共享地址空間,我們稱這樣的進(jìn)程為線程.
            137.VMA:虛擬內(nèi)存區(qū)域.
            138.頁表:雖然應(yīng)用程序操作的對象是映射到物理內(nèi)存之上的虛擬內(nèi)存,但是處理器直接操作的卻是物理內(nèi)存,所以,當(dāng)程序訪問一個(gè)虛擬地址時(shí),首先必須將虛擬地址轉(zhuǎn)化為物理地址,然后處理器才能解析地址訪問請求,地址的轉(zhuǎn)換工作需要通過查詢頁表來完成,概括地講,地址轉(zhuǎn)換需要將虛擬地址分段,使每段虛擬地址都作為一個(gè)索引指向頁表,而頁表則指向下一級別的頁表或者指向最終的物理頁面.
            139.Linux中使用三級頁表完成地址轉(zhuǎn)換。得用多級頁表能夠節(jié)約地址轉(zhuǎn)換所需要占用的空間,但如果利用三級頁表轉(zhuǎn)換地址,即使是64位機(jī)器,占用的地址空間也是很有限的,但是如果使用靜態(tài)數(shù)組來實(shí)現(xiàn)頁表,那么即使是在32位機(jī)器上,該數(shù)組也將占用巨大的存放空間。Linux對所有的體系結(jié)構(gòu),所括對那些不支持三級頁表的體系結(jié)構(gòu)都使用三級頁表進(jìn)行管理.
            140.三級頁表結(jié)構(gòu):  
               每個(gè)進(jìn)程的地址空間描述符
                     |
                 頂級頁表(PGD)   --> 頁全局目錄
                 |
                 二級頁表(PMD)   --> 中間頁目錄
                 |
                 三級頁表(PTE)   --> 指向?qū)嶋H的物理內(nèi)存頁面

             


            chapter 15
            141.頁高度緩存:是Linux內(nèi)核實(shí)現(xiàn)的一種主要的磁盤緩存,這主要用來減少對磁盤的IO操作,具體地講,是通過把磁盤中的數(shù)據(jù)緩存到物理內(nèi)存中,把對磁盤的訪問變?yōu)閷ξ锢韮?nèi)存的訪問。
            142.磁盤高速緩存的價(jià)值主要存在于兩個(gè)方面:
            a. 訪問磁盤的速度要遠(yuǎn)遠(yuǎn)低于訪問內(nèi)存的速度,因此,從內(nèi)存訪問數(shù)據(jù)比從磁盤訪問速度更快。
            b. 數(shù)據(jù)一旦被訪問,就很有可能在短期內(nèi)再次被訪問到。這種短時(shí)期內(nèi)集中訪問同一片數(shù)據(jù)的原理被稱作“臨時(shí)局部原理(temporal locality)”,臨時(shí)局部原理能夠保證,如果在第一次訪問數(shù)據(jù)時(shí)緩存它,那就極有可能在短期內(nèi)再次被高速緩存命中(訪問高速緩存中的數(shù)據(jù)).
            143.頁高速緩存是由RAM中的物理頁組成的,緩存中的每一頁對應(yīng)著磁盤中的多個(gè)塊,每當(dāng)執(zhí)行一次磁盤操作時(shí),會首先檢查需要的數(shù)據(jù)是否在高速緩存中,如果在,那么內(nèi)核就直接使用高速緩存中的數(shù)據(jù),從而避免了磁盤訪問.
            144.緩沖區(qū)高速緩存:通過I/O緩沖區(qū)把獨(dú)立的磁盤塊與頁高速緩存聯(lián)系在一起,一個(gè)緩沖就是一個(gè)單獨(dú)物理磁盤塊在內(nèi)存中的表示,緩沖就是內(nèi)存到磁盤塊的映射描述符,因此通過緩存磁盤塊以及緩沖I/O操作,頁高速緩存也可以減少對磁盤的訪問量.緩沖區(qū)高速緩存實(shí)際上并不是一個(gè)獨(dú)立的緩存,而是頁高速緩存的一部分.
            145.當(dāng)頁高速緩存中的數(shù)據(jù)比后臺磁盤中的對就數(shù)據(jù)更新時(shí),那么調(diào)整緩存中的這些緩存數(shù)據(jù)被稱作“臟數(shù)據(jù)”,需要在后面寫回到磁盤.


            chapter 16
            146.Linux是“單塊內(nèi)核”(monolithic)的操作系統(tǒng)--也就是說,整個(gè)系統(tǒng)都運(yùn)行于一個(gè)單獨(dú)的保護(hù)域中,但是Linux內(nèi)核是模塊化的,它允許在運(yùn)行時(shí)動態(tài)地向其中插入或是從中刪除代碼.這些代碼--包括子例程,數(shù)據(jù),函數(shù)入口和函數(shù)出口被一并組合在一個(gè)單獨(dú)的二進(jìn)制鏡像中,即所謂的可裝載內(nèi)核模塊,或被簡稱為“模塊”。支持模塊的好處是基本內(nèi)核鏡像可以盡可能小,因?yàn)榭蛇x的功能和驅(qū)動程序可以利用模塊的形式再提供,模塊允許我們方便地刪除和重新載入內(nèi)核代碼,也方便了調(diào)試。
            147.模塊被載入后,就會動態(tài)連接到內(nèi)核,注意,它與用戶空間的動態(tài)連接庫類似,只有當(dāng)顯示被導(dǎo)出后的外部函數(shù),才可以被動態(tài)調(diào)用。在內(nèi)核中,導(dǎo)出內(nèi)核函數(shù)需要使用特殊的命令:EXPORT_SYMBOL和
            EXPORT_SYMBOL_GPL。導(dǎo)出的內(nèi)核函數(shù)可以被模塊調(diào)用,而未導(dǎo)出的函數(shù)模塊則無法被調(diào)用,模塊代碼的鏈接和調(diào)用規(guī)則相比核心內(nèi)核鏡像中的代碼而言,要更加嚴(yán)格,核心代碼在內(nèi)核中可以調(diào)用任意非靜態(tài)接口,因?yàn)樗械暮诵拇a文件被鏈接成了同一個(gè)鏡像,當(dāng)然,被導(dǎo)出的符號表所含的函數(shù)必然也是非靜態(tài)的.導(dǎo)出的符號表被看作是導(dǎo)出的內(nèi)核接口,甚至稱為“內(nèi)核API”.


            chapter 17
            148.設(shè)備模型:設(shè)備模型專門提供了一種獨(dú)立的機(jī)制來專門表示設(shè)備,并描述其在系統(tǒng)中的拓?fù)浣Y(jié)構(gòu)。保證能以正確的順序關(guān)閉各設(shè)備的電源是設(shè)備模型的最初動機(jī).
            149.內(nèi)核事件層:實(shí)現(xiàn)了內(nèi)核到用戶的消息通知系統(tǒng),就是建立在上文一直討論的kobjects基礎(chǔ)之上的.


            chapter 18
            150.內(nèi)核提供了printk這個(gè)函數(shù)用于顯示調(diào)試信息.在任何時(shí)候,任何地方都可以調(diào)用它,它可以在中斷上下文中調(diào)用,可以在進(jìn)程上下文中調(diào)用,可以在持有鎖時(shí)調(diào)用,可以在多處理器上同時(shí)調(diào)用,而且調(diào)用者連鎖都不必使用.
            151.神奇的SysRq
            在i386和PPC上,它可以通過: ALT + PrintScreen 來訪問:該功能可以通過CONFIG_MAGIX_SYSRQ配置選項(xiàng)來啟用。
            SysRq-b 重新啟動機(jī)器
            SysRq-e 向init之外的所有的進(jìn)程發(fā)送SIGTERM信號
            SysRq-h 在控制臺顯示SysRq
            SysRq-i 向init之外的所有的進(jìn)程發(fā)送SIGKILL信號
            SysRq-k 安全訪問鍵,殺死這個(gè)控制臺上的所有程序
            SysRq-l 向包括init的所有的進(jìn)程發(fā)送SIGKILL信號
            SysRq-m 所內(nèi)核信息輸出到控制臺
            SysRq-o 關(guān)閉機(jī)器
            SysRq-p 所寄存器的信息輸出到控制臺
            SysRq-r 關(guān)閉鍵盤原始模式
            SysRq-s 把所有已安裝文件系統(tǒng)刷新到磁盤
            SysRq-t 所任務(wù)信息輸出到控制臺
            SysRq-u 卸載所有已安裝文件系統(tǒng).
            152.內(nèi)核調(diào)試的利器: kdb

            chapter 19
            153.人們通常所說的機(jī)器是多少位,它們其實(shí)說的是機(jī)器的字長是多少位,也就是一個(gè)字的bit數(shù).
            154.處理器的通用寄存器的大小和它的字長是相同的。對于一般的體系結(jié)構(gòu)來說,它的各個(gè)部件的寬度,比如,內(nèi)存總線--最少要和它的字長一樣大,地址空間的大小也等于字長.
            155.Linux類型總對應(yīng)于機(jī)器的字長.所以,我們可以通過 sizeof( long ) 為4還是8來判斷是32位機(jī)還是64位機(jī).一個(gè)指針變量的大小與寄存器的字節(jié)一致。32位機(jī)上是4字節(jié),64位機(jī)上是8字節(jié).
            156.一個(gè)char的長度恒為 8 bit。在Linux支持的所有的系統(tǒng)上,int 為 32 bit
            157.數(shù)據(jù)對齊:
             對齊是跟數(shù)據(jù)塊在內(nèi)存中的位置相關(guān)的話題,如果一個(gè)變量的內(nèi)存地址正好是它的長度的整數(shù)倍,那么它就被稱為自然對齊.舉例來說,對于一個(gè)32位類型的數(shù)據(jù),如果它在內(nèi)存中的地址剛好可以被4整除,也就是地址的最低兩位為0,那它就是自然對齊的,也就是說同個(gè)大小為2n字節(jié)的數(shù)據(jù)類型,它的地址的最低有效痊的后N位都應(yīng)該是0.一些體系結(jié)構(gòu)對對齊的要求非常嚴(yán)格,通常基于RISC的系統(tǒng),載入未對齊的數(shù)據(jù)會導(dǎo)致處理器陷入(一種可處理的錯(cuò)誤).還有一些系統(tǒng)可以訪問沒有對齊的數(shù)據(jù),只不過性能會下降,編寫可移植的代碼要避免對齊問題,保證所有的類型都能夠自然對齊.
            158.避免對齊引發(fā)的問題
            通常編譯器會通過讓所有的數(shù)據(jù)自然對齊來避免引發(fā)對齊問題,實(shí)際上,內(nèi)核開發(fā)者不用在對齊上花費(fèi)太多心思,只有搞GCC的那些老兄才應(yīng)該為此犯愁。可是當(dāng)程序員使用指針太多時(shí),數(shù)據(jù)的訪問方式走出編譯器的預(yù)期時(shí),就會引發(fā)問題了。
            一個(gè)數(shù)據(jù)類型長度較小,它本來是對齊的,如果你用一個(gè)指針進(jìn)行類型轉(zhuǎn)換,并且轉(zhuǎn)換后的類型長度較大,那么通過解引用指針進(jìn)行數(shù)據(jù)訪問時(shí)就會引發(fā)對齊問題(無論如何,對于某些體系結(jié)構(gòu)確實(shí)存在這種問題),也就是說,下面的代碼是錯(cuò)誤的:
            char dog[10];
            char *p = &dog[ 1 ];
            unsigned long l = *( unsigned long *)p;
            這個(gè)盒子將一個(gè)指向char型的指針當(dāng)作指向unsigned long型的指針來用,這會引起問題,因?yàn)榇藭r(shí)試圖從一個(gè)不能被4整除的內(nèi)存地址上載入32位的unsigned long 型的數(shù)據(jù).
            159.非標(biāo)準(zhǔn)類型的對齊
            前面說到了,對于標(biāo)準(zhǔn)數(shù)據(jù)類型來說,它的地址只要是長度的整數(shù)倍就對齊了,而非標(biāo)準(zhǔn)類型的C結(jié)構(gòu)體按照下列規(guī)則對齊:
             a. 對于數(shù)組,只要按照基本數(shù)據(jù)類型對齊就可以了(其實(shí)隨后的所有的元素自然能夠?qū)R)
             b. 對于聯(lián)合,只要它包含的長度最大的數(shù)據(jù)類型能夠?qū)R就可以了。
             c. 對于結(jié)構(gòu)體,只要它包含的長度最大的數(shù)據(jù)類型能夠?qū)R就可以了,也就是結(jié)構(gòu)體整體上來按結(jié)構(gòu)體中長度最大的一個(gè)成員來對齊,這就是說,結(jié)構(gòu)體的最終的大小要是其長度最大的成員的大小的整數(shù)倍;同時(shí),對于結(jié)構(gòu)體中的每一個(gè)成員,都要自身按照對應(yīng)的規(guī)則進(jìn)行對齊.
            160.為了保證結(jié)構(gòu)體中的每一個(gè)成員都能夠自然對齊,結(jié)構(gòu)體要進(jìn)行“對齊填補(bǔ)”.

            161.ANSI C 標(biāo)準(zhǔn)明確規(guī)定:不允許編譯器改變結(jié)構(gòu)體成員的順序.
            162.內(nèi)核開發(fā)者需要注意結(jié)構(gòu)體填補(bǔ)問題,特別是在整體使用時(shí),這是指當(dāng)需要通過網(wǎng)絡(luò)發(fā)送它們或是需要將它們寫入文件的時(shí)候,因?yàn)椴煌捏w系結(jié)構(gòu)之間需要的填補(bǔ)也不盡相同,這也是為什么C沒有提供一個(gè)內(nèi)建的結(jié)構(gòu)體比較操作符的原因之一,結(jié)構(gòu)體內(nèi)的填充字節(jié)可能會包含垃圾信息,所以,在結(jié)構(gòu)體之間進(jìn)行一字節(jié)一字節(jié)的比較就不大可能了。
            163.因?yàn)榻Y(jié)構(gòu)體可能有填充對齊的問題,所以,對于不同的相同類型的結(jié)構(gòu)體對象,不能直接使用
            memcmp來比較,而要直接成員之間的比較.
            164.字節(jié)序:
             字節(jié)序是指一個(gè)字中各個(gè)字節(jié)的順序。處理器在對字取值時(shí),既可能將最低有效位所在的字節(jié)作為每一個(gè)字節(jié)(最左邊的字節(jié)),也可能將其作為最后一個(gè)字節(jié)(最右邊的字節(jié)).如果最高有效位放在最高位上,其它的字節(jié)依次放在低字節(jié)位置上,那么這種字節(jié)序稱為:高位優(yōu)化(big endian);如果最低有效位放在最高位上,那么這種字節(jié)序稱為:低位優(yōu)先(little endian )
            165.編寫可移植的代碼
            a. 編碼盡量取最大公因子:假定任何事情都可能發(fā)生,任何潛在的約束也都存在
            b. 編碼盡量選取最小公約數(shù):不要假定給定的內(nèi)核特性是可用的,且僅僅需要最小的體系結(jié)構(gòu)功能.


            chapter 20
            166.內(nèi)核開發(fā)的優(yōu)秀站點(diǎn):
             www.kernel.org
             www.kernelnew-bies.org
             www.lwn.org
             www.kerneltraffix.org

             


             

            posted on 2010-03-03 23:23 luckycat 閱讀(7679) 評論(4)  編輯 收藏 引用 所屬分類: 開卷有益

            評論:
            # re: 《Linux Kernel Development》讀書筆記[未登錄] 2010-03-04 09:49 | zuhd
            好文章,收藏仔細(xì)閱讀  回復(fù)  更多評論
              
            # re: 《Linux Kernel Development》讀書筆記 2010-03-04 10:57 | Tuotoo
            欽哥?  回復(fù)  更多評論
              
            # re: 《Linux Kernel Development》讀書筆記 2011-04-22 17:39 | roczhang
            剛買了一本,到貨,準(zhǔn)備看了  回復(fù)  更多評論
              
            # re: 《Linux Kernel Development》讀書筆記 2012-03-11 01:58 | le
            Re.98:
            關(guān)于中譯本自旋鎖的一處翻譯錯(cuò)誤。第98條,
            "在中斷處理程序中使用自旋鎖時(shí)???"
            對比原文此段意思應(yīng)為:
            "如果一個(gè)自旋鎖需要被中斷處理程序使用,那么(在任何地方)獲取此鎖時(shí)都要屏蔽當(dāng)前處理器中斷???"  回復(fù)  更多評論
              

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            久久99热这里只有精品国产| 国产精品一久久香蕉产线看| 久久精品国产秦先生| 久久精品三级视频| 久久丫精品国产亚洲av不卡| 噜噜噜色噜噜噜久久| 武侠古典久久婷婷狼人伊人| 久久久久久青草大香综合精品| 日本欧美久久久久免费播放网| 91久久精品国产成人久久| 热99re久久国超精品首页| 91精品久久久久久无码| 久久久久国产精品熟女影院| 久久99精品综合国产首页| 亚洲午夜久久久久妓女影院 | 夜夜亚洲天天久久| 久久久受www免费人成| 无码人妻久久一区二区三区免费| 亚洲精品蜜桃久久久久久| 人人狠狠综合久久亚洲| 亚洲国产高清精品线久久| 亚洲伊人久久大香线蕉综合图片 | 中文国产成人精品久久不卡| 久久久久久噜噜精品免费直播 | 国产美女久久精品香蕉69| 欧美日韩中文字幕久久伊人| 国产成人精品久久一区二区三区av | 国产精品久久久久影视不卡| 狠狠色婷婷久久一区二区三区| 久久国产欧美日韩精品| 伊人久久精品无码二区麻豆| 亚洲精品乱码久久久久久自慰| 精品久久人人爽天天玩人人妻| 亚洲精品tv久久久久久久久| 无码国内精品久久人妻蜜桃| 久久久久久国产精品美女| 色欲综合久久躁天天躁蜜桃| 久久综合狠狠综合久久综合88 | 久久99精品久久久久久久久久| 国产精品毛片久久久久久久| 亚洲狠狠久久综合一区77777|