前言
對於剛入職的新員工,總會遇到一個頭疼的問題,那就是如何快速上手公司的大型軟體專案。要知道,一般公司裡的軟體專案都經過上十年的迭代,軟體功能很多、架構也很複雜。這比閱讀一般的開源專案難度更大,雖然很棘手,但也不要慌,還是有套路可循的。
現代大型軟體的基本架構
不管是開源專案還是公司大型軟體,基本組成主要可以分成四部分:
1 原始碼
沒什麼可說的,C/C++/JAVA/Python 等各種語言的原始碼。
2 依賴的庫檔案
C/C++ 依賴的靜態庫(.a)和動態庫檔案(.so),JAVA 依賴的 package 等。
3 配置檔案
配置檔案的格式一般為 json、yml、xml(現在用的比較少了),這些配置檔案存在的意義是什麼呢?如果能硬編碼在程式碼裡,誰也不樂意維護這些雜七雜八的檔案。但是,配置檔案能使軟體更靈活,能適應不同的應用場景、硬體平臺、作業系統,還有些用於 LLT 測試等。
這些配置檔案一般都放在不同的目錄下,需要搞明白不同的配置檔案對哪個程式碼模組起作用。
4 構建系統
現在有的開源專案用 meson(一款基於 Python3 的構建系統),後端採用 ninja(谷歌的一款增量編譯器)。而公司裡的 C/C++ 專案採用 cmake/make 居多,你要對如何編寫 CMakeLists.txt 有一定的瞭解。
一般開源專案裡還有個資料夾 examples,裡面是一些示例程式碼。而公司的專案裡當然少不了 LLT 測試程式碼等。
大型軟體專案的分析思路
1 物理部署
2 程式執行開始階段
上面零零散散講了很多,到這裡我們才進入正題。
現代大型軟體必然會使用多程序、多執行緒技術。不同程序的程式碼閱讀方法是一樣的,你只要知道不同程序的功能是什麼即可。這裡,我們來看一個具體的程序。
以 C/C++ 為例(JAVA 也是如此),程式的入口是 main 函式,也就是一個程序的入口。進入 main 函式執行的初期,一般是一些初始化、部署、載入等操作,比如讀配置檔案、載入程式執行所需要的 so、載入程序模版、執行緒模版、佇列模板等。
3 程序、執行緒
main 函式所在的執行緒稱之為主執行緒,隨著程式碼往下執行,相繼會創建出許多子執行緒,這些子執行緒可以由主執行緒建立,也可以由其他子執行緒建立,每個子執行緒裡都是死迴圈執行某個或者某些任務。你需要走讀程式碼,瞭解以下幾點:
有哪些型別的子執行緒(也就是執行緒模版個數)?不同型別的執行緒執行什麼樣的任務(也就是執行緒功能)?每種型別的子執行緒建立了多少個?這些子執行緒的建立順序及建立時間點?每個子執行緒掛載了哪些任務,這些任務是什麼?以及這些任務的排程方式和排程權重是什麼?子執行緒上的任務有模板嗎?比如任務單元之類的4 執行緒間通訊、佇列
一個程序中的不同執行緒一般來說是相互獨立的,比如不同的業務執行緒。但有時候,執行緒間也是需要通訊的,比如控制執行緒和業務執行緒,執行緒間通訊有哪幾種方式呢?簡單一點的有共享記憶體,稍微複雜一點的就是透過訊息佇列實現執行緒間通訊的。你需要明確以下幾點:
哪些執行緒間需要通訊?不同的執行緒在什麼情況下需要通訊?通訊的目的又是什麼?有哪些佇列型別(也就是佇列模板個數)?不同執行緒使用的佇列個數有幾個?執行緒從哪個佇列裡讀訊息?執行緒往哪個佇列裡寫訊息?一般來說,某個執行緒會往其他執行緒的佇列裡發訊息,而從自己獨有的執行緒佇列裡讀訊息。
5 模組程式碼
模組程式碼大體可以分為兩大類:控制模組和業務模組。
而業務模組程式碼又可以分為許多子模組,也可以看成一個個微服務。不同的業務模組程式碼有的跑在不同的執行緒上,有的同時跑在多個執行緒上,這種情況下對於模組中所使用到的一些全域性變數就需要加鎖處理。大量微服務的業務程式碼跑在業務執行緒上,這需要一個任務排程框架。這個任務排程框架有多種實現方式,有基於狀態機的,也可以基於事件路由。什麼是事件路由呢?
我們事先在配置檔案中定義好一堆事件,每個事件下面對應一些微服務處理模組。事件執行上有一個預設的順序,但也可以在得到某個特定的微服務執行結果時,跳轉到非預設事件。
6 走讀程式碼的利器 - 除錯工具
上述列的問題需要我們走讀程式碼才能尋找到答案。而使用 GDB(Linux 系統下 GNU 的除錯工具)可以邊除錯邊走讀程式碼,gdb 可以清晰打印出函式呼叫棧(命令:bt)資訊和執行緒資訊(命令:info thread)。這裡強烈推薦大家使用如下命令,跟蹤某個具體執行緒上函式呼叫情況:
b 函式名(檔名:行號)thread 執行緒ID
總結
不管是 Windows、Linux 還是 Andorid 中的大型軟體,上手方法都是大同小異的。從軟體的部署、組成、程序、執行緒、元件、佇列及執行緒間通訊的角度入手,你將迅速對整個工程有了全面認識,而那些具體函式是怎麼實現的,逐行看程式碼就行了,也是閱讀大型軟體程式中最為簡單的部分了。