色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

從微觀角度來看Linux內核設計

Linux閱碼場 ? 來源:未知 ? 作者:李倩 ? 2018-11-15 16:29 ? 次閱讀

◆◆從微觀角度來看Linux內核設計◆◆

余生皆歡喜

最近總結出來學習內核有兩個大的角度,一種就是從宏觀角度來看,總的來說就是順著抽象,管理,操作來看,這種角度更多的是內核中應用層面的內容,用來理解內核中是怎么運轉起來的。第二種就是從內核的最細節部分出發,深入到一個個具體的宏,看看內核設計者在細節部分有著怎么樣的巧妙之處,這樣也有助于我們夯實C語言基礎,也可以學習到GNU C的用法。

最近學習了如下的GNU C的內容:

指定初始化

語句表達式

typeof關鍵字

內核第一宏

我們來看看這些內容是怎么設計的,GNU C就是打輔助的,專門為了OS而存在,(為什么全世界不統一使用GNU C呢?)它帶來了太多的方便,換句話說,它幫助內核設計人員解決了很多內核設計者在設計內核時所遇到的問題,我這樣認為,GNU C中每一條功能,就是內核設計者在實際設計中遇到的問題。

這里再次分析總結gitbook中的兩個宏,一個是max/min宏,一個是內核第一宏container_of。

max/min宏

內核中的樣子:

這里的max宏可以讓我們學會語句表達式,typeof關鍵字;基礎方面可以鞏固運算符優先級。

這個宏是怎么得到的呢?

我們來寫一個宏,用來比較兩個變量的大小,我一定會這么寫:

那么我們來比較一下4!=4和2!=3,結果是錯誤的,原因是運算符優先級出了問題。那么我們來解決,使用括號是最簡單的方法:

我們來運行一條語句:printf("max = %d\n",3 + MAX(4,5));,結果是7,這里是因為+的運算優先級大于>了,換句話說,是因為外部的語句,影響到了宏,那么我就把自己隔離起來:

再來運行一下printf("max=%d\n",MAX(2++,3++));,輸出的會是4,但我們只想要比較2和3的值,這里是因為自增自減運算符導致的問題,那么怎么解決呢?和交換兩個數字的想法一樣,通過一個中轉值來存放,就可以隔離影響了

這里就有一些內核代碼中的味道了,注意一個細節,這里的第四行沒有括號了,為什么?這里就是因為語句表達式了,不存在上面的影響了。這里我們回顧一下代碼,再看看目前這個宏的第二三行,是int,也就是我們這個宏只能比較int類型的變量,而在內核中需要比較大小的變量有很多,那么我們來提高一下:

這個宏就可以用來比較任意類型的變量了,再來看一下代碼,我們需要替換的變量有type,x,y三個,如果有了typeof關鍵字,我們還可以減少一個:

接著來,如果我們使用了一次宏,是MAX(i,j),其中i是int類型,j是float類型,這樣比較是可以的,但是在內核的設計過程之中,很有可能有些地方會出現問題,所以還需要改造:

這就是究極形態了,我們添加了第四行的代碼,來看&_min1,它的意思是取_min1的地址,而&_min2的意思是取_min2的地址,我們也知道,這兩個地址肯定不可能是一樣的,那為什么還要這樣寫呢?這里就很巧妙了,當兩個變量的類型不同時,對應的地址,也就是指針類型也不相同,比如一個是int類型,一個是char類型,那么指向他們的指針就是int *和char *,這兩個指針在比較的時候,就比較的是類型了。如果比較的類型不一樣,gcc會警告的。

我們來看這一系列改進,我相信內核設計人員也想把代碼寫成# define MAX(x,y) x > y? x : y的樣子,但是現實是殘酷的,我們為了代碼的健壯性,就必須這樣一步一步來改進,所以,內核代碼看起來很復雜,又很巧妙,是因為我們直接看到的是究極形態的代碼,它是向現實妥協了多次以后的產物,也就是健壯性+GNU C。但是,內核設計者的初衷,或者說最初的想法和我們都是一樣的。

有內核源碼在旁邊,鞏固基礎知識就不用像以前的學習模式了,可以在源碼中代入學習,增添一份趣味性,并且可以很快理解。

在以后處理因為運算符而導致的問題的時候,使用括號是最方便的,內核就這么干了。

在寫程序的時候,要巧用中轉變量,雖然只是簡單的存入另一個變量之中,但是代碼的健壯性提高了很多。

兩個地址在進行比較的時候,我們可以得知這兩個指針類型是否一致。

內核第一宏

gitchat中把container_of宏叫做內核第一宏,我也很喜歡這個稱號,因為學內核兩個月里見這個宏的次數太多了。在陳老師講list.h的時候,就學習過這個宏,但是并沒有完完全全地剖析開。

高能預警:

這個宏的作用我們已經很清楚了,根據結構體中某一成員的地址,就可以獲得這個結構體的首地址,再說的明白一點,假如你是內核設計人員,前面也說道了,我們已經對數據進行了多次封裝,我們一定會遇到這種情況:傳給某個函數的參數是某個結構體成員變量,但是我們在這個函數中還想使用這個結構體的其它成員變量,這個時候就需要想辦法,于是才有了我們現在看到的這個內核第一宏。

它的三個參數是:

ptr:此結構體內成員member的地址

type:此結構體類型

member:此結構體內的成員

我們直接看代碼,這個宏的最后的值,就是最后一條語句,(type *)( (char *)__mptr - offsetof(type,member) );}),這條語句也是這個宏的中心思想拿結構體成員的地址減去此成員的偏移,這里也體現了指針做減法是很有意義的。成員的地址好說,我們直接傳進來了,偏移是通過offsetof來實現的,來看看這個offsetof:將0強制類型轉換成這個結構體的指針類型,然后訪問這個成員,加上&得到它的偏移,返回。這里要注意一下,那就是為什么只通過TYPE和MEMBER就可以得到偏移,我一開始認為的是內核中這個類型的結構體多了,到底用的是哪一個結構體來得到的,最后發現,并沒有關系,因為我們需要的是字節數,與實際這個字段賦什么樣的值并沒有關系,因為所有這個類型的結構體中,各成員的字節大小是一樣的。

再來看(char *)__mptr,這個通過第四行代碼可以很容易得出它是成員的地址,為什么要強制轉換成char *呢?轉換成int *不行嗎?這里又可以學習一下C指針的基礎知識,通過代碼可以很容易知道有什么區別:

打印出來的值,p(int *)類型,增加了4字節,而q(char *)增加了1字節,回到宏中,我們的偏移是按照字節來算的,所以不能使用(int *),必須使用(char *)。在最后,再次強制類型轉換成指向這個結構體的指針類型。

回過頭來看第四行代碼,const typeof( ((type *)0)->member ) *__mptr = (ptr);,這里和max宏之中類似,使用了中轉變量來存放,這里為什么要使用中轉變量?max宏中是為了防止自增自減的影響(當然只是原因之一了),但我們在使用的時候總不至于發過來成員的地址再加一個++運算符吧。我們可以從const的用法來思考,const int * p //p可變,p指向的內容不可變,所以,使用了const,我們就可以保證ptr指向的內容在這里只是可讀的,這也許就是為什么使用中轉變量的原因,為了防止我們通過指針改變了原有的成員的值,畢竟指針雖然強大,但也是很危險的,所以,這里的中轉要配合const來使用。既然是中轉,那么類型就必須要求一致了,所以我們要得到和這個成員一致的類型,就通過typeof來得到了,將0強制類型轉換成這個這個結構體的指針類型,然后訪問這個變量,(注意仔細看代碼,這里的代碼和offsetof非常類似)這里沒有使用&,所以只是訪問到變量了,沒有得到偏移。另外根據const的用法,第四行的代碼也可以寫成typeof( ((type *)0)->member ) const *__mptr = (ptr);也就是把const放到后面。

我們再來注意一個細節,就是offsetof里的size_t,這個是什么,這里在敲代碼的過程中偶然學到一個小技巧,就是這個size_t絕對是封裝,就是C語言中那幾種變量類型,我們可以typedef int size_t;然后運行,gcc就會報錯,并且會給你顯示:以前已經定義過:typedef __SIZE_TYPE__ size_t,并且會指定這個值在哪個文件,我們就可以知道它的真面目了。換句話說,gcc這么強大,我們當然可以把它當做一個學習工具來使用。

另外還可以通過sublime,可以很快找到它的真面目(3.10版本):

最后,為了更深入理解這些知識的使用方法,還是需要自己動手來敲代碼的,尤其是內核第一宏,將代碼寫到用戶態下,然后瘋狂改造,這樣才會真正理解這個宏。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11320

    瀏覽量

    209832
  • C語言
    +關注

    關注

    180

    文章

    7608

    瀏覽量

    137111
  • 代碼
    +關注

    關注

    30

    文章

    4801

    瀏覽量

    68735

原文標題:趙晨雨: 從微觀角度來看linux內核設計

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux內核data段和bss段的區別

    進程的角度Linux內核是采用虛擬地址空間的,如下兩張圖所示,分別為32位、64位系統下進程地址空間的大概布局。
    發表于 10-13 17:07 ?9030次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b>data段和bss段的區別

    Linux內核中系統調用詳解

    Linux內核中設置了一組用于實現各種系統功能的子程序,稱為系統調用。用戶可以通過系統調用命令在自己的應用程序中調用它們。某種角度來看,系
    發表于 08-23 10:37 ?798次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b>中系統調用詳解

    Linux內核教程

    本章學習目標掌握LINUX內核版本的含義理解并掌握進程的概念掌握管道的概念及實現了解內核的數據結構了解LINUX內核的算法掌握
    發表于 04-10 16:59 ?0次下載

    linux內核啟動流程

    Linux的啟動代碼真的挺大,匯編到C,Makefile到LDS文件,需要理解的東西很多。畢竟Linux內核是由很多人,花費了巨大的時間
    發表于 11-14 16:19 ?4358次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內核</b>啟動流程

    Linux 內核才是真正的規則改變者

    Linux 內核被稱為創新,但它又被稱為現代計算中最大的奇跡,一個微觀世界中的龐然大物。
    發表于 09-28 01:31 ?728次閱讀

    Linux內核架構--基本概念

    首先,Linux整體的架構如圖: 再來看Linux內核架構, 內核由五個主要子系統組成: Process Scheduler : 進程調度(
    發表于 05-20 09:28 ?747次閱讀

    linux內核是什么_linux內核學習路線

    Linux內核是一個操作系統(OS)內核,本質上定義為類Unix。它用于不同的操作系統,主要是以不同的Linux發行版的形式。Linux
    發表于 09-16 15:49 ?2657次閱讀

    linux內核參數設置_linux內核的功能有哪些

    本文主要闡述了linux內核參數設置及linux內核的功能。
    發表于 09-17 14:40 ?1383次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內核</b>參數設置_<b class='flag-5'>linux</b><b class='flag-5'>內核</b>的功能有哪些

    最硬核的Linux內核文章

    來源 :頭條號@Linux學習教程,冰凌塊兒 01 前言 本文主要講解什么是Linux內核,以及通過多張圖片展示Linux內核的作用與功能,
    的頭像 發表于 10-19 17:46 ?2135次閱讀
    最硬核的<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>文章

    快速理解什么是Linux內核以及Linux內核的內容

    01 前言 本文主要講解什么是Linux內核,以及通過多張圖片展示Linux內核的作用與功能,以便于讀者能快速理解什么是Linux
    的頭像 發表于 10-21 12:02 ?4309次閱讀
    快速理解什么是<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>以及<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>的內容

    如何使用Linux內核實現USB驅動程序框架

    Linux內核提供了完整的USB驅動程序框架。USB總線采用樹形結構,在一條總線上只能有唯一的主機設備。 Linux內核主機和設備兩個
    發表于 11-06 17:59 ?20次下載
    如何使用<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>實現USB驅動程序框架

    Linux環境編程:應用到內核

    Linux環境編程:應用到內核資料下載。
    發表于 06-01 14:51 ?18次下載

    軟件角度分析linux內核USB子系統的熱插拔過程

    本文軟件角度分析linux內核USB子系統的熱插拔過程,以實際分析思路和過程行文,基于linux內核
    的頭像 發表于 01-15 09:28 ?5712次閱讀

    linux內核源代碼詳解

     在安裝好的Linux系統中,內核的源代碼位于/ust/src/linux.如果是GNU網站下載的Linux
    發表于 09-06 17:01 ?4次下載

    C++在Linux內核開發中爭議到成熟

    Linux 內核郵件列表中一篇已有六年歷史的老帖近日再次引發激烈討論 —— 主題是建議將 Linux 內核的開發語言 C 轉換為更現代的
    的頭像 發表于 01-31 14:11 ?649次閱讀
    C++在<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>開發中<b class='flag-5'>從</b>爭議到成熟
    主站蜘蛛池模板: 亚洲国产成人精品久久久久| 3a丝袜论坛| caoporon超碰在线视频| 年轻的母亲4线在线观看完整| 99视频精品全部免费免费观| 日本护士喷水| 国产又粗又黄又爽的大片| 亚洲永久免费视频| 魔乳 堕乳漫画acg产卵| 囯产精品久久久久久久久免费蜜桃| 亚洲国产精品免费线观看视频| 久久久久久91香蕉国产| younv 学生国产在线视频| 性做久久久久免费观看| 麻豆国产人妻精品无码AV| 动漫美女性侵| 伊人大香人妻在线播放| 人与禽交3d动漫羞羞动漫| 国产三级级在线电影| 91久久偷偷看嫩草影院无费| 四虎永久在线精品国产免费| 久久久中日AB精品综合| 福利视频久久| 1234成人网| 迅雷哥在线观看高清| 欧美gay老头互吃| 国产香蕉视频在线播放| FREE乌克兰嫩交HD| 亚洲色欲国产免费视频| 日韩精品免费在线观看| 久久两性视频| 国产乱对白精彩在线播放| 97色伦图片7778久久| 亚洲国产精麻豆| 日本护士性生活| 口工漫画r18全彩啪啪| 国产日韩亚洲专区无码| 被窝国产理论一二三影院| 一本色道久久综合亚洲精品蜜桃冫 | 火影忍者高清无码黄漫| 第一会所欧美无码原创|