學Linux內核的作用與方法?

第一次發知乎提問,不懂知乎規矩還請包涵

我就是在嵌入式培訓機構中的萌寵。培訓機構培訓內容太多時間太少,我現在想從事的方向是Linux驅動與移植。但是現在學內核的時候感覺很迷茫。

不知道怎麼下手?

不知道學內核的目的?

不知道應該怎樣正確有效的學內核?

不知道怎樣讀代碼?


先寫C語言,有個2萬行代碼量。再懂點彙編。

然後買個開發板,最好先找對應的視頻看。

因為一有個人出氣自己也不會覺得無聊,韋山東的視頻還算不錯。

做到這裡你可以算是了解了。

二就是看linux kernel development 這本書入門

內存管理和文件系統比較繞,看不懂也沒關係。

看完這本書你大致就對linux內核有個模糊的了解,就可以跟你同事吹比紅黑樹和內核優先順序演算法了。也能獲得一些成就感。

看書同時也得寫你的C,應該也有3W行水平了,除去一些噁心人的宏定義,依賴關係,預處理指令苦手以外。大部分的程序拿來就知道他這步幹了啥,不求你懂意思。

這時候你應該也找到一份工作了,跟著工作裡面的內容開始專心研究裡面的驅動代碼,建議從簡單的字元設備研究開始,比如按鍵,比如led燈。

這時候和看視頻那個階段不一樣,那時候是跟著過程溜。現在是自己研究寫,找BUG,想設計還是不一樣的。

慢慢的你寫到上千行驅動代碼,就會更加深入的去了解別的驅動,比如塊設備,網路設備,內存,啟動步驟等等。

這時候可以看看宋寶華寫的linux設備驅動開發詳解。(極不推薦一開始就看他的書,他的書目的性太強,只能教你填充結構體,使用那個函數,並不告訴你為什麼,你跟著他的那個globalmem寫下來也是一頭霧水)這本書應該給有一定驅動研發基礎,想了解別的驅動應該怎麼寫的人。

(或者你根本不想研究,學會他的寫作方法應付大部分常見驅動代碼也沒問題。)

你學會了塊設備,字元設備,也擅長各種鎖各種資源共享了。解決竟態也輕車路熟.甚至也懂了OOPS這些內核調試方法。但是你仍舊覺得這玩意好煩,還是一頭霧水。

你該去看Understanding the Linux Kernel,較深入的了解一下linux 內核的運行機制。這時候你豁然開朗,明白了自己寫的驅動只是浮雲,也懂了為什麼會加鎖,為什麼在寫驅動的時候使用那些函數。

這時候你也要工作兩年了,你對某個模塊應該有更深入的了解了。比如usb 比如wifi,usb可以去看fudan_abc寫的usb的那些事兒,你對大多數函數結構體不陌生看這些有一種心心相印的感覺。再也不會覺得繁雜和苦手。你在他的陪伴下已經可以讀明白源碼,你看到了BUG也沒那麼害怕了。因為她就是在你床前脫光了的粉頭。

了解的越多,你發現你會的越少,於是你開始悶頭喝酒讀代碼。寫kernel,你在公司已經是骨幹員工。但是你又覺得少了點什麼。

朋友,是時候訂閱郵件列表,讓Linus 感受一波你蹩腳的英文和bug無數的update。

你要報雅思,你要上模電,你不允許自己看到三極體不能一眼判斷PN結導通還是截至,你看不起前端,"你也配叫碼農?"你開始會C++ ,會JAVA。會用樹莓派晶元A20 自己畫板子,搞一個分散式的伺服器。

你突然覺得linux也不過爾爾,一切被自己踩在腳下……

可那時候,頭髮花白,十年……都過去了


開篇

學習內核,每個人都有自己的學習方法,仁者見仁智者見智。以下是我在學習過程中總結出來的東西,對自身來說,我認為比較有效率,拿出來跟大家交流一下。

內核學習,一偏之見;疏漏難免,懇請指正。

剛開始學內核的時候,不要執著於一個方面,不要專註於一個子系統就一頭扎到實際的代碼行中去,因為這樣的話,牽涉的面會很廣,會碰到很多困難,容易產生挫敗感,一個函數體中(假設剛開始的時候正在學習某個方面的某個具體的功能函數)很可能摻雜著其他各個子系統方面設計理念(多是大量相關的數據結構或者全局變數,用於支撐該子系統的管理工作)下相應的代碼實現,這個時候看到這些東西,紛繁蕪雜,是沒有頭緒而且很不理解的,會產生很多很多的疑問,(這個時候如果對這些疑問糾纏不清,刨根問底,那麼事實上就是在學習當前子系統的過程中頻繁的去涉足其他子系統,這時候注意力就分散了),而事實上等了解了各個子系統後再回頭看這些東西的話,就簡單多了,而且思路也會比較清晰。所以,要避免 「只見樹木,不見森林」,不要急於深入到底層代碼中去,不要過早研究底層代碼。

我剛開始接觸內核,就犯了這個錯誤,一頭扎到內存管理裡頭,去看非常底層的實現代碼,雖然也是建立在內存管理的設計思想的基礎上,但是相對來說,比較孤立,因為此時並沒有學習其它子系統,應該說無論是視野還是思想,都比較狹隘,所以代碼中牽涉到的其它子系統的實現我都直接跳過了,這一點還算聰明,當然也是迫不得已的。

我的學習方法

開始學習的時候,最主要的問題在於你知道不知道,而不是理解不理解,某個子系統的實現採用了某種策略、方法,而你在學習中需要做的就是知道有這麼一回事兒,然後才是理解所描述的策略或者方法。

根據自己的學習經驗,剛開始學習內核的時候,我認為要做的是在自己的腦海中建立起內核的大體框架,理解各個子系統的設計理念和構建思想,這些理念和思想會從宏觀上呈獻給你清晰的脈絡,就像一個去除了枝枝葉葉的大樹的主幹,一目了然;當然,肯定還會涉及到具體的實現方法、函數,但是此時接觸到的函數或者方法位於內核實現的較高的層次,是主(要)函數,已經了解到這些函數,針對的是哪些設計思想,實現了什麼樣的功能,達成了什麼樣的目的,混個臉熟的說法在這兒也是成立的。至於該主函數所調用的其它的輔助性函數就等同於枝枝葉葉了,不必太早就去深究。此時,也就初步建立起了內核子系統框架和代碼實現之間的關聯,關聯其實很簡單,比如一看到某個函數名字,就想起這個函數是針對哪個子系統的,實現了什麼功能。

我認為此時要看的就是LKD3,這本書算是泛泛而談,主要就是從概念,設計,大的實現方法上描述各個子系統,而對於具體的相關的函數實現的代碼講解很少涉及(對比於ULK3,此書主要就是關於具體函數代碼的具體實現的深入分析,當然,你也可以看,但是過早看這本書,會感覺很痛苦,很枯燥無味,基本上都是函數的實現),很少,但不是沒有,這就很好,滿足我們當前的需求,還避免我們過早深入到實際的代碼中去。而且本書在一些重要的點上還給出了寫程序時的注意事項,算是指導性建議。主要的子系統包括:內存管理,進程管理和調度,系統調用,中斷和異常,內核同步,時間和定時器管理,虛擬文件系統,塊I/O層,設備和模塊。(這裡的先後順序其實就是LKD3的目錄的順序)。

我學習的時候是三本書交叉著看的,先看LKD3,專於一個子系統,主要就是了解設計的原理和思想,當然也會碰到對一些主要函數的介紹,但大多就是該函數基於前面介紹的思想和原理完成了什麼樣的功能,該書並沒有就函數本身的實現進行深入剖析。然後再看ULK3和PLKA上看同樣的子系統,但是並不仔細分析底層具體函數的代碼,只是粗略地、不求甚解地看,甚至不看。因為,有些時候,在其中一本書的某個點上,卡殼了,不是很理解了,在另外的書上你可能就碰到對同一個問題的不同角度的描述,說不準哪句話就能讓你豁然開朗,如醍醐灌頂。我經常碰到這種情況。

並不是說學習過程中對一些函數體的實現完全就忽略掉,只要自己想徹底了解其代碼實現,沒有誰會阻止你。我是在反覆閱讀過程中慢慢深入的。比如VFS中文件打開需要對路徑進行分析,需要考慮的細節不少(.././之類的),但是其代碼實現是很好理解的。再比如,CFS調度中根據shedule latency、隊列中進程個數及其nice值(使用的是動態優先順序)計算出分配給進程的時間片,沒理由不看的,這個太重要了,而且也很有意思。

ULK3也會有設計原理與思想之類的概括性介紹,基本上都位於某個主題的開篇段落。但是更多的是對支持該原理和思想的主要函數實現的具體分析,同樣在首段,一句話綜述函數的功能,然後對函數的實現以1、2、3,或者a、b、c步驟的形式進行講解。我只是有選擇性的看,有時候對照著用source insight打開的源碼,確認一下代碼大體上確實是按書中所描述的步驟實現的,就當是增加感性認識。由於步驟中摻雜著各種針對不同實現目的安全性、有效性檢查,如果不理解就先跳過。這並不妨礙你對函數體功能實現的整體把握。

PLKA介於LKD3和ULK3之間。我覺得PLKA的作者(看照片,真一德國帥小伙,技術如此了得)肯定看過ULK,無論他的本意還是有意,總之PLKA還是跟ULK有所不同,對函數的仔細講解都做補充說明,去掉函數體中邊邊角角的情況,比如一些特殊情況的處理,有效性檢查等,而不妨礙對整個函數體功能的理解,這些他都有所交代,做了聲明;而且,就像LKD3一樣,在某些點上也給出了指導性編程建議。作者們甚至對同一個主要函數的講解的著重點都不一樣。這樣的話,對我們學習的人而言,有助於加深理解。另外,我認為很重要的一點就是PLKA針對的2.6.24的內核版本,而ULK是2.6.11,LKD3是2.6.34。在某些方面PLKA比較接近現代的實現。其實作者們之所以分別選擇11或者24,都是因為在版本發行樹中,這兩個版本在某些方面都做了不小的變動,或者說是具有標誌性的轉折點(這些信息大多是在書中的引言部分介紹的,具體的細節我想不起來了)。

Intel V3,針對X86的CPU,本書自然是系統編程的權威。內核部分實現都可以在本書找到其根源。所以,在讀以上三本書某個子系統的時候,不要忘記可以在V3中相應章節找到一些基礎性支撐信息。

在讀書過程中,會產生相當多的疑問,這一點是確信無疑的。 大到搞不明白一個設計思想,小到不理解某行代碼的用途。各個方面,各種疑問,你完全可以把不理解的地方都記錄下來(不過,我並沒有這麼做,沒有把疑問全部記下來,只標記了很少一部分我認為很關鍵的幾個問題),專門寫到一張紙上,不對,一個本上,我確信會產生這麼多的疑問,不然內核相關的論壇早就可以關閉了。其實,大部分的問題(其中很多問題都是你知道不知道有這麼一回事的問題)都可以迎刃而解,只要你肯回頭再看,書讀百遍,其義自現。多看幾遍,前前後後的聯繫明白個七七八八是沒有問題的。我也這麼做了,針對某些子系統也看了好幾遍,切身體會。

當你按順序學習這些子系統的時候,前面的章節很可能會引用後面的章節,就像PLKA的作者說的那樣,完全沒有向後引用是不可能的,他能做的只是盡量減少這種引用而又不損害你對當前問題的理解。不理解,沒關係,跳過就行了。後面的章節同樣會有向前章節的引用,不過這個問題就簡單一些了 ,你可以再回頭去看相應的介紹,當時你不太理解的東西,很可能這個時候就知道了它的設計的目的以及具體的應用。不求甚解只是暫時的。比如說,內核各個子系統之間的交互和引用在代碼中的體現就是實現函數穿插調用,比如你在內存管理章節學習了的內存分配和釋放的函數,而你是了解內存在先的,在學習驅動或者模塊的時候就會碰到這些函數的調用,這樣也就比較容易接受,不至於太過茫然;再比如,你了解了系統時間和定時器的管理,再回頭看中斷和異常中bottom half的調度實現,你對它的理解就會加深一層。

子系統進行管理工作需要大量的數據結構。子系統之間交互的一種方式就是各個子系統各自的主要數據結構通過指針成員相互引用。學習過程中,參考書上在講解某個子系統的時候會對數據結構中主要成員的用途解釋一下,但肯定不會覆蓋全部(成員比較多的情況,例如task_struct),對其它子系統基於某個功能實現的引用可能解釋了,也可能沒做解釋,還可能說這個變數在何處會做進一步說明。所以,不要糾結於一個不理解的點上,暫且放過,回頭還可以看的。之間的聯繫可以在對各個子系統都有所了解之後再建立起來。其實,我仍然在強調先理解概念和框架的重要性。

等我們完成了建立框架這一步,就可以選擇一個比較感興趣的子系統,比如驅動、網路,或者文件系統之類的。這個時候你再去深入了解底層代碼實現,相較於一開始就鑽研代碼,更容易一些,而且碰到了不解之處,或者忘記了某個方面的實現,此時你完全可以找到相應的子系統,因為你知道在哪去找,查漏補缺,不僅完成了對當前函數的鑽研,而且可以回顧、溫習以前的內容,融會貫通的時機就在這裡了。

《深入理解linux虛擬內存》(2.4內核版本),LDD3,《深入理解linux網路技術內幕》,幾乎每一個子系統都需要一本書的容量去講解,所以說,剛開始學習不宜對某個模塊太過深入,等對各個子系統都有所了解了,再有針對性的去學習一個特定的子系統。這時候對其它系統的援引都可以讓我們不再感到茫然、複雜,不知所云。

比如,LDD3中的以下所列章節:構造和運行模塊,並發和競態,時間、延遲及延緩操作,分配內存,中斷處理等,都屬於驅動開發的支撐性子系統,雖說本書對這些子系統都專門開闢一個章節進行講解,但是詳細程度怎麼能比得上PLKA,ULK3,LKD3這三本書,看完這三本書,你會發現讀LDD3這些章節的時候簡直跟喝白開水一樣,太隨意了,因為LDD3的講解比之LKD3更粗略。打好了基礎,PCI、USB、TTY驅動,塊設備驅動,網卡驅動,需要了解和學習的東西就比較有針對性了。這些子系統就屬於通用子系統,了解之後,基於這些子系統的子系統的開發---驅動(需進一步針對硬體特性)和網路(需進一步理解各種協議)---相對而言,其學習難度大大降低,學習進度大大加快,學習效率大大提升。說著容易做來難。達到這樣一種效果的前提就是:必須得靜下心來,認真讀書,要看得進去,PLKA,ULK3厚得都跟磚頭塊兒一樣,令人望之生畏,如果沒有興趣,沒有熱情,沒有毅力,無論如何都是不行,因為需要時間,需要很長時間。我並不是說必須打好了基礎才可以進行驅動開發,只是說打好了基礎的情況下進行開發會更輕鬆,更有效率,而且自己對內核代碼的駕馭能力會更強大。這只是我個人見解,我自己的學習方式,僅供參考。

語言

PLKA是個德國人用德語寫的,後來翻譯成英文,又從英文翻譯成中文,我在網上書店裡沒有找到它的紙質英文版,所以就買了中文版的。ULK3和LKD3都是英文版的。大牛們寫的書,遣詞造句真的是簡潔,易懂,看原版對我們學習計算機編程的程序員來說完全不成問題,最好原汁原味。如果一本書確實翻譯地很好,我們當然可以看中文版的,用母語進行學習,理解速度和學習進度當然是很快的,不作他想。看英文的時候不要腦子裡想著把他翻譯成中文,沒必要。

API感想

「比起知道你所用技術的重要性,成為某一個特別領域的專家是不重要的。知道某一個具體API調用一點好處都沒有,當你需要他的時候只要查詢下就好了。」這句話源於我看到的一篇翻譯過來的博客。我想強調的就是,這句話針應用型編程再合適不過,但是內核API就不完全如此。

內核相當複雜,學習起來很不容易,但是當你學習到一定程度,你會發現,如果自己打算寫內核代碼,到最後要關注的仍然是API介面,只不過這些API絕大部分是跨平台的,滿足可移植性。內核黑客基本上已經標準化、文檔化了這些介面,你所要做的只是調用而已。當然,在使用的時候,最好對可移植性這一話題在內核中的編碼約定爛熟於心,這樣才會寫出可移植性的代碼。就像應用程序一樣,可以使用開發商提供的動態庫API,或者使用開源API。同樣是調用API,不同點在於使用內核API要比使用應用API了解的東西要多出許多。

當你了解了操作系統的實現---這些實現可都是對應用程序的基礎性支撐啊---你再去寫應用程序的時候,應用程序中用到的多線程,定時器,同步鎖機制等等等等,使用共享庫API的時候,聯繫到操作系統,從而把對該API的文檔描述同自己所了解到的這些方面在內核中的相應支撐性實現結合起來進行考慮,這會指導你選擇使用哪一個API介面,選出效率最高的實現方式。對系統編程頗有了解的話,對應用編程不無益處,甚至可以說是大有好處。

設計實現的本質,知道還是理解

操作系統是介於底層硬體和應用軟體之間的介面,其各個子系統的實現很大程度上依賴於硬體特性。書上介紹這些子系統的設計和實現的時候,我們讀過了,也就知道了,如果再深入考慮一下,為什麼整體架構要按照這種方式組織,為什麼局部函數要遵循這樣的步驟處理,知其然,知其所以然,如果你知道了某個功能的實現是因為晶元就是這麼設計的,CPU就是這麼做的,那麼你的疑問也就基本上到此為止了。再深究,就是晶元架構方面的設計與實現,對於程序員來講,無論是系統還是應用程序員,足跡探究到這裡,已經解決了很多疑問,因為我們的工作性質偏軟,而這些東西實在是夠硬。

比如,ULK3中講解的中斷和異常的實現,究其根源,那是因為Intel x86系列就是這麼設計的,去看看Intel V3手冊中相應章節介紹,都可以為ULK3中描述的代碼實現方式找到註解。還有時間和定時器管理,同樣可以在Intel V3 對APIC的介紹中獲取足夠的信息,操作系統就是依據這些硬體特性來實現軟體方法定義的。

又是那句話,不是理解不理解的問題,而是知道不知道的問題。有時候,知道了,就理解了。在整個學習過程中,知道,理解,知道,理解,知道……,交叉反覆。為什麼開始和結尾都是知道,而理解只是中間步驟呢?世界上萬事萬物自有其規律,人類只是發現而已,實踐是第一位的,實踐就是知道的過程,實踐產生經驗,經驗的總結就是理論,理論源於實踐,理論才需要理解。我們學習內核,深入研究,搞來搞去,又回到了晶元上,晶元是物質的,晶元的功用基於自然界中物質本有的物理和電子特性。追本溯源,此之謂也。

動手寫代碼

紙上得來終覺淺,絕知此事要躬行。只看書是絕對不行的,一定要結合課本給出的編程建議自己敲代碼。剛開始就以模塊形式測試好了,或者自己編譯一個開發版本的內核。一台機器的話,使用UML方式調試,內核控制路走到哪一步,單步調試看看程序執行過程,比書上的講解更直觀明了。一定要動手實際操作。

保持興趣

興趣的力量是無窮的。興趣能帶來激情,如果工作可以和興趣結合到一起,工作起來才會有熱情,那麼工作就不只是工作了,更是一種享受。


你想更深入了解學習Linux知識體系,你可以看一下我們花費了一個多月整理了上百小時的幾百個知識點體系內容:

【超全整理】《Linux雲計算從入門到精通》系列實戰筆記全放送


看到這題目,分享下這近五年嵌入式走的路。

大三下學期決心投身嵌入式,無它,門檻高,高效

並且當時認為計算機四大專業課,中只有嵌入可以涵蓋到,也是為了學以致用。畢業那年11年Android剛剛興起,很多人轉了JAVA,但是我找工作就一條原則,必須做嵌入式,傻呵呵的開始了……進入了一家做路由器的公司,選這家還有一個因素是包住宿,對於從家拿了兩千塊到上海的應屆生來說,這太誘惑了。要求很簡單,做嵌入式就行,其實我也不是很明白這個概念,只是覺得這個方向是對的。應屆生進去其實打雜為主,老司機也不樂意帶,做一些文檔,配置,測試這些,如果有一個小功能或者bug分給自己,開心的很,無論如何也要完成任務,不懂的,厚臉皮找老死機。這樣做了三個月,整個部門被挖走了,當然我這種菜鳥不會被挖……

不過,趁機轉了部門,轉的時候強烈要求不做『『客制化』』內容,我要coding,和經理談了多次,鬧的很不愉快,最後還是轉好了,因為接受我的組長希望多個人承擔工作,我主動去要工作,偷偷做,然後慢慢搬位置,最後做實了,終於成為了開發者。從web到linux應用程序,還有linux網路,畢竟做路由器。有天加班回來,臨入睡前在宿舍和室友聊天,突然茅塞頓開,理解了我們這產品軟體本質,路由器實現的本質,時至今日我寫的p2p產品,進程間通信模塊,都是這套原理,一通百通。半年過去了,功力長進,同時知道了bootloader,驅動,bsp概念,就多往樓上bsp部門跑腿,覺得這才是我想要的,真正的嵌入式。機會也來了,一家小晶元商來推產品,大家都覺得實驗貨搞不成,讓我這個應屆生和另外一個新人去應付下,後面這位新人離職了,結果fae為了推晶元,常駐公司熬夜加班,傾囊相授,並且我是甲方,對面這位fae態度很好,有問必答。我也趁機攔截一些bsp的活兒干,畢竟實際主導執行的是我,然後呢?我離職了……為了愛情離開了上海,在武漢的兩年過的異常艱難,稅後4k多,其實照行情也不少了。但是女友在讀研,一人負責兩人開銷和學費,一個月存1500,為了生活這份不喜歡的工作做了兩年,其中半年外包給華為,其實也是我主動要求去,想見識下華為,果然名不虛傳,華為不然帶優盤,上外網,我呢記筆記,三個月抄了四個筆記本,包括編程規範,代碼重構,調試技巧,以及晶元設計,軟體框架,原理,到最後我把可以搞到的資料覺得有用的全抄下來了。確實太棒了,理解了很多東西,並且養成了好的編碼習慣和技巧,後面三個月是忍無可忍了,因為分配的工作比打雜還不如,其實呢華為自己的員工也是自廢武功,一個人幾年來負責一個模塊和周邊東西,出來華為除了中興,就沒合適工作了,並且技能十分狹窄,最後不得不綁定到華為,不能跳槽……但是華為的管理確實一絕,尤其是如此體量的,比的過我到過的任何公司。後面一年半說是沒什麼內容,其實現在想想也不少,除了自學Python,還有做了一個企業交換機項目,理解了二層網路通信機制,做了大量組網測試,積累很多網路經驗,不要覺得簡單雖然大三課本上寫的很清楚,我後面回上海遇到一個思科空降的技術經理,我們在用FPGA模擬千兆網鏈路層通信的時候,發現他一無所知,這裡確實要黑思科,網通奠基者的技術骨幹就這水平……看來外企混日子的確實多,今天的intel也是如此,雖然剛入不久,但是也會在兩年內離開,感覺沒有新鮮血液吸收。離開武漢後面我回上海做了bsp……夢寐以求的uboot和驅動,甚至還有buildroot,玩了buildroot之後,博通在我心中的位置一落千丈,因為它已經無秘密可藏,不論是驅動,晶元配置,hal還是SDK架構,雖然不能面面俱到但是我心裡有底。這就是我要做底層軟體的原因,為了安全感,為了能看透本質,知道這一切花里胡哨的應用和中間件的根。最後,就是題主說的Kernel,這是我要去的最後一站,最為一個嵌入式軟體工程師,從應用層一直穿到Kernel,中間我多少次的爭取和忍耐和跳槽都是為了我的嵌入式夢。在intel面我的人,我記下了他的名字然後在Kernel源碼查提交信息找到了他貢獻的patch,確信我未來的老闆不是技術渣,安心入職,現在看這個方法挺對但是走向Kernel的路有問題。因為我現在發現學Kernel,只需要訂一個小系統或者模塊深挖就行,而不是我現在系統工程師,各個方面都插手。我最有背景的網路經驗在這裡很少遇到,浪費了經驗,所以準備以fastsocket等內核網路開源模塊入手,深挖,再擴展,波及其它模塊,如果不行……以我之前的性格,跳部門或者跳槽。

不論你想要做什麼,這個世界上給你的機會非常少,尤其是kernel這種稀少職位,門檻也很高。除非你很幸運,否則幾乎都要像我這樣一步步地挪,生活壓力,公司壓力,職業機遇……堅持夢想是需要勇氣的

十分感謝大家的鼓勵,因為本文中有一些情緒化的表達,還是匿名比較好。

說實話各個行業混飯吃容易,但是要優秀,努力是一定要的,但更多時候是不知道如何努力,甚至知道如何做但是沒機會。我在武漢遇到很多勤奮的同事,但公司總是給安排打雜的工作,甚至整個武漢分部就是打雜的,我推薦他們來上海,有人因為家庭,有人因為性格,各種原因,只能荒廢掉。大城市的神奇之處在於永遠給你機會,不論你起點如何,生物,歷史專業,只要想做it,一樣有公司要,甚至高中畢業也有的要,只要你能證明自己。


學內核看LDD和毛德操.


有很多基礎

C語言是重中之重,操作系統原理,硬體原理,都要懂一些,學習內存,Flash,進程,寄存器,文件系統,驅動框架,啟動過程,Linux的一些應用,linux Shell,當這些都差不多的時候,才可以去看源碼,

通過對linux的學習,可以鞏固你對計算機/嵌入式的認識,你會發現這簡直就是一個神奇的世界,什麼機器人,智能家居之類的簡直就是小意思,只要你想做,沒有你做不到的產品。延伸一點說在開發嵌入式產品,尤其是用Android系統的產品,難度會降低很多,體現在開發調試和發現問題的測試階段。

這是我的另一篇回答

在2016年,Android 程序員應該如何選擇? - 王錘錘的回答


將評論區的內容移植至回答區。

作為一個對驅動感興趣或者時間比較多的話,

1,可以從device driver框架入手,畢竟相關書籍和分享事例不少,如ldd,**華的linux設備驅動詳解(適合已入門驅動的人看)

或者做網路相關的,

2,可以從內核的網路協議棧實現入手。

基本上 ,從這兩點任何一點進去都是需要以點帶面,前期需要花很多的時間,去熟悉 內核其它功能特性。

-------------------------------分割------------------------

看懂linux內核代碼的一個作用是 可以脫去書本上關於操作系統等理論的枯燥。其中linux內核代碼中很多思想都是可以為嵌入式軟體開發(設計上)做借鑒的,比如 (不依耐硬體特性的)

1. 中斷框架+底半部+tasklet/workqueue

2.驅動框架+虛擬文件系統(sysfs/kernfs+設備屬性)

3. 四種io訪問模型(對應用程序)

4. uevent/熱插拔+ 內核sock(對性能的考慮)

5.framebuffer對圖形庫的設計

另外也可參考

6. dbus機制對monitor 的設計。

暫時想到這麼多。

---------------------------

補充,

7、非同步通知/事件通知鏈對基於事件程序/框架的設計

8、重定位/載入、MM對安全的影響

9、鏈接對於內存 布局的影響


我被虐過。。。3個月後放棄了。。支持劉


內核窮三代,驅動毀一生~


推薦一個看代碼的工具:lxr

全稱Linux Kernel Cross Reference


想學內核,至少要自認為對C語言熟練程度達70%以上,否則就先寫代碼把。

感覺那麼多培訓班教這個驅動,其實工作中哪有那麼多驅動能寫,80%都是現成的, 一般選晶元的時候廠商自己都有比較完善的驅動,人家高手寫了,我們看看就行。

不過就想學內核這件事來說,我建議先動手從零寫一個操作系統,知乎上類似問題好多。我最近也在照別人文檔在寫,有時間可以交流。


嵌入式那塊不是很懂,學內核,我是從趙炯的linux內核完全注釋開始的,基於0.12內核,學完後,你就大致了解了linux內核的基本原理,算是知道了全貌。然後再慢慢過渡到2.6內核,一開始就學習高版本內核的話,比較打擊積極性。這時候可以看陳君莉翻譯的linux內核設計與實現,這個看完後,如果感覺前面看的還行,大部分東西都能理解,最好多看幾遍,然後就可以接著看ulk了。

路漫漫其修遠兮


LINUX 內核 0.11詳解 國內一位大牛寫的 還不錯 至少能讀懂

預備知識 C預言基礎 看得懂彙編 Makefile基礎 比較難啃 加油


推薦閱讀:

利用iptables目標重寫巧妙變更遺留系統配置
淺談Windows 10中藏著的那個Linux
如果沒有Linux,IT業界會是怎樣的現狀?
遊戲伺服器運維疑惑?
關於固態硬碟的定址原理和定址速度的一個疑問?

TAG:Linux | 嵌入式系統 | Linux內核 |