Welcome to my testing room.

[精彩] 发一个多CPU中进程与CPU绑定的例子(转)

上一篇 / 下一篇  2009-03-13 11:45:37 / 个人分类:基本概念

TX;I#?aw0转自:http://linux.chinaunix.net/bbs/viewthread.php?tid=90490651Testing软件测试网C V4u&b7[

K PB x(at ho0现在多CPU的趋势越来越大了. 有时候为了更好地操作机器, 需要将某个进程绑定到具体的CPU上去. 下面给出了一个进程绑定到具体的CPU上去的一个例子. 51Testing软件测试网z qe5irQ"`bl
51Testing软件测试网*Q0B~Tb4b o2oO"sM
51Testing软件测试网\3qI)tu|[ y&y w
cpu.c51Testing软件测试网R;S(nSl4E*vf

T,cAL%~|*x0[CODE]
VEb?!z)Z0#include<stdlib.h>
h!yTHb)`0#include<stdio.h>
bl.O5g*| g+R0#include<sys/types.h>
#l3BghL`1dt@s0#include<sys/sysinfo.h>
T#r$c'YZ0#include<unistd.h>51Testing软件测试网5oSm1Xx+DB

Ja(C,?:D4Gl0#define __USE_GNU
2`(h,})|g}t Y w0#include<sched.h>
H6t/S6fE#|2_R kw0#include<ctype.h>51Testing软件测试网0`1I cac0I#n8Y,~-Z
#include<string.h>51Testing软件测试网e6o ?N\7Z,u
51Testing软件测试网x u%o BJ6N
int main(int argc, char* argv[])
9d5DA5x$W}/@6Ao0{51Testing软件测试网*x\)~V0x"L Z
        int num = sysconf(_SC_NPROCESSORS_CONF);
;j;jO9x] ?0        int created_thread = 0;
Ccm%X-k;_3GI0        int myid;
+T6B(] n%U,S0        int i;
(D]{.`;pn2\0        int j = 0;
)Bj?}U&h1@+lK051Testing软件测试网Jk:c*N{TI
        cpu_set_t mask;51Testing软件测试网;b$cV%e)Z?%f?
        cpu_set_t get;
}t||X-I9n3A{ j051Testing软件测试网 D:G2}-n}s!KR5vC
        if (argc != 2)51Testing软件测试网ig-gd1O I
        {51Testing软件测试网@H9MksZfSG
                printf("usage : ./cpu num\n");
Y2[sb'xn#b0                exit(1);
T!s'_ c5qL)[0        }51Testing软件测试网!kJiv P*}s G
51Testing软件测试网oM'|^:jG
        myid = atoi(argv[1]);
!M0I~3?+vRE0
{@:xM&e/I4Y*s)ZD.?0        printf("system has %i processor(s). \n", num);
z"M0KS5N.ZJ051Testing软件测试网6b*C#nKT
        CPU_ZERO(&mask);51Testing软件测试网6~g:O3L ry'a
        CPU_SET(myid, &mask);
1qR*pji.\G051Testing软件测试网lb+W@(@8z
        if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
W+kH-qb V7W(X O Y%K0        {51Testing软件测试网!m]$I+J4}d)O
                printf("warning: could not set CPU affinity, continuing...\n");51Testing软件测试网8B}*I Iq#sR$P9e2C.t
        }51Testing软件测试网)v(Un+im&Bb5G
        while (1)51Testing软件测试网 W9o9pM4S
        {
.u&j ^}Ff?b ?\&R0
H[gQ&Zql G0                CPU_ZERO(&get);51Testing软件测试网 g}`2G0J wb2bD
                if (sched_getaffinity(0, sizeof(get), &get) == -1)
fu%n._$w5Nq0                {
!O&@7bdr+yn+V@:b*Z0                        printf("warning: cound not get cpu affinity, continuing...\n");51Testing软件测试网/D\vqC:_o
                }
\j` f)n uH4@G0                for (i = 0; i < num; i++)
)j^\fM0?0                {
4m(q}p&T0                        if (CPU_ISSET(i, &get))51Testing软件测试网Y!]'l0},T3B%v CA,e
                        {51Testing软件测试网9j%r]-L0na,u
                                printf("this process %d is running processor : %d\n",getpid(), i);51Testing软件测试网+L?8}/~^&\ NxGL&cT
                        }51Testing软件测试网+TUe4l2~ V
                }51Testing软件测试网4B"C^A'ZhXa*ZnN4?
        }51Testing软件测试网A7v7B \K\v B
        return 0;
p5F5WK G(K^H*|u[0}
$Phq8M%|UM.wd*f0[/CODE]51Testing软件测试网/^ Y:LVu%@&N3D
51Testing软件测试网T,vKnQQ0s
下面是在两个终端分别执行了./cpu 0  ./cpu 2 后得到的结果. 效果比较明显. 
1c!R\y5P0
7lSR^ G^|0[QUOTE]51Testing软件测试网#s|CNQ's,~
Cpu0  :  5.3%us,  5.3%sy,  0.0%ni, 87.4%id,  0.0%wa,  0.0%hi,  2.0%si,  0.0%st
!b-~7@"s9ziL MI0Cpu1  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
w)du-@+U Z`0Cpu2  :  5.0%us, 12.2%sy,  0.0%ni, 82.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st51Testing软件测试网[4J!~5bI2o1z
Cpu3  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Su3cv \0k KF(xE0Cpu4  :  0.0%us,  0.0%sy,  0.0%ni, 99.7%id,  0.3%wa,  0.0%hi,  0.0%si,  0.0%st
pC)LzL0Cpu5  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st51Testing软件测试网1s"z Zf"W*B ]b
Cpu6  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st51Testing软件测试网u%O}/fq c3N0C1z.E
Cpu7  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
-zlVQ y#g"i_0[/QUOTE]
9o${|_0{oj051Testing软件测试网sp)]?8^Md J7Y

X vJ lg\T3M }#l/{0


 wawxdyy回复于:2007-07-31 10:24:5551Testing软件测试网 v`Q\9Fu)v5DhU

U@$X%_V y5{f.Y1l0晕啊,刚才运行了一下,差点死了,呵呵,机器太差了,兄弟能具体说上面那个统计表都是什么意思吗,不太懂,另外像#define __USE_GNU这样的宏在哪能找到帮助51Testing软件测试网r-U!A!}'L!mGZk

(D0Q]G UHn7b!vE0
 scutan回复于:2007-07-31 10:54:2651Testing软件测试网}~ V#F i#{M/NJ
51Testing软件测试网U6P qid^;cg6h}
引用:原帖由 wawxdyy 于 2007-7-31 10:24 发表 [url=http://linux.chinaunix.net/bbs/redirect.php?goto=findpost&pid=6377024&ptid=904906]51Testing软件测试网o$W[z\
晕啊,刚才运行了一下,差点死了,呵呵,机器太差了,兄弟能具体说上面那个统计表都是什么意思吗,不太懂,另外像#define __USE_GNU这样的宏在哪能找到帮助 

-H0J?| t051Testing软件测试网$s!~-dO5SS

0E%I:J(T9A:X0
^%mO%d$k^8jN h4Y0那个是在运行top命令之后再按1就出现了对每个CPU的统计.
/GU#w[Xi{'}*G0us 用户空间占用CPU百分比 
H5oFk }(['o ]0sy 内核空间占用CPU百分比 
'N,k.P ZB!J B7U9Ux0ni 用户进程空间内改变过优先级的进程占用CPU百分比 
6m\1X4p}o8B0id 空闲CPU百分比 51Testing软件测试网 Z+ArT.Qf(p-f
wa 等待输入输出的CPU时间百分比 
7k[ L@Dp@9g0后面两个我也不是太清楚,麻烦清楚的朋友说一下. 51Testing软件测试网%d%`i&t {$u7u
51Testing软件测试网bn t:VOR7hmI
使用#define __USE_GNU是为了使用CPU_SET()等宏. 具体在/usr/include/sched.h中有如下的定义. 
1In/H-}$FS;^.VE0因为我开始编写的时候没有加这个宏, 出现了错误, 后来查看了这个定义才知道要使用这个东西. 
_p&} |7p!h0[CODE]
_.s"l+K p;Y%B?0#ifdef __USE_GNU
Nz#F8M*N f0/* Access macros for `cpu_set'.  */
M7U Ct)XQkyl0#define CPU_SETSIZE __CPU_SETSIZE51Testing软件测试网9p0r%MW3er
#define CPU_SET(cpu, cpusetp)   __CPU_SET (cpu, cpusetp)
cJ%tOi t:l0#define CPU_CLR(cpu, cpusetp)   __CPU_CLR (cpu, cpusetp)51Testing软件测试网iG\5vQ'G6N7d
#define CPU_ISSET(cpu, cpusetp) __CPU_ISSET (cpu, cpusetp)51Testing软件测试网J:T}5M6kO_"D
#define CPU_ZERO(cpusetp)       __CPU_ZERO (cpusetp)
XV6qSWhSfD0
-{FR$BX d0
0xRM#nG*F0/* Set the CPU affinity for a task */
+oWI q9J{0extern int sched_setaffinity (__pid_t __pid, size_t __cpusetsize,
Y}{ U;FN8BM)@YLi0                              __const cpu_set_t *__cpuset) __THROW;
#wW_7`\-A051Testing软件测试网v` eCYh1Z ^'Q0U
/* Get the CPU affinity for a task */51Testing软件测试网F/wP?2G ]|
extern int sched_getaffinity (__pid_t __pid, size_t __cpusetsize,
J0w7W$Lq8S5N#Q E0                              cpu_set_t *__cpuset) __THROW;51Testing软件测试网+~a-M}y)m2}3a-U%GO
#endif
\ q!}'G/O:[$]f(o(U0
eJW]}j0[/CODE]51Testing软件测试网_ FZ:T-z \%|)U

7ZN?t a |*k6w0
 MMMIX回复于:2007-07-31 11:22:08
yhW$s3[Oy8W051Testing软件测试网J0~ b9Pr*T
支持共享。
$`%h OC*|:`c051Testing软件测试网p)`GVi
再花些精力解释一下,提供些参考资料,直接就可以加入精华 :-)51Testing软件测试网,L,t{ B5{5\4@

3mda&N"|c o0
 wawxdyy回复于:2007-07-31 12:17:09
;KJ |a!^3L"ux0?051Testing软件测试网8hFc2Q{j
引用:原帖由 scutan 于 2007-7-31 10:54 发表 [url=http://linux.chinaunix.net/bbs/redirect.php?goto=findpost&pid=6377046&ptid=904906]
{^$N'a9z^-f&V051Testing软件测试网;m7|h6PD

nF(q&M#yU0
?;uB*s H9d6\0那个是在运行top命令之后再按1就出现了对每个CPU的统计.
dFzk4rM ~/l0us 用户空间占用CPU百分比 51Testing软件测试网~8P*Z!ei xIq(w
sy 内核空间占用CPU百分比 51Testing软件测试网!e0@"ygM!t)|B5L;Is
ni 用户进程空间内改变过优先级的进程占用CPU百分比 
2q L:t2p4a p s:|0id 空闲CPU百分比 
"c ] Q8IW*p$s0wa 等待输入 ... 
51Testing软件测试网] j,Y4kr!ri

lGAz1ip6i!i3?-i0谢谢,原来我还以为那个宏是为了优化编译呢
.E+n9KJV&bF0
1q3}8q(` S0oa9Z0
 scutan回复于:2007-07-31 12:57:38
6?A V5p/`,wa0C051Testing软件测试网8d*g%y [\W
非常感谢版主的鼓励.
S{$J Dl0f0我又加了一点内容,希望能够对大家有用.51Testing软件测试网2]vJw P9PX4p

*]WY;]$h[}q p0CPU Affinity (CPU亲合力)51Testing软件测试网)P?3glL`0Am

,Uf|Hw^B0CPU亲合力就是指在Linux系统中能够将一个或多个进程绑定到一个或多个处理器上运行.51Testing软件测试网 k%?!`'D/T[Q(dY
一个进程的CPU亲合力掩码决定了该进程将在哪个或哪几个CPU上运行.在一个多处理器系统中,设置CPU亲合力的掩码可能会获得更好的性能.
`%Wk*br'e0一个CPU的亲合力掩码用一个cpu_set_t结构体来表示一个CPU集合,下面的几个宏分别对这个掩码集进行操作:51Testing软件测试网+Fn'm E } C2~$G-K
CPU_ZERO() 清空一个集合
]M n B,wv+Q(} P mS0CPU_SET()与CPU_CLR()分别对将一个给定的CPU号加到一个集合或者从一个集合中去掉.
x [e Tn}]8j0CPU_ISSET()检查一个CPU号是否在这个集合中.
Z kw:f/p]x(Y-T0其实这几个的用法与select()函数那几个调用差不多.
_y*eG3oo(i r0下面两个函数就是最主要的了:
w7Sk@o0sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)
FeF%b X4V7B0该函数设置进程为pid的这个进程,让它运行在mask所设定的CPU上.如果pid的值为0,则表示指定的是当前进程,使当前进程运行在mask所设定的那些CPU上.第二个参数cpusetsize是
EJ&Sno?6C0
z @KMXMr|(k0mask所指定的数的长度.通常设定为sizeof(cpu_set_t).如果当前pid所指定的CPU此时没有运行在mask所指定的任意一个CPU上,则该指定的进程会从其它CPU上迁移到mask的指定的51Testing软件测试网'[q.qyVBK5i4dy
51Testing软件测试网"oalRXkP
一个CPU上运行.51Testing软件测试网K/Yd^-{q/d%c
sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)
Z!Fg"se'q2?]0该函数获得pid所指示的进程的CPU位掩码,并将该掩码返回到mask所指向的结构中.即获得指定pid当前可以运行在哪些CPU上.同样,如果pid的值为0.也表示的是当前进程.51Testing软件测试网 ^eX)j#@CM

I)A,R7}&K].H0这几个宏与函数的具体用法前面已经有讲解.
| qe;T5|_0
-li)A n3Uc'aYrD0关于cpu_set_t的定义
#}9MfIO psRz*[0[CODE]
n"Z2JP4~.We0# define __CPU_SETSIZE  102451Testing软件测试网)bb ZP%tl,To(P
# define __NCPUBITS     (8 * sizeof (__cpu_mask))51Testing软件测试网U_Y8l7|"e
51Testing软件测试网AL3Y?et
typedef unsigned long int __cpu_mask;
'G%^#H|B1{0zP0
A6]1O'c6j2{,T_0# define __CPUELT(cpu)  ((cpu) / __NCPUBITS)51Testing软件测试网^B&{b}0r@7[
# define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
!d!Y7X(R;c,I051Testing软件测试网|i"fQ c'K2mB5t
typedef struct51Testing软件测试网 ]zy$p&M|
{51Testing软件测试网GDq7zVGk`-J
  __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS];51Testing软件测试网+O:j$~.Z'|G:n n;hRp
} cpu_set_t;51Testing软件测试网(U`qUQ%EW%t

x2EP(OF2ny$h8H0# define __CPU_ZERO(cpusetp) \
b%z@7Kd#EK0  do {                                                                        \51Testing软件测试网1Q:Pl5Iq(K!j
    unsigned int __i;                                                         \51Testing软件测试网1[t$bP8f'K
    cpu_set_t *__arr = (cpusetp);                                             \51Testing软件测试网W9dr pfw6En
    for (__i = 0; __i < sizeof (cpu_set_t) / sizeof (__cpu_mask); ++__i)      \51Testing软件测试网}1k6Sc\(a3or
      __arr->__bits[__i] = 0;                                                 \
8M't SJ/H ^$u0u0x0  } while (0)
$LlSt ]#r7D8Cns;Uf0# define __CPU_SET(cpu, cpusetp) \51Testing软件测试网*}i)_8[9r#d ^X:_
  ((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu))
1MD0Ns,tY0# define __CPU_CLR(cpu, cpusetp) \
'PW(c9mAIT0  ((cpusetp)->__bits[__CPUELT (cpu)] &= ~__CPUMASK (cpu))51Testing软件测试网;d&hl-Rw3[H
# define __CPU_ISSET(cpu, cpusetp) \51Testing软件测试网(T*Ks%jw ?d L.q
  (((cpusetp)->__bits[__CPUELT (cpu)] & __CPUMASK (cpu)) != 0)
[8EET'{K-d6l0
8g!yI Wry)e0[/CODE]
Bp(PYaN!cI0
J*Jk:|kfQ `0在我的机器上sizeof(cpu_set_t)的大小为128,即一共有1024位.第一位代表一个CPU号.某一位为1则表示某进程可以运行在该位所代表的cpu上.例如51Testing软件测试网)ABU4Ck9f I
CPU_SET(1, &mask);51Testing软件测试网$M]T9`I n+V8z+D!YL
则mask所对应的第2位被设置为1.51Testing软件测试网tys^ v&S-H
此时如果printf("%d\n", mask.__bits[0]);就打印出2.表示第2位被置为1了.51Testing软件测试网V2p2yd3jj1Ku
51Testing软件测试网'Q4y](B.i P1gKm

O qV/Fw CrSfht051Testing软件测试网Q@ B.J3C!m1b0{
具体我是参考man sched_setaffinity文档中的函数的. 51Testing软件测试网W3Jc~k_w_&F0zS`
然后再参考了一下IBM的 developerWorks上的一个讲解. 
&RJ'o1n3D pBs0http://www.ibm.com/developerworks/cn/linux/l-affinity.html
Kr PFJ2J/Wz0
o9s8w!M*_7_ g$fC#Fo0
 xiaozhu2007回复于:2007-10-10 00:48:3551Testing软件测试网#Xct|1U

7_dW&lC _m!Y0gcc cpu.c -o cpu51Testing软件测试网 ycAG.?rp+Mls-Y^
cpu.c:(.text+0x86): undefined reference to `CPU_ZERO'
8zG:{sjI?0cpu.c:(.text+0x9b): undefined reference to `CPU_SET'
4^3[UKY[)r0cpu.c:(.text+0xdc): undefined reference to `CPU_ZERO'51Testing软件测试网.fu;W0M#I wm mE!Q
cpu.c:(.text+0x126): undefined reference to `CPU_ISSET'
B C"Q#M c9A E0collect2: ld returned 1 exit status51Testing软件测试网sYM,h Vu a
51Testing软件测试网s Ucl3y

 scutan回复于:2007-10-10 12:45:34
!@B#O-mC0
^ ZEa(`I0你是不是没有加下面这一行? 51Testing软件测试网x1u&u!|!HY8uv
#define __USE_GNU51Testing软件测试网JyoG.L
51Testing软件测试网V/ev%k3F O*qJ

 xiaozhu2007回复于:2007-10-10 22:10:09
Y+wl IOUe*z051Testing软件测试网t(`Y&xZ1Ii
加了。51Testing软件测试网#QKe"\k'X
另外问一下,
(] t$C"rW6n T oSL[0#include<sys/types.h>
"T7\wk5j0#include<sys/sysinfo.h>
mK8O Q RL0
3C%X3o"fgU#P0#include<ctype.h>51Testing软件测试网I}9Q3G!^/~
#include<string.h>51Testing软件测试网&Z9A%e&g3g1Iu?{H
这几个头文件这里需要引用吗?
x,c[a w6D0一会我在试一试。
jOB&H^.r{3Cw051Testing软件测试网9e i%g5[N0JK
先夸一下,牛啊!51Testing软件测试网j }j-]"b
这是属于内核编程吗?APUE里好象没有讲这方面的内容。
)SQUTd051Testing软件测试网%Q"y;T5i}6f

 xiaozhu2007回复于:2007-10-11 01:13:1451Testing软件测试网+T"FXp/|U4\Y
51Testing软件测试网;m%R UL]'A/YXg
知道是怎么回事了 。51Testing软件测试网B6X\J7fr+\
#define __USE_GNU
\%_0qv5cE0不是#define _USE_GNU
aT,Bp)k?5pL051Testing软件测试网1WbO8U'|#Hd*h$ov
还有:#include<sys/types.h>51Testing软件测试网 KF4yg4~!jiX
#include<sys/sysinfo.h>51Testing软件测试网;KW,Uo%F.W O
#include<ctype.h>51Testing软件测试网6E%cdC)Je1?$j
#include<string.h>这4个头文件可以不用,没什么用。51Testing软件测试网{qB(Q|e

,E ya*L$@2_&}+U0
 xiaozhu2007回复于:2007-10-11 01:48:51
&bVP,Dgq:dK }2l0
3v!Y/f*t4^`#C0我打开了 两个terminal51Testing软件测试网c_(V6p^ Aa
分别运行:./cpu    0     51Testing软件测试网\%r/hZrM_;R,z
./cpu    2
P oeVx0在另一个terminal上输入top命令后,然后按1,结果始终只有cpu0的信息;两个运行cpu 0和cpu  2的终端始终显示的 是:51Testing软件测试网$\KWu?@1\;K
this process 3268 is running processor:0
h)xU.Y(Jpf?z0this process 3269 is running processor:0 
l`UQe#V(V)j9h0也就是说当前进程始终都 是在编号为0的cpu上。51Testing软件测试网;]$X"r3eCV R hr

tG.H,SoTR0我想应该是int num = sysconf(_SC_NPROCESSORS_CONF);的缘故,我机器是单cpu,所以num = 1
1r J*f6eGo6n*_R7b0所以在for(i=0;i<num;i++)循环中,CPU_ISSET始终只能检测到CPU亲和力掩码的第一位(编号为0),所以只有cpu0的信息。
"nN2E9h)[)Td0请问你是怎么运行的才能得到cpun(n>0)的信息呢?(在单cpu的条件下)
\ ~m],k*O051Testing软件测试网\ ]+^U?]xC3l

 scutan回复于:2007-10-11 09:00:5251Testing软件测试网XeQ h3]n&P"}G#L

cot*dyi3x0单CPU的情况下也只能有一个CPU运行, 我这个例子主是要针对多CPU的情况下的.

/T,M@V;dl,gB!F0

TAG:

 

评分:0

我来说两句

日历

« 2024-04-28  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 31139
  • 日志数: 54
  • 图片数: 1
  • 建立时间: 2008-10-20
  • 更新时间: 2010-01-13

RSS订阅

Open Toolbar