Linux 入門:操作系統進程詳解

目錄

一.馮諾依曼體系結構

一). 軟件運行前為什么要先加載?程序運行之前在哪里?

二).理解數據流動?

二.操作系統OS(Operator System)?

一).概念?

二).設計OS的目的

三).如何理解操作系統OS的“管理”

四).系統調用和庫函數概念?

三.進程

一).進程基本概念與基本操作?

1.描述進程-PCB

2.task_ struct?

3.查看進程

1). 進程的信息可以通過 /proc 系統文件夾查看

2). 大多數進程信息同樣可以使用top和ps這些用戶級工具來獲取

4.通過系統調用獲取進程標示符

5.通過系統調用創建進程-fork初識

1).認識fork?

2).父子進程代碼共享,數據各自開辟空間,私有一份(采用寫時拷貝)?

3).fork有兩個返回值?

4).fork 之后通常要用 if 進行分流??

二).進程狀態

1.Linux內核源代碼怎么說

2.運行 && 阻塞 && 掛起?

3.進程狀態查看

4.Z(zombie)-僵尸進程

5.孤兒進程

三).進程優先級?

1.基本概念

2.查看系統進程

3.查看修改進程優先級

4.補充概念---競爭、獨立、并行、并發

四).進程切換

1.死循環進程如何運行?

2. CPU和寄存器

3.如何切換?

五).Linux真實的調度算法

1.優先級

2.活動隊列

3.過期隊列

4.active指針和expired指針


一.馮諾依曼體系結構


這里我們討論學習的是紅色的數據信號

我們所認識的計算機,都是由一個個的硬件組件組成

  • 輸入單元:包括鍵盤, 鼠標,掃描儀, 寫板,磁盤等
  • 中央處理器(CPU):含有運算器和控制器等
  • 輸出單元:顯示器,打印機,磁盤等
  • 存儲器:內存

關于馮諾依曼,必須強調幾點:

1.這里的存儲器指的是內存。

2.不考慮緩存情況,這里的CPU能且只能對內存進行讀寫,不能訪問外設(輸入或輸出設備)。

3.外設(輸入或輸出設備)要輸入或者輸出數據,也只能寫入內存或者從內存中讀取

4.一句話,所有設備都只能直接和內存打交道。

那為什么有這些設定呢?速度差距大。

我們設計出不同存儲速度的內存進行存儲。當代計算機是性價比的產物。

我們從兩個問題開始詳細認識這個體系。

一). 軟件運行前為什么要先加載?程序運行之前在哪里?

二).理解數據流動?

請解釋,從你登錄上qq開始和某位朋友聊天開始,數據的流動過程。從你打開窗口,開始給他發消息,到他的到消息之后的數據流動過程。如果是在qq上發送文件呢?

二.操作系統OS(Operator System)?


一).概念?

任何計算機系統都包含一個基本的程序集合,稱為操作系統(OS),操作系統是一款進行軟硬件管理的軟件。籠統的理解,操作系統包括:

? 內核(進程管理,內存管理,文件管理,驅動管理)

? 其他程序(例如函數庫,shell程序等等)

二).設計OS的目的

對下,與硬件交互,管理所有的軟硬件資源(目的

對上,為用戶程序(應用程序)提供一個良好的執行環境(手段

對于操作系統我們要認識以下幾點:

1.軟硬件體系結構------>層狀結構

2.訪問操作系統,必須使用系統調用------其實就是函數,不過是系統提供的

3.我們的程序,只要你判斷出它訪問了硬件,那么它必須貫穿整個軟硬件體系結構。比如:printf的本質:是你把你的數據寫到了硬件里。

4.庫可能在底層封裝了系統調用

在整個計算機軟硬件架構中,操作系統的定位是:一款純正的“搞管理”的軟件?

三).如何理解操作系統OS的“管理”

對于OS的管理,我們使用生活中的例子來進行描述。對于一件事情我們分為兩個步驟1.決策2.執行

管理的例子 ----- 學生,輔導員,校長。

加速理解:

1.對于校長管理學生,我們可以知道,我們一學期甚至大學四年都見不到校長幾次?,而對于校長的決策,比如:什么時候舉辦運動會,將全校最高的幾個男生組成籃球隊打比賽,我們都是要去執行的。

2.對于選全校身高最高的學生這個決策如何進行呢?校長一個一個的找同學去問嗎?并不是,而是通過學生的身高數據去篩選。

3.那么,身高數據從哪來?那當然是輔導員統計上交的啦。

那么,我們可以得到幾個結論:

1.要管理,管理者和被管理者,可以不需要見面

?2.管理者怎么管理被管理者,根據“數據”進行管理

3.不需要見面,如何得到數據?由中間層獲取。?

那么校長對于學生數據就可以進行數據建模,使用結構體來描述一個學生的信息

校長進行數據建模的行為,我們可以認為是先描述,再組織。

操作系統對于計算機管理硬件

1. 描述起來,用struct結構體。

2. 組織起來,用鏈表或其他高效的數據結構。

四).系統調用和庫函數概念?

在開發角度,操作系統對外會表現為一個整體,但是會暴露自己的部分接口,供上層開發使用,這部分由操作系統提供的接口,叫做系統調用。

系統調用在使用上,功能比較基礎,對用戶的要求相對也比較高,所以,有心的開發者可以對部分系統調用進行適度封裝,從而形成庫,有了庫,就很有利于更上層用戶或者開發者進行二次開發。

三.進程


操作系統是怎么管理進行進程管理的呢?很簡單,先把進程描述起來,再把進程組織起來!

一).進程基本概念與基本操作?

課本概念:程序的一個執行實例,正在執行的程序等?

內核觀點:擔當分配系統資源(CPU時間,內存)的實體

加速理解:?

我們可以簡單的形容為我們找工作的過程:內存中的代碼和數據就是“我們”,進程控制塊就是“我們的簡歷”,CPU就是“面試官”,進程列表就是“我們的簡歷在排隊”,我們在等待面試官篩選的過程本質上是我們的簡歷在等待被篩選,也就是進程控制塊在被讀取而不是我們的代碼和數據,而進程控制塊上的代碼和數據地址就是“我們的電話號碼和居住地址”。這樣應該就能稍微理解進程了。

1.描述進程-PCB

task_struct ---- PCB的一種

在Linux中描述進程的結構體叫做task_struct。

task_struct是Linux內核的一種數據結構,它會被裝載到RAM(內存)里并且包含著進程的信息

總結:

進程 = 內核數據結構對象? +??自己的代碼和數據?

在這里就是:進程 = PCB(task_struct)? +? 自己的代碼和數據?

2.task_ struct?

?內容分類

  • 標示符: 描述本進程的唯一標示符,用來區別其他進程。
  • 狀態: 任務狀態,退出代碼,退出信號等。
  • 優先級: 相對于其他進程的優先級。
  • 程序計數器: 程序中即將被執行的下一條指令的地址。
  • 內存指針: 包括程序代碼和進程相關數據的指針,還有和其他進程共享的內存塊的指針。
  • 上下文數據: 進程執行時處理器的寄存器中的數據。
  • I/O狀態信息: 包括顯示的I/O請求,分配給進程的I/O設備和被進程使用的文件列表。
  • 記賬信息: 可能包括處理器時間總和,使用的時鐘數總和,時間限制,記賬號等。
  • 其他信息。

組織進程

可以在內核源代碼里找到它。所有運行在系統里的進程都以task_struct鏈表的形式存在內核里

3.查看進程

1). 進程的信息可以通過 /proc 系統文件夾查看

如:要獲取PID為1的進程信息,你需要查看 /proc/1 這個文件夾。?

2). 大多數進程信息同樣可以使用top和ps這些用戶級工具來獲取

我們歷史上執行的所有的指令,工具,自己的程序,運行起來,全部都是進程。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{while(1){sleep(1);printf("我是一個進程pid: %d\n",getpid());}return 0;
}  

getpid() 的作用

查看運行程序的進程?ps axj | grep code

添加屬性列:ps axj | head -1;ps axj | grep code

殺掉進程 ctrl + c 或? kill -9 pid

4.通過系統調用獲取進程標示符

  • 進程id(PID)
  • 父進程id(PPID)
  1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/types.h>4 5 int main()6 {7   while(1)8   {9     sleep(1);10     printf("我是一個子進程pid: %d,我的父進程:%d\n",getpid(),getppid());11   }                                                                          12 }

那么這個135370進程是什么呢??

操作系統會給每一個用戶分配一個bash

查看bash:while :; do ps axj |head -1;ps axj | grep 'bash' | grep -v grep ; sleep 1 ; done

5.通過系統調用創建進程-fork初識

1).認識fork?

運行?man fork?

  1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/types.h>4 5 int main()6 {7 8   printf("父進程開始運行,pid: %d\n", getpid());9   pid_t id = fork();10   printf("進程開始運行,pid: %d\n", getpid());11 }     
2).父子進程代碼共享,數據各自開辟空間,私有一份(采用寫時拷貝)?

3).fork有兩個返回值?

返回值中子進程為0,父進程為子進程的pid?

4).fork 之后通常要用 if 進行分流??
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{printf("父進程開始運行,pid: %d\n", getpid());pid_t id = fork();if(id < 0){perror("fork");return 1;}else if(id == 0){// childwhile(1){sleep(1);printf("我是一個子進程 !, 我的pid: %d, 我的父進程id: %d\n", getpid(), getppid());}}   else{   //fatherwhile(1){   sleep(1);printf("我是一個父進程 !, 我的pid: %d, 我的父進程id: %d\n", getpid(), getppid());}                                                                                                                                        }printf("進程開始運行,pid: %d\n", getpid());
}

那么我們會產生下面幾個問題

1.fork為什么會有兩個返回值?

因為? 父進程 :子進程 ==? 1? :n??父進程可能有多個子進程,父進程需要管理子進程,所以需要得到子進程的pid,所以父進程的返回值為子進程的pid,而子進程只需要管理好自己,子進程pid可以通過getpid得到,所以返回0。

2.為什么一個函數會被返回兩次

fork語句后創建了子進程且被調度了,父進程執行一次return,子進程也執行一次return

3.一個變量怎么能讓 if 和 else if 同時成立?這個問題需要在后面才能解釋清楚。

首先我們要知道一個前提:進程具有獨立性。也就是父進程掛掉了子進程也無影響。

代碼測試:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int gval=100;
int main()
{printf("父進程開始運行,pid: %d\n", getpid());pid_t id = fork();if(id < 0){perror("fork");return 1;}else if(id == 0){printf("我是一個子進程 !, 我的pid: %d, 我的父進程id: %d, gval: %d\n", getpid(), getppid(), gval);sleep(5);// childwhile(1){sleep(1);printf("子進程修改變量: %d->%d", gval, gval+10);gval+=10; // 修改printf("我是一個子進程 !, 我的pid: %d, 我的父進程id: %d\n", getpid(), getppid());}}else{//fatherwhile(1){sleep(1);printf("我是一個父進程 !, 我的pid: %d, 我的父進程id: %d, gval: %d\n", getpid(), getppid(), gval);                  }}printf("進程開始運行,pid: %d\n", getpid());
}

二).進程狀態

1.Linux內核源代碼怎么說

為了弄明白正在運行的進程是什么意思,我們需要知道進程的不同狀態。一個進程可以有幾個狀態(在Linux內核里,進程有時候也叫做任務)。

下面的狀態在kernel源代碼里定義:

*
*The task state array is a strange "bitmap" of
*reasons to sleep. Thus "running" is zero, and
*you can test for combinations of others with
*simple bit tests.
*/
static const char *const task_state_array[] = {"R (running)", /*0 */"S (sleeping)", /*1 */"D (disk sleep)", /*2 */"T (stopped)", /*4 */"t (tracing stop)", /*8 */"X (dead)", /*16 */"Z (zombie)", /*32 */
}

進程狀態就是一個整數?

2.運行 && 阻塞 && 掛起?

掛起:將進程交換到磁盤的swap分區

運行:進程在調度隊列中,進程的狀態都是running

阻塞:等待某種設備或資源就位(鍵盤,顯示器,網卡....)?

進程狀態的變化表現之一:就是要在不同的隊列中進行流動,本質都是數據結構的增刪查改

3.進程狀態查看

循環查看進程狀態:while :; do ps axj |head -1; ps axj | grep code ;sleep 1; done

a:顯示一個終端所有的進程,包括其他用戶的進程。

x:顯示沒有控制終端的進程,例如后臺運行的守護進程。

j:顯示進程歸屬的進程組ID、會話ID、父進程ID,以及與作業控制相關的信息

u:以用戶為中心的格式顯示進程信息,提供進程的詳細信息,如用戶、CPU和內存使用情況等

我們通過代碼來具體查看進程狀態?

R運行狀態(running): 并不意味著進程一定在運行中,它表明進程要么是在運行中要么在運行隊列里。

S睡眠狀態(sleeping): 意味著進程在等待事件完成(這里的睡眠有時候也叫做可中斷睡眠(interruptible sleep))。

D磁盤休眠狀態(Disk sleep)有時候也叫不可中斷睡眠狀態(uninterruptible sleep),在這個狀態的進程通常會等待IO的結束。

這個狀態很少見,當磁盤老化,內存嚴重不足時才有可能出現

T/t停止狀態(stopped): 可以通過發送 SIGSTOP 信號給進程來停止(T)進程。這個被暫停的進程可以通過發送 SIGCONT 信號讓進程繼續運行。

小 t 狀態,程序被debug,斷點,程序被暫停了

X死亡狀態(dead):這個狀態只是一個返回狀態,你不會在任務列表里看到這個狀態。

4.Z(zombie)-僵尸進程

僵死狀態(Zombies)是一個比較特殊的狀態。當進程退出并且父進程(使用wait()系統調用,后面講)沒有讀取到子進程退出的返回代碼時就會產生僵死(僵尸)進程

僵死進程會以終止狀態保持在進程表中,并且會一直在等待父進程讀取退出狀態代碼。

所以,只要子進程退出,父進程還在運行,但父進程沒有讀取子進程狀態,子進程進入Z狀態

我們使用下面這段代碼查看僵尸狀態

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t id = fork();if(id == 0){//childint count = 5;while(count)  //5次后退出{printf("我是子進程,我正在運行: %d\n", count);sleep(1);count--;}}else {while(1){printf("我是父進程,我正在運行...\n");sleep(1);}}return 0;
}

僵尸進程危害

  • 進程的退出狀態必須被維持下去,因為他要告訴關心它的進程(父進程),你交給我的任務,我辦的怎么樣了。可父進程如果一直不讀取,那子進程就一直處于Z狀態?是的!那么就會造成內存泄漏。
  • 維護退出狀態本身就是要用數據維護,也屬于進程基本信息,所以保存在task_struct(PCB)中,換句話說,Z狀態一直不退出,PCB一直都要維護?是的!
  • 那?個父進程創建了很多子進程,就是不回收,是不是就會造成內存資源的浪費?是的!因為數據結構對象本身就要占用內存。

5.孤兒進程

父進程如果提前退出,那么子進程后退出,進入Z之后,那該如何處理呢?

父進程先退出,子進程就稱之為“孤兒進程”

孤兒進程被1號systemd進程領養,當然要有systemd進程回收嘍。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t id = fork();if(id == 0){// childwhile(1){printf("我是一個子進程, pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);}}else{// fatherint cnt = 5;while(cnt){printf("我是一個父進程, pid: %d, ppid: %d\n", getpid(), getppid());cnt--;sleep(1);}}                                                                                                      return 0;
}

那么這個1號進程是什么呢??為什么要領養呢?

1號進程就是操作系統。

如果不領養,子進程退出,進入僵尸狀態后就無法回收,造成內存泄漏。

三).進程優先級?

1.基本概念

  • cpu資源分配的先后順序,就是指進程的優先權(priority)。
  • 優先權高的進程有優先執行權利。配置進程優先權對多任務環境的linux很有用,可以改善系統性能。
  • 還可以把進程運行到指定的CPU上,這樣?來,把不重要的進程安排到某個CPU,可以大大改善系統整體性能

當然,這么看還是很陌生,我們從三個方向認識。

是什么?

是進程得到cpu資源的先后順序。

為什么?

目標資源稀缺,導致要通過優先級確認誰先誰后的問題。

怎么辦?

也是一種數字。值越低,優先級越高,反之,優先級越低。基于時間片的分時操作系統,考慮公平性,優先級可能變化,但是變化幅度不能太大。

2.查看系統進程

?ps -al | head -1 && ps -al |grep code

  • UID : 代表執行者的身份
  • PID : 代表這個進程的代號
  • PPID :代表這個進程是由哪個進程發展衍?而來的,亦即父進程的代號
  • PRI :代表這個進程可被執行的優先級,其值越小越早被執行
  • NI :代表這個進程的nice值

注意:?

1.nice其取值范圍是-20?19,一共40個級別 。

2.當nice值為負值的時候,那么該程序將會優先級值將變小,即其優先級會變高,則其越快被執行。

3.程真實的優先級=PRI(默認優先級80)+NI。

3.查看修改進程優先級

用top命令更改已存在進程的nice:

  • top
  • 進入top后按“r”?>輸?進程PID?>輸入nice值。注意是輸入nice值。

命令用途
nice啟動時設置Nice值
renice修改運行中進程的Nice值
chrt查看/設置實時優先級
ps -o pid,ni,pri,rtprio,comm查看各種優先級
top交互式查看和修改優先級

注意:優先級設立不合理,會導致優先級低的進程長時間得不到CPU資源,進而導致:進程饑餓

4.補充概念---競爭、獨立、并行、并發

競爭性: 系統進程數目眾多,而CPU資源只有少量,甚至1個,所以進程之間是具有競爭屬性的。為了高效完成任務,更合理競爭相關資源,便具有了優先級。

獨立性: 多進程運行,需要獨享各種資源,多進程運行期間互不干擾。

并行: 多個進程在多個CPU下分別,同時進行運行,這稱之為并行。

并發: 多個進程在?個CPU下采用進程切換的方式,在一段時間之內,讓多個進程都得以推進,稱之為并發。

四).進程切換

CPU上下文切換:其實際含義是任務切換, 或者CPU寄存器切換。當多任務內核決定運行另外的任務時, 它保存正在運行任務的當前狀態, 也就是CPU寄存器中的全部內容。這些內容被保存在任務自己的堆棧中, 入棧工作完成后就把下一個將要運行的任務的當前狀況從該任務的棧中重新裝入CPU寄存器, 并開始下一個任務的運行, 這一過程就是context switch。

當然這么看還是不理解,我們先認識下幾個問題 。

1.死循環進程如何運行?

  • ?一旦一個進程占有CPU,會把自己的代碼執行完嗎?不會,只執行一段時間片的東西。
  • 死循環進程不會一直占有CPU。

2. CPU和寄存器

3.如何切換?

加速理解:

可以理解為我們進入大學后去服兩年兵役,此時我們需要向導員報告,學校需要保存我們的學籍信息。兩年后,我們回來繼續上學,那么我們要提前通知導員,讓學校恢復我們的學籍信息。我們可以粗略的認為:學校-----CPU;導員-----調度器;我們-----進程;學籍-----進程運行的臨時數據,CPU內寄存器里面的內容(當前進程的上下文數據);保留學籍-----保存進程上下文數據,CPU內寄存器里面的內容保存起來;恢復數據-----恢復進程上下文數據,恢復到CPU內寄存器里;去服兵役-----進程從CPU上剝離下來。

時間片:當代計算機都是分時操作系統,沒有進程都有它合適的時間片(其實就是?個計數器)。時間片到達,進程就被操作系統從CPU中剝離下來。

五).Linux真實的調度算法

圖是Linux2.6內核中進程隊列的數據結構?

1.優先級

  • 普通優先級:100?139(我們都是普通的優先級,想想nice值的取值范圍,可與之對應!)
  • 實時優先級:0?99(不關心)

2.活動隊列

  • 時間片還沒有結束的所有進程都按照優先級放在該隊列
  • nr_active: 總共有多少個運行狀態的進程
  • queue[140]: 一個元素就是一個進程隊列,相同優先級的進程按照FIFO規則進行排隊調度,所以,數組下標就是優先級!
  • 從該結構中,選擇一個最合適的進程,過程是怎么的呢?
    1. 從0下表開始遍歷queue[140]
    2. 找到第一個非空隊列,該隊列必定為優先級最高的隊列
    3. 拿到選中隊列的第一個進程,開始運行,調度完成!
    4. 遍歷queue[140]時間復雜度是常數!但還是太低效了
  • bitmap[5]:一共140個優先級,一共140個進程隊列,為了提高查找非空隊列的效率,就可以用5*32個比特位表示隊列是否為空,這樣,便可以大大提高查找效率!

3.過期隊列

  • 過期隊列和活動隊列結構一模一樣
  • 過期隊列上放置的進程,都是時間片耗盡的進程
  • 當活動隊列上的進程都被處理完畢之后,對過期隊列的進程進行時間片重新計算

4.active指針和expired指針

  • active指針永遠指向活動隊列
  • expired指針永遠指向過期隊列
  • 可是活動隊列上的進程會越來越少,過期隊列上的進程會越來越多,因為進程時間片到期時?直都存在的。
  • 沒關系,在合適的時候,只要能夠交換active指針和expired指針的內容,就相當于有具有了一批新的活動進程!

那么我們理解了這算法,我們也就知道了為什么要有 PRI和NI兩個值了,如果沒有NI,那當我們修改進程的優先級時,是在活動隊列直接將進程的優先級修改然后再排序嗎?不,那會大大增加時間成本;而是將修改的結果計算好,當進程在活動隊列運行結束后進入過期隊列后直接鏈接,不用排序。

  • PRI :代表這個進程可被執行的優先級,其值越小越早被執行
  • NI :代表這個進程的nice值

總結:?在系統當中查找一個最合適調度的進程的時間復雜度是一個常數,不隨著進程增多而導致時間成本增加,我們稱之為進程調度O(1)算法!

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

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

相關文章

word交叉引用圖片、表格——只引用編號的處理方法

交叉引用圖片/表格 在“引用”選項卡上的“題注”組中&#xff0c;單擊“插入題注”。勾選【從題注中排除標簽】。在文中插入題注。 【注 意】 這時候插入的題注只有編號項了。然后手動打上標簽【TABLE】&#xff0c;并在標簽和編號項之間加上【樣式分隔符&#xff0c;AltCt…

rails 8 CSS不起效問題解決

很久沒用rails了&#xff0c;最近打算重新復習一下。在配置好環境后&#xff0c;創建了項目&#xff0c;通過腳手架創建了數據庫表&#xff0c;和相關的文件。但我發現卻沒有生成相應的CSS文件&#xff0c;可能是rails8 取消了吧。于是自己手動創建了相應的css文件。但是刷新頁…

【nlohmann\json.hpp】‘_snprintf‘: is not a member of ‘std‘

這個問題時有發生但是為啥現在更新了vs2022 后,發生了這些報錯:2>(compiling source file ../worker/src/fargo/PacedVideoSenderGo.cpp) 2>D:\XTRANS\thunderbolt\ayame

數據結構--【二叉樹】

目錄 定義結構體&#xff1a; 初始化&#xff1a; 手動創建一個二叉樹&#xff1a; 前序遍歷&#xff1a; 中序遍歷&#xff1a; 后序遍歷 二叉樹節點個數&#xff1a; 葉子節點個數&#xff1a; 二叉樹第k層節點個數&#xff1a; 二叉樹的高度&#xff1a; 查找值為x…

深入解析Linux進程間通信(IPC):機制、應用與最佳實踐

引言 在多任務操作系統中&#xff0c;進程間通信&#xff08;Inter-Process Communication, IPC&#xff09;是協同工作的核心機制。Linux作為現代操作系統的典范&#xff0c;提供了8種主要IPC方式&#xff0c;從傳統的管道到面向網絡的套接字&#xff0c;每種方法都暗藏獨特的…

2025年“深圳杯”數學建模挑戰賽B題-LED顯示屏顏色轉換設計與校正

LED顯示屏顏色轉換設計與校正 小驢數模 問題的背景 走在晚風都市&#xff0c;或春日田野&#xff0c;我們都會看到一個色彩斑斕的世界。色彩是我們對世界一種重要感知。什么是色彩&#xff0c;或顏色&#xff1f;顏色是光作用于人眼引起的視覺感知現象&#xff0c;它與物體的…

Java學習手冊:Spring MVC 架構與實現

一、Spring MVC 概述 Spring MVC 是 Spring 框架的一個模塊&#xff0c;它提供了一套 Web 應用開發的解決方案&#xff0c;實現了 MVC&#xff08;Model-View-Controller&#xff09;設計模式。Spring MVC 提供了清晰的分離邏輯層、視圖層和控制器層的結構&#xff0c;便于開發…

【TF-BERT】基于張量的融合BERT多模態情感分析

不足&#xff1a;1. 傳統跨模態transformer只能處理2種模態&#xff0c;所以現有方法需要分階段融合3模態&#xff0c;引發信息丟失。2. 直接拼接多模態特征到BERT中&#xff0c;缺乏動態互補機制&#xff0c;無法有效整合非文本模態信息 改進方法&#xff1a;1. 基于張量的跨模…

maven坐標導入jar包時剔除不需要的內容

maven坐標導入jar包時剔除不需要的內容 問題描述解決方案 問題描述 maven坐標導入jar包時剔除不需要的內容 解決方案 Spring Boot 默認使用 Logback&#xff0c;需在 pom.xml 中排除其依賴&#xff1a; <dependency><groupId>org.springframework.boot</gro…

C與指針——輸入輸出

錯誤定位 當一個庫函數出錯時&#xff0c;errno會被重置 perror(const char* s);\\輸出s: errno 對應的錯誤信息 \\如果單獨想要錯誤信息可以 char* e strerror(errno);\\系統錯誤碼轉換為對應的錯誤信息字符串輸出緩沖區 一般輸出緩沖區滿的時候才刷新&#xff0c;也就是…

JSON Web Token 默認密鑰 身份驗證安全性分析 dubbo-admin JWT硬編碼身份驗證繞過

引言 在web開發中&#xff0c;對于用戶認證的問題&#xff0c;有很多的解決方案。其中傳統的認證方式&#xff1a;基于session的用戶身份驗證便是可采用的一種。 基于session的用戶身份驗證驗證過程&#xff1a; 用戶在用進行驗證之后&#xff0c;服務器保存用戶信息返回sess…

STM32GPIO輸出實戰-LED模板

STM32GPIO輸出實戰-LED模板 一&#xff0c;LED控制原理1&#xff0c;LED控制時GPIO的配置2&#xff0c;LED連接方式3&#xff0c;使用HAL庫控制LED的常用函數&#xff1a; 二&#xff0c;任意控制LED模板1&#xff0c;Led底層2&#xff0c;代碼詳細解析 三&#xff0c;實用技巧…

第二十七屆華東杯數學建模A 題 跳臺滑雪問題 完整思路模型及代碼

題目背景 跳臺滑雪起源于 19 世紀&#xff0c;是冬季運動會的傳統競技項目。今年亞洲冬季運動會在我國 哈爾濱舉行&#xff0c;跳臺滑雪項目吸引了包括中國在內的亞洲各國運動健兒踴躍參加&#xff0c;我國運動員取得了優異的成績。 跳臺滑雪融合了速度、力量與精確控制&…

Python之學習筆記(六)

文章目錄 1. 字典&#xff08;Dictionary&#xff09;2. 集合&#xff08;Set&#xff09;3. 字典 vs 集合4. 應用場景5. 注意事項 Python中的字典&#xff08; dict&#xff09;和集合&#xff08; set&#xff09;是兩種高效且常用的數據結構&#xff0c;適用于不同的場景。…

緩存與數據庫的高效讀寫流程解析

目錄 前言1 讀取數據的流程1.1 檢查緩存是否命中1.2 從數據庫讀取數據1.3 更新緩存1.4 返回數據 2 寫入數據的流程2.1 更新數據庫2.2 更新或刪除緩存2.3 緩存失效 3 緩存與數據庫的一致性問題3.1 寫穿&#xff08;Write-through&#xff09;策略3.2 寫回&#xff08;Write-back…

PowerShell 備份 Windows10/11 還原計算機驅動程序SOP

一、現在計算機C目錄下創建一個新的文件夾名稱為 driverbackup 二、打開cmd 以管理員身份執行 dism /online /export-driver /destination: C:\driverbackup 在正常情況下&#xff0c;Windows 10會自動檢測您的設備所需的驅動程序&#xff0c;并將其安裝到您的PC上。 但是&am…

自監督學習(Self-supervised Learning)李宏毅

目錄 Self-supervised Learning簡介&#xff1a; BERT : How to use BERT case1&#xff1a;sequence to class 語言積極性OR消極性判斷 case2&#xff1a;sequence to sequence句子中的詞語詞性標注 case3&#xff1a;sequence2 to class兩個句子是不是一個為前提一個為…

Python基于Django的全國二手房可視化分析系統【附源碼】

博主介紹&#xff1a;?Java老徐、7年大廠程序員經歷。全網粉絲12w、csdn博客專家、掘金/華為云/阿里云/InfoQ等平臺優質作者、專注于Java技術領域和畢業項目實戰? &#x1f345;文末獲取源碼聯系&#x1f345; &#x1f447;&#x1f3fb; 精彩專欄推薦訂閱&#x1f447;&…

解決 3D Gaussian Splatting 中 SIBR 可視化組件報錯 uv_mesh.vert 缺失問題【2025最新版!】

一、&#x1f4cc; 引言 在使用 3D Gaussian Splatting&#xff08;3DGS&#xff09;進行三維重建和可視化的過程&#xff0c;SIBR_gaussianViewer_app 是一款官方推薦的本地可視化工具&#xff0c;允許我們在 GPU 上實時瀏覽重建結果。然而&#xff0c;許多用戶在啟動該工具時…

shell_plus

python manage.py shell_plus 是由 django-extensions 提供的一個增強版的 Django shell&#xff0c;它自動導入你的所有模型和其他一些便捷功能&#xff0c;使得交互式開發更加方便。 如果你遇到配置或運行問題&#xff0c;特別是與 RQ_SHOW_ADMIN_LINK 相關的 ImproperlyCon…