1. 程式人生 > >c語言設定cpu affinity (設定程式需要使用的cpu核心) cpu mask

c語言設定cpu affinity (設定程式需要使用的cpu核心) cpu mask

最近打算寫個小程式, 需要控制使用的是哪個 cpu 核心,所以做了一些調查, 整理一下分享給大家。 

ps: 因為畢業季很久沒有寫部落格了, 以後繼續。 順便鄙視一下那些轉載不宣告出處的, by watkins.song

pps: 最近有了個新的id, 因為在Oracle, wei.x.song, 不知到以後用哪個id比較酷一點

主要參考: 

http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html/

http://stackoverflow.com/questions/7296963/gnu-source-and-use-gnu

https://gcc.gnu.org/ml/fortran/2005-10/msg00365.html

設定想要使用的cpu核心, 因為現在絕大部分都是多核心的cpu, 其實就是設定cpu的affinity,

網上找的例子這樣寫:

#include <stdio.h>
#include <math.h>

#include <unistd.h>
#include <sys/times.h>
#define __USE_GNU
#include <sched.h>

但是, 可以很確定的說,這種寫法是不對的, 因為在https://gcc.gnu.org/ml/fortran/2005-10/msg00365.html 這裡,很多年以前就說了不能由使用者直接定義 __USE_GNU的巨集定義, 雖然這樣做可以正常使用, 能夠編譯通過, 但是違反了一些原則,在工程裡面就不能這麼使用了。

先看一下我總結的程式碼:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <unistd.h>
#include <sys/times.h>

void set_cpu(int id);

int main(void)
{
	puts("cpu affinity set");
	set_cpu(0x0003);

	while(1)
	{
		//sleep(10);
		//printf("in the while\n");
	}

	return 1;
}

// setup the cpu set of this program to run on
void set_cpu(int id)
{
    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(id, &mask);
    if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
    {
        fprintf(stderr, "warning: could not set CPU affinity/n");
    }
}
#define _GNU_SOURCE

這個巨集定義一定要放在程式碼檔案的最開始位置, 即使你把它放在了<sched.h>之前,但是如果不是檔案最開始部分,那麼也編譯不了。

看一下系統的執行:


可以看到在指定的cpu上執行的程式。

然後, 看一下具體的一些細節。

cpu_set_t 是一個cpu集合, 用於表明使用哪些核心, 所以也可以稱為是mask, cpu_set_t的實現如下:

typedef struct
{
  __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS];
} cpu_set_t;

是一個結構體,  __cpu_mask的定義為:
/* Type for array elements in 'cpu_set_t'.  */
typedef unsigned long int __cpu_mask;

__cpu_mask是一個unsigned long int型別。

執行的時候, 沒有執行CPU_ZERO() 之前 __bits = {0, 140737351860832, 10, 140737354104832, 17, 140737348450122, 16, 17, 10, 4196320, 140737488347648, 140737348456117, 140737351860832, 140737348456959, 140737351860832, 16}

然後執行CPU_ZERO() 將cpu_set都重置為0, 這個時候:

__bits = {0 <repeats 16 times>}

sched_setaffinity(0, sizeof(mask), &mask) == -1 這句程式碼則根據已經設定的cpu mask設定當前程序採用哪個cpu核心執行。

sched_setaffinity()的原型函式為:

int sched_setaffinity (pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset)

This function installs the cpusetsize bytes long affinity mask pointed to by cpuset for the process or thread with the ID pid. If successful the function returns zero and the scheduler will in future take the affinity information into account.

If the function fails it will return -1 and errno is set to the error code:

ESRCH
No process or thread with the given ID found. 
EFAULT
The pointer cpuset is does not point to a valid object. 
EINVAL
The bitset is not valid. This might mean that the affinity set might not leave a processor for the process or thread to run on.

This function is a GNU extension and is declared in sched.h.


來看一下  sched.h 標頭檔案, 標頭檔案中有這樣一段:

#ifdef __USE_GNU
/* Access macros for `cpu_set'.  */
# define CPU_SETSIZE __CPU_SETSIZE
# define CPU_SET(cpu, cpusetp)	 __CPU_SET_S (cpu, sizeof (cpu_set_t), cpusetp)
# define CPU_CLR(cpu, cpusetp)	 __CPU_CLR_S (cpu, sizeof (cpu_set_t), cpusetp)
# define CPU_ISSET(cpu, cpusetp) __CPU_ISSET_S (cpu, sizeof (cpu_set_t), \
						cpusetp)
# define CPU_ZERO(cpusetp)	 __CPU_ZERO_S (sizeof (cpu_set_t), cpusetp)
# define CPU_COUNT(cpusetp)	 __CPU_COUNT_S (sizeof (cpu_set_t), cpusetp)

# define CPU_SET_S(cpu, setsize, cpusetp)   __CPU_SET_S (cpu, setsize, cpusetp)
# define CPU_CLR_S(cpu, setsize, cpusetp)   __CPU_CLR_S (cpu, setsize, cpusetp)
# define CPU_ISSET_S(cpu, setsize, cpusetp) __CPU_ISSET_S (cpu, setsize, \
							   cpusetp)
# define CPU_ZERO_S(setsize, cpusetp)	    __CPU_ZERO_S (setsize, cpusetp)
# define CPU_COUNT_S(setsize, cpusetp)	    __CPU_COUNT_S (setsize, cpusetp)

# define CPU_EQUAL(cpusetp1, cpusetp2) \
  __CPU_EQUAL_S (sizeof (cpu_set_t), cpusetp1, cpusetp2)
# define CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \
  __CPU_EQUAL_S (setsize, cpusetp1, cpusetp2)

# define CPU_AND(destset, srcset1, srcset2) \
  __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, &)
# define CPU_OR(destset, srcset1, srcset2) \
  __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, |)
# define CPU_XOR(destset, srcset1, srcset2) \
  __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, ^)
# define CPU_AND_S(setsize, destset, srcset1, srcset2) \
  __CPU_OP_S (setsize, destset, srcset1, srcset2, &)
# define CPU_OR_S(setsize, destset, srcset1, srcset2) \
  __CPU_OP_S (setsize, destset, srcset1, srcset2, |)
# define CPU_XOR_S(setsize, destset, srcset1, srcset2) \
  __CPU_OP_S (setsize, destset, srcset1, srcset2, ^)

# define CPU_ALLOC_SIZE(count) __CPU_ALLOC_SIZE (count)
# define CPU_ALLOC(count) __CPU_ALLOC (count)
# define CPU_FREE(cpuset) __CPU_FREE (cpuset)


/* Set the CPU affinity for a task */
extern int sched_setaffinity (__pid_t __pid, size_t __cpusetsize,
			      __const cpu_set_t *__cpuset) __THROW;

/* Get the CPU affinity for a task */
extern int sched_getaffinity (__pid_t __pid, size_t __cpusetsize,
			      cpu_set_t *__cpuset) __THROW;
#endif

如果定義了 __USE_GNU 的話, 則定義以下若干巨集定義,  但是我們說了, 使用者不能定義 __USE_GNU這個巨集, 那麼這是在哪裡的呢?  sched.h最開始包含了 features.h 這個標頭檔案, 在這個標頭檔案中有如下定義:
#ifdef	_GNU_SOURCE
# define __USE_GNU	1
#endif

所以在我們程式的最開始位置, 定義了 _GNU_SOURCE 這個巨集定義

相關推薦

c語言設定cpu affinity (設定程式需要使用的cpu核心) cpu mask

最近打算寫個小程式, 需要控制使用的是哪個 cpu 核心,所以做了一些調查, 整理一下分享給大家。  ps: 因為畢業季很久沒有寫部落格了, 以後繼續。 順便鄙視一下那些轉載不宣告出處的, by watkins.song pps: 最近有了個新的id, 因為在Oracle,

C語言setpriority()函式:設定程式程序執行優先權

相關函式:getpriority, nice 標頭檔案:#include <sys/time.h>    #include <sys/resource.h> 定義函式:int setpriority(int which, int who, int p

windows下C語言版串列埠接收程式(基於VS2017)

#include "pch.h" #define _CRT_SECURE_NO_WARNINGS  #include <iostream> #include <stdio.h> #include <windows.h> #include <s

windows下C語言版串列埠傳送程式(基於VS2017)

#include "pch.h" #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <windows.h> #include <string.h> #include <conio.h&

[原始碼和文件分享]基於C語言的個人簡歷錄入程式

一 需求分析 此個人簡歷錄入程式可實現相關資訊的新增、刪除、修改。 通過文字框錄入姓名,通過單選按鈕選擇性別,通過組合框選擇專業(計算機,電子,工商等)和文化程度(大專,本科,碩士,博士等),設定“提交”與“取消”兩個按鍵,當用滑鼠點選“提交”按鍵時,在文字框中顯示所填寫以及選擇的資

使用C語言編寫貪食蛇程式原始碼

#include <windows.h> #include <stdlib.h> #include <time.h> #include <stdio.h> #include <string.h> #include <conio.h&g

C語言:開平方根sqrt程式02

#include <stdio.h> int sqrt01(int x); void main(void){ int x=49,y; y=sqrt01(x); if(y<0) printf("Error:sqrt return %d\n",y); else printf("The sq

c語言尋找指定字串的程式程式利用指標完成封裝)

一定要注意註釋了*的位置  我除錯了好久才發現自己沒有分配內訓 指標定義完一定要記得三選一 1.去null了 2.分配記憶體 3.指向特定的位置 還有就是宕機基本本質上都跟錯誤的操作記憶體有關 還有就是關於字串的輸出問題 首先下面的是正確的但是可以發現這樣寫編譯器

ARM基礎:為何C語言(的函式呼叫)需要堆疊,而組合語言卻不需要堆疊

https://www.cnblogs.com/liuchengchuxiao/p/4113233.html 為何C語言(的函式呼叫)需要堆疊,而組合語言卻不需要堆疊 之前看了很多關於uboot的分析,其中就有說要為C語言的執行,準備好堆疊。 而自己在Uboot的start.S彙編程

C語言練習題】編寫一個程式,它從標準輸入讀取C原始碼,並驗證所有花括號都正確成對出現

《C和指標》課後練習題   問:編寫一個程式,它從標準輸入讀取C原始碼,並驗證所有花括號都正確成對出現。   程式碼 思路:在while迴圈條件中讀取我輸入的字元,只有當輸入緩衝區沒有資料或者我這裡產生回車符'\n'時,才會判斷條件不成立。c

(c語言版)一個完整的程式,實現隨機生成20個元素的連結串列,快速查詢中間結點的值並顯示

一、分清struct 與typedef struct 方法1: #include <stdio.h> typedef struct{     int a;     int b; }test; //使用typedef 將t

C語言10個經典小程式——小白必備!

網上有很多的人說程式設計有多麼多麼無聊。。。。So Boring ! 。。。其實小編想說:不要管別人怎麼說,別人說什麼,做你自己喜歡做的事就好。堅持下來,你會發現程式設計的樂趣的。。。。當然,如果你覺得學習程式語言很痛苦,堅持了一段時間後無果,南無果斷放棄未必不是一個好的選擇。。。。哈哈哈哈。。。

C語言實現簡易的shell程式,支援多重管道及重定向

1 簡介 用C語言實現的一個簡易的shell,能夠接受使用者輸入的命令並執行操作,支援多重管道及重定向。 程式執行後,會模擬shell用綠色字型顯示當前的使用者名稱、主機名和路徑,等待使用者輸入命令。程式逐次讀取使用者輸入的指令後,將指令按空

C語言實現串列埠通訊程式

1. 首先安裝虛擬串列埠vspd軟體,用於建立虛擬串列埠進行互聯除錯2.開啟vspd軟體,選擇COM1和COM4,點選Add pair,把COM1和COM4互聯3.開啟虛擬串列埠助手,設定串列埠號為COM1,波特率為19200,其他設定使用預設值,點選連線4.用C語言編寫串列

linux C語言獲取當前可執行程式的路徑及檔名 vs 獲取當前工作路徑

 獲取當前工作路徑: 標頭檔案:#include <unistd.h> 定義函式:char * getcwd(char * buf, size_t size); 函式說明:getcwd()會將當前的工作目錄絕對路徑複製到引數buf 所指的記憶體空間,引數size

C語言實現進度條小程式 全知識點!

知識點: “%-100s” : '100’表示輸出的資料佔位100不足的空格彌補; '-'表示資料左對齊; “%”的列印注意需要轉義; fflush(stdout):對標準輸出流的清理,但是它並不是把資料丟掉,而是及時地列印資料到螢幕上。標準輸出是以每行為單位進行

C語言實現的RSA演算法程式

程式中有關型別轉換程式碼略做修改,並且已經能夠編譯執行。 程式如下: #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h>

C語言:利用指標編寫程式,定義一個3行3列的二維陣列,並在程式中對其進行賦值,陣列元素的型別不限,輸出該二維陣列以及各行的均值

題目來源:大工慕課 連結 作者:Caleb Sung 題目要求 利用指標編寫程式,定義一個3行3列的二維陣列,並在程式中對其進行賦值,陣列元素的型別不限,輸出該二維陣列以及各行的均值,各行

C++語言寫bmp檔案的程式完整版

#include <stdio.h> #include <stdlib.h> /* 定義WORD為兩個位元組的型別 */ typedef unsigned short WORD; /* 定義DWORD為四個位元組的型別 */ typedef uns

C語言中記憶體分佈及程式執行中(BSS段、資料段、程式碼段、堆疊)

BSS段:(bss segment)通常是指用來存放程式中未初始化的全域性變數的一塊記憶體區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態記憶體分配。 資料段 :資料段(data segment)通常是指用來存放程式中 已初始化