成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

被神話的Linux, 一文帶你看清Linux在多核可擴展性設(shè)計上的不足

系統(tǒng) Linux
說起微內(nèi)核,其性能往往因為IPC飽受詬病。然而除了這個顯而易見的 “缺陷” ,其它方面貌似被關(guān)注的很少。因此我寫點稍微不同的。

 我其實并不想討論微內(nèi)核的概念,也并不擅長去闡述概念,這是百科全書的事,但無奈最近由于鴻蒙的發(fā)布導致這個話題過火,也就經(jīng)不住誘惑,加上我又一直比較喜歡操作系統(tǒng)這個話題,就來個老生常談吧。

說起微內(nèi)核,其性能往往因為IPC飽受詬病。然而除了這個顯而易見的 “缺陷” ,其它方面貌似被關(guān)注的很少。因此我寫點稍微不同的。

微內(nèi)核的性能 “缺陷” 我假設(shè)是高開銷的IPC引起的(實際上也真是),那么,我接下來便繼續(xù)假設(shè)這個IPC性能是可以優(yōu)化的,并且它已經(jīng)被優(yōu)化(即便不做任何事,隨著硬件技術(shù)的發(fā)展,所謂的歷史缺點往往也將逐漸弱化...)。我不公道地回避了核心問題,這并不是很道德,但為了下面的行文順利,我不得不這么做。

很多人之所以并不看好微內(nèi)核,很大程度上是因為它和Linux內(nèi)核是如此不同,人們認為不同于Linux內(nèi)核的操作系統(tǒng)內(nèi)核都有這樣那樣的缺陷,這是因為Linux內(nèi)核給我們洗了腦。

Linux內(nèi)核的設(shè)計固化了人們對操作系統(tǒng)內(nèi)核的理解上的觀念 ,以至于 Linux內(nèi)核做什么都是對的,反Linux的大概率是錯的。 Linux內(nèi)核就一定正確嗎?

在我看來,Linux內(nèi)核只是在恰當?shù)臅r間出現(xiàn)的一個恰好能跑的內(nèi)核,并且恰好它是開源的,讓人們可以第一次內(nèi)窺一個操作系統(tǒng)內(nèi)核的全貌罷了,這并不意味著它就一定是正確的。相反,它很可能是錯誤的。【 20世紀90年代,Windows NT系統(tǒng)初始,但很難看到它的內(nèi)在,《windows internal》風靡一時;UNIX陷入糾紛,GNU呼之卻不出,此時Linux內(nèi)核滿足了人們一切的好奇心,于是先入為主,讓人們覺的操作系統(tǒng)就應該是這個樣子,并且在大多數(shù)人看來,這是它唯一的相貌。 】

本文主要說 內(nèi)核的可擴展性 。

先潑一盆冷水,Linux內(nèi)核在這方面做得并非已經(jīng)爐火純青。

誠然,近十幾年來Linux內(nèi)核從2.6發(fā)展到5.3,一直在SMP多核擴展方面精益求精,但是說實話架構(gòu)上并沒有什么根本性的調(diào)整,要說比較大的調(diào)整,當屬:

  •  $O(1)$調(diào)度算法。
  •  SMP處理器域負載均衡算法。
  •  percpu數(shù)據(jù)結(jié)構(gòu)。
  •  數(shù)據(jù)結(jié)構(gòu)拆鎖。

都是一些細節(jié),沒有什么讓人哇塞的東西,還有更細節(jié)的cache刷新的管理,這種第二天不用就忘記的東西,引多少人競折腰。

這不禁讓人想起在交換式以太網(wǎng)出現(xiàn)之前,人們不斷優(yōu)化CSMA/CD算法的過程,同樣沒有讓人哇塞,直到交換機的出現(xiàn),讓人眼前一亮,CSMA/CD隨之幾乎被完全廢棄,因為它不是 正確 的東西。

交換機之所以 正確 的核心在于 仲裁。

當一個共享資源每次只能容納一個實體占用訪問時,我們稱該資源為 “必須串行訪問的共享資源” ,當有多個實體均意欲訪問這種資源時,one by one是必然的,one by one的方案有兩種:

哪個好?說說看。

爭搶必會產(chǎn)生沖突,沖突便耽誤整體通過的時間,你會選哪個?

現(xiàn)在,我們暫時忘掉諸如宏內(nèi)核,微內(nèi)核,進程隔離,進程切換,cache刷新,IPC等概念,這些概念對于我們理解事情的本質(zhì)毫無幫助,相反,它們會阻礙我們建立新的認知。比如,無論你覺得微內(nèi)核多么好,總有人跳出來說IPC是微內(nèi)核的瓶頸,當你提出一個類似頁表項交換等優(yōu)化后,又會有人說進程切換刷cache,寄存器上下文save/restore的開銷也不小,然后你可能知道點 帶有進程PID鍵值的cache方案 ,吧啦吧啦,最后一個show me the code 讓你無言以對,一來二去,還沒有認識全貌,便已經(jīng)陷入了細節(jié)。

所以,把這些忘掉,來看一個觀點:

  •  對待必須串行訪問的共享資源,正確的做法是引入一個仲裁者排隊調(diào)度訪問者,而不是任由訪問者們?nèi)ゲl(fā)爭鎖!

所謂 操作系統(tǒng) 這個概念,本來就是莫須有的,你可以隨便叫它什么,早期它叫 監(jiān)視器 ,現(xiàn)在我們姑且就叫它操作系統(tǒng)吧,但這并不意味著這個概念有多么神奇。

操作系統(tǒng)本就是用來協(xié)調(diào)多個進程(這也是個抽象后的概念,你叫它任務也可以,無所謂)對底層共享資源的 多對一訪問 的,最典型的資源恐怕就是CPU資源了,而幾乎所有人都知道,CPU資源是需要調(diào)度使用的,于是任務調(diào)度一直都是一個熱門話題。

你看, CPU就不是所有任務并發(fā)爭搶使用的,而是調(diào)度器讓誰用誰才能用 。調(diào)度,或者說仲裁,這是操作系統(tǒng)的精髓。

那么對于系統(tǒng)中共享的文件,socket,對于各種表比如路由表等資源,憑什么要用并發(fā)爭搶的方式去使用?!所有的共享資源,都應該是被調(diào)度使用的,就像CPU資源一樣。

如果我們循著操作系統(tǒng)理應實現(xiàn)的最本質(zhì)的功能去思考,而不是以Linux作為先入為主的標準去思考,會發(fā)現(xiàn)Linux內(nèi)核處理并發(fā)明顯是一種錯誤的方式!

Linux內(nèi)核大量使用了自旋鎖,這明顯是從單核向SMP進化時最最最簡單的方案,即 只要保證不出問題的方案!

也確實如此,單核上的自旋鎖并不能如其字面表達的那樣 自旋 , 在單核場景下,Linux的自旋鎖實現(xiàn)僅僅是 禁用了搶占 。因為,這樣即可保證 不出問題 。

但到了必須要支持SMP的時候,簡單的禁用搶占已經(jīng)無法保證不出問題,所以 待在原地自旋等待持鎖者離開 便成了最顯而易見的方案。自旋鎖就這樣一直用到了現(xiàn)在。一直到今天,自旋鎖在不斷被優(yōu)化,然而無論怎么優(yōu)化,它始終都是一個不合時宜的自旋鎖。

可見,Linux內(nèi)核一開始就不是為SMP設(shè)計的,因此其并發(fā)模式是錯誤的,至少不是合適的。

有破就要有立,我下面將用一套用戶態(tài)的代碼來模擬 無仲裁的宏內(nèi)核 以及 有仲裁的微內(nèi)核 分別是如何對待共享資源訪問的。代碼比較簡單,所以我就沒加入太多的注釋。

以下的代碼模擬宏內(nèi)核中訪問共享資源時的自旋鎖并發(fā)爭搶模式:

  1. #include <pthread.h>  
  2. #include <signal.h>  
  3. #include <stdio.h>  
  4. #include <unistd.h>  
  5. #include <stdlib.h> 
  6. #include <errno.h>  
  7. #include <sys/time.h>  
  8. static int count = 0 
  9. static int curr = 0 
  10. static pthread_spinlock_t spin;  
  11. long long end, start;  
  12. int timer_start = 0 
  13. int timer = 0 
  14. long long gettime()  
  15.  
  16.     struct timeb t;  
  17.     ftime(&t);  
  18.     return 1000 * t.time + t.millitm;  
  19.  
  20. void print_result()  
  21.  
  22.     printf("%d\n", curr);  
  23.     exit(0);  
  24.  
  25. struct node {  
  26.     struct node *next;  
  27.     void *data;  
  28. };  
  29. void do_task() 
  30.  
  31.     int i = 0j = 2k = 0 
  32.     // 為了更加公平的對比,既然模擬微內(nèi)核的代碼使用了內(nèi)存分配,這里也fake一個。  
  33.     struct node *tsk = (struct node*) malloc(sizeof(struct node));  
  34.     pthread_spin_lock(&spin); // 鎖定整個訪問計算區(qū)間  
  35.     if (timer && timer_start == 0) {   
  36.         struct itimerval tick = {0};  
  37.         timer_start = 1 
  38.         signal(SIGALRM, print_result);  
  39.         tick.it_value.tv_sec = 10 
  40.         tick.it_value.tv_usec = 0 
  41.         setitimer(ITIMER_REAL, &tick, NULL);  
  42.     }  
  43.     if (!timer && curr == count) {  
  44.         end = gettime();  
  45.         printf("%lld\n", end - start);  
  46.         exit(0);  
  47.     }  
  48.     curr ++;  
  49.     for (i = 0; i < 0xff; i++) { // 做一些稍微耗時的計算,模擬類似socket操作。強度可以調(diào)整,比如0xff->0xffff,CPU比較猛比較多的機器上做測試,將其調(diào)強些,否則隊列開銷會淹沒模擬任務的開銷。 
  50.          k += i/j;  
  51.     }  
  52.     pthread_spin_unlock(&spin);  
  53.     free(tsk);  
  54.  
  55. void* func(void *arg)  
  56.  
  57.     while (1) {  
  58.         do_task();  
  59.     }  
  60.  
  61. int main(int argc, char **argv)  
  62.  
  63.     int err, i;  
  64.     int tcnt;  
  65.     pthread_t tid;  
  66.     count = atoi(argv[1]);  
  67.     tcnt = atoi(argv[2]);  
  68.     if (argc == 4) {  
  69.         timer = 1 
  70.     }  
  71.     pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE);  
  72.     start = gettime();  
  73.     // 創(chuàng)建工作線程  
  74.     for (i = 0; i < tcnt; i++) {  
  75.         err = pthread_create(&tid, NULL, func, NULL);  
  76.         if (err != 0) {  
  77.             exit(1);  
  78.         }  
  79.     }  
  80.     sleep(3600);  
  81.     return 0;  

相對的,微內(nèi)核采用將請求通過IPC發(fā)送到專門的服務進程,模擬代碼如下:   

  1. #include <pthread.h>  
  2.     #include <signal.h>  
  3.     #include <stdio.h>  
  4.     #include <unistd.h>  
  5.     #include <stdlib.h>  
  6.     #include <errno.h>  
  7.     #include <sys/time.h> 
  8.     static int count = 0 
  9.     static int curr = 0 
  10.     long long end, start; 
  11.     int timer = 0
  12.     int timer_start = 0 
  13.     static int total = 0 
  14.     long long gettime()  
  15.     {  
  16.         struct timeb t;  
  17.         ftime(&t);  
  18.         return 1000 * t.time + t.millitm;  
  19.     }  
  20.     struct node {  
  21.         struct node *next;  
  22.         void *data;  
  23.     };  
  24.     void print_result()  
  25.     {  
  26.         printf("%d\n", total);  
  27.         exit(0);  
  28.     }  
  29.     struct node *head = NULL 
  30.     struct node *current = NULL 
  31.     void insert(struct node *node)  
  32.     {  
  33.         node->data = NULL 
  34.         node->next = head 
  35.         head = node 
  36.     }  
  37.     struct node* delete()  
  38.     {  
  39.         struct node *tempLink = head 
  40.         headhead = head->next;  
  41.         return tempLink;  
  42.     }  
  43.     int empty()  
  44.     {  
  45.         return head == NULL;  
  46.     }  
  47.     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER 
  48.     static pthread_spinlock_t spin;  
  49.     int add_task()  
  50.     {  
  51.         struct node *tsk = (struct node*) malloc(sizeof(struct node));  
  52.         pthread_spin_lock(&spin);  
  53.         if (timer || curr < count) {  
  54.             curr ++;  
  55.             insert(tsk);  
  56.         }  
  57.         pthread_spin_unlock(&spin);  
  58.         return curr;  
  59.     }  
  60.     // 強度可以調(diào)整,比如0xff->0xffff,CPU比較猛比較多的機器上做測試,將其調(diào)強些,否則隊列開銷會淹沒模擬任務的開銷。  
  61.     void do_task()  
  62.     {   
  63.         int i = 0j = 2k = 0 
  64.         for (i = 0; i < 0xff; i++) {  
  65.             k += i/j;  
  66.         }  
  67.     } 
  68.     void* func(void *arg)  
  69.     {  
  70.         int ret;  
  71.         while (1) {  
  72.             ret = add_task();  
  73.             if (!timer && ret == count) {  
  74.                 break;  
  75.             }  
  76.         } 
  77.     }  
  78.     void* server_func(void *arg)  
  79.     {  
  80.         while (timer || total != count) {  
  81.             struct node *tsk;  
  82.             pthread_spin_lock(&spin);  
  83.             if (empty()) {  
  84.                 pthread_spin_unlock(&spin);  
  85.                 continue;  
  86.             }  
  87.             if (timer && timer_start == 0) {  
  88.                 struct itimerval tick = {0};  
  89.                 timer_start = 1
  90.                 signal(SIGALRM, print_result);  
  91.                 tick.it_value.tv_sec = 10 
  92.                 tick.it_value.tv_usec = 0
  93.                 setitimer(ITIMER_REAL, &tick, NULL);  
  94.             }  
  95.             tsk = delete();  
  96.             pthread_spin_unlock(&spin);  
  97.             do_task();  
  98.             free(tsk);  
  99.             total++;  
  100.         }  
  101.         end = gettime();  
  102.         printf("%lld   %d\n", end - start, total);  
  103.         exit(0);  
  104.     }  
  105.     int main(int argc, char **argv)  
  106.     {  
  107.         int err, i;  
  108.         int tcnt;  
  109.         pthread_t tid, stid;  
  110.         count = atoi(argv[1]);  
  111.         tcnt = atoi(argv[2]);  
  112.         if (argc == 4) {  
  113.             timer = 1 
  114.         } 
  115.         pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE);  
  116.         // 創(chuàng)建服務線程  
  117.         err = pthread_create(&stid, NULL, server_func, NULL);  
  118.         if (err != 0) {  
  119.             exit(1);  
  120.         }  
  121.         start = gettime();  
  122.         // 創(chuàng)建工作線程  
  123.         for (i = 0; i < tcnt; i++) {  
  124.             err = pthread_create(&tid, NULL, func, NULL);  
  125.             if (err != 0) {  
  126.                 exit(1);  
  127.             }  
  128.         }  
  129.         sleep(3600);  
  130.         return 0;  
  131.     } 

我們對比一下執(zhí)行同樣多的任務,在不同的線程數(shù)的約束下,兩種模式的時間開銷對比圖:

我們看到,在模擬微內(nèi)核的代碼中,用多線程執(zhí)行并行訪問共享數(shù)據(jù)curr時,開銷不會隨著線程數(shù)量的變化而變化,而模擬宏內(nèi)核的代碼中,總時間隨著線程數(shù)的增加而線性增加,顯然,這部分開銷是自旋鎖的開銷。當今流行的CPU cache結(jié)構(gòu)已經(jīng)排隊自旋鎖的開銷符合這種線性增長。

那么為什么微內(nèi)核的模擬代碼中的鎖開銷沒有隨著線程數(shù)量的增加而增加呢?

因為在類似宏內(nèi)核的同步任務中,由于并發(fā)上下文的相互隔離,整個任務必須被一個鎖保護,比如 Linux內(nèi)核的tcp_v4_rcv 里面的:       

  1. bh_lock_sock_nested(sk);  
  2.        // 這部分耗時時間不確定,因此CPU空轉(zhuǎn)率不確定,低效,浪費!  
  3.        ret = 0
  4.        if (!sock_owned_by_user(sk)) {  
  5.            if (!tcp_prequeue(sk, skb)) 
  6.                ret = tcp_v4_do_rcv(sk, skb);  
  7.        } else if (unlikely(sk_add_backlog(sk, skb,  
  8.                           sk->sk_rcvbuf + sk->sk_sndbuf))) {  
  9.            bh_unlock_sock(sk);  
  10.            NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);  
  11.            goto discard_and_relse;  
  12.        }  
  13.        bh_unlock_sock(sk); 

然而,在微內(nèi)核的代碼中,類似上面的任務被打包統(tǒng)一交給單獨的服務線程去 調(diào)度執(zhí)行 了,大大減少了鎖區(qū)里的延時。

宏內(nèi)核的隔離上下文并發(fā)搶鎖場景需要鎖整個任務,造成搶鎖開銷巨大,而微內(nèi)核只要鎖任務隊列的入隊出隊操作即可,這部分開銷和具體任務無關(guān),完全可預期的開銷。

接下來讓我們對比一下執(zhí)行同樣的任務,在不同CPU數(shù)量的約束下,兩種模式的時間開銷對比圖:

可見,隨著CPU數(shù)量的增加,模擬宏內(nèi)核的代碼鎖開銷大致在線性增加,而模擬微內(nèi)核的代碼,鎖開銷雖然也有所增加,但顯然并不明顯。

為什么會這樣?請看下面宏內(nèi)核和微內(nèi)核的對比圖,先看宏內(nèi)核:

再看微內(nèi)核:

這顯然是一種更加 現(xiàn)代 的方式,不光是減小了鎖的開銷提高了性能,更重要的是大大減少了CPU的空轉(zhuǎn),提高了CPU的利用率。

我們先看一下模擬宏內(nèi)核的代碼在執(zhí)行10秒時的CPU利用率:

觀察下熱點,可以猜測就是spinlock:

顯然,CPU利用率那么高,并非真的在執(zhí)行有用的task,而是在spin空轉(zhuǎn)。

我們再看下模擬微內(nèi)核的代碼在同樣情況下的表現(xiàn):

看下熱點:

顯然,仍然有個spinlock的熱點,但顯然降低了很多。在更高執(zhí)行效率的保證下,CPU并沒有那么高,剩余的空閑時間可以再去執(zhí)行更多有意義的工作進程。

本文只是展示一個定性的效果,實際中,微內(nèi)核服務進程的任務隊列的管理效率會更高。甚至可以硬件實現(xiàn)。【參見交換機背板的交換網(wǎng)絡實現(xiàn)。】

說了這么多,也許有人會說, NO,你這兩個比對的case不嚴謹,你只模擬了訪問共享的數(shù)據(jù),如果是真的可并行執(zhí)行的代碼用微內(nèi)核的方案豈不是要降低性能嗎?平白自廢武功,將并行改成串行!確實如此,但是 內(nèi)核本身就是共享的。 操作系統(tǒng)本身就是協(xié)調(diào)用戶進程對底層共享資源訪問的。

所以真并行需要程序員自己來 設(shè)計可并行的應用程序。

內(nèi)核本身就是共享的。共享資源的多線程訪問就應該嚴格串行化,并發(fā)爭鎖是一種最無序的方式,而最有效的方式則是統(tǒng)一仲裁調(diào)度。

在我們?nèi)粘I钪校覀冿@然能看到和理解為什么排隊上車比擁擠著上車更加高效。在計算機系統(tǒng)領(lǐng)域,同樣的事情我們也見于交換式以太網(wǎng)和PCIe,相比CSMA/CD的共享式以太網(wǎng),交換機就是一個仲裁調(diào)度器,PCIe的消息hub也是扮演著同樣的角色。

其實,即便是宏內(nèi)核,在訪問共享資源時,也并不是全都是并發(fā)爭鎖的方式,對于敏感度比較高的資源,比如時延要求很高的硬件資源,系統(tǒng)底層也是仲裁調(diào)度實現(xiàn)的,比如網(wǎng)卡上層發(fā)包的隊列調(diào)度程序,此外對于磁盤IO也有對應的磁盤調(diào)度程序。

然而對于宏內(nèi)核,更加上層的邏輯資源,比如VFS文件對象,socket對象,各種隊列等等卻沒有采用仲裁調(diào)度的方式去訪問,當它們由多個線程并發(fā)訪問時,采用了令人遺憾的并發(fā)爭鎖模式,這也是不得已而為之,因為沒有哪個實體可以完成仲裁,畢竟訪問它們的上下文是隔離的。

    來個插敘。當進行Linux系統(tǒng)調(diào)優(yōu)時,瞄準這些方面相關(guān)的熱點基本就夠了。大量熱點問題都是這種引起的,open/close同一個文件,進程上下文和軟中斷同時操作同一個socket,收包時多個CPU上的軟中斷上下文將包排入同一個隊列,諸如此類。\如果你不準備去調(diào)優(yōu)Linux,或許你已經(jīng)知道Linux內(nèi)核在SMP環(huán)境下的根本缺陷,調(diào)它作甚。多看看外面的世界,搞不好比你眼前唯一的那個要好。

當我們評價傳統(tǒng)UNIX以及Linux這種操作系統(tǒng)內(nèi)核時,應該更多的去看它們?nèi)笔Я耸裁矗皇且晃兜挠X得它們就是對的。【你認為它是的,可能僅僅因為它是你第一個見到并且唯一見過的】

如果非要說下概念,那就有必要說說 現(xiàn)代操作系統(tǒng) 的虛擬機抽象。

對于我們經(jīng)常說的 現(xiàn)代操作系統(tǒng) 而言,按照最初的馮諾伊曼結(jié)構(gòu),只有 “CPU和內(nèi)存” 在 多處理(包括所有的多進程,多線程等機制) 機制中被抽象了出來,而對于文件系統(tǒng),網(wǎng)絡協(xié)議棧等等卻沒有進行多處理抽象。換句話說,現(xiàn)代操作系統(tǒng)為進程提供了 獨占的虛擬機抽象 ,該虛擬機僅僅包括CPU和內(nèi)存:

  •  時間片調(diào)度讓進程認為自己獨占了CPU。
  •  虛擬內(nèi)存讓進程認為自己獨享了內(nèi)存。
  •  再無其它虛擬機抽象。

在進程使用這些抽象資源時,現(xiàn)代操作系統(tǒng)無疑采用了仲裁調(diào)度機制:

  •  操作系統(tǒng)提供任務調(diào)度器仲裁CPU的分時復用(典型的是多級反饋優(yōu)先級隊列算法),為進程/線程統(tǒng)一分配物理CPU的時間片資源。
  •  操作系統(tǒng)提供內(nèi)存分配算法仲裁物理內(nèi)存空間的分配(典型的是伙伴系統(tǒng)算法),為進程/線程統(tǒng)一分配物理內(nèi)存映射給虛擬內(nèi)存。

顯然,正如本文開頭說過的,操作系統(tǒng)并未任由進程們?nèi)ゲl(fā)爭搶CPU和內(nèi)存資源,然而對于其它幾乎所有資源,操作系統(tǒng)并未做任何嚴格的規(guī)定。操作系統(tǒng)以兩種態(tài)度對待它們:

  1.  認為其它資源并非操作系統(tǒng)核心的一部分,于是微內(nèi)核,用戶態(tài)驅(qū)動等等就形成了概念。
  2.  認為其它底層的資源也是操作系統(tǒng)核心的一部分,這就是宏內(nèi)核比如Linux的態(tài)度。

態(tài)度如何,這并不重要,宏內(nèi)核,微內(nèi)核,用戶態(tài),內(nèi)核態(tài),這些也只是概念而已,沒有什么大不了的。關(guān)鍵的問題乃是:

  •  如何協(xié)調(diào)共享資源的分配。 或空間資源,或時間資源的或并發(fā)爭鎖,或仲裁調(diào)度的方式分配。

無疑,最大的爭議就在CPU/內(nèi)存之外如何協(xié)調(diào)非進程虛擬化的文件系統(tǒng)的訪問和網(wǎng)絡協(xié)議棧的訪問。但無論它們倆的哪一個,目前無論是宏內(nèi)核還是微內(nèi)核都有非常非常棒的方案。遺憾的是,這些很棒的方案都不是Linux內(nèi)核所采用的方案。

哦,對了Nginx便采取了類似微內(nèi)核,交換機,PCIe的方法,Apache卻不是。還有很多別的例子,不再一一贅述,只是想說一點,操作系統(tǒng)領(lǐng)域,核心的東西都是大象無形的,而不是那些形形色色的概念。

摘錄一段王垠聊微內(nèi)核時的一段話:

跟有些人聊操作系統(tǒng)是件鬧心的事,因為我往往會拋棄一些術(shù)語和概念,從零開始討論。我試圖從“計算本質(zhì)”的出發(fā)點來理解這類事物,理解它們的起因,發(fā)展,現(xiàn)狀和可能的改進。我所關(guān)心的往往是“這個事物應該是什么樣子”,“它還可以是什么(也許更好的)樣子”,而不只是“它現(xiàn)在是什么樣子”。不明白我的這一特性,又自恃懂點東西的人,往往會誤以為我連基本的術(shù)語都不明白。于是天就這樣被他們聊死了。

這其實也是我想說的。

so,忘掉微內(nèi)核,宏內(nèi)核,忘掉內(nèi)核態(tài),用戶態(tài),忘掉實模式,保護模式,這樣你會更深刻地理解如何仲裁共享資源的訪問的本質(zhì)。 

 

責任編輯:龐桂玉 來源: Linux學習
相關(guān)推薦

2019-10-10 08:42:37

Linux內(nèi)核操作系統(tǒng)

2021-09-02 09:42:11

測試軟件可擴展性開發(fā)

2021-06-04 09:35:05

Linux字符設(shè)備架構(gòu)

2021-02-22 09:05:59

Linux字符設(shè)備架構(gòu)

2020-12-18 11:54:22

Linux系統(tǒng)架構(gòu)

2010-07-21 11:21:05

SQL Server

2022-09-05 15:17:34

區(qū)塊鏈比特幣可擴展性

2023-03-13 22:28:06

Linux包依賴

2010-06-30 17:15:39

向外擴展SQL Ser

2020-04-14 12:03:49

AI擴展性機器學習

2021-12-03 14:41:00

云存儲可擴展性存儲

2024-10-10 14:01:34

2021-05-17 07:28:23

Spring可擴展性項目

2016-10-13 14:38:51

OpenStack可擴展性IT人員

2021-12-09 05:36:16

云存儲可擴展性數(shù)據(jù)存儲云存儲

2010-07-01 11:38:13

向外擴展 SQL Se

2018-04-10 14:38:10

區(qū)塊鏈

2009-09-03 17:18:40

C#擴展性對象模型

2015-05-13 17:15:01

Elasticsear分布式搜索插件

2009-09-03 17:33:08

C#常規(guī)擴展性模型
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 宅男伊人| 一区二区三区av | 久久www免费人成看片高清 | 91精品一区 | 欧美一区二区三区在线播放 | 亚洲国产免费 | 一级欧美 | 国产欧美精品一区二区 | 自拍偷拍亚洲视频 | 国产超碰人人爽人人做人人爱 | 免费一区二区三区 | 日韩欧美高清 | 国产无人区一区二区三区 | 四虎影院免费在线播放 | www.国产精品 | 亚洲69p | 欧美一级全黄 | 久久人人国产 | 国产欧美精品 | 在线观看涩涩视频 | 国产激情在线 | 欧美日韩成人一区二区 | 国产精品一区二区三区四区 | 久久婷婷av | 国产在线1 | av在线免费不卡 | 97精品国产97久久久久久免费 | 午夜精品网站 | 亚洲人免费视频 | 波多野结衣二区 | 丁香婷婷综合激情五月色 | 精品欧美一区二区三区久久久 | 欧洲av一区 | 91精品国产综合久久香蕉麻豆 | 成人欧美一区二区三区黑人孕妇 | 亚洲欧美国产一区二区三区 | 情侣酒店偷拍一区二区在线播放 | 色黄视频在线 | 午夜视频免费网站 | 久久久久一区二区 | 国内精品久久久久久久 |