<编程之美>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 }