【Linux】進程優先級 | 進程調度(三)

目錄

前言:

一、進程優先級:

1.通過nice值修改優先級:?

二、進程切換:

三、上下文數據

四、Linux真實調度算法:

五、bitmap位圖:

六、命令總結:

總結:


前言:

我們已經知道了進程的一些屬性,和進程的各種狀態及孤兒進程,那么接下來我們就需要知道進程的調度方法和優先級,少年,開始吧!

一、進程優先級:

進程優先級也就是獲取某種資源的先后順序。為什么存在?本質就是目標資源較少。

在task_struct中的優先級屬性是使用幾個int類型的變量表示的。優先級數字越小,優先級越高,也就和我們的排名一樣。

為了方便觀察,我們依舊寫一個死循環的程序:

當我們想查看一個進程的優先級信息,我們可以使用ps -l查看優先級信息:

如果你是新開的Xshell窗口,需要加上-a選項來查看全局的進程。

1.通過nice值修改優先級:?

我們一般是通過修改nice值對優先級進行修改的:

插一嘴:UID是什么?

我們平時文件的擁有者,所屬組都是一個字符串,系統做對比的時候所需時間就很多,所以OS會對每一個用戶維護一個叫做UID的東西。也就是用戶ID(USER identify)。我們可以使用ls -ln來查看。-n選項是把能顯示成數字的就顯示成數字,尤其是用戶。

所以操作系統使用UID來區分進程是誰啟動的,所有操作都是進程操作,進程會記錄誰啟動的我;而文件會記錄下擁有者,所屬組和對應權限。所以進程去啟動相關文件時,就會進行UID的對比,從而實現權限控制。

進程的優先級是為了競爭CPU資源做準備的。?接下來我們修改進程優先級,可以通過指令也可以通過代碼修改。

注意這里把nice拉到最大100(原來1767進程PRI為80,NI為0):

之后我們再次把nice值拉到最低-100,并再次觀察結果:

可以看到并沒有從上次的99加上nice值(-20)得到79,而是從最開始的80加上(-20)得到60最終優先級。?

為什么nice在可控范圍以內呢?因為我們使用的是分時OS,在進程調度的時候要盡量公平。

優先級的存在是為了更合理競爭相關資源。

二、進程切換:

當一個進程的時間片到了,進程就要被切換;Linux是基于時間片,進行調度輪轉的。但是一個進程的時間片到了并不一定就跑完了,可在任何地方被重新調度切換。

三、上下文數據

當一個進程的時間片到了,OS要保留上下文數據;當其又被調度的時候,OS要恢復上下文數據。

進程在運行的時候,會有很多臨時數據,這些數據都在寄存器中保存。CPU內部的寄存器數據,是進程執行時的瞬時狀態信息。

我們需要來具體了解幾個寄存器,如果各位不知道寄存器是什么,可以先臨時了解,就是存放各種信息的東西可以是地址,也可以是數據,寄存器在CPU上。

其中指令指針寄存器(也稱IP、PC程序計數器),它里面記錄下次要執行的命令的地址;IR(Instruction Register)即指令寄存器,存放的是當前執行代碼的地址。?

進程在運行的時候,會有很多臨時數據,這些數據都在寄存器中保存。CPU內部的寄存器數據,是進程執行時的瞬時狀態信息,只寫信息我們可以當做進程的上下文數據。

學過硬件的都知道,每個進程不是都需要用到寄存器嗎?IP寄存器即使這次存儲了進程A的下次執行地址,但是A的時間片到了,進程B執行,IP內的內容應該是B下次執行的地址;B的時間片到了,CPU調度進程A,有是怎么找進程A的執行地址呢?

我們之前已經講過PCB(task_struct)里面有一個屬性專門保存進程的上下文數據,所以在進程A執行完以后,寄存器中的內容會存放在PCB的上下文數據中,對于B也是,所以下次再次調度A就可以根據PBC來恢復上下文,繼續順序執行代碼。

我們找到第一版本的Linux內核代碼,其中tast_struct中的一個結構體屬性是tss(任務狀態段),之后看里面的屬性:

可以看到PCB中包含tss_struct(可以理解為保存上下文數據的屬性)?

這里面可以看到很多熟悉的寄存器。?所以上下文保存在PCB中,也就是內存中,而不是寄存器中。

我們之前講到過,進程是通過runqueue的task_struct*head找到第一個進程并讓CPU調度,當時間片結束就放在隊尾,也就是FIFO(先進先出)的方式。但是我們又講到了優先級,所以實際上,進程調度并不是FIFO,而是盡量的公平調度。

四、Linux真實調度算法:

所以我們來講解Linux的真實調度算法:

runqueue隊列中,有兩個指針維護調度的進程列表。*active活躍的進程列表,*expired過期的進程列表。

進程列表是一個指針數組,前100個是實時進程,我們無法對其改變優先級;后40個是分時進程,我們可以改變優先級。這也就解釋了之前的nice值為什么只有40個。

進程真正的優先級范圍為[60,99],而優先級為60對應的數組下標為100。

比如此時有一個優先級為61的進程要放入queue中,會61 - 60(startpri) + 100 = 101

如果再來一個進程優先級為61進程,則會連接在第一個進程后面:

這也就是一個哈希桶,但是其實runqueue中包含兩個哈希桶,維護兩個,接下來我們來具體了解。

為什么要這樣設計?比如此時active哈希桶中有一個進程:?

調度一般分為三種情況:

1.運行退出
2.不退出但時間片到了
3.有新進程產生了

第一種情況進程退出程序就釋放掉了,我們不做討論。

我們首先討論有新進程產生。此時有一個問題,如果一直有新的進程產生,并且創建的新進程優先級一直都是最高的,是不是會和之前講的調度器要非常均衡的進行進程調度所矛盾?優先級很高,表示一定要一直優先嗎?優先級很低,表示要一直等待嗎?

這樣的話優先級低的進程就永遠不會被調度,這叫做進程饑餓問題。

所以新進程會放入expired(過期)哈希桶中,而且時間片到了的進程,也會被放入expired哈希桶中。

所以active哈希桶中,進程只會越來越少,不會增多。?因為時間片會到,進程會退出。

當active為空時,OS會將active和expired指針指向的內容交換(swap(&active, &expired)),之后使用相同的調度算法,輪轉執行。

注意:實時進程(0-99)不收調度影響

回到之前queue定義中的nr_active是代表對應當前哈希桶中有多少進程,?它決定要不要交換,當nr_active為0就需要交換。

五、bitmap位圖:

而其中的bitmap[5],注意這是一個整形。5個整形也就有5*32=160個bit位,剛好覆蓋140。因為實際上還是從上到下進行遍歷看桶是否為空,這樣還是很慢的。而bitmap就可以快速定位,一次查找32個bit位看是否為空。這是位圖的概念。

類似這樣:

for(int i = 0; i < 5; ++i) 
{if (bitmap[i] == 0) {continue;}else {//確定在32個比特位那個位置有進程}
}

這就是Linux的進程O(1)算法,?所有的進程都要有鏈表連接,而且進程可以在調度隊列中,阻塞隊列中。

Linux中的鏈式結構為雙鏈表結構。但是它并不是我們想象的那樣將數據和指針都放在一個節點中;其實內核中只有鏈接字段,沒有屬性字段。

所以一個進程既可以在全局鏈表中,也可以在任何一個其他數據結構中,只要加上節點字段即可。?

我們進程其實只知道task_struct中的link字段地址,那么它是如何找到結構體的起始地址呢?這其實就是結構體部分的內容。

struct S
{char c1;int a;char c2;
};#define OFFSETOF(struct_name,member_name) (int)&(((struct_name*)0)->member_name)int main()
{struct S s = { 'a', 10, 'b' };//printf("%d\n", OFFSETOF(struct S, c1));//printf("%d\n", OFFSETOF(struct S, a));//printf("%d\n", OFFSETOF(struct S, c2));printf("%p\n", &s);printf("%p\n", (struct S*)( (char*) & s.a - OFFSETOF(struct S, a)));//這是作者自己實現的OFFSETOF宏,各位可以直接使用offsetof宏來求偏移量//使用offsetof要引用stddef.h同文件printf("%p\n", (struct S*)((char*)&s.a - offsetof(struct S, a)));return 0;
}

這里為什么要轉換為char*?這樣可以按照字節為單位去操作,更好的計算。各位可以試試其他類型,會發現結果并不符合預期。

六、命令總結:

ps -l:查看當前系統中進程狀態,將能顯示為數字的都顯示為數字。

總結:

大佬不愧為大佬,這個調度算法和位圖的設計簡直無敵,接下來我們就會講解命令行參數和環境變量,這部分知識也更為炸裂,各位敬請期待!

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

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

相關文章

【redis】數據類型之hyperloglog

Redis的HyperLogLog&#xff08;HLL&#xff09;是一種高效的概率數據結構&#xff0c;也是一種基于字符串的數據結構&#xff0c;用于估計大數據集的唯一元素數量&#xff08;基數統計&#xff09;。它通過極低的內存占用&#xff08;約 12KB&#xff09;實現接近線性的時間復…

【C語言】第八期——指針、二維數組與字符串

目錄 1 初始指針 2 獲取變量的地址 3 定義指針變量、取地址、取值 3.1 定義指針變量 3.2 取地址、取值 4 對指針變量進行讀寫操作 5 指針變量作為函數參數 6 數組與指針 6.1 指針元素指向數組 6.2 指針加減運算&#xff08;了解&#xff09; 6.2.1 指針加減具體數字…

SpringBoot——生成Excel文件

在Springboot以及其他的一些項目中&#xff0c;或許我們可能需要將數據查詢出來進行生成Excel文件進行數據的展示&#xff0c;或者用于進行郵箱發送進行附件添加 依賴引入 此處demo使用maven依賴進行使用 <dependency><groupId>org.apache.poi</groupId>&…

mac 下 java 調用 gurobi 不能加載 jar

在 mac 電腦中的 java 始終不能加載 gurobi 的 jar 包&#xff0c;java 的開發軟件 eclipse&#xff0c;idea 總是顯示找不到 gurobi 的 jar 包&#xff0c;但是 jar 包明明就在那里。 摸索了三個小時&#xff0c;最后發現原因竟然是&#xff1a; jar 包太新&#xff0c;替換…

服務端配置TCP探活,超出探活時間后的行為?

server端啟動 &#xff08;完整源碼在最后&#xff09; 配置探活 setsockopt(client_fd, IPPROTO_TCP, TCP_KEEPIDLE, &(int){5}, sizeof(int)); // 空閑60秒后探測setsockopt(client_fd, IPPROTO_TCP, TCP_KEEPINTVL, &(int){10}, sizeof(int)); // 探測間隔10秒…

LLC諧振變換器恒壓恒流雙競爭閉環simulink仿真

1.模型簡介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2017Ra&#xff09;軟件。建議采用matlab2017 Ra及以上版本打開。&#xff08;若需要其他版本可聯系代為轉換&#xff09;針對全橋LLC拓撲&#xff0c;利用Matlab軟件搭建模型&#xff0c;分別對輕載&#xf…

MySQL 中如何查看 SQL 的執行計劃?

SQL 語句前面使用 EXPLAIN 關鍵字&#xff1a; EXPLAIN SELECT * FROM users WHERE id 1; 字段 含義 id 查詢的序號&#xff08;如果是子查詢或聯合查詢&#xff0c;會有多個 id&#xff09;。 select_type 查詢的類型&#xff08;簡單查詢、子查詢、聯合查詢等&#xff…

Discourse 中集成 Claude 3.7 Sonnet 模型

如果 Discourse 實例已經接入了 Anthropic。 那么只需要在后臺挑一個不希望繼續使用的模型改下就好。 否則需要重新在 Discourse 實例中配置 AI&#xff0c;然后獲得 Anthropic 的 key。 進入后臺的 AI 然后選擇 LLMs 雖然我們這里已經顯示成 3.7 了&#xff0c;但實際上所有…

Oracle 12c Docker安裝問題排查 sga_target 1536M is too small

一、問題描述 在虛擬機環境&#xff08;4核16GB內存&#xff09;上部署 truevoly/oracle-12c 容器鏡像時&#xff0c;一切運行正常。然而&#xff0c;當在一臺 128 核 CPU 和 512GB 內存的物理服務器上運行時&#xff0c;容器啟動時出現了 ORA-00821 等錯誤&#xff0c;提示 S…

DeepSeek 提示詞:高效的提示詞設計

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;精通Java編…

KIMI K1.5:大規模強化學習在大語言模型中的應用與工程實踐

目錄 1、核心技術創新:長上下文強化學習 2、策略優化的技術細節 2.1、在線鏡像下降變體 2.2、長度懲罰機制 2.3、智能采樣策略 3、工程架構創新 3.1、混合部署框架 3.2、代碼沙箱與獎勵模型 3.3、分布式系統架構 4、實驗成果與性能提升 5、結論與未來展望 大語言模…

從 0 到 1:使用 Docker 部署個人博客系統

引言 在當今數字化時代&#xff0c;擁有一個個人博客來記錄自己的學習、生活和見解是一件非常有意義的事情。然而&#xff0c;傳統的博客部署方式往往涉及復雜的環境配置和依賴管理&#xff0c;容易讓人望而卻步。而 Docker 的出現&#xff0c;為我們提供了一種簡單、高效的解…

多進程網絡服務端詳細說明文檔

多進程網絡服務端詳細說明文檔 一、概述 本項目實現了一個基于多進程的 TCP 網絡服務端&#xff0c;主要用于處理多個客戶端的連接請求。為了提高代碼的可維護性和可復用性&#xff0c;分成了頭文件&#xff08;.h&#xff09;和多個源文件&#xff08;.cpp&#xff09;。具體…

HDFS數據多目錄、異構存儲、回收站

1.NameNode元數據多目錄 HDFS集群中可以在hdfs-site.xml中配置“dfs.namenode.name.dir”屬性來指定NameNode存儲數據的目錄&#xff0c;默認NameNode數據存儲在${hadoop.tmp.dir}/dfs/name目錄&#xff0c;“hadoop.tmp.dir”配置項在core-site.xml中。 我們也可以將NameNod…

TFChat:騰訊大模型知識引擎(DeepSeek R1)+飛書機器人實現AI智能助手

效果 TFChat項目地址 https://github.com/fish2018/TFChat 騰訊大模型知識引擎用的是DeepSeek R1&#xff0c;項目為sanic和redis實現&#xff0c;利用httpx異步處理流式響應&#xff0c;同時使用buffer來避免頻繁調用飛書接口更新卡片的網絡耗時。為了進一步減少網絡IO消耗&…

HTML5 面試題

1. HTML5 新增了哪些重要特性&#xff1f; 語義化標簽&#xff1a;這些標簽有助于提高頁面的可讀性和可維護性。多媒體支持&#xff1a;HTML5 引入了 和 標簽&#xff0c;可以直接嵌入音頻和視頻文件&#xff0c;無需依賴插件。本地存儲&#xff1a;引入了 localStorage 和 se…

【Linux】Linux常用命令

目錄 文件和目錄相關命令查看和管理進程磁盤和文件系統管理用戶和權限管理網絡相關命令文本處理命令系統狀態查看命令軟件包管理命令計劃任務和后臺作業其他常用命令 1. 文件和目錄相關命令 命令作用示例pwd顯示當前工作目錄pwdls列出目錄內容ls -l 查看詳細信息cd切換目錄cd…

布署elfk-準備工作

建議申請5臺機器部署elfk&#xff1a; filebeat(每臺app)--> logstash(2臺keepalived)--> elasticsearch(3臺)--> kibana(部署es上)采集輸出 處理轉發 分布式存儲 展示 ELK中文社區: 搜索客&#xff0c;搜索人自己的社區 官方…

DeepSeek:我的AI助手之旅

★【前言】: 初次使用AI助手幫我寫作,就像摸石頭過河一樣,一點點的前行。我在慢慢的摸索,慢慢的體會中,感悟出的一點個人心得體會現分享給大家。這也說明一個問題,網站上各種使用方法和技巧是對于已經使用過的人來說的方便和快捷,但對于剛剛接觸的使用者來說,網上的各…