本回将尝试在Linux环境下能否在系统监视器中画出一个正弦曲线。本人环境为Ubuntu 11.04.
基本思想还是和Windows下面的相同,更换系统调用,便可以实现功能的迁移。
#include <time.h> #include <sys/time.h> #include <unistd.h> #include<stdlib.h> #include<math.h> #define DWORD unsigned long #define UINT64 unsigned long long const double SPLIT = 0.01; const int COUNT = 200; const double PI = 3.14159265; const int INTERVAL = 300; int main(int argc, char* argv[] ) { struct timeval tms; DWORD busySpan[COUNT]; DWORD idleSpan[COUNT]; int half = INTERVAL/2, i; double radian = 0.0; for(i = 0; i < COUNT; ++i) { busySpan[i] = (DWORD)(half + (sin(PI * radian) * half)); idleSpan[i] = INTERVAL - busySpan[i]; radian += SPLIT; } clock_t startTime = 0; int j = 0; while(1) { j = j % COUNT; timerclear(&tms); gettimeofday(&tms,NULL); UINT64 startTime = tms.tv_usec; while(1)//clock返回该进程从启动到现在经历的毫秒数(千分之一秒) { timerclear(&tms); gettimeofday(&tms,NULL); UINT64 nowTime = tms.tv_usec; if((nowTime - startTime)/1000 > busySpan[j]) break; } if(usleep(idleSpan[j]*1000)) //精确到微秒(百万分之一秒)的函数 exit(-1); j++; } return 0; }
gettimeofday()函数用来取得当前时间(微秒,百万分之一秒)。并通过参数传递给结构体timeval类型的tms。
int gettimeofday(struct timeval *tv, struct timezone *tz);
tz用来获取时区信息。不做介绍。
结构体timeval的定义为:
struct timeval
{
time_t tv_sec; //seconds
suseconds_t tv_usec; //microseconds
};
tz如果是NULL的话将不传递时区信息。tv提供秒为单位的和微妙为单位的从Epoch开始的计数。
结构体timeval的域为类型long的域。
此函数返回0,表示成功,-1表示失败。
Windows中,GetTickCount返回的是从系统启动到现在的毫秒。
int usleep(useconds_t usec);
定义在头文件unistd.h中。它使当前进程挂起至少usec微秒(百万分之一秒).睡眠时间可能会被任意系统活动或进程切换开销或系统计时器的精确度而轻微延迟。成功时返回0,错误时返回-1.
或者使用clock()来得到系统时间也是可以的。它返回从进程启动到现在经历的时间,单位是毫秒(千分之一秒)。定义在头文件time.h下.
clock_t clock(void);
相应代码如下。
#include <time.h> #include <sys/time.h> #include <unistd.h> #include<stdlib.h> #include<math.h> #define DWORD unsigned long #define UINT64 unsigned long long const double SPLIT = 0.01; const int COUNT = 200; const double PI = 3.14159265; const int INTERVAL = 300; int main(int argc, char* argv[] ) { struct timeval tms; DWORD busySpan[COUNT]; DWORD idleSpan[COUNT]; int half = INTERVAL/2, i; double radian = 0.0; for(i = 0; i < COUNT; ++i) { busySpan[i] = (DWORD)(half + (sin(PI * radian) * half)); idleSpan[i] = INTERVAL - busySpan[i]; radian += SPLIT; } clock_t startTime = 0; int j = 0; while(1) { j = j % COUNT; timerclear(&tms); gettimeofday(&tms,NULL); clock_t startTime = clock(); while((clock()-startTime) <= busySpan[j])//clock返回该进程从启动到现在经历的毫秒数(千分之一秒) ; if(usleep(idleSpan[j]*1000)) //精确到微秒(百万分之一秒)的函数 exit(-1); j++; } return 0; }
但对于多核CPU,如何限制进程在一个CPU上运行呢?
如何察看某个进程在哪个CPU上运行:
在控制台中输入:
#top -d 1
之后按下f.进入top Current Fields设置页面:
选中:j: P = Last used cpu (SMP)
则多了一项:P 显示此进程使用哪个CPU。
经过试验发现:同一个进程,在不同时刻,会使用不同CPU Core.这应该是Linux Kernel SMP处理的。
本程序通过这个方法查看,将会在多个CPU上运行。
想要让它在一个CPU上执行,可以这样做:
1.下载包schedtool.
在控制台中输入:sudo apt-get install schedtool,然后输入你的密码。
schedtool是Linux下用来查询或设置CPU状态的工具。通过不同的参数可以查看或设置不同的属性。
[-0|-N] [-1|-F] [-2|-R] [-3|-B] [-4|-I] [-5|-D] [-M policy] [-a affinity] [-p prio] [-n nice_level] [-e command [arg ...]] [-r] [-v] [-h]我们这里要用到的是 -a和-e。其他可以参考这里:
http://linux.die.net/man/8/schedtool-a用来设置进程在哪个CPU上运行。-a的参数为:0x1 表示只运行在CPU0(00000001)0x2 表示只运行在CPU1(00000010)0x4表示紫云行在CPU2(00000100)0x8表示只运行在CPU3(00001000)etc.或者,多CPU运行可以这样表示,0x7表示可以运行在CPU0,1,2 (00000111)0x5表示可运行在CPU0,2 (00000101)以此类推。-e用来通过指定的参数来执行命令。后面的参数为控制台命令。
在Linux下,如何确认是多核或多CPU:
#cat /proc/cpuinfo
如果有多个类似以下的项目,则为多核或多CPU:
processor : 0
......
processor : 1
在编译后,我们执行命令:sched -a 0x1 -e ./桌面/sin
可以通过上面介绍的方法查看进程sin是否在同一个CPU上运行。
然后就可以通过系统监视器查看运行结果啦!
运行结果(橙色线):
还有一段Python的代码,运行是与上面类似的,这个来自于网上^_^:
#!/usr/bin/env python import itertools, math, time, sys time_period = float(sys.argv[1]) if len(sys.argv) > 1 else 30 # seconds time_slice = float(sys.argv[2]) if len(sys.argv) > 2 else 0.04 # seconds N = int(time_period / time_slice) for i in itertools.cycle(range(N)): busy_time = time_slice / 2 * (math.sin(2*math.pi*i/N) + 1) t = time.clock() + busy_time while t > time.clock(): pass time.sleep(time_slice - busy_time);
在控制台下输入命令:sched -a 0x1 -e python ./桌面/sin_p.py(此处写你源文件的路径).即可!