Linux编程-让进程或线程运行在指定的CPU上
 2016.03.18    |      应用编程    |     AilsonJack    |     暂无评论    |     3097 views
By: Ailson Jack
Date: 2016-03-18
个人博客: http://www.only2fire.com/
<p style="text-indent: 2em;">为了让程序拥有更好的性能,有时候需要将进程或线程绑定到特定的CPU上,这样可以减少调度的开销和保护关键进程或线程。</p><p class="artical_littlestyle1">1、绑定进程到指定的CPU</p><p style="text-indent: 2em;">Linux提供一个接口,可以将进程绑定到特定的CPU:<br/><span style="color: rgb(0, 112, 192);">#include &lt;sched.h&gt;<br/>int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *set);<br/>int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *set);</span><br/>参数:<br/>pid:进程的id号,如果pid为0,则表示本进程<br/>cpusetsize:set的大小<br/>set:运行进程的CPU,可以通过以下函数操作set:<br/><span style="color: rgb(0, 112, 192);">void CPU_ZERO(cpu_set_t *set); // Clears set, so that it contains no CPUs.<br/>void CPU_SET(int cpu, cpu_set_t *set); // Add CPU cpu to set.<br/>void CPU_CLR(int cpu, cpu_set_t *set); // Remove CPU cpu from set.<br/>int&nbsp; CPU_ISSET(int cpu, cpu_set_t *set); // Test to see if CPU cpu is a member of set.<br/>int&nbsp; CPU_COUNT(cpu_set_t * mask); //Return the number of CPUs in set.</span><br/></p><p style="text-indent: 2em;">进程绑定到指定CPU的演示程序如下:</p><pre class="brush:cpp;toolbar:false PrismJs">/* *gcc&nbsp;process_test.c */ #define&nbsp;_GNU_SOURCE #include&nbsp;&lt;stdio.h&gt; #include&nbsp;&lt;unistd.h&gt; #include&nbsp;&lt;math.h&gt; #include&nbsp;&lt;sched.h&gt; void&nbsp;WasteTime(void) { &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;abc&nbsp;=&nbsp;1000; &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;tmp&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;while(abc--) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp&nbsp;=&nbsp;10000*10000; &nbsp;&nbsp;&nbsp;&nbsp;sleep(1); } int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;*argv[]) { &nbsp;&nbsp;&nbsp;&nbsp;cpu_set_t&nbsp;cpu_set; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;while(1) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_ZERO(&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_SET(0,&nbsp;&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(sched_setaffinity(0,&nbsp;sizeof(cpu_set),&nbsp;&amp;cpu_set)&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;sched_setaffinity&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WasteTime(); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_ZERO(&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_SET(1,&nbsp;&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(sched_setaffinity(0,&nbsp;sizeof(cpu_set),&nbsp;&amp;cpu_set)&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;sched_setaffinity&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WasteTime(); &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_ZERO(&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_SET(2,&nbsp;&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(sched_setaffinity(0,&nbsp;sizeof(cpu_set),&nbsp;&amp;cpu_set)&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;sched_setaffinity&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WasteTime(); &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_ZERO(&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_SET(3,&nbsp;&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(sched_setaffinity(0,&nbsp;sizeof(cpu_set),&nbsp;&amp;cpu_set)&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;sched_setaffinity&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WasteTime(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0; }</pre><p style="text-indent: 2em;">测试:编译程序,之后运行,我编译出的文件名为a.out,执行下列命令,得到a.out的PID:<span style="color: rgb(255, 0, 0);">ps -elf | grep a.out</span>,之后输入命令:<span style="color: rgb(255, 0, 0);">top&nbsp; -p&nbsp; 进程ID</span>,接着输入f,选择P选项(移到P处,按下空格),按ESC退出,具体过程如下:</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.25/1535186267431668.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535186267431668.png&#39;)"/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.25/1535186267668142.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535186267668142.png&#39;)"/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.25/1535186270428046.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535186270428046.png&#39;)"/></p><p style="text-indent: 2em;">此时可以看到进程在cpu0 cpu1 cpu2 cpu3之间不停切换:</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.25/1535186267809476.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535186267809476.png&#39;)"/></p><p class="artical_littlestyle2">2、绑定线程到指定的CPU</p><p style="text-indent: 2em;">不仅仅进程可以绑定到CPU,线程也可以。Linux提供一个接口,可以将线程绑定到特定的CPU:<br/><span style="color: rgb(0, 112, 192);">#include &lt;pthread.h&gt;<br/>int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);<br/>int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);</span><br/></p><p style="text-indent: 2em;">该接口与进程绑定到CPU的接口的使用方法基本一致。<br/></p><p style="text-indent: 2em;">当进程绑定到特定的CPU之后,线程还是可以绑定到其他的CPU的,没有冲突。<br/></p><p style="text-indent: 2em;">示例代码如下:</p><pre class="brush:cpp;toolbar:false PrismJs">/* *gcc&nbsp;thread_test.c&nbsp;-lpthread */ #define&nbsp;_GNU_SOURCE #include&nbsp;&lt;stdio.h&gt; #include&nbsp;&lt;math.h&gt; #include&nbsp;&lt;pthread.h&gt; #include&nbsp;&lt;unistd.h&gt; #include&nbsp;&lt;sched.h&gt; void&nbsp;WasteTime(void) { &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;abc&nbsp;=&nbsp;1000; &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;temp&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;while(abc--) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;=&nbsp;10000*10000; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;sleep(1); } void&nbsp;*thread_func1(void&nbsp;*param) { &nbsp;&nbsp;&nbsp;&nbsp;cpu_set_t&nbsp;cpu_set; &nbsp;&nbsp;&nbsp;&nbsp;while(1) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_ZERO(&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_SET(1,&nbsp;&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(pthread_setaffinity_np(pthread_self(),&nbsp;sizeof(cpu_set),&amp;cpu_set)&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;pthread_setaffinity_np&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WasteTime(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_ZERO(&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_SET(2,&nbsp;&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(pthread_setaffinity_np(pthread_self(),&nbsp;sizeof(cpu_set),&amp;cpu_set)&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;pthread_setaffinity_np&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WasteTime(); &nbsp;&nbsp;&nbsp;&nbsp;} } void&nbsp;*thread_func2(void&nbsp;*param) { &nbsp;&nbsp;&nbsp;&nbsp;cpu_set_t&nbsp;cpu_set; &nbsp;&nbsp;&nbsp;&nbsp;while(1) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_ZERO(&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU_SET(3,&nbsp;&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(pthread_setaffinity_np(pthread_self(),&nbsp;sizeof(cpu_set),&amp;cpu_set)&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;pthread_setaffinity_np&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WasteTime(); &nbsp;&nbsp;&nbsp;&nbsp;} } &nbsp; int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;*argv[]) { &nbsp;&nbsp;&nbsp;&nbsp;pthread_t&nbsp;my_thread; &nbsp;&nbsp;&nbsp;&nbsp;cpu_set_t&nbsp;cpu_set; &nbsp;&nbsp;&nbsp;&nbsp;CPU_ZERO(&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;CPU_SET(0,&nbsp;&amp;cpu_set); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(sched_setaffinity(0,&nbsp;sizeof(cpu_set),&nbsp;&amp;cpu_set)&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;sched_setaffinity&quot;); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(pthread_create(&amp;my_thread,&nbsp;NULL,&nbsp;thread_func1,NULL)&nbsp;!=&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;pthread_create&quot;); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(pthread_create(&amp;my_thread,&nbsp;NULL,&nbsp;thread_func2,NULL)&nbsp;!=&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;pthread_create&quot;); &nbsp;&nbsp;&nbsp;&nbsp;while(1) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WasteTime(); &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;pthread_exit(NULL); }</pre><p style="text-indent: 2em;">测试:编译程序,之后运行,我编译出的文件名为a.out,执行下列命令,得到a.out的PID:<span style="color: rgb(255, 0, 0);">ps -elf | grep a.out</span>,之后输入命令:<span style="color: rgb(255, 0, 0);">top -H -p&nbsp; 进程ID</span>,接着输入f,选择P选项(移到P处,按下空格)和nTH选项,按ESC退出,具体过程如下:</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.25/1535186269451477.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535186269451477.png&#39;)"/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.25/1535186268210412.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535186268210412.png&#39;)"/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.25/1535186270330139.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535186270330139.png&#39;)"/></p><p style="text-indent: 2em;">可以看到主线程一直保持在cpu0,一个线程在cpu1 cpu2之间切换,另一个线程一直保持在cpu3:</p><p style="text-align: center;"><img src="/uploads/AilsonJack/2018.08.25/1535186267340066.png" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535186267340066.png&#39;)"/></p>
欢迎关注博主的公众号呀,精彩内容随时掌握:
热情邀请仔细浏览下博客中的广告,万一有对自己有用或感兴趣的呢。◕ᴗ◕。。
如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^,当然了能够赞赏博主,那就非常感谢啦!
注: 转载请注明出处,谢谢!^_^
暂无评论,要不要来个沙发
发表评论

 
Copyright © 2015~2023  说好一起走   保留所有权利   |  百度统计  蜀ICP备15004292号