RV126平臺NFS網絡啟動終極復盤報告

1. 初始目標與環境
  • 目標: 將RV1126開發板的啟動方式,由從eMMC內部存儲掛載根文件系統(rootfs),切換為通過網絡掛載位于NFS服務器上的根文件系統。

  • 動機: 提升開發調試效率,實現代碼修改后僅需重啟即可驗證,免除eMMC的反復燒寫。

  • 硬件/軟件環境:

  • 目標板:RV1126?

  • 引導加載程序:U-Boot 2017.09

  • 內核: Linux 4.19.111 (由Rockchip SDK的./build.sh kernel命令編譯)

  • 啟動鏡像: boot.itb (eMMC默認), zboot.img (編譯產物)

  • NFS/TFTP服務器IP: 192.168.1.78

  • 目標板預設靜態IP: 192.168.1.105

2. 調試歷程與問題演進

問題一bootargs參數沖突,NFS設置被eMMC配置覆蓋

  • 操作: 初步嘗試通過在U-Boot中設置bootargsbootcmd變量來引導NFS。

  • 現象: 重啟后,開發板完全忽略了NFS設置,依然從eMMC啟動了原有系統。

  • 關鍵線索: 系統啟動后,在串口終端執行cat /proc/cmdline,查看到內核實際接收到的啟動參數

    [    0.000000] Kernel command line: user_debug=31 storagemedia=emmc ... root=PARTUUID=614e0000-0000 rootfstype=ext4 ...
    
  • 分析過程:

    1. 問題定位: 內核啟動參數中完全沒有我們設置的nfsroot等字段,反而存在明確指向eMMC分區的root=PARTUUID=...。這證明U-Boot環境變量中的bootargs在傳遞給內核的過程中被覆蓋了。

    2. 原理分析: 內核啟動參數的來源主要有二:U-Boot環境變量和設備樹(FDT)中的/chosen節點。Rockchip平臺默認的boot_fit命令會從eMMC加載一個FIT鏡像,此鏡像內部打包了內核和FDT。如果FDT的/chosen節點內也定義了bootargs屬性,它將擁有極高的優先級。

    3. 根源確認: 檢查設備樹源碼 rv1126-alientek.dts 時,找到了問題的直接原因:

  • 解決方案: 修改rv1126-alientek.dts文件,將/chosen節點下的bootargs屬性整行刪除。之后重新編譯設備樹(.dtb),并用新的.dtb重新打包FIT鏡像,最后將這個“干凈”的FIT鏡像重新燒錄到eMMC。此操作旨在從根源上消除沖突參數。

問題二:遭遇Kernel Panic,深入內核排查驅動初始化時序

現象描述:在完成了2.1節中的設備樹修改(刪除/chosen節點下的bootargs屬性)、重新編譯并燒錄了新的FIT鏡像后,我重啟了開發板。系統行為發生了關鍵變化:

  1. 系統不再從eMMC啟動,證明2.1節的修改是有效的。

  2. 在U-Boot加載內核、打印 Starting kernel ... 之后,內核日志開始滾動,但在大約0.8秒后,系統完全崩潰,串口終端被Kernel Panic信息刷屏。

關鍵線索(日志節選): 我從串口捕獲了完整的崩潰日志。最核心的錯誤信息如下:

[ 0.194338] rk_gmac-dwmac ffc40000.ethernet: no regulator found
[ 0.826993] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,255) 
[ 0.837762] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.111 #8 
[ 0.838305] Hardware name: Generic DT based system 
[ 0.838756] [<b010ff9c>] (unwind_backtrace) from [<b010c298>] (show_stack+0x10/0x14) 
[ 0.839443] [<b010c298>] (show_stack) from [<b091afa4>] (dump_stack+0x90/0xa4) 
[ 0.840083] [<b091afa4>] (dump_stack) from [<b0127318>] (panic+0xfc/0x26c) 
[ 0.840692] [<b0127318>] (panic) from [<b0d01334>] (mount_block_root+0x218/0x2f4) ... 
[ 0.945002] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,255) ]---
分析與思考過程
  1. 解讀Kernel Panic: Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,255) 這句日志是Linux內核在啟動流程中的“絕望呼喊”。VFS (虛擬文件系統) 嘗試掛載bootargs中指定的根設備(在我們的NFS場景下,即nfs設備),但最終失敗了。error -6 (日志中未直接顯示,但該錯誤碼為此場景下的典型值) 代表-ENXIO,即“無此設備或地址”。這證明,在內核需要使用網絡來聯系NFS服務器時,網絡設備尚未就緒。

  2. 定位核心矛盾: 此時,一個關鍵的矛盾點浮現出來:

    • 事實A: 在從eMMC正常啟動后,ifconfig可以看到eth0,并且可以ping通網絡。這證明了物理硬件(SoC MAC + PHY芯片)是完好的。

    • 事實B: 我已經通過make menuconfig確認,內核的網絡驅動CONFIG_DWMAC_ROCKCHIP是以**內置(built-in, =y)**方式編譯的,并非模塊(module, =m)。這排除了因無法在早期加載.ko驅動模塊而導致NFS啟動失敗的常見問題。

    • 矛盾: 既然硬件完好、驅動也已內置于內核中,為何在NFS啟動的這個特定時刻,網絡設備卻不可用?

  3. 提出“驅動時序”假設: 這種“最終能用,但早期不能用”的現象,是典型的**內核驅動初始化時序(Driver Initialization Timing)**問題。Linux內核在啟動時,會按照一個復雜的依賴和優先級順序來逐一初始化(probe)各個設備的驅動。NFS啟動對網絡就緒的時效性要求極為苛刻,它需要在內核啟動的最初幾百毫秒內就完成網絡初始化。我的假設是:網卡驅動dwmac的初始化動作,早于了它所依賴的某個前置資源的初始化動作。

  4. 尋找證據并驗證假設: no regulator found 這條日志,就是驗證我假設的“鐵證”。

    • 原理: 網卡驅動(dwmac)負責控制SoC內部的MAC邏輯,但它需要通過一個外部的PHY芯片來連接物理網線。這個PHY芯片是需要獨立供電的。設備樹作為硬件的軟件描述,理應告訴dwmac驅動,它需要使用的PHY電源(regulator)是哪一個。

    • 日志解讀: no regulator found 清晰地表明,dwmac驅動在啟動的第194毫秒,確實去向內核的電源管理框架(regulator framework)申請PHY芯片的電源了,但框架回復“找不到”。

    • 深層原因: 這并不是說電源不存在,而是在那個時刻,負責管理這個電源的PMIC驅動(在我們的板子上是rk808-regulator)自己都還沒完成初始化,或者說,它還沒來得及向內核注冊它所管理的全部電源。因此,dwmac的申請必定失敗。

解決方案:在設備樹中顯式聲明依賴關系
  1. 問題的根源在于dwmac驅動和regulator驅動之間缺少一個明確的、可被內核驅動模型理解的依賴關系。解決方案必須從設備樹入手,建立這個關系。

    • 軟件映射 (設備樹分析):

      • 我打開了您提供的rv1126-alientek.dtsi文件,在i2c0總線下的rk809: pmic@20節點中,我找到了所有電源輸出的定義。

      • 通過比對,硬件上的SW4(在數據手冊中對應邏輯功能名DCDC_REG4)在代碼中的節點標簽(handle)被清晰地定義為vcc3v3_sys

    • 硬件溯源 (原理圖分析):

      • 我首先檢查了您提供的PDF原理圖。在第17頁,確認了PHY芯片(RTL8211F-CG)的主3.3V供電網絡標號為VCC33_LAN

      • 接著,在第13頁的PMIC(RK809)電路部分,我找到了VCC33_LAN的源頭——它連接到U2A芯片的SW4引腳的輸出網絡VCC3V3_SYS

      • 硬件對應關系鎖定: PHY Power -> VCC33_LAN -> VCC3V3_SYS -> PMIC SW4

實施修改: 至此,硬件和軟件的鏈條完全打通。然后修改rv1126-alientek.dtsi文件,在&gmac節點中,明確地添加下面這行至關重要的代碼:它的作用是在編譯層面為內核的驅動加載器設定了一條強制規則:“必須等待名為vcc3v3_sys的regulator設備注冊成功之后,才能對gmac設備進行probe(初始化)”。這從根本上解決了驅動初始化的時序競速問題。

在完成了此項修改后,重新編譯并燒錄了包含新設備樹的FIT鏡像后,然后從啟動日志中清楚地看到,no regulator found的警告消失了,取而代之的是:

這標志著驅動依賴與時序問題被成功攻克,接著進入下一個階段.......

問題三:無法判斷zboot.img鏡像格式,使用bootibootzbootm逐一排除

  • 在完成了第二個問題中對設備樹phy-supply的修復并重新燒錄固件后,我滿懷希望地認為問題已經解決。然而,重啟后,Kernel Panic依然如故。所有的靜態配置(設備樹)和依賴關系(電源)從理論上看都已無懈可擊。因此,問題的焦點,決定性地從“配置”轉向了U-Boot的“執行”——即bootcmd的實際行為。

    此時我的核心判斷是:Rockchip SDK默認的boot_fit命令行為過于復雜且不可控,它似乎總是以某種方式干擾bootargs。為了獲得對啟動流程的100%控制權,最標準的工程做法就是徹底繞開它,轉而使用最基礎、最通用的TFTP加載方式,手動加載內核和設備樹,再用標準命令啟動。

  • 引入的新問題:未知的zboot.img鏡像格式 這個思路立刻引入了一個新的關鍵變量:由SDK編譯生成的內核鏡像zboot.img,究竟是什么格式?

    • 是純粹的、無頭部的zImage? -> 應該用 bootz 命令。

    • 是帶有U-Boot舊版頭部的uImage? -> 應該用 bootm 命令。

    • 是針對新架構的Image? -> 應該用 booti 命令。

    啟動命令的選擇,完全取決于鏡像的格式。于是,我開始了一系列嚴謹的、逐一排除的實驗。

  • 實驗A:使用 booti 命令的嘗試

    • 原理與動機: booti是針對ARMv7/v8架構下、原始內核鏡像(如zImage/Image)的較新啟動命令。其語法 booti <kernel_addr> - <fdt_addr> 非常清晰,是我首先想到的嘗試。

    • 操作: 我在U-Boot中構造了如下命令:

      setenv bootcmd_tftp '...; tftpboot ${kernel_addr_r} zboot.img; tftpboot ${fdt_addr_r} rv1126-alientek.dtb; booti ${kernel_addr_r} - ${fdt_addr_r}'
      setenv bootcmd 'run bootcmd_tftp'
      saveenv
      
    • 現象與關鍵線索: 重啟后,U-Boot在執行該命令時,立即打印出錯誤,啟動中止。

      Unknown command 'booti' - try 'help'
      
    • 結論: 這個結果直截了當。它表明我當前使用的U-Boot版本在編譯時,并未包含booti命令的支持。這證實了該U-Boot經過了功能裁剪,此路被完全堵死。

  • 實驗B:使用 bootz 命令的嘗試與“意外的劫持”

    • 原理與動機: booti失敗后,我轉向了更經典的、同樣用于啟動zImagebootz命令。同時,為了徹底搞清楚zboot.img的身份,我計劃在TFTP下載后,手動中斷腳本,并使用iminfo命令來一探究竟。

    • 操作: 我在串口終端手動執行了tftpboot 0x0a200000 zboot.img,準備下一步執行iminfo

    • 現象與關鍵線索: 出現了完全出乎意料的日志。U-Boot在下載完文件后,腳本并未停止等待我輸入下一條命令,而是立刻開始嘗試啟動,并打印出截然不同的日志:

      Loading: ####################################################### ... done
      Bytes transferred = 7593984 (73e000 hex)
      ## TFTP bootm zboot.img at 0x2008000 size 0x73e000
      BOOTM: transferring to board FIT
      ## Booting FIT Image Sysmem Error: "KERNEL" ... alloc is overlap with existence "FIT_USER" ...
      

      我本來想等他下載完之后,在uboot命令行執行iminfo去查看一下這個zboot.img到底是什么類型的內核鏡像,可是我壓根沒機會去運行iminfo命令,他下載完成之后直接去starting kernel了,由此可以獲得結論:

      1. zboot.img的身份被揭示:日志中的BOOTM: transferring to board FIT是無可辯駁的鐵證,證明了zboot.img就是一個FIT鏡像,而不是我之前假設的原始zImage

      2. U-Boot的“個性”被發現:更重要的是,這個U-Boot的tftpboot命令被賦予了“智能”,它在下載完可啟動鏡像后,會擅自、立即、自動地調用bootm命令去啟動它。這個“自動啟動”特性,使得我們任何多步驟的腳本在tftpboot這一步都會被“劫持”,后續指令根本沒有機會執行。

  • 實驗C:使用 bootm 命令的嘗試

    • 原理與動機: 既然知道了鏡像是FIT格式,且bootm是對應的命令,我便嘗試明確地使用bootm,并為它提供一個獨立的、我們修改過的設備樹,期望能以此覆蓋FIT鏡像內部的FDT。

    • 操作: 構造了bootm <kernel_addr> - <fdt_addr>的命令。

    • 現象與關鍵線索: U-Boot再次報錯并掛起:

      FDT and ATAGS support not compiled in - hanging
      
    • 結論: 這證實了該U-Boot被裁剪得非常徹底。它的bootm命令也被剝離了接收外部獨立FDT的功能,它只能處理自包含的、單一的FIT鏡像。

  • 本階段的解決方案與思路轉變

    • 分析總結: 經過這三個維度的逐一排除與失敗,情況已經非常明朗。這個U-Boot是一個高度特化的“專才”,而不是一個功能全面的“通才”。它被編譯的目的,就是為了以一種特定的方式(boot_fit)來引導一個特定的鏡像格式(FIT)。任何試圖使用通用的、將內核和設備樹作為獨立文件加載的方案(無論是用booti, bootz, 還是功能不全的bootm),對于這個平臺來說,都是行不通的。

    • 解決方案: 此時,唯一的、合乎邏輯的解決方案是:必須放棄所有繞開或替換boot_fit的嘗試,回歸到平臺原生的boot_fit啟動路徑上來。

    • 思路轉變: 我們的調試重心,必須從“更換U-Boot啟動命令”,重新轉回到“在不改變boot_fit命令的前提下,如何精確地控制其運行環境”上來。這個思路的根本性轉變,為我們解決后續的變量展開和時序問題,奠定了正確的方向。我們必須停止與系統“對抗”,而是學著去“利用”它的特性。

    • 下一步: 這直接引出了我們的下一個挑戰——問題四:既然必須用boot_fit,那我們如何解決bootargs變量在boot_fit執行過程中無法正確展開的問題?

問題四:U-Boot變量未展開,內核收到“無法理解的”錯誤參數

  • 現象描述: 在經歷了命令與鏡像格式的迷局后,我們被迫回歸到唯一可行的boot_fit方案,并創造性地使用ping命令來代替sleep解決網絡時序問題。然而,在滿懷期待地重啟后,系統依然Kernel Panic

  • 關鍵線索: 這一次,我們吸取了教訓,第一時間檢查內核收到的Kernel command line,終于發現了那個隱藏最深的錯誤:

    [    0.000000] Kernel command line: user_debug=31 root=/dev/nfs nfsroot=${serverip}:${nfs_dir},v3,tcp ip=192.168.1.105...
    

    ip=部分是我們硬編碼的,所以是正確的。但nfsroot=部分,內核收到的竟然是${serverip}${nfs_dir}這兩個未經展開的變量名

  • 分析過程:

    1. 問題定位: U-Boot環境變量展開失敗。

    2. 原理分析: ping ${serverip}命令執行時,serverip被正確展開了。但是,在我們構造的bootcmd_ultimate_nfs腳本中,執行setenv bootargs ${bootargs_nfs}時,U-Boot的腳本解釋器只是簡單地將bootargs_nfs變量的字面內容(一個包含${...}的字符串)賦給了bootargs,而沒有進行二次展開

    3. 根源確認: 內核不具備解析U-Boot變量語法的能力。當它看到nfsroot=${serverip}:${nfs_dir}時,視其為無效路徑,從而導致NFS客戶端無法啟動,最終引發Kernel Panic

  • 解決方案: 為了徹底規避U-Boot腳本解釋器在嵌套和多級解析上的不確定性,我們必須采用最直接、最無歧義的方法:硬編碼(Hardcoding)。即在setenv bootargs命令中,直接寫入最終的、不包含任何${...}變量的、純凈的字符串。最終的bootargs為:bootargs_nfs=root=/dev/nfs nfsroot=192.168.1.78:/home/alientek/workspace/rv1126/src_code/sdk_linux/buildroot/output/alientek_rv1126/target,v3,tcp ip=192.168.1.105:192.168.1.78:192.168.1.1:255.255.255.0::eth0:off rw console=ttyFIQ0,1500000

問題五:勝利的假象?——掛載成功但系統“癱瘓”,空的/proc/sys

  • 現象描述: 在解決了U-Boot變量展開、FIT鏡像配置覆蓋、內核驅動時序等一系列底層問題后,系統終于不再Kernel Panic。內核啟動日志滾動到最后,沒有出現崩潰信息,串口輸出停止。這看起來像是成功了。然而,系統卻處于一種“癱瘓”狀態:

    1. 嘗試通過ssh root@192.168.1.105登錄,連接被拒絕(Connection refused)或超時(timeout),證明SSH服務沒有啟動。

    2. Telnet服務同樣無法連接。

    3. 串口終端在內核啟動日志結束后,沒有任何反應,沒有打印出login:提示符。

    4. 在一個偶然的、能得到一個極簡陋shell的啟動版本中,執行ls /procls /sys,發現這兩個目錄是空的。進而導致pstopfreemount等所有依賴于這兩個偽文件系統的核心命令全部失效。

  • 分析與思考過程:

    1. 定位問題邊界: 內核沒有崩潰,證明了從U-Boot到內核加載,再到NFS掛載操作本身是成功的。問題已經從我們之前一直糾結的內核空間(Kernel Space),決定性地轉移到了用戶空間(User Space)。也就是說,內核已經把控制權交給了NFS服務器上的/sbin/init進程,但這個init進程沒能把系統完全地、正確地“拉起來”。

    2. 剖析根文件系統源: 我回顧了NFS服務器的配置,共享的目錄是.../buildroot/output/alientek_rv1126/target。這個目錄是Buildroot在執行完所有軟件包的編譯和安裝后,生成的一個**“暫存區”或“安裝目錄”。它包含了根文件系統的所有文件和目錄結構藍圖,但它不是一個最終的、可啟動的根文件系統**。

    3. 闡述原理——“暫存區”與“成品”的區別: 一個能夠讓Linux系統正常運行的根文件系統,除了包含程序和庫文件外,還必須滿足幾個關鍵條件,而這些恰恰是target目錄所缺失的:

      • 正確的文件權限: 尤其是/bin, /sbin, /etc下的可執行文件和腳本,必須有正確的執行權限。Buildroot的target目錄在打包成最終鏡像前,不保證所有權限都已正確設置。

      • 關鍵的設備節點: /dev目錄下必須存在console, null, tty, zero等一系列基礎設備節點。沒有這些節點,init進程甚至無法正確地將日志輸出到控制臺,SSH等服務也無法創建偽終端。Buildroot的target目錄下的/dev通常是空的,這些節點是在打包成.ext4.tar鏡像的過程中,由mdevsystemd的機制動態或靜態創建的。

      • 完整的啟動腳本和服務配置: /etc/init.d/systemd服務必須被正確配置,能夠執行掛載/proc/sys/dev/pts等偽文件系統的任務,并啟動如dropbear(SSH服務)或telnetd等關鍵網絡服務。target目錄中的配置可能不完整或不適用。

    4. 最終假設: 內核成功掛載了target目錄,但由于該目錄本質上是一個“半成品”,它缺少正確的設備節點和文件權限,導致/sbin/init進程在啟動初期就因無法打開基礎設備(如/dev/console)而失敗或掛起。因此,它未能執行后續的啟動腳本來掛載/proc/sys,也未能啟動dropbear(SSH服務),導致了我們觀察到的系統“癱瘓”現象。

  • 解決方案與驗證: 解決方案是停止使用臨時的target目錄,轉而使用Buildroot生成的最終的、完整的根文件系統鏡像

    1. 創建正確的根文件系統掛載點: 我在NFS服務器上,找到了由Buildroot生成的最終產物rootfs.ext4鏡像文件。

      # 在NFS服務器上執行以下操作# 1. 創建一個新的目錄作為我們真正的NFS根目錄
      mkdir /home/alientek/workspace/rv1126/src_code/sdk_linux/rv1126_nfs_rootfs# 2. 使用loop設備,將.ext4鏡像掛載到這個新目錄
      #    這步操作相當于把一個硬盤分區“解壓”到了一個文件夾里
      sudo mount -o loop /path/to/your/buildroot/output/images/rootfs.ext4 /home/alientek/workspace/rv1126/src_code/sdk_linux/rv1126_nfs_rootfs
      
    2. 配置NFS服務器: 我修改了/etc/exports文件,將共享目錄指向這個新的、正確的掛載點,并重啟了NFS服務。

      # /etc/exports 文件中的修改
      # 舊: /home/alientek/.../target *(...)
      # 新:
      /home/alientek/workspace/rv1126/src_code/sdk_linux/rv1126_nfs_rootfs *(rw,sync,no_root_squash,no_subtree_check)
      
    3. 修改U-Boot啟動參數: 最后,我回到U-Boot命令行,修改了bootcmd中的硬編碼路徑,使其指向新的NFS共享目錄。

      setenv bootargs 'root=/dev/nfs nfsroot=192.168.1.78:/home/alientek/workspace/rv1126/src_code/sdk_linux/rv1126_nfs_rootfs,v3,udp ip=192.168.1.105:192.168.1.78:192.168.1.1:255.255.255.0::eth0:off rw console=ttyFIQ0,1500000 storagemedia=emmc androidboot.storagemedia=emmc androidboot.mode=normal'
      saveenv
      
    4. 最終驗證: 重啟開發板后,內核成功掛載了新的、從rootfs.ext4鏡像中來的完整根文件系統。init進程正常執行,/proc/sys被自動掛載,SSH服務(dropbear)也成功啟動。最終,我通過ssh root@192.168.1.105成功登錄,所有命令工作正常。問題徹底解決。

4. 總結與反思

此次調試歷程,從一個看似簡單的目標開始,最終演變為一場涉及U-Boot、設備樹、內核和用戶空間的全鏈路排查。它雄辯地證明了,任何一個環節的微小疏忽,都可能導致整個系統的啟動失敗。

  • eMMC與NFS啟動的差異不僅僅在于bootargs,更在于對根文件系統完整性和正確性的要求。

  • Buildroot的target目錄是一個常見的陷阱,它只可用于檢查文件內容,而不能作為可啟動的根文件系統直接使用。

  • 一個健壯的調試流程,需要我們對從Bootloader到用戶空間的整個啟動鏈有清晰的認識,并能通過日志,將問題精確定位到其所屬的層面。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914991.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914991.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914991.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一臺顯示器上如何快速切換兩臺電腦主機?

我注意到很多人會遇到一個常見的情況&#xff1a;他們有兩臺電腦&#xff0c;一臺舊的用來處理基本的辦公任務&#xff0c;另一臺新的用來玩游戲。新手通常會用 DP端口連接第一臺電腦的顯示器&#xff0c;用 HDMI 連接第二臺電腦。當他們想在兩臺電腦之間切換時&#xff0c;經常…

抗輻照與國產替代:ASM1042在衛星光纖放大器(EDFA)中的應用探索

摘要&#xff1a;本文以國科安芯推出的ASM1042芯片為例&#xff0c;通過分析ASM1042的抗輻照性能、高速數據傳輸能力、可靠性以及國產化優勢&#xff0c;結合EDFA系統的需求特點&#xff0c;深入探討了其在商業衛星光纖放大器&#xff08;EDFA&#xff09;項目中的應用潛力。AS…

鴻蒙ArkUI:聲明式開發,高效構建全場景體驗

目錄 導言&#xff1a;開啟鴻蒙應用開發的新范式 ArkUI框架概覽 - 鴻蒙UI的靈魂 深入核心 - 聲明式UI開發范式 命令式 vs 聲明式&#xff1a;范式革命 ArkUI如何實現聲明式&#xff1f; 創建內置組件 創建自定義組件 自定義組件的基本結構 ArkUI框架的核心特性與優勢 …

數據查找 二叉查找樹

查找一般分為有序查找和無序查找&#xff0c;這邊在講有序查找例二分查找二分查找就是在有序數組中&#xff0c;通過mid(lowhigh)/2來判定中間值&#xff0c;將中間值與待查找的值進行比較&#xff0c;如果待查找的值大于中間值&#xff0c;那么就將范圍縮小&#xff0c;查找右…

幾款開源的安全監控與防御工具分享

安全監控與防御工具概述 在現代網絡安全架構中,合理選擇和部署一系列的安全監控、檢測、響應工具至關重要。下面我們將介紹一些常見的安全工具,包括 Elkeid、Wazuh、Caldera、ELK、Snort、Suricata、OpenHFW、OSSEC、GScan 和 Sysom,并詳細介紹它們的下載鏈接、用處、使用方…

Elasticsearch:ES|QL 改進的時間線

作者&#xff1a;來自 Elastic Toms Mura 讓我們回顧一下 ES|QL 的歷史和它的改進。 更多閱讀&#xff0c;Elasticsearch&#xff1a;ES|QL 查詢展示。 Elasticsearch 配備了眾多新功能&#xff0c;幫助你為自己的用例構建最佳搜索方案。查看我們的示例筆記本了解更多內容&…

Linux | Bash 子字符串提取

注&#xff1a;本文為 “ Bash 子字符串提取” 相關合輯。 英文引文&#xff0c;機翻未校。 如有內容異常&#xff0c;請看原文。 How to Extract Bash Substring? [5 methods] 如何提取 Bash 子字符串&#xff1f;[5 種方法] 2024-04-28 00:00:00 In Bash, a substring is…

Vue2 前端開發 - vue-quill-editor 富文本編輯器(編輯器基礎案例、編輯器配置參數解讀、編輯器事件)

一、vue-quill-editor 1、vue-quill-editor 概述vue-quill-editor 是一個基于 Quill 富文本編輯器的 Vue 組件vue-quill-editor 在 Vue 2 項目中可以很方便地集成與使用2、vue-quill-editor 安裝 執行如下指令&#xff0c;安裝 vue-quill-editor npm install vue-quill-editor …

斷網情況下,網線直連 Windows 筆記本 和Ubuntu 服務器

在斷網情況下&#xff0c;通過網線直連 Windows 筆記本 和 Ubuntu 服務器&#xff0c;并使用 VSCode 訪問服務器及 Docker 容器 的步驟如下&#xff1a;1. 物理連接&#xff08;網線直連&#xff09; 1.1 使用網線連接 用 網線&#xff08;Cat5e 或更高&#xff09; 連接 Windo…

消息隊列總結

為什么需要消息隊列&#xff1f; 隨著互聯網快速發展&#xff0c;業務規模不斷擴張&#xff0c;技術架構從單體演進到微服務&#xff0c;服務間調用復雜、流量激增。為了解耦服務、合理利用資源、緩沖流量高峰&#xff0c;「消息隊列」應運而生&#xff0c;常用于異步處理、服務…

C#引用轉換核心原理:類型視角切換

&#x1f50d; C#引用轉換核心原理&#xff1a;類型視角切換 引用類型由內存指針和類型標記組成&#xff08;如圖1&#xff09;。引用轉換不改變內存地址&#xff0c;僅改變編譯器識別對象的“視角”&#xff1a; B myVar1 new B(); // 實際B類型對象 A myVar2 (A)myV…

重要發布丨MaxKB V2正式發布,助力用戶快速構建企業級智能體

2025年7月18日&#xff0c;MaxKB V2版本正式發布。MaxKB是一個強大易用的企業級智能體平臺&#xff0c;致力于解決企業AI落地所面臨的技術門檻高、部署成本高、迭代周期長等問題&#xff0c;讓企業用戶落地AI更簡單。 秉承“開箱即用&#xff0c;伴隨成長”的設計理念&#xff…

大語言模型任務分解與匯總:從認知瓶頸到系統化解決方案

一、緣起&#xff1a;為什么大模型需要"分而治之" 1.1 從一個真實場景說起 設想這樣一個場景&#xff1a;你要求GPT-4幫你完成一份包含市場調研、競品分析、財務預測和戰略規劃的商業計劃書。即使是最先進的大模型&#xff0c;面對這樣的復雜任務也會"力不從心&…

Spring核心注解@RequestMapping詳解

RequestMapping 是 Spring Framework 中一個核心注解&#xff0c;用于在 Spring MVC&#xff08;或 Spring WebFlux&#xff09;中將 HTTP 請求映射到特定的處理器&#xff08;Controller 中的方法&#xff09;或處理器類。它告訴 Spring 框架&#xff1a;當一個匹配特定條件的…

OSPF路由協議的協商過程

OSPF的知識點非常多&#xff0c;協議過程也是一個不大不小的知識點&#xff0c;今天就簡單的說一下&#xff0c;OSPF是如何進行協商的。OSPF&#xff08;Open Shortest Path First&#xff09;協議是一種用于路由選擇的動態鏈路狀態協議&#xff0c;是大型網絡普遍使用的動態路…

MySql:索引,結構

文章目錄注意事項結構注意事項 主鍵字段在建表時&#xff0c;會自動創建主鍵索引添加唯一約束時&#xff0c;數據庫實際上會添加唯一索引。 解釋&#xff1a; 增&#xff1a;創建&#xff1a; create [unique] index 索引名 on 表名 (字段名……)&#xff1b;-- 舉例 :給tb…

ts學習2

JavaScript 中的每個值都有一組行為&#xff0c;您可以通過運行不同的操作來觀察這些行為。這聽起來很抽象&#xff0c;但作為一個簡單的例子&#xff0c;考慮我們可能在名為 message 的變量上運行的一些操作。 // Accessing the property toLowerCase // on message and then…

k8s環境使用Operator部署Seaweedfs集群(下)

作者&#xff1a;閆乾苓 文章目錄4.4.3 部署seaweedfs集群4.4.4 驗證集群運行狀態4.4.5 測試集群功能4.4.3 部署seaweedfs集群 集群Yaml示例 apiVersion: seaweed.seaweedfs.com/v1 kind: Seaweed metadata:name: seaweed1namespace: default spec:image: chrislusf/seaweedf…

【橘子分布式】gRPC(理論篇)

一、簡介 我們在前面學習了thrift rpc的知識&#xff0c;我們從其中接觸到了IDL&#xff0c;編解碼協議&#xff0c;服務的遠程調用(調用遠程服務就像在在本地調用一樣)等各種概念。 其實我個人對thrift的使用并不多&#xff0c;我更多的是使用今天我們要提到的一個RPC框架稱之…

OSPF高級特性之GR

一、概述OSPF GR(Graceful Restart),在路由器發生故障或管理員干預的情況下重啟了OSPF進程時,重新構建控制平面時,轉發平面不受影響,仍可以正常轉發數據。在我們OSPF網絡環境當中,假設路由器為框式路由器,通常框式路由器有多個主控板,當主主控板發生故障時會切換到備主控板上。…