ZYNQ筆記(十三):雙核 AMP 通信實驗

版本:Vivado2020.2(Vitis)

ZYNQ 裸機雙核 AMP 實驗:

????????CPU0 接收串口的數據,并寫入 OCM 中,然后利用軟件產生中斷觸發 CPU1;CPU1 接收到中斷后,根據從 OCM 中讀出的數據控制呼吸燈的頻率,并在控制結束后觸發 CPU0 中斷,實現了雙核 CPU 通信的功能。

目錄

一、介紹

(1)雙核 AMP 通信

(2)ZYNQ啟動流程(裸機)

二、硬件設計

三、軟件設計

(1)新建 CPU0 應用工程

(2)分配?CPU0 DDR 空間

(3)新建 CPU1?應用工程

(4)分配?CPU0 DDR 空間

(5)代碼部分

(6)下載

四、效果


一、介紹

????????Zynq-7000 SoC 集成了?雙核 ARM Cortex-A9 MPCore,采用對稱多處理(SMP)架構,同時支持非對稱多處理(AMP)模式,適用于嵌入式高性能計算和實時控制場景。

(1)雙核 AMP 通信

? ? ? ? 直接附上正點原子開發指南的內容切片:

????????? — — — — — — — — — — — — — 分割線 — — — — — — — — — — — —?

(2)ZYNQ啟動流程(裸機)

? ? ? ? 上面介紹有提到了一些專有名詞(如BootROM、FSBL、OCM),這里連帶介紹一下 ZYQN(Xilinx Zynq-7000 SoC) 裸機開發時的啟動流程,主要分為以下幾個階段:

1.?Boot ROM

  • 硬件自動執行:上電或復位后,芯片首先運行片內ROM中的固化代碼(Boot ROM)。

  • 啟動模式檢測:根據硬件配置(如模式引腳設置)確定啟動源(如QSPI Flash、SD卡、NAND Flash、JTAG等)。

  • 加載FSBL:從啟動設備中讀取?FSBL(First Stage Boot Loader)到芯片的 OCM(On-Chip Memory)或 DDR 中(需預先配置DDR,本次例程配置了所以程序基于 DDR 運行)。

2.?FSBL(First Stage Boot Loader)

  • 功能

    • 初始化必要外設(如DDR控制器、時鐘、PLL)。

    • 從Flash或SD卡中加載用戶程序(裸機代碼或第二階段引導程序)。

    • 可配置 PL(Programmable Logic)部分(可選,需加載比特流文件)。

  • 生成方式:通過 Xilinx SDK 或 Vitis 工具鏈生成(基于用戶硬件設計)。

  • 執行位置:通常在 OCM 中運行。

3.?用戶程序(裸機代碼)

  • 加載與執行:FSBL將用戶編寫的裸機程序(ELF文件)加載到DDR或OCM中,并跳轉到其入口地址。執行程序。

二、硬件設計

????????(1)本實驗是用軟件產生中斷(SGI)的方式來控制兩個 CPU 訪問共享內存的過程:

????????首先需要處理器向共享內存中寫入一個數據,本實驗選擇 CPU0 往共享內存中寫入數據。當 CPU0 寫入成功后就發送一條軟中斷指令去觸發 CPU1 去讀取共享內存中的數據。

????????當 CPU1 讀取到共享內存的數據后需要通過 M_AXI_GP0 接口的 AXI4-Lite 總線將數據發送到 PL 端呼吸燈的 IP 核, 呼吸燈的IP核根據PS發過來的數據對呼吸頻率進行相應的配置,然后 CPU1 發送一條軟中斷指令觸發 CPU0 繼續往共享內存中寫入數據。

????????到此便實現了兩個 CPU 通過共享內存進行數據交互的功能,同時為了對IP核進行控制以及方便觀察數據流的走向,用 UART 接收控制命令以及打印 Debug 信息。

? ? ? ? (2)關于自定義?LED 呼吸燈 IP 核的設計與使用這里不再贅述,跟之前筆記的例程操作步驟一致,詳細參考:ZYNQ筆記(六):自定義IP核-LED呼吸燈

? ? ? ? (3)最后整體 bd 設計部分如圖所示:設計檢查、Generate Output Products、 Create HDL Wrapper、管腳約束、Gnerate Bitstream、Export Hardware(包含比特流文件)、啟動Vitis

????????注意 LED 呼吸燈的 IP 核要手動添加 LED 管腳并與開發板的 LED 對應管腳綁定。

三、軟件設計

(1)新建 CPU0 應用工程

? ? ? ? 新建工程名?“cpu0_uart” ,系統工程名“AMP_2core_system”,通過cpu0實現串口通信,主要是從uart接收控制命令。如圖所示,同時處理器選擇ps7_cortexa9_0(默認也是cpu0).

(2)分配?CPU0 DDR 空間

????????單核應用工程,默認將DDR空間全部分配給cpu0,這里用到了雙核所以需要進行分配,就直接將DDR分二部分,一部分給cpu0,另一部分給cpu1(具體怎么大小分配都行),如圖所示:

????????紅框標注的地方左側為基地址,右側為存儲空間大小(單位字節),存儲空間大小將默認的完整空間大小 0x1FF00000 (十進制 535,822,336;535,822,336/1024/1024 = 511MByte),修改為為 0x0FF00000(十進制 267,386,880;267,386,880/1024/1024 = 255MByte)。修改完成后,按下“Ctrl”+ “S”保存。

????????另外圖中的 ps7_ram_0 和 ps_ram_1 為 OCM 共享內存的基地址和存儲空間大小。后面雙核通信就是通過這訪問這兩塊共享存儲區域實現的,后面軟件設計也會用到其的基地址以進行訪問(本例程任選一個即可,后面的設計選用的是 ps_ram_0 基地址0x0)。

(3)新建 CPU1?應用工程

????????在創建 CPU1 應用工程之前,需要新建基于 CPU1 的板級支持包(BSP)。雙擊 platform.spr,打開 system_wrapper 設置界面,如下圖所示:

????????之后依次對硬件平臺工程(system_wrapper)右擊選擇 Clean Project 和 Build Project。

? ? ? ? 接下來創建 CPU1 的應用工程,右鍵系統工程 AMP_2core_system?選擇“Add Application Project”,從而在系統工程下添加一個新的應用工程,工程名命名為 cpu1_led,處理器選擇 ps7_cortexa9_1, 如圖所示:

(4)分配?CPU0 DDR 空間

????????同樣需要為 cpu2 分配 DDR 空間,兩個核的DDR空間不能有重合,負責程序運行時會出現同時訪問導致程序異常,所以這里要對起始地址和大小同時進行修改,如圖所示:

????????起始地址 =?CPU0 的?DDR 起始地址 + 其分配大小 = 0x10000 + 0x0FF00000 = 0x10000000 分配大小 ≤? DDR 完整大小 -?CPU0 的?DDR 分配大小 =?0x1FF00000(由開發板DDR大小決定)-?0x0FF00000 =?0x10000000?。修改完成后,按下“Ctrl”+“S”保存。

(5)代碼部分

????????新建 cpu0_uart 應用工程源文件“mian_0.c”,編寫代碼:

#include "xparameters.h"
#include "xscugic.h"
#include "xil_printf.h"
#include "xil_exception.h"
#include "xil_mmu.h"
#include "stdio.h"//============================宏定義===============================//
#define SHARE_BASE           	0x0		                     //共享OCM首地址(根據lscript.ld設置)
#define CPU1_COPY_ADDR       	0xfffffff0                   //存放CPU1應用起始地址的地址(參考ug585手冊)
#define CPU1_START_ADDR      	0x10000000                   //CPU1應用起始地址(給cpu1分配的DDR起始地址)#define INTC_DEVICE_ID	     	XPAR_SCUGIC_SINGLE_DEVICE_ID //GIC中斷控制器ID
#define CPU1_ID              	XSCUGIC_SPI_CPU1_MASK        //CPU1 ID
#define SOFT_INTR_ID_CPU0 	 	0                            //軟件中斷號 0 ,范圍0~15
#define SOFT_INTR_ID_CPU1    	1                            //軟件中斷號 1 ,范圍0~15//"SEV"指令喚醒CPU1并跳轉至相應的程序
#define sev()                __asm__("sev")               //C語言內嵌匯編寫法 send event指令//===========================函數聲明==============================//
void start_cpu1();
void cpu0_intr_init(XScuGic *intc_ptr);
void soft_intr_handler(void *CallbackRef);//===========================全局變量==============================//
XScuGic Intc;                    //中斷控制器驅動程序實例
int rec_freq_flag = 0;           //接收到呼吸燈頻率設置的標志
int speed;                       //頻率速度檔位(0~7)//=========================CPU0 main函數===========================//
int main()
{//S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0Xil_SetTlbAttributes(SHARE_BASE,0x14de2);    //禁用OCM的Cache屬性//S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0Xil_SetTlbAttributes(CPU1_COPY_ADDR,0x14de2);//禁用0xfffffff0的Cache屬性//啟動CPU1(固化程序時需使用)//start_cpu1();//CPU0中斷初始化cpu0_intr_init(&Intc);while(1){if(rec_freq_flag == 0){xil_printf("CPU0: Input 0~7 to change breath LED frequency \r\n");xil_printf("\r\n");//輸入0~7指令scanf("%d",&speed);if(speed >= 0 && speed <= 7){xil_printf("CPU0: Input Command %d \r\n",speed);//向共享的地址中寫入輸入的數據Xil_Out8(SHARE_BASE,speed);//CPU0軟件觸發CPU1中斷XScuGic_SoftwareIntr(&Intc, SOFT_INTR_ID_CPU1, CPU1_ID);rec_freq_flag = 1;}else{xil_printf("CPU0: Command Error, out of range 0~7 \r\n");}}}return 0 ;
}//====================啟動CPU1,用于固化程序=======================//
// 如果只是通過 JTAG 模式下載程序,可以不編寫這個啟動函數,這個函數僅在固化程序的時候起作用。
void start_cpu1()
{//向 CPU1_COPY_ADDR(0Xffffffff0)地址寫入 CPU1 的訪問內存基地址Xil_Out32(CPU1_COPY_ADDR, CPU1_START_ADDR);dmb();  //等待內存寫入完成(同步)sev();  //通過"SEV"指令喚醒CPU1并跳轉至相應的程序
}//=========================中斷處理函數===========================//
void soft_intr_handler(void *CallbackRef)
{xil_printf("CPU0: Received Soft Interrupt from CPU1 (set finish) \r\n");rec_freq_flag = 0;
}//========================CPU0中斷初始化==========================//
void cpu0_intr_init(XScuGic *intc_ptr)
{//初始化中斷控制器XScuGic_Config *intc_cfg_ptr;intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID);XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr,intc_cfg_ptr->CpuBaseAddress);//設置中斷異常處理功能Xil_ExceptionInit();Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr);//使能處理器中斷Xil_ExceptionEnable();//關聯中斷函數XScuGic_Connect(intc_ptr, SOFT_INTR_ID_CPU0,(Xil_ExceptionHandler)soft_intr_handler, (void *)intc_ptr);//使能中斷XScuGic_Enable(intc_ptr, SOFT_INTR_ID_CPU0); //CPU0軟件中斷
}

????????新建 cpu1_led?應用工程源文件“mian_1.c”,編寫代碼:

#include "xparameters.h"
#include "xscugic.h"
#include "xil_printf.h"
#include "xil_exception.h"
#include "xil_mmu.h"
#include "stdio.h"
#include "breath_led_ip.h"//============================宏定義===============================//
#define SHARE_BASE  	     	0x0      		             //共享OCM首地址(根據lscript.ld設置)#define INTC_DEVICE_ID	     	XPAR_SCUGIC_SINGLE_DEVICE_ID //GIC中斷控制器ID
#define CPU0_ID              	XSCUGIC_SPI_CPU0_MASK        //CPU0 ID
#define SOFT_INTR_ID_CPU0 		0                            //軟件中斷號 0 ,范圍0~15
#define SOFT_INTR_ID_CPU1 		1                            //軟件中斷號 1 ,范圍0~15#define LED_IP_BASEADDR     	XPAR_BREATH_LED_IP_0_S0_AXI_BASEADDR //LED IP基地址
#define LED_EN					BREATH_LED_IP_S0_AXI_SLV_REG0_OFFSET //宏定義led_en  對應寄存器(slv_reg0)地址偏移量
#define SPEED_EN				BREATH_LED_IP_S0_AXI_SLV_REG1_OFFSET //宏定義speed_en對應寄存器(slv_reg1)地址偏移量
#define SPEED					BREATH_LED_IP_S0_AXI_SLV_REG2_OFFSET //宏定義speed   對應寄存器(slv_reg2)地址偏移量//===========================函數聲明==============================//
void cpu1_intr_init(XScuGic *intc_ptr);
void soft_intr_handler(void *CallbackRef);//===========================全局變量==============================//
XScuGic Intc;               //中斷控制器驅動程序實例
int soft_intr_flag = 0;     //軟件中斷的標志
int speed;                  //頻率檔位(0~7)//=========================CPU1 main函數===========================//
int main()
{//S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0Xil_SetTlbAttributes(SHARE_BASE,0x14de2);    //禁用OCM的Cache屬性//CPU1中斷初始化cpu1_intr_init(&Intc);//打開LED呼吸燈BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR, LED_EN, 0x1);//使能LED呼吸燈頻率設置BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR, SPEED_EN, 0x1);while(1){if(soft_intr_flag){speed = Xil_In8(SHARE_BASE);     //從共享OCM中讀出數據xil_printf("CUP1: Received Command is %d \r\n",speed) ;//設置LED呼吸燈頻率BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR, SPEED, speed);//CPU1軟件觸發CPU0中斷XScuGic_SoftwareIntr(&Intc,SOFT_INTR_ID_CPU0,CPU0_ID);soft_intr_flag = 0;}}return 0 ;
}//=========================中斷處理函數===========================//
void soft_intr_handler(void *CallbackRef)
{xil_printf("CPU1: Received Soft Interrupt from CPU0 (command ready) \r\n") ;soft_intr_flag = 1;
}//=========================CPU1中斷初始化=========================//
void cpu1_intr_init(XScuGic *intc_ptr)
{//初始化中斷控制器XScuGic_Config *intc_cfg_ptr;intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID);XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr,intc_cfg_ptr->CpuBaseAddress);//設置中斷異常處理功能Xil_ExceptionInit();Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr);//使能處理器中斷Xil_ExceptionEnable();//關聯中斷函數XScuGic_Connect(intc_ptr, SOFT_INTR_ID_CPU1,(Xil_ExceptionHandler)soft_intr_handler, (void *)intc_ptr);//使能中斷XScuGic_Enable(intc_ptr, SOFT_INTR_ID_CPU1); //CPU1軟件中斷
}

(6)下載

????????下載時需要將兩個應用工程以及FPGA的比特流文件全部勾選下載。操作如圖所示:

? ? ? ? 選中兩個核的應用工程:

? ? ? ? 選中同時下載FPGA波特率文件(這個選項一般是默認勾選了):

四、效果

? ? ? ? 1.下載后CPU0打印輸入指令的提示信息,同時LED燈已經開始工作:

? ? ? ? 2.第一次輸入9(正確指令范圍0~7),CPU0打印報錯信息并重新提示輸入指令。

? ? ? ? 3.第二次輸入1,CPU0打印出接受到的正確指令,接著CPU1打印接收到來自CPU0的中斷的提示(表示CPU0已經將指令寫入OCM),接著CPU0打印接收到來自CPU1的中斷的提示(表示CPU1已經從OCM讀取指令并設置LED燈速率),此時LED呼吸燈的速度發生對應變化(比初始的0檔位閃爍的快一點),最后CPU0打印輸入指令的提示信息(表示可以進行下一次設置操作)

? ? ? ? 4.第三次輸入7,流程同上,LED燈速率達到最大,閃爍最快。

????????注意:

????????本次例程用到scanf()(頭文件 stidio.h)實現串口輸入指令,這種方式可以在vitis串口終端上進行調試。但是如果要用一般的串口助手調試就不行,需要修改串口部分的軟件設計,可以加上串口中斷功能實現接收串口輸入輸出。參考筆記:ZYNQ筆記(八):UART 串口中斷

? ? ? ? 本次例程沒有進行程序固化,所以沒有使用到CPU0啟動CPU1的函數,如果需要固化需要實現該函數,同時也許在硬件設計作配置,例如固化程序到?Flash 需要配置 QSPI Flash ,相關固化可操作參考筆記:ZYNQ筆記(七):程序固化(QSPI Flash)

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

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

相關文章

桌面端開發技術棧選型:開啟高效開發之旅

在數字化浪潮中&#xff0c;桌面端應用依然占據重要地位&#xff0c;而選擇合適的技術棧是打造優質桌面端應用的關鍵一步。以下是多種主流桌面端開發技術棧的介紹與對比&#xff0c;希望能為大家提供有價值的參考。 基于 Web 技術的跨平臺框架 ? Electron&#xff1a; ? 特…

C++ 的 輸入輸出流(I/O Streams)

什么是輸入輸出流 C 的輸入輸出操作是通過 流&#xff08;stream&#xff09; 機制實現的。 流——就是數據的流動通道&#xff0c;比如&#xff1a; 輸入流&#xff1a;從設備&#xff08;如鍵盤、文件&#xff09;讀取數據 → 程序 輸出流&#xff1a;程序將數據寫入設備&…

軟件測評中心如何保障軟件質量與安全性?

軟件測評中心是一個專注于保障軟件質量、穩定性和安全性的專業機構。在整個軟件的生命周期中&#xff0c;它扮演著極其關鍵的角色。它運用科學的方法和嚴格的準則&#xff0c;對軟件進行全面而細致的檢測和評估&#xff0c;確保用戶獲得可靠的保障。 測評核心工作 軟件測評中…

論人際關系發展的階段

朋友關系的建立和發展是一個漸進的過程&#xff0c;通常需要經歷情感積累、信任磨合和價值觀融合等階段。以下是朋友關系發展的詳細階段劃分及核心特征&#xff1a; 一、表層接觸階段&#xff08;社交試探期&#xff09; 核心特征&#xff1a;以信息交換為主&#xff0c;關系停…

網絡IP沖突的成因與解決方案

網絡IP沖突的成因與解決方案 一、IP沖突的常見現象與危害二、IP沖突的常見原因三、6種實用解決方案四、預防IP沖突的4個最佳實踐五、總結 前言 肝文不易&#xff0c;點個免費的贊和關注&#xff0c;有錯誤的地方請指出&#xff0c;看個人主頁有驚喜。 作者&#xff1a;神的孩子…

前端節流、防抖函數

節流 什么是節流&#xff1f; 節流就是同一個事件 一秒鐘他執行了很多次。但是我不想他執行這么多次&#xff0c;我只想讓他執行一次 或者兩次。 那該怎么辦&#xff1f; why baby why 那我想就是他執行的時候 我就設置一個定時器&#xff0c;如果定時器是空的&#xff0c;等會…

LeetCode第171題_Excel表列序號

LeetCode 第171題&#xff1a;Excel表列序號 題目描述 給你一個字符串 columnTitle&#xff0c;表示 Excel 表格中的列名稱。返回 該列名稱對應的列序號。 例如&#xff1a; A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ...難度 簡單 題目鏈…

基于YOLO與PySide6的道路缺陷檢測系統(源碼)

道路基礎設施的健康狀況直接影響交通安全與城市運營效率。傳統人工巡檢方式存在效率低、覆蓋范圍有限等問題,而基于深度學習的自動化檢測技術為道路缺陷識別提供了創新解決方案。本文介紹一個結合YOLO目標檢測模型與PySide6圖形界面的道路塌陷檢測系統,實現了高效、可視化的缺…

04_jQuery

文章目錄 一、jQuery介紹1.1、jQuery概述1.2、jQuery特點1.3 為什么要用jQuery 二、引入jQuery2.1、直接引入2.2、CDN引入 三、jQuery語法3.1、基本使用3.2、jQuery事件及常用事件方法3.3、jQuery選擇器&#xff08;重點&#xff09;3.3.1、基本選擇器3.3.2、層次選擇器3.3.3、…

Adruino:傳感器及步進電機

一、傳感器* 1、溫濕度傳感器 DHT11它采用專用的數字采集技術和溫濕度傳感器技術&#xff0c;包括一個電阻式感濕元件和NTC測溫元件&#xff0c;并與一個高性能的8位單片機連接。DATA端采用串行接口&#xff08;單線雙向&#xff09;與微控制器進行同步和通信。 DHT11的供電電…

高中數學聯賽模擬試題精選第18套幾何題

在 △ A B C \triangle ABC △ABC 中, A B < A C AB< AC AB<AC, 點 K K K, L L L, M M M 分別是邊 B C BC BC, C A C A CA, A B AB AB 的中點. △ A B C \triangle ABC △ABC 的內切圓圓心為 I I I, 且與邊 B C BC BC 相切于點 D D D. 直線 l l l 經過線段…

ubantu18.04(Hadoop3.1.3)之Spark安裝和編程實踐

說明&#xff1a;本文圖片較多&#xff0c;耐心等待加載。&#xff08;建議用電腦&#xff09; 注意所有打開的文件都要記得保存。 第一步&#xff1a;準備工作 本文是在之前Hadoop搭建完集群環境后繼續進行的&#xff0c;因此需要讀者完成我之前教程的所有操作。 以下所有操…

DCDC芯片,boost升壓電路設計,MT3608 芯片深度解析:從架構到設計的全維度技術手冊

一、硬件架構解析:電流模式升壓 converter 的核心設計 (一)電路拓撲與核心組件 MT3608 采用恒定頻率峰值電流模式升壓(Boost)轉換器架構,核心由以下模塊構成: 集成功率 MOSFET 內置 80mΩ 導通電阻的 N 溝道 MOSFET,漏極(Drain)對應引腳 SW,源極(Source)內部接…

Java 日志:掌握本地與網絡日志技術

日志記錄是軟件開發中不可或缺的一部分&#xff0c;它為開發者提供了洞察應用程序行為、診斷問題和監控性能的手段。在 Java 生態系統中&#xff0c;日志框架如 Java Util Logging (JUL)、Log4j 和 Simple Logging Facade for Java (SLF4J) 提供了豐富的功能。然而&#xff0c;…

上位機知識篇---時鐘分頻

文章目錄 前言 前言 本文簡單介紹了一下時鐘分頻。時鐘分頻&#xff08;Clock Division&#xff09;是數字電路設計中常見的技術&#xff0c;用于將高頻時鐘信號轉換為較低頻率的時鐘信號&#xff0c;以滿足不同模塊的時序需求。它在處理器、FPGA、SoC&#xff08;片上系統&am…

推薦幾個免費提取音視頻文案的工具(SRT格式、通義千問、飛書妙記、VideoCaptioner、AsrTools)

文章目錄 1. 前言2. SRT格式2.1 SRT 格式的特點2.2 SRT 文件的組成2.3 SRT 文件示例 3. 通義千問3.1 官網3.2 上傳音視頻文件3.3 導出文案 4. 飛書妙記4.1 官網4.2 上傳音視頻文件4.3 導出文案4.4 缺點 5. VideoCaptioner5.1 GitHub地址5.2 下載5.2.1 通過GitHub下載5.2.2 通過…

Linux深度探索:進程管理與系統架構

1.馮諾依曼體系結構 我們常見的計算機&#xff0c;如筆記本。我們不常見的計算機&#xff0c;如服務器&#xff0c;大部分都遵守馮諾依曼體系。 截至目前&#xff0c;我們所認識的計算機&#xff0c;都是由?個個的硬件組件組成。 輸入設備&#xff1a;鍵盤&#xff0c;鼠標…

觀察者模式 (Observer Pattern)

觀察者模式(Observer Pattern)是一種行為型設計模式。它定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。當主題對象的狀態發生變化時,會自動通知所有觀察者對象,使它們能夠自動更新自己的狀態。 一、基礎 1. 意圖 核心目的:定義對象間的一種一對…

Network.framework 的引入,不是為了取代 URLSession

Network.framework 的引入&#xff0c;不是為了取代 URLSession 如果你感覺 Network.framework 的引入, 可能是為了取代 URLSession, 那你就大錯特錯了&#xff01;這里需要非常準確地區分一下&#xff1a; &#x1f535; Network.framework 不是為了取代 URLSession。 &…

Redis 數據分片三大方案深度解析與 Java 實戰

Redis 數據分片是將數據分散存儲在多個 Redis 實例上的技術&#xff0c;以解決單個 Redis 實例在存儲容量、性能和可用性上的限制。常見的 Redis 數據分片方案包括客戶端分片、代理分片和Redis Cluster&#xff08;集群分片&#xff09;&#xff0c;以下為你詳細介紹&#xff1…