天天看點

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,

網上找的例子這樣寫:

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

先看一下我總結的代碼:

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

看一下系統的運作:

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

可以看到在指定的cpu上運作的程式。

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

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

是一個結構體,  __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 <code>-1</code> and <code>errno</code> is set to the error code:

<dl></dl>

<dt><code>ESRCH</code></dt>

<dd>No process or thread with the given ID found. </dd>

<dt><code>EFAULT</code></dt>

<dd>The pointer cpuset is does not point to a valid object. </dd>

<dt><code>EINVAL</code></dt>

<dd>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.</dd>

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

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

如果定義了 __USE_GNU 的話, 則定義以下若幹宏定義,  但是我們說了, 使用者不能定義 __USE_GNU這個宏, 那麼這是在哪裡的呢?  sched.h最開始包含了 features.h 這個頭檔案, 在這個頭檔案中有如下定義:

是以在我們程式的最開始位置, 定義了 _GNU_SOURCE 這個宏定義