欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux下進程的CPU配置與線程綁定過程

 更新時間:2025年07月11日 15:15:54   作者:比特熊貓  
本文介紹Linux系統(tǒng)中基于進程和線程的CPU配置方法,通過taskset命令和pthread庫調整親和力,將進程/線程綁定到特定CPU核心以優(yōu)化資源分配,提升系統(tǒng)性能與實時任務響應效率,同時強調操作驗證及注意事項

1 基于進程的CPU配置

基于進程的CPU配置技術是指在Linux操作系統(tǒng)中,通過調整進程的CPU使用率來實現(xiàn)對系統(tǒng)資源的合理分配和管理。這種技術可以用于限制特定進程的CPU使用,防止其占用過多的CPU資源,從而保證系統(tǒng)的穩(wěn)定性和性能。

基于進程的CPU配置是指將一個進程綁定到特定的CPU核心或者CPU集合上運行。這樣可以控制進程在特定的CPU資源上執(zhí)行,以提高性能或實現(xiàn)特定的調度策略。

1.1 對CPU親和力的配置

對于CentOS 8下的Linux系統(tǒng),首先可以使用top命令來查看當前的CPU占用率,如下圖所示:

鍵盤上按數(shù)字1,可以以數(shù)據(jù)化的形式看到具體的使用情況,如下圖:

鍵盤上按字母t,可以以圖形化的形式看到具體的使用情況,如下圖:

可以看到,當前的CPU基本是空閑的狀態(tài)。

這時候,我們寫一個測試代碼,讓其掛在后臺運行,例如下面的一個死循環(huán)函數(shù):

#include <iostream>

int main()
{
    while (true) {
        // 在這里編寫你的代碼
        // 例如,輸出一條信息
        std::cout << "Hello, I am running in an infinite loop!" << std::endl;
    }

    return 0;
}

讓其掛在后臺運行著,暫時不管。

如下圖:

此時,我們再次使用top命令,來查看當前的CPU 狀態(tài),如下圖:

可以看到,此時循環(huán)代碼這個進程正在后臺不停運行,此時的CPU占用率相比開始,非常的高。

記住當前的進程PID,然后使用taskset -c -p 13265 命令查看當前進程的CPU親和力。13265是當前進程的PID。

可以從輸出的信息看出,pid 為13265的進程(即當前的測試進程)的親和力CPU為0-3,即它同時運行在了0,1,2,3這四個CPU上面。

現(xiàn)在我們更改pid 為13265的進程(即當前的測試進程)的親和力,將其改成只在0,1這兩個CPU上面運行。如下圖:

這里由于我使用了ctrl + c暫停了剛才的進程,然后重新啟動該進程時,進程的PID變成了13495,不過這沒有任何影響??梢钥吹剑斍暗倪M程新的親和力列表為0,1,說明設置新的CPU親和力成功。而pid 13495 的當前親和力掩碼為3,同樣能說明親和力設置成功。使用taskset命令來查看進程運行在哪個CPU上。

使用以下命令:

taskset -p < PID >

【請將< PID >替換為你要查看的進程的實際PID?!?/p>

該命令將顯示進程的當前親和力掩碼,其中每個位表示一個CPU核心。例如,如果輸出為pid 's current affinity mask: 3,表示進程當前在CPU核心0和1上運行,因為二進制表示為11。

再次實驗一下,這次我們將CPU親和力設置在CPU 1,CPU2上,如下圖:

由當前親和力掩碼可以看到,為6,說明此時運行在CPU1和CPU2上。(2^1 + 2^2 = 6)

1.2 綁定進程到指定CPU核上運行

查看CPU有幾個核

使用 cat /proc/cpuinfo 查看CPU信息,如下兩個信息:

  • ·processor:指明第幾個cpu處理器
  • ·cpu cores:指明每個處理器的核心數(shù)

以本機中虛擬機為例,有4個CPU(分別為:CPU0, CPU1, CPU2, CPU3),每個CPU有1個核。

也可以使用系統(tǒng)調用sysconf獲取CPU核心數(shù):

#include <unistd.h>

int sysconf(_SC_NPROCESSORS_CONF);/* 返回系統(tǒng)可以使用的核數(shù),但是其值會包括系統(tǒng)中禁用的核的數(shù)目,因 此該值并不代表當前系統(tǒng)中可用的核數(shù) */
int sysconf(_SC_NPROCESSORS_ONLN);/* 返回值真正的代表了系統(tǒng)當前可用的核數(shù) */

/* 以下兩個函數(shù)與上述類似 */
#include <sys/sysinfo.h>

int get_nprocs_conf (void);/* 可用核數(shù) */
int get_nprocs (void);/* 真正的反映了當前可用核數(shù) */

使用 taskset 指令 

  • 獲取進程pid:

  • 查看進程當前運行在哪個CPU上:

顯示的十六進制f轉換為二進制為最低四個是1,每個1對應一個CPU,所以進程運行在4個CPU上。

  • 指定進程10770運行在CPU0上:

注意,CPU的標號是從0開始的,所以cpu0表示第1個CPU(第一個CPU的標號是0)。

至此,就把應用程序綁定到了CPU0上運行,查看如下:

  • 啟動程序時綁定CPU:

例如啟動時綁定到第二個CPU上,即CPU1:

使用sched_setaffinity系統(tǒng)調用 

通過系統(tǒng)調用sched_setaffinity進行綁定,通過sched_getaffinity獲取綁定關系。注意這對方法是進程級別的綁定。代碼中指定cpu0和cpu3,我們可以通過top查看,兩個CPU使用達到了100%,其他的CPU均不會(正常場景)。

sched_setaffinity可以將某個進程綁定到一個特定的CPU。
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>

/* 設置進程號為pid的進程運行在mask所設定的CPU上
 * 第二個參數(shù)cpusetsize是mask所指定的數(shù)的長度
 * 通常設定為sizeof(cpu_set_t)

 * 如果pid的值為0,則表示指定的是當前進程 
 */
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);

int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);/* 獲得pid所指示的進程的CPU位掩碼,并將該掩碼返回到mask所指向的結構中 */

代碼示例:

/*

*該程序演示了如何使用sched_setaffinity函數(shù)將線程綁定到特定的CPU核心上運行。
*程序首先創(chuàng)建了兩個線程,然后使用sched_setaffinity函數(shù)將線程1綁定到CPU 0上,將線程2綁定到CPU 3上。
*運行時,可以通過查看輸出的pid來確定程序的進程ID。
*然后,程序將CPU_ZERO宏應用于一個cpu_set_t類型的變量mask,以將其初始化為空集。
*接下來,程序將CPU_SET宏應用于mask,將CPU 0和CPU 3添加到集合中。
*最后,程序調用sched_setaffinity函數(shù)將mask應用于當前進程,將線程1綁定到CPU 0上,將線程2綁定到CPU 3上。
*線程創(chuàng)建成功后,程序使用pthread_join函數(shù)等待線程1和線程2的結束。
*/
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sched.h>
#include <pthread.h>
 
void* testfunc(void* t) {
  while(1);
  return NULL; 
}
 
int main()
{
  cpu_set_t mask; // 定義cpu_set_t類型的變量mask,用于存儲CPU集合
  printf("pid=%d\n", getpid()); // 打印進程ID
  CPU_ZERO(&mask); // 將mask初始化為空集
  CPU_SET(0, &mask);//將cpu0綁定到mask中
  CPU_SET(3, &mask);//將cpu3綁定到mask中

  // 將mask應用于當前進程,綁定線程到指定的CPU核心
  sched_setaffinity(0, sizeof(cpu_set_t), &mask) ;
  
  pthread_t tid1;//創(chuàng)建線程1
  if (pthread_create(&tid1, NULL, (void *)testfunc, NULL) != 0) 
  {      
    fprintf(stderr, "thread create failed\n"); // 線程創(chuàng)建失敗,打印錯誤信息
    return -1;   
  }
  pthread_t tid2;//創(chuàng)建線程2
  if (pthread_create(&tid2, NULL, (void *)testfunc, NULL) != 0) 
  {      
    fprintf(stderr, "thread create failed\n"); // 線程創(chuàng)建失敗,打印錯誤信息
    return -1;   
  } 
  pthread_join(tid1, NULL); // 等待線程1結束
  pthread_join(tid1, NULL); // 等待線程2結束
  return 0;
}

執(zhí)行結果如下圖所示: 

  • 執(zhí)行前:

  • 執(zhí)行后:

2 基于線程的CPU配置

2.1 線程綁定:使用函數(shù)pthread_setaffinity_np

線程綁定CPU核心的意義:

  • 在多核CPU中合理的調度線程在各個核上運行可以獲得更高的性能。
  • 在多線程編程中,每個線程處理的任務優(yōu)先級是不一樣的,對于要求實時性比較高的線程或者是主線程,對于這種線程我們可以在創(chuàng)建線程時指定其綁定到某個CPU核上,以后這個核就專門處理該線程。
  • 這樣可以使得該線程的任務可以得到較快的處理,特別是和用戶直接交互的任務,較短的響應時間可以提升用戶的體驗感。

幾個重要的宏操作:

一個線程的CPU親合力掩碼用一個cpu_set_t結構體來表示一個CPU集合,下面的幾個宏分別對這個掩碼集進行操作:

CPU_ZERO() 清空一個集合
CPU_SET()與CPU_CLR()分別對將一個給定的CPU號加到一個集合或者從一個集合中去掉
CPU_ISSET()檢查一個CPU號是否在這個集合中

設置獲取線程CPU親和力狀態(tài):

sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)

該函數(shù)設置線程為pid的這個線程,讓它運行在mask所設定的CPU上。

如果pid的值為0,則表示指定的是當前線程,使當前線程運行在mask所設定的那些CPU上。

第二個參數(shù)cpusetsize是mask所指定的數(shù)的長度。通常設定為sizeof(cpu_set_t)。

如果當前pid所指定的線程此時沒有運行在mask所指定的任意一個CPU上,則該指定的線程會從其它CPU上遷移到mask的指定的一個CPU上運行。

sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)

該函數(shù)獲得pid所指示的線程的CPU位掩碼,并將該掩碼返回到mask所指向的結構中。即獲得指定pid當前可以運行在哪些CPU上。同樣,如果pid的值為0。也表示的是當前進程。

簡單的實例:

// 此代碼不完整,只是幫助理解綁定過程
// 在創(chuàng)建線程時添加以下代碼,可以將該線程綁定到1核
cpu_set_t mask;

// 將掩碼清零
CPU_ZERO(&mask);

// 將1添加到掩碼中
CPU_SET(1, &mask);

// #將本線程綁定到1核
sched_setaffinity(0, sizeof(cpu_set_t), &mask);

查看線程是否運行在指定的核上:

實際工作中,為了方便查看線程的情況,會在創(chuàng)建線程時將相關信息保存到一個文件中,需要時用cat命令查看,內容包括創(chuàng)建了哪些線程、線程名稱、線程id和pid、綁定的CPU核、優(yōu)先級、調度方式等。

使用“top”命令查看:

  • top -d 2:查看線程的運行情況和CPU狀態(tài)
  • 按’h’ 和 1:在上一句的基礎上可以查看更詳細的信息。

從文件中得到線程pid和ppid,通過top命令,查看線程在哪個CPU核上運行,驗證核綁定的核是否一樣。

對于線程綁定,我們需要借助pthread庫,通過函數(shù)pthread_setaffinity_np來設置綁定cpu關系。我們通過top查看,會發(fā)現(xiàn)cpu0和cpu3使用率達到100%。

代碼實例:

/*
 *該程序演示了如何使用pthread_setaffinity_np函數(shù)將線程綁定到特定的CPU核心上運行。
 *程序首先創(chuàng)建了兩個線程,然后使用pthread_setaffinity_np函數(shù)將線程1綁定到CPU 0上,將線程2綁定到CPU 3上。
 *運行時,可以通過查看輸出的pid來確定程序的進程ID。
 *然后,程序將CPU_ZERO宏應用于一個cpu_set_t類型的變量mask,以將其初始化為空集。
 *接下來,程序使用pthread_create函數(shù)創(chuàng)建線程1和線程2,并檢查線程創(chuàng)建是否成功。
 *然后,程序打印出線程1和線程2的ID。
 *程序使用CPU_SET宏將CPU 0添加到mask中,并使用pthread_setaffinity_np函數(shù)將mask應用于線程1,將線程1綁定到CPU 0上。
 *然后,程序清除之前設置的mask,并將CPU 3添加到mask中,并使用pthread_setaffinity_np函數(shù)將mask應用于線程2,將線程2綁定到CPU   3上。
 *最后,程序使用pthread_join函數(shù)等待線程1和線程2的結束。
*/
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sched.h>
#include <pthread.h>

void* testfunc(void* t) {
  int i = 3; // 初始化循環(huán)計數(shù)器為3
  while(i) { // 進入循環(huán),條件為i非零
     sleep(5); // 休眠5秒
     printf("tid=%d,cpu=%d\n",pthread_self(), sched_getcpu()); // 打印線程ID和CPU編號
     i--; // 計數(shù)器減一
  }
  while(1); // 進入無限循環(huán)
  return NULL; 
}

int main()
{
  cpu_set_t mask; // 定義CPU集合
  printf("pid=%d\n", getpid()); // 打印進程ID
  CPU_ZERO(&mask); // 清空CPU集合
  
  pthread_t tid1; // 定義線程tid1
  if (pthread_create(&tid1, NULL, (void *)testfunc, NULL) != 0) 
  {      
    fprintf(stderr, "thread create failed\n"); // 線程創(chuàng)建失敗,打印錯誤信息
    return -1;   
  }
  pthread_t tid2; // 定義線程tid2
  if (pthread_create(&tid2, NULL, (void *)testfunc, NULL) != 0) 
  {      
    fprintf(stderr, "thread create failed\n"); // 線程創(chuàng)建失敗,打印錯誤信息
    return -1;   
  } 
  printf("tid1=%d,tid2=%d\n", tid1,tid2); // 打印線程tid1和tid2的值
 
  CPU_SET(0, &mask); // 將CPU0加入CPU集合
  pthread_setaffinity_np(tid1, sizeof(cpu_set_t), &mask) ; // 設置線程tid1的CPU親和性為CPU0
  
  // 清除之前設置,重新設置綁定cpu3
  CPU_ZERO(&mask); // 清空CPU集合
  CPU_SET(3, &mask); // 將CPU3加入CPU集合
  pthread_setaffinity_np(tid2, sizeof(cpu_set_t), &mask) ; // 設置線程tid2的CPU親和性為CPU3
  
  pthread_join(tid1, NULL); // 等待線程tid1結束
  pthread_join(tid1, NULL); // 等待線程tid2結束
  return 0;
}
  • 執(zhí)行之后:

  • 將其kill,恢復:

建議:進行配置之前先將虛擬機拍攝快照,以防配置不當出現(xiàn)意外情況。

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • linux查看用過的命令方法總結

    linux查看用過的命令方法總結

    在本篇文章里小編給大家分享了關于linux怎么查看用過的命令的具體方法和步驟,需要的朋友們參考下。
    2019-06-06
  • Linux和GNU系統(tǒng)的關系詳解

    Linux和GNU系統(tǒng)的關系詳解

    大家好,本篇文章主要講的是Linux和GNU系統(tǒng)的關系詳解,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • linux之如何停止正在執(zhí)行腳本

    linux之如何停止正在執(zhí)行腳本

    這篇文章主要介紹了linux之如何停止正在執(zhí)行腳本問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Linux提示網絡不可達問題

    Linux提示網絡不可達問題

    這篇文章主要介紹了Linux提示網絡不可達問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Linux 常用命令掛載命令詳解

    Linux 常用命令掛載命令詳解

    這篇文章主要介紹了Linux 常用命令掛載命令詳解的相關資料,需要的朋友可以參考下
    2017-01-01
  • Linux網絡啟動問題:Device does not seem to be present解決辦法

    Linux網絡啟動問題:Device does not seem to be present解決辦法

    這篇文章主要介紹了Linux網絡啟動問題:Device does not seem to be present解決辦法的相關資料,希望通過本文能幫助到大家解決這樣的問題,需要的朋友可以參考下
    2017-10-10
  • 詳解在Ubuntu下搭建FTP服務器

    詳解在Ubuntu下搭建FTP服務器

    這篇文章主要介紹了詳解在Ubuntu下搭建FTP服務器,,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • linux中批量添加文件前綴的操作方法

    linux中批量添加文件前綴的操作方法

    這篇文章主要介紹了linux中批量添加文件前綴的操作方法,給大家擴展介紹linux下批量改變文件前綴命令,需要的朋友可以參考下
    2019-12-12
  • haproxy軟件的日志如何輸出到指定文件

    haproxy軟件的日志如何輸出到指定文件

    本文介紹了如何將haproxy的日志從系統(tǒng)syslog中分離出來,并獨立記錄到不同的日志文件中,通過修改rsyslog配置文件和haproxy配置文件,可以實現(xiàn)這一目標,并便于后期的日志管理和分析
    2024-12-12
  • Linux內核設備驅動之proc文件系統(tǒng)筆記整理

    Linux內核設備驅動之proc文件系統(tǒng)筆記整理

    今天小編就為大家分享一篇關于Linux內核設備驅動之proc文件系統(tǒng)筆記整理,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12

最新評論