--------------------------------------------------
创建两个进程(实时进程)并在它们之间传送一个令牌,如此往返传送一定的次数。其中一个进程在读取令牌时就会引起阻塞。另一个进程发送令牌后等待其返回时也处于阻塞状态。发送令牌带来的开销与上下文切换带来的开销相比,可以忽略不计。 (利用管道传递令牌)
测试程序(1) 使用gettimeofday()获取当前时间
--------------------------------------------------
#include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <time.h> #include <sched.h> #include <sys/types.h> #include <unistd.h> //pipe() int main() { int x, i, fd[2], p[2]; char send = 's'; char receive; pipe(fd); pipe(p); struct timeval tv; struct sched_param param; param.sched_priority = 0; while ((x = fork()) == -1); if (x==0) { sched_setscheduler(getpid(), SCHED_FIFO, ¶m); gettimeofday(&tv, NULL); printf("Before Context Switch Time %u us\n", tv.tv_usec); for (i = 0; i < 10000; i++) { read(fd[0], &receive, 1); write(p[1], &send, 1); } exit(0); } else { sched_setscheduler(getpid(), SCHED_FIFO, ¶m); for (i = 0; i < 10000; i++) { write(fd[1], &send, 1); read(p[0], &receive, 1); } gettimeofday(&tv, NULL); printf("After Context SWitch Time %u us\n", tv.tv_usec); } return 0; }
测试结果(进程切换时间不超过5us)
--------------------------------------------------
Before Context Switch Time 617087 us
After Context SWitch Time 702420 us
702420us - 617087us = 85333 us
85333us / 20000 = 4.26665 us
进程切换时间为4.26665 us
注: cpu MHz : 2801.042
测试程序(2) 使用rdtsc()获取当前时间
--------------------------------------------------
#include <stdio.h> #include <stdlib.h> #include <sched.h> #include <sys/types.h> #include <unistd.h> long long rdtsc() { __asm("rdtsc"); } int main() { int x, i, fd[2], p[2]; char send = 's'; char receive; pipe(fd); pipe(p); struct sched_param param; param.sched_priority = 0; while ((x = fork()) == -1); if (x==0) { sched_setscheduler(getpid(), SCHED_FIFO, ¶m); printf("Before Context Switch Time %lld\n", rdtsc()); for (i = 0; i < 10000; i++) { read(fd[0], &receive, 1); write(p[1], &send, 1); } exit(0); } else { sched_setscheduler(getpid(), SCHED_FIFO, ¶m); for (i = 0; i < 10000; i++) { write(fd[1], &send, 1); read(p[0], &receive, 1); } printf("After Context Switch Time %lld\n", rdtsc()); } return 0; }
测试结果(进程切换时间不超过5us)
--------------------------------------------------
Before Context Switch Time 16208184381648
After Context Switch Time 16208424333213
16208424333213 - 16208184381648 = 239951565(clock cycle)
239951565 * 0.357009998 ns = 85665107.74074687 ns
85665107.74074687 ns / 20000 = 4283.255387037 ns = 4.283255387037 us
注: cpu MHz : 2801.042
---------------------------------------------
2 801 042 000Hz
clock cycle = 1 000 000 000 ns / 2 801 042 000 = 0.357009998ns
查看CPU性能参数
cat /proc/cpuinfo
测试程序(3) 可直接获得进程上下文切换时间
--------------------------------------------------
#include <stdio.h> #include <stdlib.h> //drand48() #include <sched.h> #include <sys/types.h> #include <unistd.h> #include <sys/time.h> //gettimeofday() #include <time.h> typedef unsigned long long u64; double clockCycleTimeS,clockRateHZ; /* 获取当前时间,返回秒 */ double second() { struct timeval tv; gettimeofday(&tv,0); return tv.tv_sec + 1e-6 * tv.tv_usec; } /* 获取当前时间,返回clock cycle */ u64 rdtsc() { u64 tsc; __asm__ __volatile__("rdtsc" : "=A" (tsc)); return tsc; } /* 睡眠us微秒 */ void selectsleep(unsigned us) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = us; select(0, 0, 0, 0, &tv); } /* 计算当前CPU的工作频率 */ void calibrate() { double sumx = 0; double sumy = 0; double sumxx = 0; double sumxy = 0; double slope; const unsigned n = 30; unsigned i; for (i=0; i<n; i++) { double breal,real,ticks; u64 bticks; breal = second(); bticks = rdtsc(); selectsleep((unsigned)(10000 + drand48() * 200000)); ticks = rdtsc() - bticks; real = second() - breal; sumx += real; sumxx += real * real; sumxy += real * ticks; sumy += ticks; } slope = ( (sumxy - (sumx*sumy) / n) / (sumxx - (sumx*sumx) / n) ); clockRateHZ = slope; clockCycleTimeS = 1.0 / slope; printf("%3.3f MHz\n", clockRateHZ*1e-6); } int main() { calibrate(); int x, i, p1[2], p2[2], time[2]; char send = 's'; char receive; u64 old_time; pipe(p1); pipe(p2); pipe(time); struct sched_param param; param.sched_priority = 0; while ((x = fork()) == -1); if (x==0) { sched_setscheduler(getpid(), SCHED_FIFO, ¶m); old_time = rdtsc(); write(time[1], &old_time, sizeof(old_time)); for (i = 0; i < 10000; i++) { read(p1[0], &receive, 1); write(p2[1], &send, 1); } exit(0); } else { u64 new_time; sched_setscheduler(getpid(), SCHED_FIFO, ¶m); for (i = 0; i < 10000; i++) { write(p1[1], &send, 1); read(p2[0], &receive, 1); } new_time = rdtsc(); read(time[0], &old_time, sizeof(old_time)); printf("Latency time = %3.3f us\n", 1e6 * (new_time - old_time) * clockCycleTimeS / 20000); } return 0; }
测试结果(Linux-2.6.21 + RealTime Patch)
--------------------------------------------------
2801.226 MHz
Latency time = 8.129 us