DPDK 原始碼的不完全筆記(一) 初識DPDK
寫在前面
本系列記錄了作者在專案過程中由於好奇心驅使而瞭解到的部分 DPDK
實現細節。比較適合有同樣好奇心的 DPDK
的 初學者 ,通過本系列文章
您可以學習到
- DPDK的整體工作原理以及部分實現細節
您不能學習到
- 應用DPDK進行效能調優
如果對 DPDK
的起源不是很清楚的話,可以先瀏覽下 絕對乾貨!初學者也能看懂的DPDK解析 ,重點就是 Linux + x86網路IO瓶頸 這部分,總結一句話就是 Linux核心協議棧太慢了 ,為了突破這種效能瓶頸, DPDK
的方案是繞過(bypass)核心,直接從網絡卡把資料抓到使用者空間。
一些基本的概念
EAL
首先必須明白的一點就是, DPDK
是以若干個 lib 的形式提供給應用連結使用,其中最終要的一個 lib 就是 EAL
了, EAL
的全稱是(Environment Abstraction Layer, 環境抽象層),它負責為應用間接訪問底層的資源,比如記憶體空間、執行緒、裝置、定時器等。如果把我們的應用比作一個豪宅的主人的話, EAL
就是這個豪宅的管家。
lcore & socket
這兩個概念在 DPDK
的程式碼中隨處可見, 注意 這裡的 socket 不是網路程式設計裡面的那一套東西,而是 CPU 相關的東西。具體的概念可以參看 Differences between physical CPU vs logical CPU vs Core vs Thread vs Socket 或者其翻譯版本 physical CPU vs logical CPU vs Core vs Thread vs Socket(翻譯) 。
對我們來說,只要知道可以 DPDK
可以執行在多個 lcore
上就足夠了.
DPDK
如何知道有多少個 lcore
呢 ? 在啟動時解析檔案系統中的特定檔案就可以了, 參考函式 eal_cpu_detected
DPDK的執行形式
大部分 DPDK
的程式碼是以 lib 的形式執行在使用者應用的程序上下文.為了達到更高的效能。應用通常都會 多程序 或者 多執行緒 的形式執行在不同的 lcore
上
多執行緒的場景:
多程序的場景:
多程序的場景下,多個應用例項如何保證關鍵資訊(比如記憶體資源)的一致性呢? 答案是不同程序將公共的資料 mmap
同一個檔案,這樣任何一個程序對資料的修改都可以影響到其他程序。
Primary & Secondary
多程序場景下,程序有兩種角色 Primary
或者 Secondary
,正如其名字, Primary
程序可以 create 資源,而 Secondary
程序只能 attach 已存在的資源。一山不容二虎,一個多程序的應用,有且只有一個 Primary
程序,其餘都是 Secondary
程序。應用可以通過命令列引數 --proc-type 來指定應用型別。
DPDK的入口
如同 main
函式在應用程式中的地位, rte_eal_init
函式便是 DPDK
夢開始的地方(其實前面的圖已經畫出來了!),我們來看看它做了什麼事。
/* Launch threads, called at application init(). */ int rte_eal_init(int argc, char **argv) { thread_id = pthread_self(); rte_eal_cpu_init(); eal_parse_args(argc, argv); rte_config_init(); rte_eal_intr_init(); rte_mp_channel_init(); rte_eal_memzone_init(); rte_eal_memory_init(); rte_eal_malloc_heap_init() eal_thread_init_master(rte_config.master_lcore); RTE_LCORE_FOREACH_SLAVE(i) { /* create a thread for each lcore */ ret = pthread_create(&lcore_config[i].thread_id, NULL, eal_thread_loop, NULL); ..... } /* * Launch a dummy function on all slave lcores, so that master lcore * knows they are all ready when this function returns. */ rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER); rte_eal_mp_wait_lcore(); ...... }
總結起來就是
lcore