天天看点

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 这个宏定义