linux内核编程实验三
来源:互联网 发布:无名的裘德 知乎 编辑:程序博客网 时间:2024/05/16 11:42
内核的定时机制实验
问题 A
使用ITIMER_REAL型定时器实现一个gettimeofday(),将它设置为每秒产生一个信号,
并计算已经经过的秒数。
问题 B
使用以上实现的 gettimeofday()实现一个精确到微秒级的“闹钟”。
问题 C
实现以上一个父进程和两个子进程并发递归计算不同项数的fibonacci序列的程序,
分析每个进程三种类型定时器测出的时间关系。
解决问题A
一直被实现一个gettimeofday()这句话困惑,在不停思考如何实现这个方法。这是一个系统调用,由操作系统提供,涉及底层计算机架构的知识。这与我们的实验目的不符。gettimeofday函数用来获取系统时间的秒数、微秒数。通常可以在程序执行开始前获得一次时间,程序执行结束后获得一次时间,通过差的计算得到程序执行时间。(以1970年1月1日0时0分0秒为时间起点)
那么问题A的目的就明确了,就是实现为程序记时的功能,但不使用gettimeofday,要求使用setitimer和getitimer而已。
首先需要写一个SIGALRM信号处理函数,该函数用来计算时间,通过signal函数绑定。然后setitimer()。执行程序。最后通过getitimer获得计时器的值,与前面的时间一起计算出程序最终用时。
解决问题B
闹钟大家都用过,初始设置一个时间,到时间之后对用户产生提醒。因此,首先需要用户输入精确的时间,然后使用问题A的步骤绑定信号处理,设置计时器,超时之后,提醒用户时间到。获取系统当前时间并转化成微秒时间戳,然后将用户设置的时间转换成微秒时间戳,计算差值。设置计时器,让计时器只工作一次即可。
解决问题C
fork两个进程与父进程一起求fibonacci数。与问题A类似,只不过需要使用三种定时器。求fibonacci数时函数尽量选择递归,数不可太大,也不能过小,20-40之间即可,可以让实验结果更加明显。
p_realt.it_value.tv_sec = 9;
p_realt.it_value.tv_usec = 999999;
p_realt.it_interval.tv_sec = 9;
p_realt.it_interval.tv_usec = 999999;
这里其实是9秒999999微秒,但是按照10秒计算,理论上误差1微秒,实际上由于计算机执行速度的问题,这点误差可忽略。
当p_realt.it_interval.tv_sec = 9;p_realt.it_interval.tv_usec = 999999;
设置为0时,计时器只工作一次,否则计时器循环工作,it_value的值将变成it_interval。
代码如下:
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>#include <time.h> //for time()#include <sys/time.h> //for itimeval#include <sys/types.h> //for pid_t#include <sys/wait.h> //for waitpidvoid psig_real(int signum); //父进程3个信号处理函数void psig_virtual(int signum);void psig_prof(int signum);void c1sig_real(int signum); //子进程1的3个信号处理void c1sig_virtual(int signum);void c1sig_prof(int signum);void c2sig_real(int signum); //子进程2的3个信号处理void c2sig_virtual(int signum);void c2sig_prof(int signum);long fibonacci(unsigned int n); //求斐波那契//记时变量long p_real_secs=0,c1_real_secs=0,c2_real_secs=0;long p_virtual_secs=0,c1_virtual_secs=0,c2_virtual_secs=0;long p_prof_secs= 0,c1_prof_secs=0, c2_prof_secs=0;//计时器结构体struct itimerval p_realt, c1_realt, c2_realt;struct itimerval p_virtt, c1_virtt, c2_virtt;struct itimerval p_proft, c1_proft, c2_proft;//part A的信号处理void psig_real_gettime(int signum){ p_real_secs += 1;}//实现具有gettimeofday功能 ,接收一个函数void mygettimeofday(unsigned int i,long (*timefunction)(unsigned int)){ signal(SIGALRM,psig_real_gettime); p_realt.it_value.tv_sec = 0; //0 sec p_realt.it_value.tv_usec = 999999; //999999 usec p_realt.it_interval.tv_sec = 0; p_realt.it_interval.tv_usec = 999999; setitimer(ITIMER_REAL,&p_realt,NULL); timefunction(i); getitimer(ITIMER_REAL,&p_realt); printf("cost time %ld Sec : %ld Msec\n", p_real_secs, (999999 - p_realt.it_value.tv_usec) / 1000);}int wakeupme = 0; //part B闹钟void dealalarm(int signum) //闹钟处理函数{ wakeupme = 1;}int main(int argc,char **argv){ long fib = 0, microsecond; pid_t pid1, pid2; int msecond, usecond; struct timeval tv; if(argv[1][0] == '-' && argv[1][1] == 'a' && argc == 3) { printf("-----PART A-----\n"); mygettimeofday(atoi(argv[2]),fibonacci); return 0; } else if(argv[1][0] == '-' && argv[1][1] == 'b') { printf("-----PART B-----\n"); struct timeval tv; gettimeofday(&tv, NULL); struct tm *tmptime; tmptime = localtime(&tv.tv_sec); printf("now time > %d-%d-%d %d:%d:%d:%d:%d\n",tmptime->tm_year+1900,tmptime->tm_mon+1,tmptime->tm_mday,tmptime->tm_hour,tmptime->tm_min,tmptime->tm_sec,(int)tv.tv_usec/1000,(int)tv.tv_usec%1000); struct tm inputtime; int year, month, day, hour, minute, second; printf("set alarm : "); scanf("%d-%d-%d %d:%d:%d:%d:%d",&year,&month,&day,&hour, &minute,&second,&msecond,&usecond); inputtime.tm_year = year - 1900; inputtime.tm_mon = month - 1; inputtime.tm_mday = day; inputtime.tm_hour = hour; inputtime.tm_min = minute; inputtime.tm_sec = second; inputtime.tm_isdst = 0; inputtime.tm_wday = 0; inputtime.tm_yday = 0; microsecond = mktime(&inputtime) * 1000000 + msecond * 1000 + usecond; microsecond -= tv.tv_sec * 1000000 + tv.tv_usec; signal(SIGALRM,dealalarm); p_realt.it_value.tv_sec = microsecond / 1000000; p_realt.it_value.tv_usec = microsecond % 1000000; p_realt.it_interval.tv_sec = 0; p_realt.it_interval.tv_usec = 0; setitimer(ITIMER_REAL,&p_realt,NULL); while(!wakeupme); printf("wake time > %d-%d-%d %d:%d:%d:%d:%d\n",inputtime.tm_year+1900,inputtime.tm_mon+1,inputtime.tm_mday,inputtime.tm_hour,inputtime.tm_min,inputtime.tm_sec,msecond,usecond); return 0; } else if(argv[1][0] == '-' && argv[1][1] == 'c' && argc == 5) { printf("-----PART C-----\n"); //bind signal and function for parent process signal(SIGALRM,psig_real); signal(SIGVTALRM,psig_virtual); signal(SIGPROF,psig_prof); //init parent process 3 timer p_realt.it_interval.tv_sec = 9; p_realt.it_interval.tv_usec = 999999; p_realt.it_value.tv_sec = 9; p_realt.it_value.tv_usec = 999999; setitimer(ITIMER_REAL,&p_realt,NULL); p_virtt.it_interval.tv_sec = 9; p_virtt.it_interval.tv_usec = 999999; p_virtt.it_value.tv_sec = 9; p_virtt.it_value.tv_usec = 999999; setitimer(ITIMER_VIRTUAL,&p_virtt,NULL); p_proft.it_interval.tv_sec = 9; p_proft.it_interval.tv_usec = 999999; p_proft.it_value.tv_sec = 9; p_proft.it_value.tv_usec = 999999; setitimer(ITIMER_PROF,&p_proft,NULL); pid1 = fork(); if(pid1==0) { //bind signal and function for child1 process signal(SIGALRM,c1sig_real); signal(SIGVTALRM,c1sig_virtual); signal(SIGPROF,c1sig_prof); //init child1 process 3 timer c1_realt.it_interval.tv_sec = 0; c1_realt.it_interval.tv_usec = 999999; c1_realt.it_value.tv_sec = 0; c1_realt.it_value.tv_usec = 999999; setitimer(ITIMER_REAL,&c1_realt,NULL); c1_virtt.it_interval.tv_sec = 0; c1_virtt.it_interval.tv_usec = 999999; c1_virtt.it_value.tv_sec = 0; c1_virtt.it_value.tv_usec = 999999; setitimer(ITIMER_VIRTUAL,&c1_virtt,NULL); c1_proft.it_interval.tv_sec = 0; c1_proft.it_interval.tv_usec = 999999; c1_proft.it_value.tv_sec = 0; c1_proft.it_value.tv_usec = 999999; setitimer(ITIMER_PROF,&c1_proft,NULL); //get fibonacci fib = fibonacci(atoi(argv[2])); //get child1 3 time and fibnacci printf("Child1 fib = %ld\n", fib); getitimer(ITIMER_REAL,&c1_realt); printf("Child1 Real Time = %ld Sec : %ld Msec\n", c1_real_secs + 9-c1_realt.it_value.tv_sec,(999999-c1_realt.it_value.tv_usec)/1000); getitimer(ITIMER_VIRTUAL,&c1_virtt); printf("Child1 Virtual Time = %ld Sec : %ld Msec\n",c1_virtual_secs + 9-c1_virtt.it_value.tv_sec,(999999-c1_virtt.it_value.tv_usec)/1000); getitimer(ITIMER_PROF,&c1_proft); printf("Child1 Prof Time = %ld Sec : %ld Msec\n",c1_prof_secs + 9-c1_proft.it_value.tv_sec,(999999-c1_proft.it_value.tv_usec)/1000); exit(0); } else if((pid2=fork()) == 0) { //bind signal and function for child2 process signal(SIGALRM,c2sig_real); signal(SIGVTALRM,c2sig_virtual); signal(SIGPROF,c2sig_prof); //init child2 process 3 timer c2_realt.it_interval.tv_sec = 9; c2_realt.it_interval.tv_usec = 999999; c2_realt.it_value.tv_sec = 9; c2_realt.it_value.tv_usec = 999999; setitimer(ITIMER_REAL,&c2_realt,NULL); c2_virtt.it_interval.tv_sec = 9; c2_virtt.it_interval.tv_usec = 999999; c2_virtt.it_value.tv_sec = 9; c2_virtt.it_value.tv_usec = 999999; setitimer(ITIMER_VIRTUAL,&c2_virtt,NULL); c2_proft.it_interval.tv_sec = 9; c2_proft.it_interval.tv_usec = 999999; c2_proft.it_value.tv_sec = 9; c2_proft.it_value.tv_usec = 999999; setitimer(ITIMER_PROF,&c2_proft,NULL); //get fibonacci fib = fibonacci(atoi(argv[3])); //get child2 3 time and fibnacci printf("Child2 fib = %ld\n", fib); getitimer(ITIMER_REAL,&c2_realt); printf("Child2 Real Time = %ld Sec : %ld Msec\n",c2_real_secs+9-c2_realt.it_value.tv_sec,(999999-c2_realt.it_value.tv_usec)/ 1000); getitimer(ITIMER_VIRTUAL,&c2_virtt); printf("Child2 Virtual Time = %ld Sec : %ld Msec\n",c2_virtual_secs+9-c2_virtt.it_value.tv_sec,(999999-c2_virtt.it_value.tv_usec)/1000); getitimer(ITIMER_PROF,&c2_proft); printf("Child2 Prof Time = %ld Sec : %ld Msec\n",c2_prof_secs+9-c2_proft.it_value.tv_sec,(999999-c2_proft.it_value.tv_usec)/ 1000); exit(0); } else { //get fibonacci fib = fibonacci(atoi(argv[4])); //print parent 3 time and fibnacci printf("Parent fib = %ld\n", fib); getitimer(ITIMER_REAL,&p_realt); printf("Parent Real Time = %ld Sec : %ld Msec\n", p_real_secs + 9 - p_realt.it_value.tv_sec, (999999 - p_realt.it_value.tv_usec) / 1000); getitimer(ITIMER_VIRTUAL,&p_virtt); printf("Parent Virtual Time = %ld Sec : %ld Msec\n", p_virtual_secs + 9 - p_virtt.it_value.tv_sec, (999999 - p_virtt.it_value.tv_usec) / 1000); getitimer(ITIMER_PROF,&p_proft); printf("Parent Prof Time = %ld Sec : %ld Msec\n", p_prof_secs + 9 - p_proft.it_value.tv_sec, (999999 - p_proft.it_value.tv_usec) / 1000); //wait child process waitpid(pid1,NULL,0); waitpid(pid2,NULL,0); } }}//parent process signal functionvoid psig_real(int signum){ p_real_secs += 10;}void psig_virtual(int signum){ p_virtual_secs += 10;}void psig_prof(int signum){ p_prof_secs += 10;}//child1 process signal functionvoid c1sig_real(int signum){ c1_real_secs += 10;}void c1sig_virtual(int signum){ c1_virtual_secs += 10;}void c1sig_prof(int signum){ c1_prof_secs += 10;}//child2 process signal functionvoid c2sig_real(int signum){ c2_real_secs += 10;}void c2sig_virtual(int signum){ c2_virtual_secs += 10;}void c2sig_prof(int signum){ c2_prof_secs += 10;}//get fibonacci by nlong fibonacci(unsigned int n){ if(n == 1 || n == 2) return 1; return fibonacci(n-1)+fibonacci(n-2);}
- linux内核编程实验三
- Linux内核分析实验三
- Linux内核分析实验三
- Linux内核分析:实验三
- Linux内核分析:实验三
- 实验三.Linux内核编译实验
- Linux内核编程实验二
- linux内核编程实验一
- Linux内核|实验六 内核模块编程
- linux内核实验三实现过程
- Linux内核|实验三 安装、配置、编译Linux内核
- linux内核模块编程三
- Linux内核|实验一 Shell编程
- Linux内核分析:实验三--内核启动过程分析
- 主题:《Linux内核模块编程指南》(三)
- 《Linux内核编程指南》心得之三
- Linux内核编程三:uboot移植
- Linux内核开发三:多进程编程
- codeforces 617E (莫队算法)
- 36. Valid Sudoku
- TCP/IP 卷一 链路层
- 科目二相关事项
- Python Logging模块-Logger,Handler,Formatter
- linux内核编程实验三
- zoj3460(二分图,拆点,二分)
- 剑指offer(旋转数组中的最小的数字)
- POJ 2407 Relatives
- iOS学习使用NSURLSession
- 145. Binary Tree Postorder Traversal
- ElasticSearch教程(一)——简介与安装
- android GetWindow总结
- Android Studio 注解插件Android ButterKnife Zelezny使用教程