onps棧移植說明(1)——onps棧的配置及裁剪

来源:https://www.cnblogs.com/neo-T/archive/2022/11/04/onps-1.html
-Advertisement-
Play Games

1.Linux環境完全卸載mysql相關文件: 完全卸載mysql相關文件: yum remove mysql mysql-server mysql-libs compat-mysql rm -rf /var/lib/mysql rm /etc/my.cnf rpm -qa|grep mysql / ...


       onps棧的移植涉及幾個部分:1)系統配置及裁剪;2)基礎數據類型定義;3)RTOS適配層實現;4)編寫網卡驅動並註冊網卡。本文作為onps棧移植的指導性文件將給出一般性的移植說明及建議,具體的移植樣例工程及說明請移步碼雲下載:

關於onps棧的前世今生請移步上一篇博文《開源網路協議棧onps誕生記》。

1. onps棧的配置及裁剪

       協議棧源碼(碼雲/github)port/include/port/sys_config.h文件是協議棧的配置文件。它提供了一系列的配置巨集用於裁剪、配置協議棧。我們可以根據目標系統的具體情況對協議棧進行裁剪,調整配置,以減少或增加對系統資源的占用率。配置文件主要涉及幾方面的內容:

1)打開或關閉某個功能模塊;

2)指定mmu(記憶體管理單元)管理的記憶體大小;

3)協議層相關配置項,如預設ttl值、路由表大小、arp緩存表大小等;

       onps棧在數據鏈路層支持兩種類型的網路介面:ethernet有線乙太網絡介面;ppp點對點撥號網路介面。用戶必須選擇其中至少一個介面:

#define SUPPORT_PPP      1 //* 是否支持ppp:1,支持;0,不支持
#define SUPPORT_ETHERNET 1 //* 是否支持ethernet:1,支持;0,不支持

註意,你的目標系統要麼支持ppp,要麼支持ethernet,要麼二者都支持,不能兩個都選擇不支持,否則協議棧將無法正常工作。另外協議棧還提供了幾個常用的網路工具供用戶選擇使用,用戶可以根據具體應用情形選擇打開或關閉相關工具:

//* 網路工具配置項,0:不支持;1:支持,協議棧將編譯連接工具代碼到目標系統
//* ===============================================================================================
#define NETTOOLS_PING       1 //* ping工具,確定目標網路地址是否能到達
#define NETTOOLS_DNS_CLIENT 1 //* dns查詢客戶端,通過指定的dns伺服器查詢請求功能變數名稱對應的ip地址
#define NETTOOLS_SNTP       1 //* sntp客戶端,通過指定的ntp伺服器進行網路校時
//* ===============================================================================================

考慮協議棧的目標系統可能無法提供pc下常見的文件存儲系統,所以協議棧的調試日誌等信息是通過標準輸出提供的:

#define SUPPORT_PRINTF 1 //* 是否支持調用printf()輸出相關調試或系統信息
#if SUPPORT_PRINTF
  #define PRINTF_THREAD_MUTEX 1 //* 是否支持使用printf線程互斥鎖,確保不同線程的調試輸出信息不被互相干擾,值為1則支持互斥鎖
  #define DEBUG_LEVEL         1	//* 共5個調試級別:
                                //* 0 輸出協議棧底層嚴重錯誤
                                //* 1 輸出所有系統錯誤(包括0級錯誤)
                                //* 2 輸出協議棧重要的配置、運行信息,同時包括0、1級信息
                                //* 3 輸出網卡的原始通訊通訊報文(ppp為收發,ethnernet為發送),以及0、1、2級信息
                                //* 4 輸出ethernet網卡接收的原始通訊報文,被協議棧丟棄的非法(校驗和錯誤、通訊鏈路不存在等原因)通訊報文,以及0、1、2、3級信息(除ethernet發送的原始報文)                                    
#endif

基本上所有單片機系統均會提供幾個串列口,我們只需選擇其中一個將其作為printf函數的標準輸出口,我們就可以使能協議棧支持日誌輸出功能,通過printf()函數輸出的日誌信息對目標系統進行調試。如果你的目標系統支持某個串口作為printf()函數的標準輸出口,建議將SUPPORT_PRINTF巨集置1,打開協議棧的日誌輸出功能。PRINTF_THREAD_MUTEX巨集用於解決多線程環境下日誌輸出的衝突問題。如果你的目標系統互斥資源夠用,建議打開該功能,否則你在標準輸出口看到的日誌會出現亂序問題。

       協議棧在很多情形下需要動態申請不同大小的記憶體以供接下來的邏輯處理過程使用。所以,為了最大限度地提高協議棧運行過程中的記憶體利用率並儘可能地減少記憶體碎片,我們還單獨設計了一個獨立的記憶體管理單元(mmu)。考慮協議棧的目標系統為資源受限的單片機系統,這種系統的記憶體資源往往都是極度緊張的,因此我們提供了配置巨集讓用戶決定分配多少位元組的記憶體空間給協議棧的mmu:

//* 記憶體管理單元(mmu)相關配置項,其直接影響協議棧能分配多少個socket給用戶使用
//* ===============================================================================================
#define BUDDY_PAGE_SIZE  32   //* 系統能夠分配的最小頁面大小,其值必須是2的整數次冪
#define BUDDY_ARER_COUNT 9    //* 指定buddy演算法管理的記憶體塊數組單元數量

#define BUDDY_MEM_SIZE   8192 //* buddy演算法管理的記憶體總大小,其值由BUDDY_PAGE_SIZE、BUDDY_ARER_COUNT兩個巨集計算得到:
                              //* 32 * (2 ^ (9 - 1)),即BUDDY_MEM_SIZE = BUDDY_PAGE_SIZE * (2 ^ (BUDDY_ARER_COUNT - 1))
                              //* 之所以在此定義好要管理的記憶體大小,原因是buddy管理的記憶體其實就是一塊提前分配好的靜態存儲時期的位元組型
                              //* 一維數組,以此來確保協議棧不占用寶貴的堆空間
//* ===============================================================================================

協議棧的記憶體管理單元採用了buddy伙伴演算法。上述三個巨集的關係參見BUDDY_MEM_SIZE巨集的註釋。前面說過,mmu管理的記憶體用於協議棧的不同業務情形,其中最核心的一種業務情形就是socket,用戶分配的記憶體大小直接決定了用戶編寫網路應用時能夠申請的socket數量。如果你在申請分配一個新的socket時報ERRREQMEMTOOLARGE(The requested memory is too large, please refer to the macro definition BUDDY_MEM_SIZE)或ERRNOFREEMEM(The mmu has no memory available)錯誤,則意味著記憶體已經不夠用了,需要你增加記憶體或者檢視你的代碼看是否存在未及時釋放的socket句柄。另外,決定記憶體利用效率的關鍵配置項是BUDDY_PAGE_SIZE巨集,因為mmu分配記憶體的最小單位就是“頁”。這個巨集設置單個記憶體頁的大小,單位為位元組,其值必須是2的整數次冪。如果你的通訊報文不大,建議把頁面大小調整的小一些,比如16位元組、32位元組等,以儘量減少單個頁面的空餘位元組數。

       sys_config.h文件的其餘巨集均為協議層相關的配置項。這其中有幾個與底層網路介面相關的配置項需要特別關註:

#define SUPPORT_PPP 1 //* 是否支持ppp模塊:1,支持;0,不支持,如果選擇支持,則系統會將ppp模塊代碼加入到協議棧中
#if SUPPORT_PPP
  #define APN_DEFAULT           "4gnet"    //* 根據實際情況在這裡設置預設APN
  #define AUTH_USER_DEFAULT     "card"     //* ppp認證預設用戶名
  #define AUTH_PASSWORD_DEFAULT "any_char" //* ppp認證預設口令

  #define PPP_NETLINK_NUM      1 //* 協議棧載入幾路ppp鏈路(系統存在幾個modem這裡就指定幾就行)
  #define SUPPORT_ECHO         1 //* 對端是否支持echo鏈路探測
  #define WAIT_ACK_TIMEOUT_NUM 5 //* 在這裡指定連續幾次接收不到對端的應答報文就進入協議棧故障處理流程(STACKFAULT),這意味著當前鏈路已經因嚴重故障終止了
#else
  #define PPP_NETLINK_NUM 0
#endif

#define SUPPORT_ETHERNET 1 //* 是否支持ethernet:1,支持;0,不支持
#if SUPPORT_ETHERNET
  #define ETHERNET_NUM 1  //* 要添加幾個ethernet網卡(實際存在幾個就添加幾個)    
  #define ARPENTRY_NUM 32 //* arp條目緩存表的大小,只要不小於區域網內目標通訊節點的個數即可確保arp定址次數為1,否則就會出現頻繁定址的可能,當然這也不會妨礙正常通訊邏輯,只不過這會降低通訊效率    
#else
  #define ETHERNET_NUM 0
#endif

如果目標系統需要用到ppp撥號,我們在打開協議棧對ppp模塊的支持後還需要設置預設的撥號參數值,比如apn、撥號賬號及密碼等。當然你也可以不用設置,後面我們在編寫os適配層介面的時候也會設置這幾項。系統會使用os適配層的設置值代替預設值。另外協議棧在設計之初即考慮支持多路ppp同時撥號的情形,目標系統支持幾路ppp,巨集PPP_NETLINK_NUM值置幾即可。SUPPORT_ECHO巨集指定ppp鏈路是否啟用echo回顯探測功能。某些ppp接入服務商可能會關閉此項功能,如果你不確定,建議預設情況下關閉此功能。因為echo鏈路探測功能一旦被啟用,協議棧會每隔一小段時間發送探測報文到對端。對端如果不支持此功能會丟棄該探測報文不做任何響應,這將導致協議棧判定ppp鏈路故障,從而主動結束鏈路、重新撥號。

       協議棧同樣支持多路ethernet網卡,ETHERNET_NUM巨集用於指定目標系統存在幾路ethernet網卡。這裡需要特別註意的是ARPENTRY_NUM巨集,這個巨集用於指定ethernet網路環境下進行通訊時mac地址緩存表的大小。如果緩存表過小,進行通訊的目標地址並不在緩存表中時,協議棧會先發送arp查詢報文,得到對端的mac地址後才會發送實際的通訊報文。雖然這一切都是協議棧自動進行的,但通訊效率會受到影響。如果目標系統的記憶體夠用,建議放大緩存表的容量,最合理的大小是等於計劃通訊的目標地址的數量。       

       其餘協議層相關的配置項均屬於ip及其支持的上層協議:

//* ip支持的上層協議相關配置項
//* ===============================================================================================
#define SUPPORT_IPV6 0	//* 是否支持IPv6:1,支持;0,不支持
#define SUPPORT_SACK 0  //* 系統是否支持sack項,sack項需要協議棧建立發送隊列,這個非常消耗記憶體,通用版本不支持該項

#define ICMPRCVBUF_SIZE_DEFAULT 128   //* icmp發送echo請求報文時指定的接收緩衝區的預設大小,註意,如果要發送較大的ping包就必須指定較大的接收緩衝區

#define TCPRCVBUF_SIZE_DEFAULT  2048  //* tcp層預設的接收緩衝區大小,大小應是2^n次冪才能最大限度不浪費budyy模塊分配的記憶體
#define TCPUDP_PORT_START       20000 //* TCP/UDP協議動態分配的起始埠號
#define TCP_WINDOW_SCALE        0     //* 視窗擴大因數預設值
#define TCP_CONN_TIMEOUT        30    //* 預設TCP連接超時時間
#define TCP_ACK_TIMEOUT         3     //* 預設TCP應答超時時間
#define TCP_MSL                 15    //* 指定TCP鏈路TIMEWAIT態的最大關閉時長:2 * TCP_MSL,單位:秒
#define TCP_LINK_NUM_MAX        16    //* 系統支持最多建立多少路TCP鏈路(涵蓋所有TCP客戶端 + TCP伺服器的併發連接數),超過這個數量將無法建立新的tcp鏈路

#if SUPPORT_ETHERNET
  #define TCPSRV_BACKLOG_NUM_MAX 10 //* tcp伺服器支持的最大請求隊列數量,任意時刻所有已開啟的tcp伺服器的請求連接隊列數量之和應小於該值,否則將會出現拒絕連接的情況
  #define TCPSRV_NUM_MAX         2  //* 系統能夠同時建立的tcp伺服器數量
  #define TCPSRV_RECV_QUEUE_NUM  64 //* tcp伺服器接收隊列大小,所有已開啟的tcp伺服器共用該隊列資源,如果單位時間內到達所有已開啟tcp伺服器的報文數量較大,應將該值調大
#endif

#define UDP_LINK_NUM_MAX 4  //* 調用connect()函數連接對端udp伺服器的最大數量(一旦調用connect()函數,收到的非伺服器報文將被直接丟棄)
#define SOCKET_NUM_MAX   16 //* 系統支持的最大SOCKET數量,如實際應用中超過這個數量則會導致用戶層業務邏輯無法全部正常運行(icmp/tcp/udp業務均受此影響),其值應大於等於TCP_LINK_NUM_MAX值
#define IP_TTL_DEFAULT   64 //* 預設TTL值
#define ROUTE_ITEM_NUM   8  //* 系統路由表數量
//* ===============================================================================================

目前協議棧暫不支持ipv6也不支持tcp sack選項(後續版本會支持),所以SUPPORT_IPV6和SUPPORT_SACK兩個巨集不要做任何改動,始終為0即可。ICMPRCVBUF_SIZE_DEFAULT巨集與ping工具有關,如果你不想使用ping工具可以將這個值設小一些以節省記憶體。TCP_WINDOW_SCALE巨集建議不要做任何調整,對於記憶體空間有限的單片機系統tcp視窗直接使用指定值即可。TCP_ACK_TIMEOUT巨集用於指定tcp報文發送到對端後等待對端回饋tcp ack報文的超時時間,單位:秒。UDP_LINK_NUM_MAX巨集決定了目標系統在使用udp通訊時,能夠建立的udp客戶端的最大數量。比如目標系統需要建立5個udp客戶端,由於UDP_LINK_NUM_MAX值為4,那麼只有4個客戶端能正常調用connect()函數,第5個客戶端在調用connect()函數時會報ERRNOUDPLINKNODE(the udp link list is empty)錯誤。ROUTE_ITEM_NUM巨集用於指定系統緩存的路由條目數量,你可以根據實際網路情形調整這個值,但不能低於目標系統註冊的網卡數量。協議層相關的其它配置項請根據註釋自行依據實際情況進行調整即可。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在上一篇文章`《驅動開發:內核封裝WSK網路通信介面》`中,`LyShark`已經帶大家看過瞭如何通過WSK介面實現套接字通信,但WSK實現的通信是內核與內核模塊之間的,而如果需要內核與應用層之間通信則使用TDK會更好一些因為它更接近應用層,本章將使用TDK實現,TDI全稱傳輸驅動介面,其主要負責連... ...
  • 本章`LyShark`將帶大家學習如何在內核中使用標準的`Socket`套接字通信介面,我們都知道`Windows`應用層下可直接調用`WinSocket`來實現網路通信,但在內核模式下應用層API介面無法使用,內核模式下有一套專有的`WSK`通信介面,我們對WSK進行封裝,讓其與應用層調用規範保持... ...
  • 【前言】 在日常開發工作中,我們經常要對變數進行操作,例如對一個int變數遞增++。在單線程環境下是沒有問題的,但是如果一個變數被多個線程操作,那就有可能出現結果和預期不一致的問題。 例如: static void Main(string[] args) { var j = 0; for (int ...
  • 需求:在Winform使用NOPI做導入時候,需要導入數據的同時導入圖片。 雖然代碼方面不適用(我好像也沒仔細看過代碼),但是感謝大佬給了靈感http://www.wjhsh.net/IT-Ramon-p-13100039.html,將excel尾碼修改成Zip,解壓,在其中找到圖片的xml位置信息 ...
  • 嵌入式系統安全的一些解決方法及缺陷 外部硬體安全模塊:在主SoC之外包含一個專用的硬體安全模塊或可信元件,e.g. 手機的SIM卡。==隔離僅限於可以從非易失性存儲器運行的相對靜態程式== 內部硬體安全模塊:管理加密操作和密鑰存儲的硬體模塊;通用的處理引擎,放在主處理器旁邊,它使用自定義硬體邏輯來防 ...
  • 在進入正題之前我們先來瞭解一下sed的模式空間,如下 什麼是sed的模式空間? 答(僅供參考):就是從文件讀取一行文本然後存入的緩衝區,然後命令操作模式空間的內容,在初始狀態下模式空間是沒有內容的,在每次迴圈讀取數據的過程中,模式空間都會被清空並寫入新的內容。 解釋以下命令結果: seq 10 | ...
  • 前言 今天我們一起來看一下如何使用LabVIEW實現語義分割。 一、什麼是語義分割 圖像語義分割(semantic segmentation),從字面意思上理解就是讓電腦根據圖像的語義來進行分割,例如讓電腦在輸入下麵左圖的情況下,能夠輸出右圖。語義在語音識別中指的是語音的意思,在圖像領域,語義指 ...
  • iShowU Studio for Mac擁有一個整潔但有用的屏幕錄製界面,使用iShowU Studio Mac版,你可以輕鬆添加文本,註釋,過渡,指針和高亮,然後分享您的結果! 詳情:iShowU Studio for Mac(高清錄屏工具) 最新功能 1.改進捕獲和速度 更簡單的捕獲設置重新設 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...