操作系统实验3:进程运行轨迹的跟踪与统计
实验内容请查看实验指导手册
绪论
开始实验之前,需要弄清楚实验具体要做什么:
- 参考
home/teacher
目录下的process.c
编写一个能够创建多个并行子进程的程序。 - 在linux0.11系统的内核中,添加和修改程序,使得我们启动linux0.11并且运行
process.c
后,系统能够打印出一个监视进程运行的process.log
文件
一、实验内容
1.编写process.c文件
process.c代码如下:
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/times.h>
#include <sys/types.h>
#define HZ 100
void cpuio_bound(int last, int cpu_time, int io_time);
/*
1. 所有子进程都并行运行,每个子进程的实际运行时间一般不超过30秒;
2. 父进程向标准输出打印所有子进程的id,并在所有子进程都退出后才退出;
*/
int main(int argc, char * argv[])
{
pid_t n_proc[10]; /*10个子进程 PID*/
int i;
for(i=0;i<10;i++)
{
n_proc[i] = fork();
/*如果fork 失败*/
if(n_proc[i] < 0 )
{
printf("Failed to fork child process %d!\n",i+1);
return -1;
}
else if(n_proc[i] == 0)/*子进程*/
{
cpuio_bound(20,2*i,20-2*i); /*每个子进程都占用20s*/
exit(0); /*执行完cpuio_bound 以后,结束该子进程,下一次循环,该子进程不会fork出新的进程*/
}
/*一直都是那一个父进程在fork出子进程*/
}
/*打印所有子进程PID*/
for(i=0;i<10;i++)
printf("Child PID: %d\n",n_proc[i]);
/*等待所有子进程完成;
这里不是很完美,由于wait函数的特点,父进程只要有回收了一个子进程,就会结束自己*/
wait(&i); /*Linux 0.11 上 gcc要求必须有一个参数, gcc3.4+则不需要*/
return 0;
}
/* cpuio_bound函数无需修改,直接用 */
void cpuio_bound(int last, int cpu_time, int io_time)
{
struct tms start_time, current_time;
clock_t utime, stime;
int sleep_time;
while (last > 0)
{
times(&start_time);
do
{
times(¤t_time);
utime = current_time.tms_utime - start_time.tms_utime;
stime = current_time.tms_stime - start_time.tms_stime;
} while ( ( (utime + stime) / HZ ) < cpu_time );
last -= cpu_time;
if (last <= 0 )
break;
sleep_time=0;
while (sleep_time < io_time)
{
sleep(1);
sleep_time++;
}
last -= sleep_time;
}
}
process.c
的保存路径为~/oslab/hdc/usr/root/
如果你对fork()函数和wait()函数的作用以及工作方式还不是很清楚的话,建议你花点时间,看一下相关文章,这应该会帮助你更好的理解process.c
程序的功能作用
2.日志文件
2.1 修改main.c
为了让linux0.11在启动之后,就创建process.log
并开始记录,需要将~/oslab/linux-0.11/init/main.c
文件做如下修改:
//……
move_to_user_mode();
/***************添加开始***************/
setup((void *) &drive_info);
// 建立文件描述符0和/dev/tty0的关联
(void) open("/dev/tty0",O_RDWR,0);
//文件描述符1也和/dev/tty0关联
(void) dup(0);
// 文件描述符2也和/dev/tty0关联
(void) dup(0);
(void) open("/var/process.log",O_CREAT|O_TRUNC|O_WRONLY,0666);
/***************添加结束***************/
if (!fork()) {
/* we count on this going ok */
init();
}
//……
2.2 添加fprintk()函数
在内核状态下,write()
功能失效,其原理等同于《系统调用》实验中不能在内核状态调用 printf()
,只能调用printk()
。编写可在内核调用的 write() 的难度较大,所以这里直接给出源码。它主要参考了 printk()
和 sys_write()
而写成的:因为和 printk()