**重點(diǎn) 重點(diǎn) 重點(diǎn):打通Linux脈絡(luò)系列:進(jìn)程、線程和調(diào)度( 進(jìn)程和線程的一些筆記)

聲明:所有文章只作為學(xué)習(xí)筆記用,轉(zhuǎn)載非原創(chuàng)

宋寶華??https://blog.csdn.net/21cnbao/article/details/103839437


glibc是GNU發(fā)布的libc庫(kù),即c運(yùn)行庫(kù)。glibc是linux系統(tǒng)中最底層的api,幾乎其它任何運(yùn)行庫(kù)都會(huì)依賴(lài)于glibc。

linux 啟動(dòng)??http://www.itdecent.cn/p/c961875ee123

?linux 運(yùn)行原理圖 2.6?https://10.linuxstory.net/linux-kernel-map/


子進(jìn)程運(yùn)行過(guò)程:

1)父進(jìn)程調(diào)用fork() 產(chǎn)生一個(gè)新的自進(jìn)程;

2)子進(jìn)程調(diào)用exec() 指定自己要執(zhí)行的代碼;

3)子進(jìn)程調(diào)用exit() 退出,進(jìn)入zombie狀態(tài);

4)父進(jìn)程調(diào)用wait(),等待子進(jìn)程的返回,回收其所有資源;

進(jìn)程地址空間

https://zhuanlan.zhihu.com/p/68398179?

https://zhuanlan.zhihu.com/p/25098193

linux 進(jìn)程的虛擬內(nèi)存 https://blog.csdn.net/fengxinlinux/article/details/52071766

1. 每個(gè)進(jìn)程的4G內(nèi)存空間只是虛擬內(nèi)存空間,每次訪問(wèn)內(nèi)存空間的某個(gè)地址,都需要把地址翻譯為實(shí)際物理內(nèi)存地址

2. 所有進(jìn)程共享同一物理內(nèi)存,每個(gè)進(jìn)程只把自己目前需要的虛擬內(nèi)存空間映射并存儲(chǔ)到物理內(nèi)存上。

3. 進(jìn)程要知道哪些內(nèi)存地址上的數(shù)據(jù)在物理內(nèi)存上,哪些不在,還有在物理內(nèi)存上的哪里,需要用頁(yè)表來(lái)記錄

4.頁(yè)表的每一個(gè)表項(xiàng)分兩部分,第一部分記錄此頁(yè)是否在物理內(nèi)存上,第二部分記錄物理內(nèi)存頁(yè)的地址(如果在的話)

5. 當(dāng)進(jìn)程訪問(wèn)某個(gè)虛擬地址,去看頁(yè)表,如果發(fā)現(xiàn)對(duì)應(yīng)的數(shù)據(jù)不在物理內(nèi)存中,則缺頁(yè)異常

6.缺頁(yè)異常的處理過(guò)程,就是把進(jìn)程需要的數(shù)據(jù)從磁盤(pán)上拷貝到物理內(nèi)存中,如果內(nèi)存已經(jīng)滿了,沒(méi)有空地方了,那就找一個(gè)頁(yè)覆蓋,當(dāng)然如果被覆蓋的頁(yè)曾經(jīng)被修改過(guò),需要將此頁(yè)寫(xiě)回磁盤(pán)

MMU在運(yùn)行時(shí)將虛擬地址映射成(或者說(shuō)轉(zhuǎn)換成)某個(gè)物理內(nèi)存頁(yè)面中的地址。如圖所示:

https://www.cnblogs.com/linhaostudy/p/6687432.html

大多數(shù)使用虛擬存儲(chǔ)器的系統(tǒng)都使用一種稱(chēng)為分頁(yè)(paging)。虛擬地址空間劃分成稱(chēng)為頁(yè)(page)的單位

VA(虛地址),MVA(修正后虛地址),PA(物理地址)

1)VA,是程序中的邏輯地址,0x00000000~0xFFFFFFFF。

2)MVA,由于多個(gè)進(jìn)程執(zhí)行,邏輯地址會(huì)重合。所以,跟據(jù)進(jìn)程號(hào)將邏輯地址分布到整個(gè)內(nèi)存中。MVA = (PID << 25)? | VA

3)PA,MVA通過(guò)MMU轉(zhuǎn)換后的地址。

(1)cpu看到的是VA

(2)caches和MMU使用的是MVA,

(3)實(shí)際物理設(shè)設(shè)備使用的是PA。

虛擬內(nèi)存


頁(yè)表


上圖反映了如下信息:

1、 進(jìn)程的4G 線性空間被劃分成三個(gè)部分:進(jìn)程空間(0-3G)、內(nèi)核直接映射空間(3G– high_memory)、內(nèi)核動(dòng)態(tài)映射空間(VMALLOC_START - VMALLOC_END)

2、?三個(gè)空間使用同一張頁(yè)目錄表,通過(guò)?CR3?可找到此頁(yè)目錄表。但不同的空間在頁(yè)目錄表中頁(yè)對(duì)應(yīng)不同的項(xiàng),因此互相不沖突

3、?內(nèi)核初始化以后,根據(jù)實(shí)際物理內(nèi)存的大小,計(jì)算出 high_memory、VMALLOC_START、VMALLOC_END 的值。并為“內(nèi)核直接映射”空間建立好映射關(guān)系,所有的物理內(nèi)存都可以通過(guò)此空間進(jìn)行訪問(wèn)。

4、?“進(jìn)程空間”和“內(nèi)核動(dòng)態(tài)映射空間”的映射關(guān)系是動(dòng)態(tài)建立的(通過(guò)缺頁(yè)異常)

假設(shè)在有三個(gè)線性地址 addr1, addr2, addr3 ,分別屬于三個(gè)線性空間不同部分(0-3G、3G-high_memory、vmalloc_start-vmalloc_end),但是最終都映射到物理頁(yè)面1:

1、 三個(gè)地址對(duì)應(yīng)不同的頁(yè)表和頁(yè)表項(xiàng)

2、 但是頁(yè)表項(xiàng)的高20bit肯定是1,表示物理頁(yè)面的索引號(hào)是1

3、 同時(shí),根據(jù)高20bit,可以從 mem_map[]中找到對(duì)應(yīng)的struct page結(jié)構(gòu),struct page 用于管理實(shí)際的物理頁(yè)面(就是實(shí)際物理頁(yè)面的物理地址了,到這里就不繞彎子了,順便想到高速緩沖的匹配命中操作是用哈希表,換算出的要訪問(wèn)的實(shí)際物理地址拿到哈希表的輸入計(jì)算一下哈希值,看看有沒(méi)命中)(紅線)

4、 從線性地址最終的,根據(jù)頁(yè)目錄表,頁(yè)表,可以找到物理地址

5、 struct page和物理地址之間很容易互相轉(zhuǎn)換

6、 從物理地址,可以很容易的反推出在內(nèi)核直接映射空間的線性地址(藍(lán)線)。要想得到在進(jìn)程空間或者內(nèi)核動(dòng)態(tài)映射空間的對(duì)應(yīng)的線性地址,則需要遍歷相應(yīng)的“虛存區(qū)間”鏈表。


頁(yè)表?https://blog.csdn.net/m0_37329910/article/details/85222931

進(jìn)程的運(yùn)行過(guò)程?https://www.cnblogs.com/klvchen/articles/11763452.html

cgroup??https://blog.csdn.net/huang987246510/article/details/80765628

cgroups,其名稱(chēng)源自控制組群(control groups)的簡(jiǎn)寫(xiě),是Linux內(nèi)核的一個(gè)功能,用來(lái)限制、控制與分離一個(gè)進(jìn)程組的資源(如CPU、內(nèi)存、磁盤(pán)輸入輸出等)

Linux系統(tǒng)glibc庫(kù)版本信息查看?https://www.cnblogs.com/jiftle/p/11584780.html

有時(shí)我們經(jīng)常需要查看當(dāng)前系統(tǒng)的glibc版本,可以這樣查看:

/lib/libc.so.6? ? ---直接執(zhí)行

有時(shí):/lib/x86-64-linux/libc.so.6

把這個(gè)文件當(dāng)命令執(zhí)行一下

Just execute:

ldd --version? ---?ldd是list, dynamic, dependencies的縮寫(xiě)??列出動(dòng)態(tài)庫(kù)依賴(lài)關(guān)系。

ldd 命令?https://blog.csdn.net/nzjdsds/article/details/86759843

? ? ? ? ldd /bin/ls

輸出示例

libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00000039a7e00000)

libm.so.6 => /lib64/libm.so.6 (0x0000003996400000)

libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000039a5600000)

libc.so.6 => /lib64/libc.so.6 (0x0000003995800000)

/lib64/ld-linux-x86-64.so.2 (0x0000003995400000)

第一列:程序需要依賴(lài)什么庫(kù)

第二列: 系統(tǒng)提供的與程序需要的庫(kù)所對(duì)應(yīng)的庫(kù)

第三列:庫(kù)加載的開(kāi)始地址



====================================================================

linux 讀寫(xiě)文件的過(guò)程?https://blog.csdn.net/KingOfMyHeart/article/details/90272050

https://blog.csdn.net/21cnbao

視頻?https://www.bilibili.com/video/av79890150?from=search&seid=10039787655842011702

筆記?https://blog.csdn.net/qq_37375427/article/details/83004951?from=timeline

Linux 進(jìn)程映像?http://www.itdecent.cn/p/8953feee0e03

Linux的進(jìn)程地址空間(一)?https://zhuanlan.zhihu.com/p/66794639

Linux 消息隊(duì)列、共享內(nèi)存、信號(hào)量(一)消息隊(duì)列 https://blog.csdn.net/qq_33225741/article/details/72861413

Linux 如何查看一個(gè)進(jìn)程的堆棧

有兩種方法:

第一種:pstack 進(jìn)程ID

第二種,使用gdb 然后attach 進(jìn)程ID,然后再使用命令 thread apply all bt


第三種:strace -f -p pid? 該方法和pstack類(lèi)似

第四中:gcore pid ,輸出core文件,gdb cmd corefile

兩種方法都可以列出進(jìn)程所有的線程的當(dāng)前的調(diào)用棧。

不過(guò),使用gdb的方法,還可以查看某些信息,例如局部變量,指針等。

不過(guò),如果只看調(diào)用棧的話,pstack還是很方便的。

strace 用法?https://blog.csdn.net/cs729298/article/details/81906375

strace 輸出的時(shí)候會(huì)有用 Linux mmap內(nèi)存映射??https://blog.csdn.net/weixin_34101229/article/details/91395524

https://blog.csdn.net/yusiguyuan


在計(jì)算機(jī)中,系統(tǒng)調(diào)用(英語(yǔ):system call),又稱(chēng)為系統(tǒng)呼叫,指運(yùn)行在用戶空間的程序向操作系統(tǒng)內(nèi)核請(qǐng)求需要更高權(quán)限運(yùn)行的服務(wù)。

系統(tǒng)調(diào)用提供用戶程序與操作系統(tǒng)之間的接口。操作系統(tǒng)的進(jìn)程空間分為用戶空間和內(nèi)核空間:

操作系統(tǒng)內(nèi)核直接運(yùn)行在硬件上,提供設(shè)備管理、內(nèi)存管理、任務(wù)調(diào)度等功能。

用戶空間通過(guò)API請(qǐng)求內(nèi)核空間的服務(wù)來(lái)完成其功能——內(nèi)核提供給用戶空間的這些API, 就是系統(tǒng)調(diào)用。

在Linux系統(tǒng)上,應(yīng)用代碼通過(guò)glibc庫(kù)封裝的函數(shù),間接使用系統(tǒng)調(diào)用。

Linux內(nèi)核目前有300多個(gè)系統(tǒng)調(diào)用,詳細(xì)的列表可以通過(guò)syscalls手冊(cè)頁(yè)查看。這些系統(tǒng)調(diào)用主要分為幾類(lèi):

文件和設(shè)備訪問(wèn)類(lèi)?比如open/close/read/write/chmod等

進(jìn)程管理類(lèi)?fork/clone/execve/exit/getpid等

信號(hào)類(lèi)?signal/sigaction/kill?等

內(nèi)存管理?brk/mmap/mlock等

進(jìn)程間通信IPC?shmget/semget?*?信號(hào)量,共享內(nèi)存,消息隊(duì)列等

網(wǎng)絡(luò)通信?socket/connect/sendto/sendmsg?等


cpu個(gè)數(shù),核數(shù),線程之間的關(guān)系?https://blog.csdn.net/helloworld0906/article/details/90547159

PCB?https://www.cnblogs.com/Kirino1/p/9710062.html

linux 概念及架構(gòu)?http://www.itdecent.cn/p/c5ae8f061cfe




了解程序開(kāi)發(fā)過(guò)程

搭建開(kāi)發(fā)環(huán)境,了解 Linux 上程序開(kāi)發(fā)過(guò)程。

學(xué)會(huì)使用文本編輯工具 Vim,編譯工具 gcc, as, 連接工具 ld, 調(diào)試工具 gdb, make 工具,會(huì)寫(xiě) makefile。

用 C 語(yǔ)言實(shí)現(xiàn)并編譯自己的測(cè)試程序。

嘗試系統(tǒng)編程

試著在 Linux 上用 C 語(yǔ)言進(jìn)行系統(tǒng)編程,

其中需要調(diào)用 Linux 系統(tǒng)庫(kù)函數(shù) (API)。

例如,實(shí)現(xiàn)一個(gè)需要進(jìn)行網(wǎng)絡(luò)通信、操作文件的多線程/進(jìn)程程序。

以此深入了解 Linux 系統(tǒng)運(yùn)行機(jī)制。


進(jìn)程 自己的筆記:

進(jìn)程--->pcb--->task_struct

進(jìn)程: 進(jìn)程是一個(gè)資源分配單位。弄清楚一個(gè)進(jìn)程,就是搞清楚一個(gè)進(jìn)程的資源。

進(jìn)程控制塊 PCB:?進(jìn)程控制塊 (Processing Control Block),是操作系統(tǒng)核心中一種數(shù)據(jù)結(jié)構(gòu),主要表示進(jìn)程狀態(tài)。

task_struct : 描述進(jìn)程使用的資源(結(jié)構(gòu)) (?task_struct結(jié)構(gòu)體,不要死記硬背。)

pid : cat /proc/sys/kernel/pid_max 最大進(jìn)程數(shù)量

進(jìn)程是有父子關(guān)系的?

linux 描述進(jìn)程的數(shù)據(jù)結(jié)構(gòu):利用多種數(shù)據(jù)結(jié)構(gòu)來(lái)描述task_struct ( 設(shè)計(jì)思想 )

鏈表(遍歷進(jìn)程,無(wú)法表示父子結(jié)構(gòu)),樹(shù)結(jié)構(gòu)(快速查看父子結(jié)構(gòu)),哈希(例如能根據(jù)pid快速定位進(jìn)程相關(guān)信息)

進(jìn)程的生命周期: 進(jìn)程fork出來(lái)后的狀態(tài),(宏觀并行,微觀串行(狀態(tài)切換就比較微觀))

進(jìn)程生命周期中的基本狀態(tài): linux里總是“白發(fā)人(父進(jìn)程)”送“黑發(fā)人(子進(jìn)程)”

就緒 : fork 出來(lái)就處于? ?《-------? linux? 就緒和運(yùn)行的標(biāo)志是一樣的? ? ? -------》? ?運(yùn)行? ?: 拿到cpu 就是運(yùn)行態(tài)? ?

? ? ? ? ? ? ?思考: 就緒和運(yùn)行之間的切換,一個(gè)程序不可能總占用cpu,比如我運(yùn)行QQ,微信, 微博,其中任何一個(gè)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?不可能一直占用cpu,

? ? ? ? ? ? ? ? ? ? ? ? 進(jìn)程時(shí)間片和搶占(速度是非常快的,宏觀的比喻我正在用QQ聊天,但是有一個(gè)更重要的緊急事情? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?需要做)

? ? ? ? ? ? ? ? ? ? ? ? --------按時(shí)間片輪轉(zhuǎn)? ?先來(lái)先服務(wù) 短時(shí)間優(yōu)先 按優(yōu)先級(jí)別??

?睡眠? : (深睡眠,淺睡眠)

? ? ? ? ? ? ? ?深睡眠:必須要等到資源才能被喚醒(資源比如硬盤(pán)讀 ),不響應(yīng)任何signal喚醒。kill -9 也殺不掉

? ? ? ? ? ? ? ? 淺睡眠: 資源來(lái)了醒,淺睡眠還可以被signal喚醒

? ? ? ? ? ? ? ?深睡眠不響應(yīng)任何信號(hào)的kill -9 都?xì)⒉坏?。kill -l 查看signal (信號(hào)類(lèi)型就是針對(duì)一個(gè)進(jìn)程的異步打斷機(jī)制)

? ? ? ? ? ? ? ? 思考:為什么會(huì)有深睡眠。

停止態(tài): 人為停止(類(lèi)似于作業(yè)控制ctrl+z--job control? bg/fg(繼續(xù)), gdb attach debug)

? ? ? ? ? ? ? ? ?cpulimit : 利用了停止態(tài),限制pid 使用CPU利用率。cpulimit -l 百分比 -p pid?

僵尸態(tài):就是進(jìn)程已經(jīng)死了,資源已經(jīng)釋放。 非常短的臨界狀態(tài),task_struct還在,等待父進(jìn)程 wait4(api接口) 結(jié)束僵尸? ? ? ? ? ? ? ? ? ? ? ? ? ?進(jìn)程。如果父進(jìn)程不用wait清理,那僵尸進(jìn)程永遠(yuǎn)在。清理僵尸進(jìn) 程(只有父進(jìn)程也殺掉,僵尸進(jìn)程也會(huì)沒(méi)有)。

? ? ? ? ? ? ? 內(nèi)存泄露: 不是進(jìn)程死了,內(nèi)存沒(méi)有釋放,而是進(jìn)程活著,運(yùn)行越久,內(nèi)存消耗越來(lái)越多。

? ? ? ? ? ? ? 進(jìn)程運(yùn)行正常狀態(tài): 圍繞一根均線,震蕩收斂,有起有伏的。

? ? ? ? ? ? ? 怎樣觀察內(nèi)存是否泄漏: 多點(diǎn)采樣法(8-20點(diǎn),每小時(shí)采樣),內(nèi)存用的越來(lái)越多,必定有內(nèi)存泄露。

fork :?

? ? ? ? ? ? ? n.餐叉; 叉(挖掘用的園藝工具); (道路、河流等的) 分岔處,分流處,岔口,岔路;

? ? ? ? ? ? ? v.分岔; 岔開(kāi)兩條分支; 走岔路中的一條; 叉運(yùn); 叉掘;

fork()函數(shù)的返回值是返回兩次的,在父進(jìn)程中返回子進(jìn)程的pid,在子進(jìn)程中返回0

第一個(gè)fork()會(huì)生出2個(gè)進(jìn)程? ,第二次fork()會(huì)生出四個(gè)進(jìn)程,所以一共打印6次

p1是個(gè)task_struct p2也是個(gè)task_struct

? ? ? ? ? ? ?示例:打印了幾次hello

? ? ? ? ? ? ?main () {

? ? ? ? ? ? ? ?fork(); printf("hello\n") ; fork() ; printf("hello\n") ;while(1);

? ? ? ? ? ? ? ?}

?fork炸彈 : :(){:|:&};:? ??

? ? ? ? ? ? ? ? ? ? ? 原理就是定義一個(gè)函數(shù),并不斷遞歸,不停地制造后臺(tái)任務(wù)。如你所見(jiàn)那個(gè)函數(shù)名就是個(gè)冒號(hào),其實(shí)這完全就是在? ? ? ? ? ? ? ? 擾亂你的視線?!驹捳f(shuō)回來(lái)好像bash里好像也有一個(gè)啥事都不干的冒號(hào)命令】

?寫(xiě)的易懂點(diǎn):

? ? ? ? ? ? ? ? func () { #函數(shù)定義,這里把函數(shù)名改成了func}

? ? ? ? ? ? ? ? 這是bash shell的寫(xiě)法,首先定義了一個(gè)函數(shù):(),花括號(hào)里面是函數(shù)體,這里遞歸執(zhí)行函數(shù)本身,通過(guò)管道在后臺(tái)再遞? ? ? ? ? ? ?歸運(yùn)行一次本程序,最后的冒號(hào)就是立刻執(zhí)行當(dāng)前這個(gè)函數(shù)。這樣一直運(yùn)行下去,直到系統(tǒng)崩潰,這就是fork炸彈

Copy on Write COW技術(shù) 寫(xiě)入時(shí)復(fù)制 MMU= memory management unit 內(nèi)存管理單元

page fault :缺頁(yè)中斷 RD-only 才會(huì)發(fā)生

fork()?

vfork(): 父進(jìn)程阻塞直到子進(jìn)程 exit / exec

虛擬內(nèi)存是計(jì)算機(jī)系統(tǒng)內(nèi)存管理的一種技術(shù)。它使得應(yīng)用程序認(rèn)為它擁有連續(xù)可用的內(nèi)存(一個(gè)連續(xù)完整的地址空間),而實(shí)際上,它通常是被分隔成多個(gè)物理內(nèi)存碎片,還有部分暫時(shí)存儲(chǔ)在外部磁盤(pán)存儲(chǔ)器上,在需要時(shí)進(jìn)行數(shù)據(jù)交換。與沒(méi)有使用虛擬內(nèi)存技術(shù)的系統(tǒng)相比,使用這種技術(shù)的系統(tǒng)使得大型程序的編寫(xiě)變得更容易,對(duì)真正的物理內(nèi)存(例如RAM)的使用也更有效率。

注意:虛擬內(nèi)存不只是「用磁盤(pán)空間來(lái)擴(kuò)展物理內(nèi)存」的意思——這只是擴(kuò)充內(nèi)存級(jí)別以使其包含硬盤(pán)驅(qū)動(dòng)器而已。把內(nèi)存擴(kuò)展到磁盤(pán)只是使用虛擬內(nèi)存技術(shù)的一個(gè)結(jié)果,它的作用也可以通過(guò)覆蓋或者把處于不活動(dòng)狀態(tài)的程序以及它們的數(shù)據(jù)全部交換到磁盤(pán)上等方式來(lái)實(shí)現(xiàn)。對(duì)虛擬內(nèi)存的定義是基于對(duì)地址空間的重定義的,即把地址空間定義為「連續(xù)的虛擬內(nèi)存地址」,以借此「欺騙」程序,使它們以為自己正在使用一大塊的「連續(xù)」地址。

進(jìn)程與虛擬地址

32位系統(tǒng)下每個(gè)進(jìn)程都會(huì)分配4G的虛擬內(nèi)存空間,而其實(shí)所有進(jìn)程都共享著同一物理內(nèi)存,每個(gè)進(jìn)程只把自己目前需要的虛擬內(nèi)存空間映射并存儲(chǔ)到物理內(nèi)存上。每次訪問(wèn)內(nèi)存空間的某個(gè)地址,都需要把地址翻譯為實(shí)際物理內(nèi)存地址。

這時(shí)我們需要一個(gè)東西它就是MMU(內(nèi)存管理單元),它的主要作用就是完成地址的映射,也就是頁(yè)表的建立、映射過(guò)程。頁(yè)表就是用來(lái)記錄進(jìn)程中哪些內(nèi)存地址上的數(shù)據(jù)在物理內(nèi)存上以及它們所在的位置的一個(gè)結(jié)構(gòu)。每個(gè)進(jìn)程都有一個(gè)頁(yè)表,當(dāng)進(jìn)程需要訪問(wèn)某個(gè)虛擬地址時(shí),就會(huì)去訪問(wèn)頁(yè)表,頁(yè)表實(shí)現(xiàn)從頁(yè)號(hào)到物理塊號(hào)的地址映射。




引用?https://github.com/21cnbao/process-courses

# 打通Linux脈絡(luò)系列:進(jìn)程、線程和調(diào)度

* 第一部分深入徹底地搞清楚進(jìn)程生命周期,進(jìn)程生命周期創(chuàng)建、退出、停止,以及僵尸是個(gè)什么意思;

* 第二部分,深入分析進(jìn)程創(chuàng)建的寫(xiě)時(shí)拷貝技術(shù)、以及Linux的線程究竟是怎么回事(為什么稱(chēng)為輕量級(jí)進(jìn)程),此部分也會(huì)搞清楚進(jìn)程0、進(jìn)程1和托孤,以及睡眠時(shí)的等待隊(duì)列;

* 第三部分,搞清楚Linux進(jìn)程調(diào)度算法,不同的調(diào)度策略、實(shí)時(shí)性,完全公平調(diào)度算法;

* 第四部分,講解Linux多核下CPU、中斷、軟負(fù)載均衡,cgroups調(diào)度算法以及Linux為什么不是一個(gè)實(shí)時(shí)操作系統(tǒng)。

# 第一部分大綱

* Linux進(jìn)程生命周期(就緒、運(yùn)行、睡眠、停止、僵死)

* 僵尸是個(gè)什么鬼?

* 停止?fàn)顟B(tài)與作業(yè)控制,cpulimit

* 內(nèi)存泄漏的真實(shí)含義

* task_struct以及task_struct之間的關(guān)系

* 初見(jiàn)fork和僵尸

## 練習(xí)題

* fork的例子

* life-period例子,觀察僵尸

* 用cpulimit控制CPU利用率

# 第二部分大綱

* fork、vfork、clone

* 寫(xiě)時(shí)拷貝技術(shù)

* Linux線程的實(shí)現(xiàn)本質(zhì)

* 進(jìn)程0和進(jìn)程1 : 進(jìn)程1(init) 是由進(jìn)程0 生成的

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?進(jìn)程0 把其它進(jìn)程fork出來(lái)后 變成 IDLE進(jìn)程,IDLE進(jìn)程等所有進(jìn)程都停止或睡眠了,就去調(diào)用進(jìn)程0 。WFI --等中斷狀態(tài) (類(lèi)似省電模式)

? /proc/1 : cat status

? /proc/PID

? /proc/PID/task? 線程 PID?




* 進(jìn)程的睡眠和等待隊(duì)列

等待隊(duì)列 wait_queue:?

睡眠是內(nèi)核自己把資源


r_wait 隊(duì)列? ??

停止: 別人打暈的

睡眠:是自己睡得

深度睡眠: linux 發(fā)現(xiàn)你要系統(tǒng)調(diào)用 ,讀寫(xiě),要io 等資源 ,資源不來(lái) 就不醒

非阻塞O_NONBLOCK與O_NDELAY的區(qū)別?O_NONBLOCK就產(chǎn)生出來(lái),它在讀取不到數(shù)據(jù)時(shí)會(huì)回傳-1,并且設(shè)置errno為EAGAIN。還是推薦POSIX規(guī)定的O_NONBLOCK,O_NONBLOCK可以在open和fcntl時(shí)設(shè)置。阻塞操作是指,在執(zhí)行設(shè)備操作時(shí),若不能獲得資源,則進(jìn)程掛起直到滿足可操作的條件再進(jìn)行操作。非阻塞操作的進(jìn)程在不能進(jìn)行設(shè)備操作時(shí),并不掛起。被掛起的進(jìn)程進(jìn)入sleep狀態(tài),被從調(diào)度器的運(yùn)行隊(duì)列移走,直到等待的條件被滿足。?

在Linux驅(qū)動(dòng)程序中,我們可以使用等待隊(duì)列(wait queue)來(lái)實(shí)現(xiàn)阻塞操作。wait queue很早就作為一個(gè)基本的功能單位出現(xiàn)在Linux內(nèi)核里了,它以隊(duì)列為基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),與進(jìn)程調(diào)度機(jī)制緊密結(jié)合,能夠用于實(shí)現(xiàn)核心的異步事件通知機(jī)制。等待隊(duì)列可以用來(lái)同步對(duì)系統(tǒng)資源的訪問(wèn),上節(jié)中所講述Linux信號(hào)量在內(nèi)核中也是由等待隊(duì)列來(lái)實(shí)現(xiàn)的。?

sechedule? task_interruptible

?select / poll? ?epoll?https://blog.csdn.net/zxm342698145/article/details/80524331

? ?附加 : 怎么樣理解 page fault ??

??http://www.itdecent.cn/p/f9b8c139c2ed


* 孤兒進(jìn)程的托孤,SUBREAPER

fork () 與 vfork()?

vfork 共用mm struct?

linux 通過(guò) pthread_create (創(chuàng)建線程的API)創(chuàng)建線程 ,調(diào)用的就是clone (把所有的資源都clone一份,p2的所有指針都指向p1)? linux 就是用這樣的方法來(lái)實(shí)現(xiàn)線程的。所以在linux 中為什么線程也叫輕量級(jí)進(jìn)程(LWP)的原因。

思考: Linux實(shí)現(xiàn)進(jìn)程和線程 ,如果克隆一部分task_struct 那是什么(線程有了進(jìn)程的心,)

?TGID :thread group id。對(duì)于同一進(jìn)程中的所有線程,tgid都是一致的,為該進(jìn)程的進(jìn)程ID。

Top 命令看到的就是 TGID

Top -H 看到的是線程ID

進(jìn)程的托孤: 白發(fā)人送黑發(fā)人

父進(jìn)程死,子進(jìn)程變成孤兒

subreaper : 收割機(jī) (火葬場(chǎng))

圖中的init 就是個(gè)收割機(jī)



## 練習(xí)題

* fork、vfork、Copy-on-Write例子

* life-period例子,實(shí)驗(yàn)體會(huì)托孤

* pthread_create例子,strace它

* 徹底看懂等待隊(duì)列的案例

# 第三部分大綱

調(diào)度器算法

* CPU/IO消耗型進(jìn)程?https://www.cnblogs.com/beMaster/p/5380037.html

多任務(wù)操作系統(tǒng)分為非搶占式多任務(wù)操作系統(tǒng)和搶占式多任務(wù)操作系統(tǒng),現(xiàn)代的操作系統(tǒng)都是搶占式多任務(wù)操作系統(tǒng)。

除了虛擬處理器的機(jī)制外,進(jìn)程控制塊(PCB)也是使得操作系統(tǒng)能夠并發(fā)的關(guān)鍵。因?yàn)樵谶M(jìn)程切換時(shí),進(jìn)程控制塊能夠保存當(dāng)前處理器的上下文,使得該進(jìn)程下次被調(diào)度時(shí),能夠從上次停止的地方繼續(xù)運(yùn)行。

喜歡睡覺(jué)就是io消耗,喜歡干活就是cpu消耗

cpu利用率大概還是由程序本身 (一會(huì)sleep 一會(huì)兒for循環(huán))來(lái)定, 調(diào)度算法是大家都ready的時(shí)候要占用cpu的時(shí)候(誰(shuí)是優(yōu)先的) 一般情況基本就是nice值是0 的普通線程?


RT: runtime?

cpu消耗: 都花費(fèi)在cpu

該類(lèi)進(jìn)程在把時(shí)間都發(fā)在了執(zhí)行代碼上,即在該進(jìn)程執(zhí)行期間,馬不停蹄的使用處理器資源。所以除非被搶占,否則它們通常都一直不停地運(yùn)行,因此從系統(tǒng)響應(yīng)速度考慮,調(diào)度器不應(yīng)該經(jīng)常讓它們運(yùn)行。該類(lèi)進(jìn)程優(yōu)先級(jí)低,時(shí)間邊短。

io消耗 : 都花費(fèi)在io 通常伴隨用戶體驗(yàn)

而優(yōu)先調(diào)度該類(lèi)進(jìn)程是為了讓該類(lèi)進(jìn)程是為了盡可能地消耗其所需要的處理器資源,從而讓該進(jìn)程阻塞住,這樣只要用戶一完成I/O操作,該進(jìn)程就會(huì)被喚醒,從而立刻處理I/O操作,那么在用戶看來(lái),該進(jìn)程響應(yīng)非???,體現(xiàn)出了很好的用戶友好性。

* 吞吐率 vs. 響應(yīng)? :??? 有一定的矛盾, 響應(yīng)和吞吐之間傾向哪一邊,另外一邊肯定會(huì)受到影響

 上下文切換: 例如程序的切換

?  吞吐 : 有用功

  響應(yīng) : 哪怕?tīng)奚渌蝿?wù) ,也要快速響應(yīng)

* SCHED_FIFO、SCHED_RR

* SCHED_NORMAL和CFS

* nice、renice

* chrt

進(jìn)程是資源的封裝,nice是對(duì)于線程的設(shè)置


## 練習(xí)題

* 運(yùn)行2個(gè)高CPU利用率程序,調(diào)整他們的nice

* 用chrt把一個(gè)死循環(huán)程序調(diào)整為SCHED_FIFO

* 閱讀ARM的big.LITTLE架構(gòu)資料,并論述為什么ARM要這么做?

# 第四部分大綱

調(diào)度算法:FIFO? RR NORMAL(CFS通過(guò)分子ptime 來(lái)均衡)

Linux 多核是個(gè)類(lèi)似分布式系統(tǒng)的概念:在每個(gè)核心之間跳動(dòng)

多核是每個(gè)核心勞動(dòng)最高興: 核與核之間 push_rt_task() 和 pull_rt_task() ,拉取的是task_struct


軟中斷負(fù)載均衡 RPS?



* 多核下負(fù)載均衡

* 中斷負(fù)載均衡、RPS軟中斷負(fù)載均衡

* cgroups和CPU資源分群分配

* Android和NEON對(duì)cgroups的采用

* Linux為什么不是硬實(shí)時(shí)的

* preempt-rt對(duì)Linux實(shí)時(shí)性的改造

## 練習(xí)題

* 用time命令跑1個(gè)含有2個(gè)死循環(huán)線程的進(jìn)程

* 用taskset調(diào)整多線程依附的CPU

* 創(chuàng)建和分群CPU的cgroup,調(diào)整權(quán)重和quota

* cyclictest

3. 進(jìn)程要知道哪些內(nèi)存地址上的數(shù)據(jù)在物理內(nèi)存上,哪些不在,還有在物理內(nèi)存上的哪里,需要用頁(yè)表來(lái)記錄

4.頁(yè)表的每一個(gè)表項(xiàng)分兩部分,第一部分記錄此頁(yè)是否在物理內(nèi)存上,第二部分記錄物理內(nèi)存頁(yè)的地址(如果在的話)

5. 當(dāng)進(jìn)程訪問(wèn)某個(gè)虛擬地址,去看頁(yè)表,如果發(fā)現(xiàn)對(duì)應(yīng)的數(shù)據(jù)不在物理內(nèi)存中,則缺頁(yè)異常

6.缺頁(yè)異常的處理過(guò)程,就是把進(jìn)程需要的數(shù)據(jù)從磁盤(pán)上拷貝到物理內(nèi)存中,如果內(nèi)存已經(jīng)滿了,沒(méi)有空地方了,那就找一個(gè)頁(yè)覆蓋,當(dāng)然如果被覆蓋的頁(yè)曾經(jīng)被修改過(guò),需要將此頁(yè)寫(xiě)回磁盤(pán)

————————————————

版權(quán)聲明:本文為CSDN博主「Rotation.」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/fengxinlinux/article/details/52071766

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容