【系統全面】Linux內核原理——基礎知識介紹

理解內核:內核原理

計算機系統的軟件分層

不同于單片機中使用代碼直接與硬件交互,對于這種方式的缺點深有:

(1)復雜度高,調用難度高,需要深入理解硬件的工作原理和細節。

(2)細節繁瑣,特別是在處理底層寄存器和端口配置時,極易出錯。

(3)出錯時調試難度也很高,因為涉及到底層硬件的交互,定位問題相對困難。

(4)更換芯片時,往往需要重寫驅動,導致代碼的可移植性很差,增加了開發和維護 的成本。

? **為了解決這些問題,操作系統應運而生。**后者在硬件之上做了一層抽象,提供了統一 的接口和服務,隱藏了硬件的復雜性和差異性,從而簡化了程序對硬件資源的訪問和管理, 使得開發者能夠更加專注于應用邏輯的實現,而不必深入到復雜的硬件操作細節中。因此, 它為上層應用程序提供了一個統一、穩定、高效的運行環境,極大地提升了軟件開發的效 率和可靠性。

在這里插入圖片描述
? 內核 內核是操作系統的核心部分,負責管理計算機的硬件資源,包括處理器、內存、存儲 設備和其他外圍設備。內核提供系統服務的基礎,如進程管理、內存管理、設備驅動、文 件系統和網絡通信等。 內核作為硬件和應用程序之間的中介,提供一個抽象層,使得應用程序不需要直接與 硬件交互。

? 應用程序 應用程序是運行在操作系統之上的軟件,用于執行特定的任務,如文本編輯、圖像處 理、網絡通信等。 應用程序提供用戶所需的功能,依賴于操作系統提供的接口與硬件資源進行交互。

進程和程序

程序是存儲在硬盤等存儲介質的代碼,是一串二進制機器碼,是靜態的。

進程是正在運行的程序及相關資源的總稱,是一種抽象,是動態的。

在這里插入圖片描述

進程控制塊PCB

在Linux 內核中,進程控制塊的實現是struct task_struct,下述信息都存儲在這 個結構體中。

內核會保存每個進程的一些信息,稱為進程控制塊(Process Control Block, PCB),方便管理進程,內容如下:

(1)進程編號(PID),每個進程對應的唯一編號,一般為正整數形式。

(2)進程狀態信息。

(3)進程切換時需要保存和恢復的一些 CPU 寄存器,其中關鍵的有程序計數器 (Program Counter)的值,用于記錄進程恢復時應執行的指令地址。

(4)內存管理信息,如頁表、內存限制、段表等。

(5)當前工作目錄(Current Working Directory)。

(6)進程調度信息,包括進程優先級、調度隊列指針等。

(7)I/O 狀態信息,包括分配給進程的 I/O 設備列表,打開的文件描述符表等,后者 包含很多指向file結構體的指針。

(8)同步和通信信息,包括信號量、信號、等用于進程同步和通信機制的信息。

(9)用戶id和組id。

進程的內存模型

在這里插入圖片描述

在這里插入圖片描述

為什么可以同時運行的程 序數量遠大于CPU的核心數?——————CPU虛擬化和進程的調度

? 理論上,同一時刻單核CPU只能運行一個進程,但很多時候,我們可以同時運行的程 序數量遠大于CPU的核心數。這是因為,操作系統的CPU調度單元對CPU的資源做了時間 分片,即在時間尺度上對CPU做了劃分,如15:15到15:16執行進程A,15:16到15:17 執行進程B。實際上進程間的切換是非常迅速的,在用戶的角度,就好像多個進程在同一 時間運行。因此,看起來好像計算機可以同時運行的進程數遠大于CPU核心數。

進程的切換是由操作系統的CPU調度器完成的。 進程執行到某一時刻,被內核中斷,然后內核可以重新開始之前被 中斷的進程,這種決策就是調度(Scheduling),是由內核中稱為調度器(Scheduler) 的代碼處理的。當內核選擇一個新的進程時,我們說內核調度了這個進程。 

在這里插入圖片描述

抽象的進程狀態模型和統一

在這里插入圖片描述
初始態非常短暫,通常是看不到的。終止態和僵尸態實際上都是進程執行完畢之后的 狀態,嚴格意義上講,并不屬于進程運行時狀態。因此,部分操作系統資料在介紹進程狀 態時不會在進程轉換狀態機中包含。下圖是《操作系統導論》中的進程轉換狀態機。

在這里插入圖片描述

虛擬內存映射

(1)虛擬內存 虛擬內存是計算機系統內存管理的一種技術,它為每個進程提供了一種“虛擬”的地 址空間,這個地址空間對于每個程序來說看起來都是連續的,但實際上可能被分散地存儲 在物理內存和磁盤上(如交換空間或頁面文件)。虛擬內存允許系統超額分配內存,即分 配的內存總量可以超過物理內存的實際容量。虛擬內存簡化了內存的管理,使得應用程序 不需要關心物理內存的實際情況。

(2)物理內存 物理內存指的是計算機中安裝的實際RAM(隨機訪問存儲器)模塊。它是系統用來存 儲正在運行的程序和數據的硬件資源。 物理內存直接影響到計算機能夠同時處理的信息量。更多的物理內存意味著可以同時 運行更多的程序,或者處理更大的數據集。

(3)MMU 進程可以直接操作的只有虛擬內存,那么,虛擬內存畢竟是“虛擬”的,進程的代碼 段、數據、棧等最終一定要存儲到真正的物理內存,那么,我們就要建立虛擬內存和物理 內存之間的映射關系。在操作系統中,這件事是由MMU來完成的。

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

前面的共享內存與虛擬內存映射的關系

在這里插入圖片描述

異常和中斷

在這里插入圖片描述

(1)中斷 中斷(Interrupt)通常是I/O設備或時鐘觸發的,信號來自處理器外部,不是由任 何一條指令造成的,從這個角度講,它是異步的。中斷處理完畢后總是執行下一條指令。

(2)異常 異常是(Exception)CPU 執行指令時檢測到特定條件觸發的。x86-64架構定義了三 種異常:陷入(Trap)、故障(Fault)和終止(Abort)。

① 陷入 是由進程執行陷入指令(可以切換到內核態的指令)主動觸發的,是同步的,執行完 畢后總是執行下一條指令。

② 故障 故障由錯誤情況引起,可能被故障處理程序修正,如上文提到的缺頁故障就是故障的 一種。故障發生時,處理器將控制權交由故障處理程序,如果故障被修復,則返回引起故 障的指令,并重新執行。否則,處理程序返回到內核中的abort例程,后者終止引起故障 的進程。

③ 終止 終止是不可恢復的致命錯誤造成的結果。如底層硬件錯誤,或者進程產生的算數異常, 無法被修復。終止發生時,CPU將控制權交由終止處理程序,這個程序不會將CPU的控制 權返還給應用程序,而是返回到內核中的abort例程,后者終止進程。

中斷和異常的區別

在x86-64 架構中,中斷和異常區別在于:中斷處理例程被調用時,CPU會清除 EFLAGS 寄存器中的IF(Interrupt Enable)位,避免其它中斷干擾當前中斷處理例程 的執行。而異常處理例程被調用時IF不會被清除。

中斷和異常處理

在這里插入圖片描述
在這里插入圖片描述

中斷上文 中斷上文是指在異常發生之前,處理器的狀態。即中斷處理時最先壓入內核棧的數據,
包括段選擇器的值、棧指針、程序計數器、狀態相關寄存器等的值。

中斷下文 中斷下文是指涉及中斷或異常處理時內核所處的環境和狀態,包括內核棧中保存的用
戶線程狀態、狀態寄存器、段選擇器和內核棧指針等寄存器、內核態下執行的中斷或異常 處理函數等內容。

中斷和異常處理的案例——缺頁故障 原理

在這里插入圖片描述
在這里插入圖片描述

進程創建過程

? 進程是操作系統中的一個基本概念,代表了操作系統中正在運行的一個程序的實例。 進程不僅包括代碼本身,還包括運行該程序所需的各種資源,如虛擬內存空間、文件描述 符、環境變量等。每個進程都有一個獨立的虛擬地址空間,這意味著一個進程無法直接訪 問另一個進程的內存。

? 當一個新進程被創建時,操作系統會為其分配一個唯一的進程標識符(PID)和一個 新的虛擬地址空間。隨后,操作系統會加載程序代碼到虛擬內存中,并設置初始的堆棧和寄存器,包括程序計數器(PC)和棧指針(SP)。通過fork創建的子進程將繼承父進程 的資源副本,包括打開的文件描述符和環境變量。

? 當我們通過ps -ef看到的信息可以分為兩類:進程信息和內核線 程的信息,進程工作在用戶態,執行用戶程序,內核線程工作在內核態,執行內核任務。 內核啟動時會創建1號進程和2號內核線程,通常1號進程名為systemd,2號內核線程 名為kthreadd,其它進程全部由systemd及其子進程通過fork()+execve()的方式創建, 其它內核線程都是由kthreadd及其創建的內核線程通過kthread_create()這樣的方式 創建的。fork()和kthread_create()是通過創建系統調用clone()實現的。那么他們對應關系是怎樣的?

1.進程PCB的實現是struct task_struct類型的實 例

2.fork()

fork()主要完成了以下工作:

(1)為子進程創建內核棧、thread_info實例。

(2)復制父進程的 task_struct,后者包含了內核棧、虛擬內存管理信息、打開的文件 描述符表等的指針,此時子進程只是復制了這些資源的引用。

(3)清除子進程的統計信息,更新子進程task_struct的標志位。

(4)為子進程分配新的PID,將子進程的PPID設置為調用fork()的進程。

(5)清除與fork()返回值相關的寄存器,使得子進程中fork()返回的是0。

(6)復制打開的文件描述符表,這一過程底層被指向的 struct file 實例中引用計數加 一。復制文件系統信息、復制地址空間(頁表相關信息),復制信號處理信息。

(7)最后,如果子進程成功創建則被喚醒,處于就緒態。

在這里插入圖片描述
COW

寫時復制機制(Copy on Write COW)可以提高進程創建效率。子進程完整地復制了 父進程的地址空間,此時父子進程的虛擬內存空間映射到相同的物理內存空間。只有當二 者之一執行了寫入操作才會復制寫入區域的內容,為父子進程維護不同的物理頁幀。
在這里插入圖片描述

COW就是以下程序現象的原因:

#include <stdio.h> 
#include <unistd.h> 
int main() { 
int val = 123; // 定義變量接收子進程PID __pid_t pid; // 創建一個子進程 if ((pid = fork()) > 0 ){ sleep(1); printf("父進程中val 的內容是: %d\nval 所在的地址是: %p\n", val, 
&val); } else if (pid == 0) { val = 321; printf("子進程中val 的內容是: %d\nval 所在的地址是: %p\n", val, 
&val); } else { printf("子進程創建失敗\n"); } return 0; 
} 

在這里插入圖片描述

父子進程中各自打印了val變量的值和內存地址。子進程將val變量更改為321,我 們特意讓父進程休眠了一秒,確保子進程的更改先于父進程的輸出。我們發現子進程修改 了val變量的值,而父進程的val未受影響,說明兩個進程的val變量是完全獨立的。但 是,二者的內存地址卻完全相同。既然內存地址是相同的,父子進程中的val變量不就應 該是同一個嗎?但子進程修改了自己的val,父進程的val卻未受影響,從這個角度看, 二者又是完全獨立的變量?這不是矛盾了嗎?
答:沒有 原因是COW

3.execve

(1)參數和環境準備 內核檢查傳遞給execve()的參數,包括可執行文件的路徑、環境變量和命令行參數, 以確保它們的有效性和安全性。這個階段內核會在內核空間中準備一份新程序需要的命令 行參數和環境變量的備份。

(2)打開和驗證可執行文件 打開指定的二進制文件,驗證其格式是否支持(例如,ELF格式),并檢查執行權限。 如果這一步找不到可執行文件的路徑,就會直接終止。

(3)創建新的內存映射 清除進程當前的內存映射,包括用戶空間中的代碼、數據、堆和棧。 根據新的程序建立新的代碼段、數據段、堆和棧等。需要注意的是,內存映射不包含內核空間,內核空間的映射是由操作系統內核管理的, 對所有進程是共享的。execve切換的只是用戶空間。

(4)復制參數和環境變量 在新的地址空間中為命令行參數和環境變量分配空間,并將內核中它們的備份復制到 新的位置。

(5)初始化進程上下文 設置新的程序計數器、棧指針等,以便新程序可以正確執行。 清理和重設進程的各種內核資源,如文件描述符表。根據文件描述符的 close-on exec 標志(FD_CLOEXEC)進行處理,如果有該標志,則文件描述符被關閉。

(6)更新 task_struct 和其他內核結構 更新 task_struct 中關于進程地址空間、堆棧、命令行參數、環境變量的指針。 重置信號控制信息到默認狀態。 清理進程的各種內核狀態,如未處理的信號、定時器等。

(7)執行新程序 跳轉到新加載程序的入口點開始執行。度看, 二者又是完全獨立的變量?這不是矛盾了嗎? 在這里插入圖片描述

進程組

進程組ID(Process Group ID,簡稱PGID)在UNIX和類UNIX系統(如Linux) 中用來標識一個或多個進程的集合。進程組用于信號傳遞和終端控制(如作業控制)。在 很多方面,進程組的概念是為了更好地支持在終端中運行的交互式作業。

進程切換過程

1)進程切換的場景 如果進程的運行不會被打斷,那么操作系統內核想要回CPU的控制權就只能寄希望于 進程主動歸還,或者強制重啟計算機。現代計算機提供了中斷和異常機制,二者都可以打 斷正在執行的進程,將CPU的控制權交還給內核。進程的切換需要內核介入,必然要通過 中斷或異常來實現。進程切換主要在以下幾種情況下發生。

(1)時鐘中斷觸發,被中斷的進程獲得的 CPU 時間片耗盡,操作系統決定切換進程。

(2)當前進程發生故障,內核奪回 CPU 控制權,如果故障無法被修復,則內核終止 該進程,切換至其它進程。 (3)時鐘中斷觸發,當前進程在等待IO操作,為避免資源浪費,切換至其他進程。

(4)時鐘中斷觸發,高優先級進程處于就緒狀態,內核將 CPU 使用權由當前進程轉 交給高優先級進程。

2)進程切換過程 進程的切換需要借助中斷或異常,流程如下。假設正在運行的進程A要被切換到進程 B。

(1)CPU暫存棧指針、程序計數器、段選擇器和狀態寄存器的值。

(2)棧指針由進程A的用戶棧切換至它的內核棧,操作系統切換至內核態。

(3)CPU將第一步暫存的寄存器值壓入內核棧。

(4)將錯誤碼壓入內核棧。

(5)程序計數器指向中斷或異常處理程序。

(6)操作系統執行中斷或異常處理程序。

7)在中斷或異常處理程序中,調度器會判斷是否滿足進程切換條件,如果滿足則執 行以下操作:

① 將進程A所有相關寄存器的值保存至進程A的PCB(Linux底層實現為struct task_struct)。這會包含它的頁表基址。

② 有些架構會清除TLB。

③ 將進程B的PCB中記錄的頁表基址、棧指針等寄存器信息加載(恢復)到對應寄 存器。此時棧指針指向進程B的內核棧。進程A回到調度隊列。如果進程A是因為CPU時 間片耗盡,則處于就緒狀態,回到就緒隊列。

? 要注意,打開的文件描述符表等相關資源的切換不需要通過寄存器實現,這些資源存 儲在struct task_struct 結構體中,調度器可以從調度隊列獲得task_struct,完成 資源切換。

(8)執行權限檢查,判斷當前是否處于內核態。

(9)從進程B的內核棧恢復CS和程序計數器,后者指向B的用戶進程代碼。

(10)恢復進程B的狀態寄存器RFLAGS。

(11)從進程 B的內核棧恢復 SS和棧指針,后者指向進程 B的用戶棧,此時切換到 用戶態。

(12)在用戶態下繼續進程B的執行,進程切換完成。

在這里插入圖片描述

進程上下文

1)進程上文 進程上文是指進程被掛起時其執行狀態的集合,這使得進程能夠在未來某個時間點繼 續執行。它包括進程的程序計數器、棧指針等寄存器狀態,進程的內核棧和用戶棧的信息、 內存映射信息(如頁表條目),打開的文件描述符表等。

2)進程下文 進程下文是指將要被加載和執行的掛起進程的執行狀態集合。包括將要被執行的進程 的程序計數器、棧指針等寄存器狀態,進程的內核棧和用戶棧的信息、內存映射信息(如 頁表條目),打開的文件描述符表等。

系統調用和庫函數

在這里插入圖片描述

線程真的存在嗎?

線程是進程中的執行單元,它共享進程的資源和地址空間,但擁有自己的執行堆棧、 程序計數器和一組寄存器。由于線程共享相同進程內的資源,它們之間的通信和數據共享 相對容易。在很多類Unix系統中,線程被稱為輕量級的進程,創建和上下文切換的開銷 小于進程。

線程實際上在底層是不存在的,它只是人為規定的一個概念

線程和進程的區別與聯系

在Linux 中,線程等同于輕量級進程,二者都有獨立的task_struct結構體實例。 線程創建和進程創建在技術上是完全等同的,fork()和進程創建函數pthread_create() 底層都調用了系統調用clone()。

1)創建進程

當我們調用fork()時,等同于調用clone(SIGCHLD, 0),SIGCHLD標志的作用是告 訴操作系統:當子進程終止時,父進程應當接收到SIGCHLD 信號。這個信號是默認的方式, 用于通知父進程其子進程已經結束。這樣一來,父進程就可以在子進程退出后執行清理操 作。

2)創建線程

創建線程時,底層會調用clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0),這些 Flag 的含義如下。

? CLONE_VM:共享地址空間。從技術上將,被創建的線程和創建者的 struct task_struct 實例中 struct mm_struct 指針類型的字段 mm和 active_mm指向相同的實例。

? CLONE_FS:共享文件系統信息。從技術上將,被創建的線程和創建者的 struct task_struct 實例中 struct fs_struct 指針類型的字段 fs指向相同的實例。

? CLONE_FILES:共享打開的文件描述符表,從技術上講,被創建的線程和創建者 的struct task_struct 實例中 struct files_struct 指針類型的字段 files指向相同的實例。

? CLONE_SIGHAND:共享信號處理函數表。從技術上講,被創建的線程和創建者 的struct task_struct 實例中 struct signal_struct 指針類型的字段和 struct sighand_struct指針類 型的字段指向相同的實例。

3)進程創建和線程創建的區別

從clone()系統調用的角度,我們可以得出結論:如果多個進程共享了地址空間、文 件系統信息、打開的文件信息、信號處理信息,那么他們就是同屬于一個進程的線程。

task_struct 結構體中的pid實際上表示的是進程或線程ID,tgid字段表示的是線 程組ID,等同于傳統意義上的線程ID。對于單線程的進程,pid字段和tgid字段相同。 對于多線程進程,主線程的pid等于tgid,pid此時可以理解為主線程的線程ID或者進 程ID,普通線程的tgid等于主線程的pid和tgid,即當前線程所屬的線程組ID和進程 ID,而pid字段此時相當于線程ID。

在這里插入圖片描述
在這里插入圖片描述

線程的特點

1)資源共享 thread_info 實例 mm_struct 實例 files_struct 實例 signal_struct 實例 線程之間共享進程資源,包括地址空間、文件系統信息、打開的文件描述符和信號處 理函數,而不同進程之間的資源是隔離的。

2)通信 線程間的通信通常比進程間的通信(例如,通過管道、共享內存)更為高效。因為地 址空間是共享的,線程間可以直接通過如全局變量這樣的方式通信。

3)創建和管理開銷 線程的創建和上下文切換通常比進程更輕量級,因此在需要頻繁創建和銷毀執行單元 的場景中,線程可能是更合適的選擇。

內核線程

Linux的內核線程是在內核空間中運行的輕量級 進程,它們沒有獨立的地址空間和大部分用戶空間資源。內核線程是操作系統內核功能的 一部分,主要用于管理和執行內核級任務,如硬件中斷處理、系統調用服務、內存管理等。

1)內核棧 內核線程擁有自己的內核棧。

2)控制內核線程的數據結構 內核線程的信息也存儲在task_struct結構體中。

3)地址空間 不同于普通進程,struct mm_struct類型的字段mm及active_mm取值為NULL, 它們通常共享內核的全局地址空間。

4)標記字段 內核線程的task_struct 中flags字段被標記為PF_KTHREAD,用于表示這是一個 內核線程。

5)內核線程的ID 內核線程工作在內核態,相互之間地位是等同的,因此,任意內核線程的 TID、TGID、 PID 都是相同的。并且,所有內核線程的PGID都是0。這是因為內核線程不與任何特定的 終端相關聯,也不參與普通的作業控制和信號處理,這些通常是用戶空間進程的特性。 PGID 設置為0是設計上的選擇,用于確保內核線程在操作系統中的特殊性和隔離性。

6)打開的文件描述 此外,內核進程不需要執行I/O操作或者直接操作文件描述符,因此,不需要文件描 述符表,它的task_struct中,指向struct files_struct實例的字段為NULL。

7)文件系統信息 同樣地,指向struct fs_struct實例的字段也通常是NULL。fs_struct用于管理 文件系統相關的信息。內核線程不與特定的文件系統路徑交互,所以不需要此信息。

8)信號處理信息 struct signal_struct和struct sighand_struct實例主要用于處理用戶級信號, 因此,內核線程的task_struct實例中,指向它們的指針也通常為NULL。

在這里插入圖片描述

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

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

相關文章

Oracle自治事務——從問題到實踐的深度解析

一、引言&#xff1a;當“關鍵操作”遇上主事務的“生死綁定”?先問大家一個問題&#xff1a;假設你在開發一個用戶管理系統&#xff0c;核心功能是“用戶注冊”&#xff0c;同時需要記錄“操作日志”。某天&#xff0c;用戶提交注冊信息時&#xff0c;數據庫突然因磁盤空間不…

廣播(Broadcast)和組播(Multicast)對比

概述 廣播&#xff08;Broadcast&#xff09;和組播&#xff08;Multicast&#xff09;是計算機網絡中兩種重要的一對多通信方式&#xff0c;用于高效地將數據同時分發給多個接收者&#xff0c;它們的核心區別在于目標接收者的范圍和控制精度&#xff0c;基于業務對效率、規模和…

在 HTTP GET 請求中傳遞參數有兩種標準方式

方法 1&#xff1a;URL 查詢參數&#xff08;Query Parameters&#xff09;格式&#xff1a;?參數名值&參數名2值2示例請求http://localhost:8080/hello?name張三&age25后端接收方式GetMapping("/hello") public String sayHello(RequestParam String name…

pycharm windows/linux/mac快捷鍵

適用于mac的快捷鍵 適用于windows和linux的快捷鍵 參考資料&#xff1a; https://www.jetbrains.com/zh-cn/help/pycharm/mastering-keyboard-shortcuts.html

前端包管理工具深度對比:npm、yarn、pnpm 全方位解析

前言&#xff1a;為什么我們需要包管理工具&#xff1f; 在現代前端開發中&#xff0c;模塊化已成為標配。一個中型項目可能依賴數百個第三方包&#xff0c;手動管理這些依賴幾乎是不可能的任務。包管理工具應運而生&#xff0c;它們不僅解決了依賴安裝問題&#xff0c;還提供了…

調試Claude code的正確姿勢

隨著kimi k2的發布&#xff0c;Claude code的使用頻率愈發的頻繁&#xff0c;在發現moonshot官方提供了調試工具之后&#xff0c;我對claude code的交互過程愈發好奇。 moonpalace的安裝 官方moonpalace倉庫地址 go語言編寫&#xff0c;可以直接下載二進制二進制文件&#x…

【常見分布及其特征(5)】連續型隨機變量-連續均勻分布

概率密度函數&#xff08;PDF&#xff09;與概率質量函數&#xff08;PMF&#xff09;說明 基本概念區分 對于連續型隨機變量&#xff0c;通常使用 概率密度函數 (Probability Density Function, PDF) 進行描述&#xff1b;這與離散型隨機變量使用的 概率質量函數 (Probabili…

FAN-UNET:用于生物醫學圖像分割增強模型

目錄 一、論文結構概述 二、創新點詳解 三、創新點結構與原理 &#xff08;1&#xff09;Vision-FAN Block&#xff1a;全局與周期特征的融合引擎 &#xff08;2&#xff09;FANLayer2D&#xff1a;周期性建模的核心 四、代碼復現思路 五、仿真結果分析 &#xff08;1&…

基于SpringBoot的籃球運動員體測數據分析及訓練管理系統論文

第1章 緒論 1.1 課題背景 互聯網發展至今&#xff0c;無論是其理論還是技術都已經成熟&#xff0c;而且它廣泛參與在社會中的方方面面。它讓信息都可以通過網絡傳播&#xff0c;搭配信息管理工具可以很好地為人們提供服務。所以各行業&#xff0c;尤其是規模較大的企業和學校等…

矩陣算法題

矩陣算法題1、矩陣置零2、螺旋矩陣3、旋轉圖像4、搜索二維矩陣1、矩陣置零 解題思路&#xff1a;這道題核心是要確定哪些行和哪些列要置零。所以定義兩個數組&#xff0c;一個記錄要置零的行&#xff0c;一個記錄要置零的列。遍歷整個矩陣&#xff0c;如果當前位置是0的話&…

Spring底層(二)Spring IOC容器加載流程原理

一、怎么理解SpringIoc IOC&#xff1a;Inversion Of Control&#xff0c;即控制反轉&#xff0c;是一種設計思想。之前對象又程序員自己new自己創建&#xff0c;現在Spring注入給我們&#xff0c;這樣的創建權力被反轉了。 所謂控制就是對象的創建、初始化、銷毀。 創建對象…

UDP中的單播,多播,廣播

文章目錄UDP 簡單回顧一、單播&#xff08;Unicast&#xff09;定義特點應用舉例二、廣播&#xff08;Broadcast&#xff09;定義特點應用三、多播&#xff08;Multicast&#xff09;定義特點應用UDP 單播、廣播、多播的對比總結額外說明代碼簡要示例&#xff08;C&#xff09;…

數據庫練習3

一、建立product表&#xff0c;操作方式operate表要求&#xff1a;1.定義觸發器實現在產品表(product)中每多一個產品,就在操作表(operate)中記錄操作方式和時間以及編號記錄。注&#xff1a;操作說明&#xff1a;標記執行delete 、insert、 update2.定義觸發器實現在產品表(pr…

pycharm和anaconda安裝,并配置python虛擬環境

1、pycharm和anaconda安裝 PyCharm與Anaconda超詳細安裝配置教程_anaconda pycharm安裝-CSDN博客https://blog.csdn.net/qq_32892383/article/details/116137730 2、pycharm漢化 PyCharm漢化&#xff1a;簡單兩步搞定&#xff01;PyCharm怎么設置中文簡體&#xff0c;為什么…

EP04:【Python 第一彈】函數編程

一、定義 函數指將一組語句的集合通過一個變量名封裝起來&#xff0c;調用這個函數變量名&#xff0c;就可以執行函數。 二、特點 減少重復邏輯代碼的編寫將程序中的邏輯可以進行擴展維護項目程序的代碼更簡單 三、創建 def 函數名():邏輯代碼1邏輯代碼2return 結果 函數名…

linux安裝Mysql后添加mysql的用戶和密碼

在 MySQL 中創建用戶并設置密碼的完整指南如下&#xff1a; 方法 1&#xff1a;使用 CREATE USER 語句&#xff08;推薦&#xff09; -- 創建新用戶并設置密碼 CREATE USER newuserlocalhost IDENTIFIED BY your_password;-- 授予權限&#xff08;示例&#xff1a;授予所有數據…

React hooks——memo

一、簡介React.memo 是 React 提供的一個高階組件&#xff08;Higher-Order Component&#xff09;&#xff0c;用于優化函數組件的渲染性能&#xff0c;它通過淺比較&#xff08;shallow compare&#xff09;props 的變化來決定是否重新渲染組件。1.1 基本用法const MyCompone…

leetcode15.三數之和題解:邏輯清晰帶你分析

介紹 題源 分析 1.雙指針固定一個數 首先明白一點&#xff0c;我們有三個數&#xff0c;我們想使用雙指針&#xff0c;那就必須固定一個數。 2.二分 本題還涉及二分&#xff0c;雙指針經常和二分結合使用&#xff08;二分本質就是雙指針&#xff0c;仔細思考這思考這句話&…

exports使用 package.json字段控制如何訪問你的 npm 包

目錄 想象一下你正在開發一個 npm 包…… 術語 什么是exports領域&#xff1f; exports好處 保護內部文件 多格式包 將子路徑映射到dist目錄 子路徑導出 單一入口點 多個入口點 公開軟件包文件的子集 有條件出口 設置使用條件 默認條件 句法 針對 Node.js 和瀏…

AngularJS 安裝使用教程

一、AngularJS 簡介 AngularJS 是 Google 開發的一款前端 JavaScript 框架&#xff0c;采用 MVVM 架構&#xff0c;提供了數據雙向綁定、依賴注入、模塊化、路由管理等強大功能&#xff0c;適合構建單頁面應用&#xff08;SPA&#xff09;。注意&#xff1a;AngularJS&#xf…