精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一次腦殘的記錄:Linux 中實時任務調度與優先級

系統 Linux
在本文中,可以把線程約等于進程,有的地方也可能稱為任務,在不同的語境下有一些不同的慣用說法。

[[405787]]

失敗是成功之母,這篇文章就是一次真實的失敗調試記錄。

通過這篇文章,您能深刻體驗到 Linux 系統中下面幾個概念:

  1. 實時進程和普通進程的調度策略;
  2. Linux 中混亂的進程優先級是如何計算的;
  3. CPU親和性的測試;
  4. 多處理器(SMP)遇到實時進程和普通進程的程序設計;
  5. 道哥的腦袋被門夾了一下的短路經歷;

背景知識:Linux 調度策略

關于進程的調度策略,不同的操作系統有不同的整體目標,因此調度算法也就各不相同。

這需要根據進程的類型(計算密集型?IO密集型?)、優先級等因素來進行選擇。

對于 Linux x86 平臺來說,一般采用的是 CFS:完全公平調度算法。

之所以叫做完全公平,是因為操作系統以每個線程占用 CPU 的比率來進行動態的計算,操作系統希望每一個進程都能夠平均的使用 CPU 這個資源,雨露均沾。

我們在創建一個線程的時候,默認就是這個調度算法 SCHED_OTHER,默認的優先級為 0。

  • PS: 在 Linux 操作系統中,線程的內核對象與進程的內核對象(其實就是一些結構體變量)是很類似的,所以線程可以說是輕量級的進程。
  • 在本文中,可以把線程約等于進程,有的地方也可能稱為任務,在不同的語境下有一些不同的慣用說法。

可以這么理解:如果系統中一共有 N 個進程,那么每個進程會得到 1/N 的執行機會。每個進程執行一段時間之后,就被調出,換下一個進程執行。

如果這個 N 的數量太大了,導致每個進程剛開始執行時,分給它的時間就到了。如果這個時候就進行任務調度,那么系統的資源就耗費在進程上下文切換上去了。

因此,操作系統引入了最小粒度,也就是每個進程都有一個最小的執行時間保證,稱作時間片。

除了 SCHED_OTHER 調度算法,Linux 系統還支持兩種實時調度策略:

  • 1. SCHED_FIFO:根據進程的優先級進行調度,一旦搶占到 CPU 則一直運行,直達自己主動放棄或被被更高優先級的進程搶占;
  • 2. SCHED_RR:在 SCHED_FIFO 的基礎上,加上了時間片的概念。當一個進程搶占到 CPU 之后,運行到一定的時間后,調度器會把這個進程放在 CPU 中,當前優先級進程隊列的末尾,然后選擇另一個相同優先級的進程來執行;

本文想測試的就是 SCHED_FIFO 與普通的 SCHED_OTHER 這兩種調度策略混合的情況。

背景知識:Linux 線程優先級

在 Linux 系統中,優先級的管理顯得比較混亂,先看下面這張圖:

這張圖表示的是內核中的優先級,分為兩段。

前面的數值 0-99 是實時任務,后面的數值 100-139 是普通任務。

數值越低,代表這個任務的優先級越高。

數值越低,代表這個任務的優先級越高。

數值越低,代表這個任務的優先級越高。

再強調一下,以上是從內核角度來看的優先級。

好了,重點來了:

我們在應用層創建線程的時候,設置了一個優先級數值,這是從應用層角度來看的優先級數值。

但是內核并不會直接使用應用層設置的這個數值,而是經過了一定的運算,才得到內核中所使用的優先級數值(0 ~ 139)。

1. 對于實時任務

我們在創建線程的時候,可以通過下面這樣的方式設置優先級數值(0 ~ 99):

  1. struct sched_param param; 
  2. param.__sched_priority = xxx; 

當創建線程函數進入內核層面的時候,內核通過下面這個公式來計算真正的優先級數值:

  1. kernel priority = 100 - 1 - param.__sched_priority 

如果應用層傳入數值 0,那么在內核中優先級數值就是 99(100 - 1 - 0 = 99),在所有實時任務中,它的優先級是最低的。

如果應用層傳輸數值 99,那么在內核中優先級數值就是 0(100 - 1 - 99 = 0),在所有實時任務中,它的優先級是最高的。

因此,從應用層的角度看,傳輸人優先級數值越大,線程的優先級就越高;數值越小,優先級就越低。

與內核角度是完全相反的!

2. 對于普通任務

調整普通任務的優先級,是通過 nice 值來實現的,內核中也有一個公式來把應用層傳入的 nice 值,轉成內核角度的優先級數值:

  1. kernel prifoity = 100 + 20 + nice 

nice 的合法數值是:-20 ~ 19。

如果應用層設置線程 nice 數值為 -20,那么在內核中優先級數值就是 100(100 + 20 + (-20) = 100),在所有的普通任務中,它的優先級是最高的。

如果應用層設置線程 nice 數值為 19,那么在內核中優先級數值就是 139(100 +20 +19 = 139),在所有的普通任務中,它的優先級是最低的。

因此,從應用層的角度看,傳輸人優先級數值越小,線程的優先級就越高;數值越大,優先級就越低。

與內核角度是完全相同的!

背景知識交代清楚了,終于可以進行代碼測試了!

[[405789]]

測試代碼說明

注意點:

  1. #define _GNU_SOURCE 必須在 #include 之前定義;
  2. #include 必須在 #include 之前包含進來;
  3. 這個順序能夠保證在后面設置繼承的 CPU 親和性時,CPU_SET, CEPU_ZERO這兩個函數能被順利定位到。

  1. // filename: test.c 
  2. #define _GNU_SOURCE 
  3. #include <unistd.h>   
  4. #include <stdio.h> 
  5. #include <stdlib.h> 
  6. #include <sched.h> 
  7. #include <pthread.h> 
  8.  
  9. // 用來打印當前的線程信息:調度策略是什么?優先級是多少? 
  10. void get_thread_info(const int thread_index) 
  11.     int policy; 
  12.     struct sched_param param; 
  13.  
  14.     printf("\n====> thread_index = %d \n", thread_index); 
  15.  
  16.     pthread_getschedparam(pthread_self(), &policy, &param); 
  17.     if (SCHED_OTHER == policy) 
  18.         printf("thread_index %d: SCHED_OTHER \n", thread_index); 
  19.     else if (SCHED_FIFO == policy) 
  20.         printf("thread_index %d: SCHED_FIFO \n", thread_index); 
  21.     else if (SCHED_RR == policy) 
  22.         printf("thread_index %d: SCHED_RR \n", thread_index); 
  23.  
  24.     printf("thread_index %d: priority = %d \n", thread_index, param.sched_priority); 
  25.  
  26. // 線程函數, 
  27. void *thread_routine(void *args) 
  28.     // 參數是:線程索引號。四個線程,索引號從 1 到 4,打印信息中使用。 
  29.     int thread_index = *(int *)args; 
  30.      
  31.     // 為了確保所有的線程都創建完畢,讓線程睡眠1秒。 
  32.     sleep(1); 
  33.  
  34.     // 打印一下線程相關信息:調度策略、優先級。 
  35.     get_thread_info(thread_index); 
  36.  
  37.     long num = 0; 
  38.     for (int i = 0; i < 10; i++) 
  39.     { 
  40.         for (int j = 0; j < 5000000; j++) 
  41.         { 
  42.             // 沒什么意義,純粹是模擬 CPU 密集計算。 
  43.             float f1 = ((i+1) * 345.45) * 12.3 * 45.6 / 78.9 / ((j+1) * 4567.89); 
  44.             float f2 = (i+1) * 12.3 * 45.6 / 78.9 * (j+1); 
  45.             float f3 = f1 / f2; 
  46.         } 
  47.          
  48.         // 打印計數信息,為了能看到某個線程正在執行 
  49.         printf("thread_index %d: num = %ld \n", thread_index, num++); 
  50.     } 
  51.      
  52.     // 線程執行結束 
  53.     printf("thread_index %d: exit \n", thread_index); 
  54.     return 0; 
  55.  
  56. void main(void) 
  57.     // 一共創建四個線程:0和1-實時線程,2和3-普通線程(非實時) 
  58.     int thread_num = 4; 
  59.      
  60.     // 分配的線程索引號,會傳遞給線程參數 
  61.     int index[4] = {1, 2, 3, 4}; 
  62.  
  63.     // 用來保存 4 個線程的 id 號 
  64.     pthread_t ppid[4]; 
  65.      
  66.     // 用來設置 2 個實時線程的屬性:調度策略和優先級 
  67.     pthread_attr_t attr[2]; 
  68.     struct sched_param param[2]; 
  69.  
  70.     // 實時線程,必須由 root 用戶才能創建 
  71.     if (0 != getuid()) 
  72.     { 
  73.         printf("Please run as root \n"); 
  74.         exit(0); 
  75.     } 
  76.  
  77.     // 創建 4 個線程 
  78.     for (int i = 0; i < thread_num; i++) 
  79.     { 
  80.         if (i <= 1)    // 前2個創建實時線程 
  81.         { 
  82.             // 初始化線程屬性 
  83.             pthread_attr_init(&attr[i]); 
  84.              
  85.             // 設置調度策略為:SCHED_FIFO 
  86.             pthread_attr_setschedpolicy(&attr[i], SCHED_FIFO); 
  87.              
  88.             // 設置優先級為 51,52。 
  89.             param[i].__sched_priority = 51 + i; 
  90.             pthread_attr_setschedparam(&attr[i], &param[i]); 
  91.              
  92.             // 設置線程屬性:不要繼承 main 線程的調度策略和優先級。 
  93.             pthread_attr_setinheritsched(&attr[i], PTHREAD_EXPLICIT_SCHED); 
  94.              
  95.             // 創建線程 
  96.             pthread_create(&ppid[i], &attr[i],(void *)thread_routine, (void *)&index[i]); 
  97.         } 
  98.         else        // 后兩個創建普通線程 
  99.         { 
  100.             pthread_create(&ppid[i], 0, (void *)thread_routine, (void *)&index[i]); 
  101.         } 
  102.          
  103.     } 
  104.  
  105.     // 等待 4 個線程執行結束 
  106.     for (int i = 0; i < 4; i++) 
  107.         pthread_join(ppid[i], 0); 
  108.  
  109.     for (int i = 0; i < 2; i++) 
  110.         pthread_attr_destroy(&attr[i]); 

編譯成可執行程序的指令:

  1. gcc -o test test.c -lpthread 

腦殘測試開始

首先說一下預期結果,如果沒有預期結果,那其他任何問題都壓根不用談了。

一共有 4 個線程:

  1. 線程索引號 1和2:是實時線程(調度策略是 SCHED_FIFO,優先級是 51,52);
  2. 線程索引號 3和4:是普通線程(調度策略是 SCHED_OTHER, 優先級是 0);

我的測試環境是:Ubuntu16.04,是一臺安裝在 Windows10 上面的虛擬機。

我期望的結果是:

  1. 首先打印 1 號和 2 號這兩個線程的信息,因為它倆是實時任務,需要優先被調度;
  2. 1 號線程的優先級是 51,小于 2 號線程的優先級 52,因此應該是 2 號線程結束之后,才輪到 1 號線程執行;
  3. 3 號和 4 號線程是普通進程,它倆需要等到 1 號和 2 號線程全部執行結束之后才開始執行,并且 3 號和 4 號線程應該是交替執行,因為它倆的調度策略和優先級都是一樣的。

我滿懷希望的在工作電腦中測試,打印結果如下:

  1. ====> thread_index = 4  
  2. thread_index 4: SCHED_OTHER  
  3. thread_index 4: priority = 0  
  4.  
  5. ====> thread_index = 1  
  6. thread_index 1: SCHED_FIFO  
  7. thread_index 1: priority = 51  
  8.  
  9. ====> thread_index = 2  
  10. thread_index 2: SCHED_FIFO  
  11. thread_index 2: priority = 52  
  12. thread_index 2: num = 0  
  13. thread_index 4: num = 0  
  14.  
  15. ====> thread_index = 3  
  16. thread_index 3: SCHED_OTHER  
  17. thread_index 3: priority = 0  
  18. thread_index 1: num = 0  
  19. thread_index 2: num = 1  
  20. thread_index 4: num = 1  
  21. thread_index 3: num = 0  
  22. thread_index 1: num = 1  
  23. thread_index 2: num = 2  
  24. thread_index 4: num = 2  
  25. thread_index 3: num = 1 
  26.  
  27. 后面打印內容不用輸出了,因為前面已經出現了問題。 

 問題很明顯:為什么 4 個線程為什么被同時執行了?

1 號和 2 號這兩個線程應該被優先執行啊,因為它倆是實時任務!

怎么結果是這個樣子?徹底凌亂了,一點都不符合預期!

想不出個所以然,只能求助網絡!但是沒有找到有價值的線索。

其中有一個信息涉及到 Linux 系統的調度策略,這里記錄一下。

Linux 系統中,為了不讓實時任務徹底占據 CPU 資源,會讓普通任務有很小的一段時間縫隙來執行。

在目錄 /proc/sys/kernel 下面,有 2 個文件,用來限制實時任務占用 CPU 的時間:

  • sched_rt_runtime_us: 默認值 950000 sched_rt_period_us: 默認值 1000000

意思是:在 1000000 微秒(1秒)的周期內,實時任務占用 950000 微秒(0.95秒),剩下的 0.05 秒留給普通任務。

如果沒有這個限制的話,假如某個 SCHED_FIFO 任務的優先級特別高,恰巧出了 bug:一直占據 CPU 資源不放棄,那么我們壓根就沒有機會來 kill 掉這個實時任務,因為此時系統無法調度其他的任何進程來執行。

而有了這個限制呢,我們就可以利用這 0.05 秒的執行時間,來 kill 掉有 bug 的那個實時任務。

回到正題:資料上說,如果實時任務沒有被優先調度,可以把這個時間限制刪掉就可以了。方法是:

  1. sysctl -w kernel.sched_rt_runtime_us=-1 

我照做之后,依舊無效!

換一臺虛擬機,繼續測試

難道是電腦環境的問題嗎?于是,把測試代碼放到另一臺筆記本里的虛擬機 Ubuntu14.04 里測試。

編譯的時候,有一個小問題,提示錯誤:

  1. error: ‘for’ loop initial declarations are only allowed in C99 mode 

只要把編譯指令中添加 C99 標準就可以了:

  1. gcc -o test test.c -lpthread -std=c99 

執行程序,打印信息如下:

  1. ====> thread_index = 2  
  2.  
  3. ====> thread_index = 1  
  4. thread_index 1: SCHED_FIFO  
  5. thread_index 1: priority = 51  
  6. thread_index 2: SCHED_FIFO  
  7. thread_index 2: priority = 52  
  8. thread_index 1: num = 0  
  9. thread_index 2: num = 0  
  10. thread_index 2: num = 1  
  11. thread_index 1: num = 1  
  12. thread_index 2: num = 2  
  13. thread_index 1: num = 2  
  14. thread_index 2: num = 3  
  15. thread_index 1: num = 3  
  16. thread_index 2: num = 4  
  17. thread_index 1: num = 4  
  18. thread_index 2: num = 5  
  19. thread_index 1: num = 5  
  20. thread_index 2: num = 6  
  21. thread_index 1: num = 6  
  22. thread_index 2: num = 7  
  23. thread_index 1: num = 7  
  24. thread_index 2: num = 8  
  25. thread_index 1: num = 8  
  26. thread_index 2: num = 9  
  27. thread_index 2: exit  
  28.  
  29. ====> thread_index = 4  
  30. thread_index 4: SCHED_OTHER  
  31. thread_index 4: priority = 0  
  32. thread_index 1: num = 9  
  33. thread_index 1: exit  
  34.  
  35. ====> thread_index = 3  
  36. thread_index 3: SCHED_OTHER  
  37. thread_index 3: priority = 0  
  38. thread_index 3: num = 0  
  39. thread_index 4: num = 0  
  40. thread_index 3: num = 1  
  41. thread_index 4: num = 1  
  42. thread_index 3: num = 2  
  43. thread_index 4: num = 2  
  44. thread_index 3: num = 3  
  45. thread_index 4: num = 3  
  46. thread_index 3: num = 4  
  47. thread_index 4: num = 4  
  48. thread_index 3: num = 5  
  49. thread_index 4: num = 5  
  50. thread_index 3: num = 6  
  51. thread_index 4: num = 6  
  52. thread_index 3: num = 7  
  53. thread_index 4: num = 7  
  54. thread_index 3: num = 8  
  55. thread_index 4: num = 8  
  56. thread_index 3: num = 9  
  57. thread_index 3: exit  
  58. thread_index 4: num = 9  
  59. thread_index 4: exit 

1 號和 2 號線程同時執行,完畢之后,再 3 號和 4 號線程同時執行。

但是這同樣也不符合預期:2 號線程的優先級比 1 號線程高,應該優先執行才對!

不知道應該怎么查這個問題了,想不出思路,只好請教 Linux 內核的大神,建議檢查一下內核版本。

這時,我才想起來在 Ubuntu16.04 這臺虛擬機上因為某種原因,降過內核版本。

往這個方向去排查了一下,最后確認也不是內核版本的差異導致的問題。

比較結果,尋找差異

只好再回過頭來看一下這兩次次打印信息的差異:

  1. 工作電腦里的 Ubuntu16.04 中:4 個線程同時調度執行,調度策略和優先級都沒有起作用;
  2. 筆記本里的 Ubuntu14.04 中:1 號和 2 號實時任務被優先執行了,說明調度策略起作用了,但是優先級沒有起作用;

突然, CPU 的親和性從腦袋里蹦了出來!

緊接著立馬感覺到問題出在哪里了:這TMD大概率就是多核引起的問題!

[[405790]]

于是我把這 4 個線程都綁定到 CPU0 上去,也就是設置 CPU 親和性。

在線程入口函數 thread_routine 的開頭,增加下面的代碼:

  1. cpu_set_t mask; 
  2. int cpus = sysconf(_SC_NPROCESSORS_CONF); 
  3. CPU_ZERO(&mask); 
  4. CPU_SET(0, &mask); 
  5. if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) 
  6.     printf("set thread affinity failed! \n"); 

然后繼續在 Ubuntu16.04 虛擬機中驗證,打印信息很完美,完全符合預期:

  1. ====> thread_index = 1  
  2.  
  3. ====> thread_index = 2  
  4. thread_index 2: SCHED_FIFO  
  5. thread_index 2: priority = 52  
  6. thread_index 2: num = 0  
  7. 。。。 
  8. thread_index 2: num = 9  
  9. thread_index 2: exit  
  10. thread_index 1: SCHED_FIFO  
  11. thread_index 1: priority = 51  
  12. thread_index 1: num = 0  
  13. 。。。 
  14. thread_index 1: num = 9  
  15. thread_index 1: exit  
  16.  
  17. ====> thread_index = 3  
  18. thread_index 3: SCHED_OTHER  
  19. thread_index 3: priority = 0  
  20.  
  21. ====> thread_index = 4  
  22. thread_index 4: SCHED_OTHER  
  23. thread_index 4: priority = 0  
  24. thread_index 3: num = 0  
  25. thread_index 4: num = 0  
  26. 。。。 
  27. thread_index 4: num = 8  
  28. thread_index 3: num = 8  
  29. thread_index 4: num = 9  
  30. thread_index 4: exit  
  31. thread_index 3: num = 9  
  32. thread_index 3: exit 

至此,問題真相大白:就是多核處理器導致的問題!

而且這兩臺測試的虛擬機,安裝的時候分配的 CPU 核心是不同的,所以才導致打印結果的不同。

真相大白

最后,再確認一下這 2 個虛擬機中的 CPU 信息:

Ubuntu 16.04 中 cpuinfo 信息:

  1. $ cat /proc/cpuinfo  
  2. processor : 0 
  3. vendor_id : GenuineIntel 
  4. cpu family : 6 
  5. model  : 158 
  6. model name : Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz 
  7. stepping : 10 
  8. cpu MHz  : 2807.996 
  9. cache size : 9216 KB 
  10. physical id : 0 
  11. siblings : 4 
  12. core id  : 0 
  13. cpu cores : 4 
  14. 。。。其他信息 
  15.  
  16. processor : 1 
  17. vendor_id : GenuineIntel 
  18. cpu family : 6 
  19. model  : 158 
  20. model name : Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz 
  21. stepping : 10 
  22. cpu MHz  : 2807.996 
  23. cache size : 9216 KB 
  24. physical id : 0 
  25. siblings : 4 
  26. core id  : 1 
  27. cpu cores : 4 
  28. 。。。其他信息 
  29.  
  30. processor : 2 
  31. vendor_id : GenuineIntel 
  32. cpu family : 6 
  33. model  : 158 
  34. model name : Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz 
  35. stepping : 10 
  36. cpu MHz  : 2807.996 
  37. cache size : 9216 KB 
  38. physical id : 0 
  39. siblings : 4 
  40. core id  : 2 
  41. cpu cores : 4 
  42. 。。。其他信息 
  43.  
  44. processor : 3 
  45. vendor_id : GenuineIntel 
  46. cpu family : 6 
  47. model  : 158 
  48. model name : Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz 
  49. stepping : 10 
  50. cpu MHz  : 2807.996 
  51. cache size : 9216 KB 
  52. physical id : 0 
  53. siblings : 4 
  54. core id  : 3 
  55. cpu cores : 4 
  56. 。。。其他信息 

在這臺虛擬機中,正好有 4 個核心,而我的測試代碼正好也創建了 4 個線程,于是每個核心被分配一個線程,一個都不閑著,同時執行。

因此打印信息中顯示 4 個線程是并行執行的。

這個時候,什么調度策略、什么優先級,都不起作用了!(準確的說:調度策略和優先級,在線程所在的那個 CPU 中是起作用的)

如果我在測試代碼中,一開始就創建 10 個線程,很可能會更快發現問題!

再來看看筆記本電腦里虛擬機 Ubuntu14.04 的 CPU 信息:

  1. $ cat /proc/cpuinfo  
  2. processor   : 0 
  3. vendor_id   : GenuineIntel 
  4. cpu family  : 6 
  5. model       : 142 
  6. model name  : Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz 
  7. stepping    : 9 
  8. microcode   : 0x9a 
  9. cpu MHz     : 2304.000 
  10. cache size  : 4096 KB 
  11. physical id : 0 
  12. siblings    : 2 
  13. core id     : 0 
  14. cpu cores   : 2 
  15. 。。。其他信息 
  16.  
  17.  
  18. processor   : 1 
  19. vendor_id   : GenuineIntel 
  20. cpu family  : 6 
  21. model       : 142 
  22. model name  : Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz 
  23. stepping    : 9 
  24. microcode   : 0x9a 
  25. cpu MHz     : 2304.000 
  26. cache size  : 4096 KB 
  27. physical id : 0 
  28. siblings    : 2 
  29. core id     : 1 
  30. cpu cores   : 2 
  31. 。。。其他信息 

在這臺虛擬機中,有 2 個核心,于是 2 個實時任務 1 號和 2 號被優先執行(因為是 2 個核心同時執行,所以這 2 個任務的優先級也就沒什么意義了),結束之后,再執行 3 號和 4 號線程。

再思考一下

這一圈測試下來,真的想用鍵盤敲自己的腦袋,怎么就沒有早點考慮到多核的因素呢?!

深層的原因:

  1. 之前的很多項目,都是 ARM、mips、STM32等單核情況,思維定式讓我沒有早點意識到多核這個屏體因素;
  2. 做過的一些 x86 平臺項目,并沒有涉及到實時任務這樣的要求。一般都是使用系統默認的調度策略,這也是 Linux x86 作為通用電腦,在調度策略上所關注的重要指標:讓每一個任務都公平的使用 CPU 資源。

隨著 x86 平臺在工控領域的逐漸應用,實時性問題就顯得更突出、更重要了。

所以才有了 Windows 系統中的 intime,Linux 系統中的 preempt、xenomai 等實時補丁。

本文轉載自微信公眾號「 IOT物聯網小鎮」,可以通過以下二維碼關注。轉載本文請聯系 IOT物聯網小鎮公眾號。

 

責任編輯:姜華 來源: IOT物聯網小鎮
相關推薦

2020-06-04 08:36:55

Linux內核線程

2021-04-23 21:40:33

Python優先級調度器

2021-04-06 10:45:18

React前端優先級

2023-01-05 08:48:57

技術管理排優先級

2023-11-03 08:22:09

Android系統算法

2025-07-29 02:00:00

2012-08-14 09:38:29

WAN優化

2021-02-02 14:55:48

React前端高優先

2010-09-01 14:10:36

CSS優先級

2019-07-31 15:14:33

2024-10-10 10:32:04

2013-12-24 13:59:03

2022-12-23 09:41:14

優先級反轉

2023-11-16 09:30:27

系統任務

2020-03-10 07:51:35

面試諷刺標準

2018-01-15 14:50:49

APP轉讓App賬號

2023-03-29 09:36:32

2019-11-01 12:36:14

人工智能機器學習技術

2025-06-30 07:00:00

JavaScript開發線程

2020-09-30 09:07:37

DevOps
點贊
收藏

51CTO技術棧公眾號

成人激情视频网站| 狠狠色狠狠色综合系列| 国产成人免费观看| 亚洲 国产 日韩 综合一区| 国产做受69高潮| 亚洲aⅴ天堂av在线电影软件| 久久精品视频5| 99精品视频在线观看播放| 日韩视频免费观看高清完整版| 日本国产中文字幕| 亚洲综合激情网| 国产精品日韩在线播放| 免费又黄又爽又色的视频| 亚洲黄色录像| 精品少妇一区二区三区| 男人插女人下面免费视频| 怡红院红怡院欧美aⅴ怡春院| av电影在线观看一区| 日韩一级中文字幕| 日韩啪啪电影网| 亚洲国产中文字幕在线观看| 天天干天天操天天玩| 爱啪视频在线观看视频免费| 中文字幕一区二区三| 鲁鲁视频www一区二区| www.亚洲黄色| 美女一区二区三区| 性欧美xxxx| 亚洲av无码一区二区三区在线| 亚洲警察之高压线| 欧美一级爆毛片| av网站在线不卡| 新片速递亚洲合集欧美合集| 亚洲国产精品麻豆| 日本a级片在线观看| 超碰在线国产| 国产天堂亚洲国产碰碰| 久久久久一区二区| 午夜性色福利视频| 成人福利视频网站| 成人综合电影| 成人激情四射网| 国产精品99久久久久久有的能看| 国产一区香蕉久久| 91高潮大合集爽到抽搐| 蜜乳av一区二区三区| 国产精品精品视频一区二区三区| 日本中文字幕久久| 久久青草久久| 国产成人高潮免费观看精品| 不卡av电影在线| 久久午夜精品一区二区| 98精品国产自产在线观看| jizz国产免费| 99伊人成综合| 91av福利视频| 51国偷自产一区二区三区| 可以在线观看av的网站| 日韩视频免费| 日韩av电影院| 国产成人a v| 性欧美videos高清hd4k| 国产亚洲人成网站| 无遮挡亚洲一区| 91精品国产91久久久久游泳池 | 国产性生交xxxxx免费| 亚洲涩涩在线| 欧美视频一区二区三区在线观看| 色七七在线观看| 天天综合在线观看| 日韩免费视频一区二区| 久久国产精品久久久久| 在线免费观看亚洲视频| 欧美区日韩区| 午夜精品一区二区三区在线| 欧美日韩www| 欧美视频第三页| 精品免费av在线 | 给我免费播放片在线观看| a级片在线免费| 色婷婷久久99综合精品jk白丝| 亚洲 中文字幕 日韩 无码| 一区二区三区日本视频| 日韩精品一区在线观看| 亚洲国产综合视频| 欧美视频免费| 九九久久国产精品| aaa人片在线| 六月丁香综合在线视频| 99热最新在线| 噜噜噜噜噜在线视频| 国产精品福利一区二区三区| 97久久国产亚洲精品超碰热| 国产伦子伦对白在线播放观看| 在线观看亚洲精品视频| 91免费视频污| 国产精品最新| 欧美激情手机在线视频| 欧美日韩 一区二区三区| 国产精品资源在线看| 欧洲国产精品| av3级在线| 欧美高清dvd| 中国黄色a级片| 一区二区三区午夜探花| 国产成人精品视频在线| 亚洲女同志亚洲女同女播放| 欧美激情一区三区| 免费无码不卡视频在线观看| 国产精品高清一区二区| 国产午夜精品免费一区二区三区 | 国产精品综合在线| 粉嫩欧美一区二区三区高清影视| 欧美日韩综合网| 91小视频xxxx网站在线| 在线一区二区三区四区五区| 亚洲色图欧美另类| 久久美女视频| 日本高清视频精品| 亚洲精品视频网| 国产精品嫩草99a| 男人操女人免费软件| 国产成年精品| 最近2019好看的中文字幕免费| 欧美一级视频免费观看| 国产一区二区福利| 亚洲人成77777| 日韩一区二区三区在线免费观看| 亚洲第一在线视频| 综合五月激情网| 青青草国产精品亚洲专区无| 久久99精品久久久久久秒播放器 | 国产精品区在线| 久久99蜜桃| 欧美在线激情网| 五月天婷婷视频| 亚洲一区二区三区四区中文字幕| www.cao超碰| 日韩av二区| 国产精品成人播放| 国产精品无码2021在线观看| 精品久久久久久电影| 欧美久久久久久久久久久| 在线看片不卡| 亚洲精品欧美日韩专区| 一级日本在线| 欧美日韩久久一区| 亚洲色图日韩精品| 日韩美女视频在线观看| 亚洲精品视频91| 亚洲一区二区三区精品在线| 秋霞午夜鲁丝一区二区| 欧美日韩午夜| 国产精品综合久久久久久| 成年人视频免费在线播放| 精品999在线播放| jizz国产免费| 久久久国产精华| 国产精品人人爽人人爽| 999精品在线| 激情黄产视频在线免费观看| 精品久久久久久久久久久久久久久 | 久久女同互慰一区二区三区| 日韩avxxx| 国产精品一区二区av日韩在线| 国产精品91久久久| 欧美高清视频| 精品欧美一区二区久久| 欧美亚韩一区二区三区| 久久精品男人天堂av| 天天色综合社区| 这里只有精品在线| 国产一区二区在线网站| 深夜成人福利| 久久视频在线视频| 成人午夜精品福利免费| 欧美视频在线观看免费| 调教驯服丰满美艳麻麻在线视频| 精品亚洲aⅴ乱码一区二区三区| 免费成人进口网站| 国产91社区| 阿v免费在线观看| 欧美日本精品一区二区三区| 全网免费在线播放视频入口| 成人毛片在线观看| 亚洲黄色a v| 欧美/亚洲一区| 美乳视频一区二区| 96视频在线观看欧美| 国内久久久精品| av亚洲在线| 精品国产百合女同互慰| 亚洲天堂五月天| 一区二区视频免费在线观看| 日本黄色录像片| 美女视频一区二区| 缅甸午夜性猛交xxxx| 色777狠狠狠综合伊人| 国产美女99p| 国产a亚洲精品| 97婷婷涩涩精品一区| 日本在线免费中文字幕| 日韩精品极品视频| 午夜久久福利影院| 国产精品国产三级国产专业不| 激情伊人五月天久久综合| www在线观看免费| 久久久久久久久久久妇女| 精品国产乱码一区二区三区四区| 欧美91在线|欧美| 97精品国产97久久久久久免费| 免费观看在线黄色网| 国产视频欧美视频| 亚洲黄色精品视频| 欧美无人高清视频在线观看| 日本黄色片视频| 亚洲美女免费在线| 欧美性猛交xxxx乱大交少妇| 91亚洲大成网污www| 日本成人在线免费观看| 青草国产精品久久久久久| 国产精品50p| 黄色工厂这里只有精品| 色乱码一区二区三区熟女| 欧美人与物videos另类xxxxx| 国产精品久久国产精品| 国产精品成人3p一区二区三区| 国产精品久久网| 刘亦菲一区二区三区免费看| 亚洲**2019国产| 青草在线视频| 欧美日本高清视频| 福利在线视频网站| 久久亚洲精品一区| 蜜桃视频在线观看免费视频网站www| 亚洲黄页网在线观看| 成人毛片在线免费观看| 亚洲精品一线二线三线无人区| 99久久一区二区| 日韩午夜三级在线| 国产丰满美女做爰| 日韩欧美中文字幕公布| 国产v在线观看| 日韩一级精品视频在线观看| 国产乱子伦精品无码码专区| 欧美高清视频不卡网| 在线免费观看中文字幕| 欧美日韩国产一级| 一级黄色大片免费| 欧美二区三区91| 国产麻豆精品一区| 日韩欧美视频一区| 亚洲精品国产手机| 亚洲国产天堂久久国产91| 天天干免费视频| 猫咪在线永久网站| 欧美影片第一页| 欧美视频xxxx| 在线观看免费一区| 国产精品国产一区二区三区四区 | japansex久久高清精品| 91在线视频九色| 日韩精品亚洲专区在线观看| 波多野结衣久草一区| 国产精品超碰| 日本在线播放一区| 欧美黄色大片在线观看| 亚洲国产精品影视| 伊人成年综合电影网| 丝袜老师办公室里做好紧好爽| 久久精品1区| 污污网站在线观看视频| 国产老肥熟一区二区三区| 欧美激情一区二区三区p站| 成人黄色一级视频| 无码人妻精品一区二区中文| 国产精品乱码一区二三区小蝌蚪| 四虎精品免费视频| 精品久久久免费| 最新国产中文字幕| 欧美一区二区三区影视| 色婷婷中文字幕| 亚洲最新av在线网站| 丝袜综合欧美| 日本精品久久久久影院| 97精品资源在线观看| 九九热久久66| 国产精品久久久久久影院8一贰佰| 4444亚洲人成无码网在线观看| 99亚洲伊人久久精品影院红桃| 黄色手机在线视频| 成人免费高清视频| 免费看91的网站| 亚洲国产欧美在线| 中文字幕一区2区3区| 精品免费日韩av| 在线激情免费视频| 91高清在线免费观看| 999精品视频在线观看| 久久精品国产精品国产精品污| 99久久婷婷国产综合精品电影√| 久久99久久久久久| 麻豆精品视频在线观看| 成年人网站免费看| 亚洲精品久久久蜜桃| 中文字幕高清在线免费播放| 欧美不卡一二三| 日本中文字幕在线观看| 欧美一级免费看| 大奶一区二区三区| 中文字幕中文字幕在线中心一区| 国产欧美69| 肉丝美足丝袜一区二区三区四| 国产欧美日韩不卡免费| 中日韩精品视频在线观看| 欧美精品久久99| 9i精品一二三区| 4388成人网| 久久草在线视频| 日本丰满少妇黄大片在线观看| 久久婷婷久久| 国产交换配乱淫视频免费| 亚洲一区二区精品久久av| 国产免费不卡av| 日韩在线小视频| 日本欧美一区| 欧美日韩精品免费观看视一区二区| 1024日韩| 风韵丰满熟妇啪啪区老熟熟女| 国产精品国产三级国产三级人妇| 中国女人一级一次看片| 亚洲欧美国产精品| 无遮挡爽大片在线观看视频| 国产亚洲精品美女久久久m| 国产一区日韩一区| 人妻巨大乳一二三区| 亚洲日本一区二区| 亚洲字幕av一区二区三区四区| 亚洲视频在线免费看| jk漫画禁漫成人入口| 麻豆av一区二区| 国产精品毛片一区二区三区| 自拍视频一区二区| 精品成人久久av| 三级网站免费观看| 91wwwcom在线观看| 日韩精品福利一区二区三区| 狠狠干 狠狠操| 91老师片黄在线观看| 色婷婷av国产精品| 亚洲精品中文字| 亚洲www.| 亚洲欧美日韩另类精品一区二区三区| 日韩经典中文字幕一区| 国产极品视频在线观看| 欧美日韩在线电影| 日本www在线观看| 7777精品久久久大香线蕉小说| 欧美1区2区| 国产精品成人99一区无码 | 这里只有精品国产| 神马久久久久久| 麻豆精品一区| 你真棒插曲来救救我在线观看| av电影在线观看不卡| 中文字幕第四页| 中文字幕欧美国内| 精品中文字幕一区二区三区四区| 日韩一级特黄毛片| av不卡在线观看| 欧美高清69hd| 免费91在线视频| 麻豆一区二区| 污污网站免费看| 最新成人av在线| 亚洲人妻一区二区| 国产精品久久久久久久av电影| 99热在线成人| 这里只有精品在线观看视频| 欧美午夜女人视频在线| aaa在线观看| 国产欧美日韩在线播放| 日本中文字幕一区二区有限公司| 男人av资源站| 亚洲国产日韩一区| 成人午夜亚洲| 老太脱裤让老头玩ⅹxxxx| 欧美国产一区二区| 在线观看av黄网站永久| 操日韩av在线电影| 欧美成人基地| 污视频网址在线观看| 亚洲一区二区三区精品在线| 国产视频网站在线| 波多野结衣久草一区| 日产欧产美韩系列久久99| 久久久久久av无码免费网站| 亚洲欧美国产视频| 亚洲欧美日本国产| 亚洲一区在线不卡|