馮諾依曼體系結構+os管理
- 一.馮諾依曼體系結構:
- 1.簡單介紹(準備一)
- 2.場景:
- 1.程序的運行:
- 2.登錄qq發送消息:
- 3.為什么需要內存:
- 1.簡單的引入:
- 2.計算機存儲體系:
- 3.內存的意義:
- 二.操作系統:
- 1.概念引入:
- 2.故事引入:(校園環境做背景)
- 1.管理者和被管理者是不需要見面
- 2.管理者如何獲取被管理者信息?
- 3.數據量較大的時候怎么辦?
- 4.建立學生的數據結構:保存在容器中
- 5.總結:管理的過程就是一個 先描述再組織的一個過程!
- 3.系統調用和庫函數的概念:
- 1.基本概念:
- 2.從上到下需要注意的一些問題:
- 三.進程管理:
- 1.承上啟下:
- 2.基本概念:
- 2-1事實:
- 3.描述進程:PCB :task_struct(linux系統下)
- 4.場景一:加載多個程序到內存:
- 5.task_struct 內容分類:
- 5-1:程序計數器
- 6.組織和查看進程:
- 6-0:在C/C++下獲取當前程序的子父進程號的函數:
- 6-1:查看進程簡單方式:
- 6-2:創建文件:
- 6-3:chdir() 修改當前工作目錄:
- 7.系統調用創建進程——fork
- 7-1:創建子進程:
- 7-2:三個問題:
- 1:給父進程返回子進程的pid 給子進程返回0?
- 2:一個函數只能返回一個值?這個tmp有兩個值?返回了兩次嗎?
- 3:if 和else 的判斷都滿足條件說明 tmp==0 并且大于0?
- 4:一個進程奔潰了影不影響另一個進程?
- 8.進程狀態:
- 8-1:進程排隊:
- 問題一:需要找到結構體的首地址!
- 問題二:隊列:
- 8-2:狀態:
- 8-3:運行:
- 8-4:阻塞:
- 8-5:掛起:
一.馮諾依曼體系結構:
1.簡單介紹(準備一)
常見的輸入設備:磁盤 ,鍵盤,鼠標,攝像頭,麥克風,聲卡,網卡,數位板。
常見的輸出設備:顯示器,聲卡,網卡,打印機。
輸入+輸出:聲卡,網卡。
cpu的功能:進行運算操作+控制cpu的信息流動。
存儲器就是我們的內存:所以的設備都只能和內存打交道。
2.場景:
1.程序的運行:
一個程序的運行是直接加載到內存當中的!
2.登錄qq發送消息:
3.為什么需要內存:
1.簡單的引入:
1.假設我們的體系結構中只有輸入設備,輸出設備,cpu三個主要部分?
2.結論:系統效率大大降低,效率只取決與輸入輸出設備:
2.計算機存儲體系:
1.從上到下速度越來越慢:
2.造價越來越便宜:
3.每級之間效率相差不大:
3.內存的意義:
1.因為cpu直接和輸入輸出設備進行交互太緩慢:運行程序多的時候就只能看輸入和輸出設備:
2.輸入設備的中的可執行程序加載到內存中cpu沒有執行之前程序都可以預先加載到內存中。
3.cpu要進行運算就從內存中去拿到程序。
4.執行結果也可以在內存中進行保存讓輸出設備一個一個的拿出去。
有了上面兩個知識的鋪墊我們就可以解釋內存存在的意義:
1.整個系統的效率就由內存的效率決定了:
2.減少了使用成本并且體系結構使用穩定:
3.綜上所述:整個硬件體系就不存在影響效率的問題了,轉換到了軟件的問題,整個機器的效率就要看操作系統了。
二.操作系統:
1.概念引入:
1.操作系統本質是一個軟件,是第一個軟件。
2.操作系統和底層硬件之間的聯系結構圖。
2.故事引入:(校園環境做背景)
校長—>做決策:
輔導員—>保證管理和決策落地:
學生---->被管理人:
1.管理者和被管理者是不需要見面
1.管理者和被管理者之間是通過管理者獲取到被管理者的信息進行管理本質上是對信息做管理。
2.管理者如何獲取被管理者信息?
1.通過輔導員拿到被管理者的信息!
3.數據量較大的時候怎么辦?
1.當管理者在面對大量的被管理者的時候,這么多的數據如何去處理?把對人的管理變成對數據的管理!
4.建立學生的數據結構:保存在容器中
1.我們知道每一個學生都有相同的屬性不同的內容,每一個學生的屬性內容都是不一樣的。
2.建立學生結構體,把信息保存在容器中,進行對學生數據的管理:
3.對學生的管理就轉移到了對容器的每一個學生信息結構體的增刪查改。
5.總結:管理的過程就是一個 先描述再組織的一個過程!
通過上面的介紹:對于底層硬件的管理就是
1.操作系統(驅動管理)----------->校長。
2.硬件驅動-------->輔導員
3.硬件本身-------->學生
4.總結:對于硬件的管理本質上就是一個先描述再組織的過程。
描述:結構體進行描述 組織:使用數據結構進行組織
5.為什么需要操作系統?
5-1:沒有操作系統需要自己管理和控制硬件:
5-2:對下:更好的控制軟硬件資源:
5-3:對上:提供良好的運行環境:
5-4:穩定,高效,安全。
3.系統調用和庫函數的概念:
1.基本概念:
1.在開發角度,對外會表現為一個整體,但是會暴露自己的部分接口,供上層進行開發使用,這部分由操作系統提供的接口叫做系統調用。
2.系統調用在使用上,功能比較基礎,對用戶的要求相對比較高,所以有心的開發者可以對部分系統進行適度的封裝,從而形成了庫,有了庫,就更加利于用戶的使用和開發者的開發。
3意義:解決系統調用:減少接口使用成本:
4.上面這個概念有可能不是特別容易聽懂:說一個故事!
可以把系統調用接口想象成銀行的取錢的窗口,一個比較會存取錢的人(不需要lib庫可以直接和系統接口交互)來了呢可以直接取號去到窗口辦理業務。那么現在有一位老大爺要來取錢老大爺什么也不會那么這個老大爺就找到了大堂經理(lib庫),大堂經理就幫助老大爺進行拿號到窗口辦理業務取錢的整個過程相當于調用系統接口借助了lib庫的幫助一樣。
2.從上到下需要注意的一些問題:
1.從上到下是不可以發生越級訪問。
2.不可以繞過操作系統
3.操作系統從頭到尾是貫穿的。
三.進程管理:
1.承上啟下:
操作系統是怎么進行進程管理的呢?
非常簡單先描述再組織的一個過程!
2.基本概念:
課本上:程序的一個執行實例,正在執行的的一個程序:
內核上:擔當分配系統資源(cpu時間 , 內存)實體。
上面這些概念不是特別的好可以不看!用網上比較火的說法就是:如說!
2-1事實:
1.我們可以同時啟動多個程序—多個exe加載到內存中:
2.操作系統需要管理多個加載到內存中的程序!
3.操作系統如何管理加載到內存中的程序呢?先描述再組織!
3.描述進程:PCB :task_struct(linux系統下)
task_struct(進程控制塊:進程屬性的合集) 是PCB的一種是linux系統下的描述進程屬性的結構體,它會被裝載到RAM(內存)里并且包含進程的信息。
4.場景一:加載多個程序到內存:
總結:
進程 = 可執行程序+內核PCB對象
進程 = 可執行程序+內核數據結構
5.task_struct 內容分類:
標示符: 描述本進程的唯一標示符,用來區別其他進程。
狀態: 任務狀態,退出代碼,退出信號等。
優先級: 相對于其他進程的優先級。
程序計數器: 程序中即將被執行的下一條指令的地址。
內存指針: 包括程序代碼和進程相關數據的指針,還有和其他進程共享的內存塊的指針
上下文數據: 進程執行時處理器的寄存器中的數據[休學例子,要加圖CPU,寄存器]。
I/O狀態信息: 包括顯示的I/O請求,分配給進程的I/O設備和被進程使用的文件列表。
記賬信息: 可能包括處理器時間總和,使用的時鐘數總和,時間限制,記賬號等。
其他信息
5-1:程序計數器
程序計數器: 程序中即將被執行的下一條指令的地址。
6.組織和查看進程:
1.PCB->task_struct :PCB操作系統規定的名稱!
2.結構體中包含進程的所有屬性:
6-0:在C/C++下獲取當前程序的子父進程號的函數:
#include<unistd.h>
#include<sys/types.h>
1.獲取當前程序的進程:getpid():
2.獲取當前程序的父進程:getppid():
6-1:查看進程簡單方式:
方法一:查看系統文件夾:/proc/ 下的進程信息!
方法二:通過命令進行查詢:
ps ajx | head -1 && ps ajx | grep mybin
ps ajx 查看當前系統的所有進程
方法三:使用腳本進行進程的刷新:
while : ; do ps ajx | head -1 && ps ajx | grep mybin ;sleep 1 ; done
功能:可以進行實時的進程信息觀察:
6-2:創建文件:
1.我們知道在C語言中我們使用fopen()函數打開一個文件進行只寫操作,如果當前路徑下沒有這個文件會創建一個文件用來進行寫入!
2.那么 這個路徑在linux中是以什么進行保存的呢?
3.我們查看了proc中存放的該進程的程序:
cwd(當前工作路徑):/LIMO/proc_learn/
exe(可執行程序的路徑):/LIMO/proc_learn/mybin
4.fopen() 函數可以找到cwd的路徑并且在這個路徑下生成文件!
6-3:chdir() 修改當前工作目錄:
動圖效果:
7.系統調用創建進程——fork
7-1:創建子進程:
使用man fork 查看一下信息!
1.復制當前進程稱為父進程生成一個子進程。
2.fork有兩個返回值!
3.父進程拿到新開辟子進程的pid,子進程拿到pid為0的返回值!
4.子進程的意義,我們想要生成的子進程去給我們做事情!
44 int main()45 {46 int n1=5;47 while(n1--)48 {49 printf("當前進程:%d 當前父進程: %d\n",getpid(),getppid());50 }51 52 pid_t tmp = fork();53 printf("程序pid: %d",getpid());54 55 while(1)56 {57 if(tmp == 0)58 {59 60 printf("當前進程是子進程的進程號:%d 當前父進程: %d\n",getpid(),g etppid());61 }62 else63 {64 65 printf("當前進程是父進程的進程號:%d 當前父進程: %d\n",getpid(),g etppid());66 }67 sleep(1);68 }69 return 0;70 }
//觀察一下動圖效果:
7-2:三個問題:
1:給父進程返回子進程的pid 給子進程返回0?
父進程:子進程 = 1:n 一個父進程有可能有多個子進程,所以想要父進程可以確定的找到某一個子進程就需要返回子進程的pid 。對于子進程來說父進程只有一個所以找到父進程是非常容易的所以返回0;
2:一個函數只能返回一個值?這個tmp有兩個值?返回了兩次嗎?
fork()函數的實現:
子父進程共享變量,在return的時候發生寫時拷貝變量名是相同的,地址不相同,進程號不相同,拷貝使用不同的內存空間!在linux下可以使用同一個變量名表示不同的內存!
3:if 和else 的判斷都滿足條件說明 tmp==0 并且大于0?
這個問題需要一些后面的知識以后再說!
4:一個進程奔潰了影不影響另一個進程?
命令: kill -9 進程號 :單獨殺死一個進程!
動圖效果:
8.進程狀態:
8-1:進程排隊:
1.進程具有這樣的連接狀態,只要進程的task_struct 進行這樣的排隊。直接連在這個地方。我們只要有這個節點就可以找到這個鏈表,就可以鏈入全局雙鏈表或者鏈入隊列!
問題一:需要找到結構體的首地址!
找到了task_struct 的首地址就可以對對象數據進行任意的訪問!
在全局還是任何隊列消息非常容易找到!
問題二:隊列:
1.進程·不是一直在運行的(有可能在等待軟硬件的資源)進程放在cpu中也不是一直都會運行的!
2.只要是進程排隊就是pcb排隊!
3.如何排隊就是通過struct listnode 結構體保存信息進行排隊!
8-2:狀態:
運行,阻塞,掛起:都是一個狀態這些狀態都有對應的隊列!
進程的一個狀態就是:進程在狀態隊列進行的一個排隊!把對應的struct listnode 加到保存的對應的位置!
這些狀態是如何進行保存的呢?
struct task_struct {
int status;
……………………
}
#define New 1
#define Ready 2
#define runing 3
#define block 4
8-3:運行:
1.一個cpu一個運行隊列:
2.struct runqueue{
int num;
task_struct* q ;//保存了pcb中的struct listnode 這個對象的地址!
}
3.已經加載到運行時隊列,表示的意思是我已經準備好被隨時的進行調度了!
8-4:阻塞:
1.這個時候就進入了阻塞狀態。
2.為什么產生?需要獲取軟硬件的資源所以進入阻塞狀態!
3.阻塞狀態是有一個阻塞隊列的和運行隊列是一個作用!
4.阻塞隊列(等待隊列)是由對應的的硬件提供的!
5.進程進入等待隊列是把進程鏈入底層設備的一個過程!
6.對于設備來說輸入數據完成就是表示硬件已經就緒?這個狀態只有操作系統最清楚!操作系統在這個地方就進行了管理!
總結:進程在等待軟硬件資源的時候,如果沒有準備好我們的task_struct
1.將自己設置為阻塞狀態,進入對應軟硬件提供的等待隊列。
2.把自己的pcb鏈入對應軟硬件提供的等待隊列。
3.狀態的改變,導致pcb會被os變遷到不同的隊列中!
8-5:掛起:
1.進入掛起的前提是:資源已經非常吃緊了!
2.這個掛起也叫做阻塞掛起!
3.在阻塞狀態下把進程相關的代碼和數據轉換到外設中節省內存空間。
4.意義:我們可以慢一些但是不可以為了快產生資源吃緊導致有可能最后操作系統就掛掉了!