日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

【操作系统】虚拟化CPU、Memory,共享文件

發布時間:2023/11/30 windows 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【操作系统】虚拟化CPU、Memory,共享文件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

幾個概念

  • CPU、虛擬CPU
  • 進程
  • 內存、虛擬地址空間
    • 物理的CPU被OS虛擬成了多個虛擬的CPU,這些虛擬CPU分別運行各自的程序,這些正在運行的程序被稱為進程。
    • 物理內存被OS虛擬成了多個虛擬地址空間,每個進程都有獨立的、自己的地址空間,程序的指令和數據都在地址空間中
    • 磁盤被OS虛擬化為文件系統,文件是被多個程序共享的,它并不是多個虛擬的磁盤,不過也不是無條件共享,涉及到例如互斥共享等多個問題,以后再談。

    1 Virtualizing the CPU

    我們在Linux系統上運行C語言程序,體會一下虛擬化的意義。

    Windows對多用戶的支持不是很好,相關的系統API可能也沒有,推薦適用Linux或Unix系統。

    // cpu.c

    #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <assert.h>int main(int argc,int *argv[]){if(argc != 2){fprintf(stderr,"usage:cpu <string>\n");exit(1);}char *str = argv[1];for(int i = 0;i < 4;i++){sleep(1);printf("%s\n",str);}return 0; }

    這個程序很容易,需要運行的時候輸入一個參數,比如一個字符,值得解釋的是sleep(1),也就是讓程序暫停1秒,這非常重要,這意味著物理的CPU在這1s時間可以不用執行該進程,轉而執行其他進程。

    注意,虛擬后的CPU,最終仍然要在真實物理CPU來執行,要想讓每個進程都得到執行,那就應該以合理的方式讓他們切換執行

    我們先運行一個進程試試看,輸入命令./cpu A1:

    打印了4個A1,并且是每隔1s打印一個,這與我們的預期相符。

    接下來,我們同時運行多個進程試試看,輸入命令./cpu A1 & ./cpu B2 & ./cpu C3 &

    按照直觀的理解,不應該是

    A1
    A1
    A1
    A1
    B2
    B2
    B2
    B2
    C3
    C3
    C3
    C3

    不應該是這樣嗎?但是看起來這3個進程并不是順序執行的,而是并發執行的,也就是它們趁著其他進程在sleep的時候,搶占了CPU去執行自己了(注意,我們假設計算機只有1個CPU,而且是單核的)。

    這樣一來,就出現了圖中的亂序了。

    我們也能充分的感受到,不要讓物理CPU閑著的重要理念,同時我們也能想象到,多個進程同時執行,就會涉及到更多的問題,如果是之前的順序執行,我們只需要進程1執行,其他等待–>進程1執行完成,進程2執行,其他等待–>進程2執行完成,進程3執行–>進程3執行完成。

    也就是說,我們只需要等著一個程序執行完,再執行其他程序,這樣很簡單,但是效率非常低,比如,如果正在執行的程序不使用CPU,去“sleep”了,或者去找I/O設備“玩”了,CPU就只能呆著,其他程序也不能進來執行,CPU利用率很低


    為了避免這種問題,現代OS都采用了類似多道批處理的技術,正在執行的程序不執行時,其他程序會進入CPU執行,而不會允許CPU空閑,要榨干CPU!

    就如上面的程序,當一個進程sleep的時候,其他進程就會進入CPU執行,但是,具體如何執行,取決于OS的調度程序,取決于OS設計的策略,所以目前我們還不能得知它具體是如何運作的(也許你可以查看Linux內核,不過如果你有此能力,就不會看見這篇文章了)。

    1.1 補充:實例中的C語言知識

    以下請自學

    1.1.1 main函數參數,argc和argv

    1.1.2 fprintf()

    1.1.3 sleep()

    2 Virtualizing Memory

    我們先上代碼

    // mem.c

    #include <unistd.h> #include <stdio.h> #include <stdlib.h>int main(int argc,int *argv[]){int *p = malloc(sizeof(int)); // assert(p != NULL);printf("(%d) memory address of p: %08x\n",getpid(),(unsigned)p);*p = 0;for(int i = 0;i < 4;i++){sleep(1);*p = *p + 1;printf("(%d) p: %d\n",getpid(),*p);}return 0; }

    運行程序./mem

    運行多個進程:./mem & ./mem & ./mem &

    這里,我們依然能夠看到的是虛擬化CPU,不過,虛擬化內存在哪里呢?目前還看不出來,因為Linux默認是啟動地址空間隨機化的,這樣會讓系統更安全,不易受到攻擊,不過為了展現虛擬化內存,我們應該關掉它。

    輸入命令sysctl -w kernel.randomize_va_space=0,再輸入./mem & ./mem & ./mem &


    我們可以看到,三個進程居然地址完全一樣!按理說,1個地址只能對應1個進程,所以,你就能體會到虛擬地址空間的含義了,這并不是真實的物理地址,它會通過某種機制,映射到真實物理地址去。

    3 Sharing Disk Information

    還記得我們剛才的兩個程序嗎?他們同時啟動了多個進程,并且,這幾個進程是同一個程序,也就是說,同一個存儲在磁盤的文件,被多次讀取到了內存,這也就意味著,磁盤信息是可以被同時多次讀取的,我們也可以說,這幾個進程共享了一個磁盤文件


    思考:為什么內存和CPU要虛擬化為多個,而磁盤卻是共享的?

    • 進程是運行中的程序,它是“活的
    • 程序是靜止在磁盤中的指令和數據,它是“死的”。

    對于正在運行的進程來說,我們需要為其獨立地分配一整套生態系統,保證它正常執行,并且每個程序運行時候的結果可能不同,所以,就虛擬地提供了CPU和地址空間,讓它們是相互獨立的;而對于靜止的指令和數據來說,完全沒有必要虛擬成多份,那反而是浪費空間,當然這是針對讀取而言,寫入還需要視情況,不過整體來說,讀取信息是及其場景的,將磁盤設為共享也是合理的。


    另外要談的是,磁盤文件必須通過軟件和硬件協作的方式,使其持久地保存,而不是很快就消失了,或者被其他數據覆蓋掉了。

    4 Concurrency

    虛擬化對應的是進程,而并發對應的不僅僅是OS的進程,在OS之上的應用程序,也存在并發的問題,他就是多線程編程;虛擬化讓一個CPU能并發地執行多個進程,而一個進程,也能并發地執行多個線程。

    你一定知道多線程編程,是的,就是那個,我們現在重新審視一下它。

    // threads.c

    #include <stdio.h> #include <stdlib.h> #include <pthread.h>volatile int counter = 0; int loops;void *worker(void *arg) {int i;for (i = 0; i < loops; i++) {counter++;}return NULL; }int main(int argc, char *argv[]) {if (argc != 2) {fprintf(stderr, "usage: threads <value>\n");exit(1);}loops = atoi(argv[1]);pthread_t p1, p2;printf("Initial value : %d\n", counter);pthread_create(&p1, NULL, worker, NULL);pthread_create(&p2, NULL, worker, NULL);pthread_join(p1, NULL);pthread_join(p2, NULL);printf("Final value : %d\n", counter);return 0; }

    我們進行編譯gcc threads.c -o threads -lpthread,注意,<pthread.h>不是Linux默認的庫,編譯鏈接需要加上參數-lpthread,也就是需要鏈接額外的Import Library:libpthread.a。

    我們進行測試:

    對于輸入的參數N,輸出結果應該是2N(先知道事實,看不懂多線程程序沒有關系),但是最后兩個,當參數足夠大,比如5億的時候,結果就詭異了

    這是由于計數器的值的更新不是原子操作,他需要:

    • 內存–>寄存器
    • 寄存器遞增
    • 寄存器–>內存

    3個步驟,但是,這幾個步驟可能被其他操作打斷,這就造成了結果的詭異。關于原子操作以后再說。

    5 小結

    我們談了幾件事兒

    • 物理CPU – 虛擬化CPU – 多進程并發
    • 物理內存 – 虛擬地址空間 – 進程獨立地址空間
    • 磁盤(持久性) – 文件系統 – 共享磁盤信息
    • OS之上的并發:單個進程中的多線程

    版權聲明

    本文是讀書筆記,來自于書籍《Operating System:Three Easy Pieces》

    總結

    以上是生活随笔為你收集整理的【操作系统】虚拟化CPU、Memory,共享文件的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。