<编程之美>1.1: 让CPU占用率曲线听你指挥(under Linux)

拿到这本书, 第一题就挺有意思: 让CPU曲线走一个正弦曲线.

注意到 1. 一个死循环会使得CPU占满 2. 不开其他东西时, CPU跑的是shell+后台一些东向, 占用是比较低的(10%-20%)

那么, 程序需要的就是在这两种状态之间找到平衡. 我们可以让程序主体跑死循环, 在之前设定一个定时器(setitimer()), 定时把程序sleep掉, 就会达到需要的占用率.

之后看书上的解法, 他没用定时器, 用的一个叫GetTickCount()的win下api. 道理是一样的.

另外, 他是在之前就把正弦曲线的各个采样点数据存在一个数组里, 我之前是需要每次sleep时去计算. 这个他的更好.

编译的时候用gcc -lm -o cpuline cpuline.c.

运行的时候注意taskset 0x00000001 ./cpuline. 我的机器是双核的, 不然内核跑一会就会把程序放另一个CPU上.

用这个能限制在第一个CPU上. man了一下, taskset还是<Linux Kernel Development>的作者写的, 哈哈.

 

以下是代码(c)和运行效果:

 1 /* This is cpuline.old.c written by leaforestd@gmail.com.
 2  * (use gcc -lm -o cpuline.old cpuline.old.c
 3  * and  taskset 0x00000001 ./cpuline.old)
 4  */
 5 #include <math.h>
 6 #include <sys/time.h>
 7 #include <unistd.h>
 8 #include <stdio.h>
 9 #include <signal.h>
10 #define SAMPLE_COUNT 200
11 #define REFRESH_USEC 50000 /* one cycle: SAMPLE_COUNT * REFRESH_USEC / 10^6 (10s, refresh: 0.05s)*/
12 
13 const double Pi = 3.1415926535;
14 int Sleep_array[SAMPLE_COUNT];
15 
16 void sleep_counter();
17 void initial_array(void);
18 
19 int main() {
20     int retval = 0; /* error if -1 */
21     struct itimerval timer;
22 
23     initial_array();
24 
25     /* timer */
26     timer.it_interval.tv_sec = 0;
27     timer.it_interval.tv_usec = REFRESH_USEC;
28     timer.it_value.tv_sec = 0;
29     timer.it_value.tv_usec = REFRESH_USEC;
30     if ((retval = setitimer(ITIMER_REAL, &timer, 0)) == -1) {
31         printf("setitimer error\n");
32         return retval;
33     }
34     
35     /* signal */
36     if ((retval = (int)signal(SIGALRM, sleep_counter)) == -1) {
37         printf("signal error\n");
38         return retval;
39     }
40 
41     /* infinite loop */
42     while (1) 
43         ;
44     return 0;
45 }
46 
47 void sleep_counter() {
48     static int index = 0;
49     usleep(Sleep_array[index]);
50 
51     if (index == 199)
52         index = 0;
53     else
54         index++;
55 }
56 
57 void initial_array(void) {
58     int index;
59     double percent;
60     double i = 0;
61 
62     for (index = 0; index < SAMPLE_COUNT; index++) {
63         percent = (sin(i / 100 * Pi) + 1) / 2; /* range: [0, 1] */
64         Sleep_array[index] = (int)(percent * REFRESH_USEC + 0.5);
65         i++;
66     }

 

posted @ 2012-11-12 22:17  leaforestd  阅读(336)  评论(0编辑  收藏  举报