哈工大操作系统之进程与线程(Lab3 进程运行轨迹的跟踪与统计 超详细全流程分析)
发布日期:2021-06-30 22:31:47 浏览次数:2 分类:技术文章

本文共 25533 字,大约阅读时间需要 85 分钟。

文章目录


专栏博客链接


相关查阅链接



前引


我觉得整个Lab做下来其实还是挺不容易的

因为其实实验册中还是有很多东西没有说
但是需要我们自己去做去补充
而且还需要我们对很多函数有一定的理解
整个Lab在做什么 整个Lab的实验流程是怎么样的

这个Lab3还与Lab1 和 Lab2其中的一部分有关

Lab1 和 Lab2有些地方没弄懂或者没做的
这个Lab有的地方也会卡住

话不多说 直接进入这个Lab吧

待会我还要去上体育课 麻了还要体测


实验注意与提醒


如果是用实验楼 蓝桥云课的hxd的话

其实我这边是建议冲一个月会员的
反正可以去网上找优惠码30
但是可以随时保存环境

前几个Lab因为 忘记保存或者做到晚上

还差一点没有完成 就导致我很多程序没有存下来
并且会清空
这几个Lab的话 一个月之内肯定是可以完成的
所以我这边还是推荐整一个会员

第二个就是

还是对于操作系统的一些小细节的问题
比如我们挂载hdc 卸载hdc时 或者启动虚拟机的时候
一定一定要注意 我们当前文件系统一定不要指向 hdc中的目录
不然的话 指向的目录就会被破坏 你之后那个文件就会访问不了 切记


预处理(正式开始实验)


实验前预先准备


一、

我们需要准备预先知识 就是实验准备的
Ubuntu和Linux文件交换的知识
这个我觉得应该做到现在是知道的
我前面的几个Lab也是用到过

二、

这个Lab要结合我们上一个Lab中用到的
我们添加一个调用程序 我们需要修改MakeFile文件
如果上个Lab没有做明白的话 这里会有个地方卡住


实验册预浏览


我们刚开始可以不用 一章一章一页一页的仔细看

先总览的看一下Lab在说什么 我们要达成的目标是什么

process.c,50%

日志文件建立成功,5%
能向日志文件输出信息,5%
5 种状态都能输出,10%(每种 2 %)
调度算法修改,10%
实验报告,20%

看完后 其实我的完成顺序是

日志文件建立->向日志文件输入信息->创建process.c并进行调试->
调试中肯定会发现自己输入信息的有的地方有误修正日志输出->运行./stat_log.py再次调试->结束实验

我的调度算法修改就没有做了 如果感兴趣还想做的

这里我贴一个链接 我觉得这个博客也讲的挺细致的

如果我有的地方卡住了 或者出错调试了半天 我也会借鉴别人的结果

看看自己哪里有问题 不然的话会浪费大量时间


实验中须知知识


fork() 和 wait() 和 waitpid()函数

必须要求有所掌握及能使用
但是这个可以不急 可以等着我们把日志文件创建及输出弄完后再来弄


开始编写文件


提前读Log文件


分析过程实验册已经讲的很清楚了

这里就不再重复了

我们先修改代码

move_to_user_mode();	setup((void *) &drive_info);	/* for visiting log document in prc0 in advance 	这是后面加进去的*/	(void) open("/dev/tty0",O_RDWR,0);	(void) dup(0);	(void) dup(0);	(void) open("/var/process.log",O_CREAT|O_TRUNC|O_WRONLY,0666);	/*这上面部分是需要添加的*/		if (!fork()) {
/* we count on this going ok */ init(); }

写入Log文件部分


向系统添加fprintk函数


这里主要说的是如何向系统添加fprintk函数

这里实验册说 函数就已经给出来了 编写难度太大
然后推荐我们的是放到
kernel\printk.c
我记得之前我们的Lab2中就让我们添加系统调用
但那个是系统调用 这个fprintk函数其实本质是调用了其他的系统调用
所以我们不需要在系统调用表中修改 调用数 函数名
我们就按照实验册中说的把这个函数添加到 kernel\printk.c

下面是实验册直接给出的在 kernel\printk.c 添加之后的代码

/* *  linux/kernel/printk.c * *  (C) 1991  Linus Torvalds *//* * When in kernel-mode, we cannot use printf, as fs is liable to * point to 'interesting' things. Make a printf with fs-saving, and * all is well. */#include 
#include
#include
/*之后添加进去的*/#include "linux/sched.h"#include "sys/stat.h"/*之后添加进去的*/static char buf[1024];/*之后添加进去的*/static char logbuf[1024];/*之后添加进去的*/extern int vsprintf(char * buf, const char * fmt, va_list args);int printk(const char *fmt, ...){
va_list args; int i; va_start(args, fmt); i=vsprintf(buf,fmt,args); va_end(args); __asm__("push %%fs\n\t" "push %%ds\n\t" "pop %%fs\n\t" "pushl %0\n\t" "pushl $buf\n\t" "pushl $0\n\t" "call tty_write\n\t" "addl $8,%%esp\n\t" "popl %0\n\t" "pop %%fs" ::"r" (i):"ax","cx","dx"); return i;}/*之后添加进去的*/int fprintk(int fd, const char *fmt, ...){
va_list args; int count; struct file * file; struct m_inode * inode; va_start(args, fmt); count=vsprintf(logbuf, fmt, args); va_end(args); if (fd < 3) {
__asm__("push %%fs\n\t" "push %%ds\n\t" "pop %%fs\n\t" "pushl %0\n\t" "pushl $logbuf\n\t" "pushl %1\n\t" "call sys_write\n\t" "addl $8,%%esp\n\t" "popl %0\n\t" "pop %%fs" ::"r" (count),"r" (fd):"ax","cx","dx"); } else {
if (!(file=task[0]->filp[fd])) return 0; inode=file->f_inode; __asm__("push %%fs\n\t" "push %%ds\n\t" "pop %%fs\n\t" "pushl %0\n\t" "pushl $logbuf\n\t" "pushl %1\n\t" "pushl %2\n\t" "call file_write\n\t" "addl $12,%%esp\n\t" "popl %0\n\t" "pop %%fs" ::"r" (count),"r" (file),"r" (inode):"ax","cx","dx"); } return count;}/*之后添加进去的*/

这里我卡了一会 因为我发现当我make all 编译内核时

这个地方的函数是出错的
我就一直在想 究竟怎么把这个函数给存进去
我就忽然想起来 上一个Lab 实验册说了一句话
里面的函数链接编译都是按照 MakeFile 里面的来链接的
因为我们这里把我们之后添加的头文件也给写进去
所以我们编写的函数就无法找到对应的头文件

所以我们就打开 MakeFile 按照人家的链接方式依葫芦画瓢的

路径 kernel\MakeFile
把我们之后添加的头文件编译进去(应该是需要按照我们添加的顺序的)

printk.s printk.o: printk.c ../include/stdarg.h ../include/stddef.h \  ../include/linux/kernel.h \/*之后添加的部分*/  ../include/linux/sched.h \  ../include/sys/stat.h/*之后添加的部分*/

之后编译 我还是发现不对 这个时候我随便点了几个头文件

进去看了看 发现是有函数声明的
就类似 sys_open这些函数
这个时候我就想到了 我们添加的函数 还没有在一个头文件中声明
而我们需要声明的函数 应该是在printk函数声明的头文件里
所以我就找到了在
/include/linux/kernel.h
于是就加了一句声明 此时编译就发现通过了

在这里插入图片描述


写入Log文件函数fprintk分析


下面的实验册部分给出了两个示例

// 向stdout打印正在运行的进程的IDfprintk(1, "The ID of running process is %ld", current->pid);// 向log文件输出跟踪进程运行轨迹fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'R', jiffies);

不难看出 最后这个函数

fprintk(3, "%ld\t%c\t%ld\n", current->pid, 'R', jiffies);
这个是我们的核心函数 也是我们最后要经常使用的函数
用法也给出来了 我们直接用即可

这里顺带再介绍一下jiffies 是记录时钟中断数

并且是一个全局变量 一次时钟中断实验册分析出来是10ms 1/100s


寻找状态切换点


‘N’ ‘J’ ‘R’ ‘W’ ‘E’ 符号含义


X 可以是 N、J、R、W 和 E 中的任意一个,分别表示进程新建(N)、进入就绪态(J)、进入运行态®、进入阻塞态(W) 和退出(E);


向log写入添加代码 copy_process.c


实验册中其实写的还是挺清晰的

就是让我们写在kernel\fork.c的的copy_process中
这里才是我们实际创建的进程

对于这个函数我就简单分析一下

我就贴出来 我修改部分的代码

'N' 位置代码区

p = (struct task_struct *) get_free_page();	if (!p)	return -EAGAIN;	task[nr] = p;	*p = *current;	/* NOTE! this doesn't copy the supervisor stack */	p->state = TASK_UNINTERRUPTIBLE;	p->pid = last_pid;	//这里应该是创建了新的进程之后	//对p进程赋值 拿末尾的进程号赋值给p	//我认为 这里就可以说 这里开始创建新进程了 所以我就选择在这里fprintk	//并且还设置了state 更说明了这里应该设置	fprintk(3,"%ld\t%c\t%ld\n",p->pid,'N',jiffies);	p->father = current->pid;	p->counter = p->priority;

'J' 位置代码区

set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));	set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));	p->state = TASK_RUNNING;	/* do this last, just in case */	//	修改state状态是很明显的状态转移赋值	fprintk(3,"%ld\t%c\t%ld\n",p->pid,'J',jiffies);	//		return	last_pid;

向log写入添加代码 sche.c


因为添加的小部分函数太多

人懒 我就直接把sche.c的代码全复制下来
按照那个实验册的函数 应该是能找到我添加的位置的

温馨提醒 利用 ctrl+f 快速定位fprintk 可以快速找到对应修改函数位置及代码

/* *  linux/kernel/sched.c * *  (C) 1991  Linus Torvalds *//* * 'sched.c' is the main kernel file. It contains scheduling primitives * (sleep_on, wakeup, schedule etc) as well as a number of simple system * call functions (type getpid(), which just extracts a field from * current-task */#include 
#include
#include
#include
#include
#include
#include
#include
#define _S(nr) (1<<((nr)-1))#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))void show_task(int nr,struct task_struct * p){ int i,j = 4096-sizeof(struct task_struct); printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state); i=0; while (i
>2 ] ;struct { long * a; short b; } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };/* * 'math_state_restore()' saves the current math information in the * old math state array, and gets the new ones from the current task */void math_state_restore(){ if (last_task_used_math == current) return; __asm__("fwait"); if (last_task_used_math) { __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387)); } last_task_used_math=current; if (current->used_math) { __asm__("frstor %0"::"m" (current->tss.i387)); } else { __asm__("fninit"::); current->used_math=1; }}/* * 'schedule()' is the scheduler function. This is GOOD CODE! There * probably won't be any reason to change this, as it should work well * in all circumstances (ie gives IO-bound processes good response etc). * The one thing you might take a look at is the signal-handler code here. * * NOTE!! Task 0 is the 'idle' task, which gets called when no other * tasks can run. It can not be killed, and it cannot sleep. The 'state' * information in task[0] is never used. */void schedule(void){ int i,next,c; struct task_struct ** p;/* check alarm, wake up any interruptible tasks that have got a signal */ for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) if (*p) { if ((*p)->alarm && (*p)->alarm < jiffies) { (*p)->signal |= (1<<(SIGALRM-1)); (*p)->alarm = 0; } if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) && (*p)->state==TASK_INTERRUPTIBLE) { (*p)->state=TASK_RUNNING; fprintk(3,"%ld\t%c\t%ld\n",(*p)->pid,'J',jiffies); } }/* this is the scheduler proper: */ while (1) { c = -1; next = 0; i = NR_TASKS; p = &task[NR_TASKS]; while (--i) { if (!*--p) continue; if ((*p)->state == TASK_RUNNING && (*p)->counter > c) c = (*p)->counter, next = i; } if (c) break; for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) if (*p) (*p)->counter = ((*p)->counter >> 1) + (*p)->priority; } if(task[next]->pid != current->pid) { if(current->state == TASK_RUNNING) fprintk(3,"%ld\t%c\t%ld\n", current->pid,'J',jiffies); fprintk(3,"%ld\t%c\t%ld\n", task[next]->pid,'R',jiffies); } switch_to(next);}int sys_pause(void){ current->state = TASK_INTERRUPTIBLE; if(current->pid) fprintk(3,"%ld\t%c\t%ld\n",current->pid,'W',jiffies); schedule(); return 0;}void sleep_on(struct task_struct **p){ struct task_struct *tmp; if (!p) return; if (current == &(init_task.task)) panic("task[0] trying to sleep"); tmp = *p; *p = current; current->state = TASK_UNINTERRUPTIBLE; fprintk(3,"%ld\t%c\t%ld\n",current->pid,'W',jiffies); schedule(); if (tmp) { tmp->state=0; fprintk(3,"%ld\t%c\t%ld\n",tmp->pid,'J',jiffies); }}void interruptible_sleep_on(struct task_struct **p){ struct task_struct *tmp; if (!p) return; if (current == &(init_task.task)) panic("task[0] trying to sleep"); tmp=*p; *p=current;repeat: current->state = TASK_INTERRUPTIBLE; fprintk(3,"%ld\t%c\t%ld\n",current->pid,'W',jiffies); schedule(); if (*p && *p != current) { (**p).state=0; goto repeat; } *p=NULL; if (tmp) { tmp->state=0; fprintk(3,"%ld\t%c\t%ld\n",tmp->pid,'J',jiffies); }}void wake_up(struct task_struct **p){ if (p && *p) { (**p).state=0; fprintk(3,"%ld\t%c\t%ld\n",(**p).pid,'J',jiffies); *p=NULL; }}/* * OK, here are some floppy things that shouldn't be in the kernel * proper. They are here because the floppy needs a timer, and this * was the easiest way of doing it. */static struct task_struct * wait_motor[4] = { NULL,NULL,NULL,NULL};static int mon_timer[4]={ 0,0,0,0};static int moff_timer[4]={ 0,0,0,0};unsigned char current_DOR = 0x0C;int ticks_to_floppy_on(unsigned int nr){ extern unsigned char selected; unsigned char mask = 0x10 << nr; if (nr>3) panic("floppy_on: nr>3"); moff_timer[nr]=10000; /* 100 s = very big :-) */ cli(); /* use floppy_off to turn it off */ mask |= current_DOR; if (!selected) { mask &= 0xFC; mask |= nr; } if (mask != current_DOR) { outb(mask,FD_DOR); if ((mask ^ current_DOR) & 0xf0) mon_timer[nr] = HZ/2; else if (mon_timer[nr] < 2) mon_timer[nr] = 2; current_DOR = mask; } sti(); return mon_timer[nr];}void floppy_on(unsigned int nr){ cli(); while (ticks_to_floppy_on(nr)) sleep_on(nr+wait_motor); sti();}void floppy_off(unsigned int nr){ moff_timer[nr]=3*HZ;}void do_floppy_timer(void){ int i; unsigned char mask = 0x10; for (i=0 ; i<4 ; i++,mask <<= 1) { if (!(mask & current_DOR)) continue; if (mon_timer[i]) { if (!--mon_timer[i]) wake_up(i+wait_motor); } else if (!moff_timer[i]) { current_DOR &= ~mask; outb(current_DOR,FD_DOR); } else moff_timer[i]--; }}#define TIME_REQUESTS 64static struct timer_list { long jiffies; void (*fn)(); struct timer_list * next;} timer_list[TIME_REQUESTS], * next_timer = NULL;void add_timer(long jiffies, void (*fn)(void)){ struct timer_list * p; if (!fn) return; cli(); if (jiffies <= 0) (fn)(); else { for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++) if (!p->fn) break; if (p >= timer_list + TIME_REQUESTS) panic("No more time requests free"); p->fn = fn; p->jiffies = jiffies; p->next = next_timer; next_timer = p; while (p->next && p->next->jiffies < p->jiffies) { p->jiffies -= p->next->jiffies; fn = p->fn; p->fn = p->next->fn; p->next->fn = fn; jiffies = p->jiffies; p->jiffies = p->next->jiffies; p->next->jiffies = jiffies; p = p->next; } } sti();}void do_timer(long cpl){ extern int beepcount; extern void sysbeepstop(void); if (beepcount) if (!--beepcount) sysbeepstop(); if (cpl) current->utime++; else current->stime++; if (next_timer) { next_timer->jiffies--; while (next_timer && next_timer->jiffies <= 0) { void (*fn)(void); fn = next_timer->fn; next_timer->fn = NULL; next_timer = next_timer->next; (fn)(); } } if (current_DOR & 0xf0) do_floppy_timer(); if ((--current->counter)>0) return; current->counter=0; if (!cpl) return; schedule();}int sys_alarm(long seconds){ int old = current->alarm; if (old) old = (old - jiffies) / HZ; current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; return (old);}int sys_getpid(void){ return current->pid;}int sys_getppid(void){ return current->father;}int sys_getuid(void){ return current->uid;}int sys_geteuid(void){ return current->euid;}int sys_getgid(void){ return current->gid;}int sys_getegid(void){ return current->egid;}int sys_nice(long increment){ if (current->priority-increment>0) current->priority -= increment; return 0;}void sched_init(void){ int i; struct desc_struct * p; if (sizeof(struct sigaction) != 16) panic("Struct sigaction MUST be 16 bytes"); set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); p = gdt+2+FIRST_TSS_ENTRY; for(i=1;i
a=p->b=0; p++; p->a=p->b=0; p++; }/* Clear NT, so that we won't have troubles with that later on */ __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); ltr(0); lldt(0); outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ set_intr_gate(0x20,&timer_interrupt); outb(inb_p(0x21)&~0x01,0x21); set_system_gate(0x80,&system_call);}

向log写入添加代码 exit.c


下面这部分是 exit.c 中含有修改添加 fprintk的全代码

ctrl+f 搜索fprintk 可以快速定位

/* *  linux/kernel/exit.c * *  (C) 1991  Linus Torvalds */#include 
#include
#include
#include
#include
#include
#include
int sys_pause(void);int sys_close(int fd);void release(struct task_struct * p){ int i; if (!p) return; for (i=1 ; i
32) return -EINVAL; if (priv || (current->euid==p->euid) || suser()) p->signal |= (1<<(sig-1)); else return -EPERM; return 0;}static void kill_session(void){ struct task_struct **p = NR_TASKS + task; while (--p > &FIRST_TASK) { if (*p && (*p)->session == current->session) (*p)->signal |= 1<<(SIGHUP-1); }}/* * XXX need to check permissions needed to send signals to process * groups, etc. etc. kill() permissions semantics are tricky! */int sys_kill(int pid,int sig){ struct task_struct **p = NR_TASKS + task; int err, retval = 0; if (!pid) while (--p > &FIRST_TASK) { if (*p && (*p)->pgrp == current->pid) if ((err=send_sig(sig,*p,1))) retval = err; } else if (pid>0) while (--p > &FIRST_TASK) { if (*p && (*p)->pid == pid) if ((err=send_sig(sig,*p,0))) retval = err; } else if (pid == -1) while (--p > &FIRST_TASK) { if ((err = send_sig(sig,*p,0))) retval = err; } else while (--p > &FIRST_TASK) if (*p && (*p)->pgrp == -pid) if ((err = send_sig(sig,*p,0))) retval = err; return retval;}static void tell_father(int pid){ int i; if (pid) for (i=0;i
pid != pid) continue; task[i]->signal |= (1<<(SIGCHLD-1)); return; }/* if we don't find any fathers, we just release ourselves *//* This is not really OK. Must change it to make father 1 */ printk("BAD BAD - no father found\n\r"); release(current);}int do_exit(long code){ int i; free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); for (i=0 ; i
father == current->pid) { task[i]->father = 1; if (task[i]->state == TASK_ZOMBIE) /* assumption task[1] is always init */ (void) send_sig(SIGCHLD, task[1], 1); } for (i=0 ; i
filp[i]) sys_close(i); iput(current->pwd); current->pwd=NULL; iput(current->root); current->root=NULL; iput(current->executable); current->executable=NULL; if (current->leader && current->tty >= 0) tty_table[current->tty].pgrp = 0; if (last_task_used_math == current) last_task_used_math = NULL; if (current->leader) kill_session(); current->state = TASK_ZOMBIE; current->exit_code = code; fprintk(3,"%ld\t%c\t%ld\n",current->pid,'E',jiffies); tell_father(current->father); schedule(); return (-1); /* just to suppress warnings */}int sys_exit(int error_code){ return do_exit((error_code&0xff)<<8);}int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options){ int flag, code; struct task_struct ** p; verify_area(stat_addr,4);repeat: flag=0; for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) { if (!*p || *p == current) continue; if ((*p)->father != current->pid) continue; if (pid>0) { if ((*p)->pid != pid) continue; } else if (!pid) { if ((*p)->pgrp != current->pgrp) continue; } else if (pid != -1) { if ((*p)->pgrp != -pid) continue; } switch ((*p)->state) { case TASK_STOPPED: if (!(options & WUNTRACED)) continue; put_fs_long(0x7f,stat_addr); return (*p)->pid; case TASK_ZOMBIE: current->cutime += (*p)->utime; current->cstime += (*p)->stime; flag = (*p)->pid; code = (*p)->exit_code; release(*p); put_fs_long(code,stat_addr); return flag; default: flag=1; continue; } } if (flag) { if (options & WNOHANG) return 0; current->state=TASK_INTERRUPTIBLE; fprintk(3,"%ld\t%c\t%ld\n",current->pid,'W',jiffies); schedule(); if (!(current->signal &= ~(1<<(SIGCHLD-1)))) goto repeat; else return -EINTR; } return -ECHILD;}

运行虚拟机质检process.log


编译内核部分 具体我就不说了

进入 linux-0.11 make all即可

注意:

退出时记得
记住 sync 记住 sync
输入命令sync 即可向磁盘同步输入 防止文件未被写入

如何质检虚拟机process.log呢

其实还是非常简单的 就是我们可以等待一下虚拟机运行一段时间
sync 得到process.log process.log文件在 hdc/var中
之后我们挂载 hdc 进入linux-0.11把文件copy出来

退出时记得

记住 sync 记住 sync

至于怎么进入linux-0.11 交换文件

这个问题应该重新去看看 实验册第一章 详细介绍了
如果不想看的也可以去看一下我写的Lab2的博客
里面也详细介绍了如何挂载 与注意事项

质检部分 如果还没有写process.c

只是先测验一下 ok 我们拿那个log和我们实验册中的 示例log做一个对比
如下

示例log

1    N    48    //进程1新建(init())。此前是进程0建立和运行,但为什么没出现在log文件里?1    J    49    //新建后进入就绪队列0    J    49    //进程0从运行->就绪,让出CPU1    R    49    //进程1运行2    N    49    //进程1建立进程2。2会运行/etc/rc脚本,然后退出2    J    491    W    49    //进程1开始等待(等待进程2退出)2    R    49    //进程2运行3    N    64    //进程2建立进程3。3是/bin/sh建立的运行脚本的子进程3    J    642    E    68    //进程2不等进程3退出,就先走一步了1    J    68    //进程1此前在等待进程2退出,被阻塞。进程2退出后,重新进入就绪队列1    R    684    N    69    //进程1建立进程4,即shell4    J    691    W    69    //进程1等待shell退出(除非执行exit命令,否则shell不会退出)3    R    69    //进程3开始运行3    W    754    R    755    N    107    //进程5是shell建立的不知道做什么的进程5    J    1084    W    1085    R    1084    J    1105    E    111    //进程5很快退出4    R    1114    W    116    //shell等待用户输入命令。0    R    116    //因为无事可做,所以进程0重出江湖4    J    239    //用户输入命令了,唤醒了shell4    R    2394    W    2400    R    240……

log如果没问题 或者只是很少部分和这个有误差

那我们可以进入下一步了
编写process.c了


编写process.c


其实思路 需要我们有个大概的轮廓

对于多进程的编写 可以参照我上面给出的链接
linux 多进程编程示例 这里我就不再详细说我怎么编写的了

这里我还对linux-0.11编译有很大的怨气

因为我觉得编译真的很不方便
我不知道为什么有的时候 我命名int都能说
undefined reference to这些信息
这里我浪费了很多时间调试

process.c代码

#include 
#include
#include
#include
//需要这些头文件 新添加#include
#include
//新添加#define HZ 100void cpuio_bound(int last, int cpu_time, int io_time);//主函数改写 新添加int main(int argc, char * argv[]){ pid_t child1,child2,childret; child1 = fork(); if(child1 == -1) { printf("child1 fork error!"); exit(-1); } else if(child1 == 0) { cpuio_bound(10,1,1); exit(0); } else { child2 = fork(); if(child2 == -1) { printf("child2 fork error!"); exit(-1); } else if(child2 == 0) { cpuio_bound(10,3,2); exit(0); } childret = waitpid(child1,NULL,0); if(childret == -1) { printf("child1 fork error!\n");exit(0);} else { printf("the child1 exit pid is %d\n!",childret);} childret = waitpid(child2,NULL,0); if(childret == -1) { printf("child2 fork error!\n");exit(0);} else { printf("the child2 exit pid is %d\n!",childret);} } return 0;}//改写主函数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(&current_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; }}

运行./stat_log.py 得到结果


这对于我来说就是最后一步了

再简单说一下 我们需要最后把process.c在linux-0.11下编译 运行后
等待我们结束process.c的多线程工作
之后sync 得到process.log 我们把其
复制到ubuntu中

stat_log.py 在home\teacher

我们把他复制到 我们的ubuntu process.log旁边
这样就可以用相对路径直接运行了
之后 我们先对脚本命令修改权限 chmod +x stat_log.py
运行命令看下图示例
在这里插入图片描述

最后提一嘴 你需要把你运行的进程进程号记下来

这样子 你最后跟踪的进程才是你想要的 在运行stat_log.py时限制统计进程号
防止统计到一些系统调用进程了


结束实验(含我的process.log 和 部分stat.py 运行结果)


这里就贴一下我的process.log 和 stat.py部分运行结果

可做参考

process.log

1	N	481	J	480	J	481	R	482	N	492	J	491	W	492	R	493	N	633	J	642	J	643	R	643	W	682	R	682	E	741	J	741	R	744	N	744	J	741	W	744	R	745	N	1065	J	1074	W	1075	R	1074	J	1095	E	1104	R	1104	W	1150	R	1154	J	6984	R	6984	W	6980	R	6984	J	7184	R	7184	W	7180	R	7184	J	7424	R	7424	W	7420	R	7424	J	7654	R	7664	W	7660	R	7664	J	8104	R	8104	W	8100	R	8104	J	8364	R	8364	W	8360	R	8364	J	8714	R	8714	W	8720	R	8724	J	8894	R	8894	W	8890	R	8894	J	9244	R	9244	W	9240	R	9244	J	9294	R	9294	W	9290	R	9294	J	9774	R	9774	W	9770	R	9774	J	9924	R	9924	W	9920	R	9924	J	10134	R	10134	W	10130	R	10134	J	10184	R	10184	W	10180	R	10184	J	11064	R	11064	W	11060	R	11064	J	11114	R	11114	W	11110	R	11114	J	11354	R	11354	W	11350	R	11354	J	11564	R	11564	W	11560	R	11564	J	11604	R	11604	W	11600	R	11604	J	11774	R	11774	W	11770	R	11774	J	11884	R	11884	W	11880	R	11884	J	11984	R	11984	W	11980	R	11984	J	12704	R	12704	W	12700	R	12704	J	12914	R	12914	W	12910	R	12914	J	13374	R	13374	W	13370	R	13374	J	13574	R	13574	W	13570	R	13574	J	13804	R	13804	W	13800	R	13804	J	13994	R	13994	W	13990	R	13994	J	14224	R	14224	W	14220	R	14224	J	14494	R	14494	W	14490	R	14494	J	14684	R	14694	W	14690	R	14694	J	15444	R	15444	W	15440	R	15444	J	15774	R	15774	W	15770	R	15774	J	16304	R	16304	W	16300	R	16304	J	16514	R	16514	W	16510	R	16514	J	18064	R	18064	W	18060	R	18064	J	18144	R	18144	W	18140	R	18144	J	18334	R	18334	W	18330	R	18334	J	18584	R	18584	W	18580	R	18584	J	19024	R	19024	W	19020	R	19024	J	19214	R	19214	W	19210	R	19214	J	19884	R	19894	W	19890	R	19894	J	20144	R	20144	W	20140	R	20144	J	20374	R	20374	W	20370	R	20374	J	20524	R	20524	W	20520	R	20524	J	20934	R	20934	W	20930	R	20944	J	21194	R	21194	W	21190	R	21194	J	21494	R	21504	W	21500	R	21504	J	21724	R	21724	W	21720	R	21724	J	22014	R	22014	W	22010	R	22024	J	22294	R	22294	W	22290	R	22294	J	22534	R	22534	W	22530	R	22534	J	22794	R	22794	W	22790	R	22794	J	23864	R	23864	W	23860	R	23864	J	24244	R	24244	W	24240	R	24244	J	24544	R	24544	W	24550	R	24554	J	24744	R	24744	W	24740	R	24744	J	24774	R	24774	W	24770	R	24774	J	25214	R	25214	W	25210	R	25214	J	25264	R	25264	W	25260	R	25264	J	25534	R	25534	W	25530	R	25534	J	25664	R	25664	W	25660	R	25664	J	25814	R	25814	W	25810	R	25814	J	26124	R	26124	W	26120	R	26124	J	26364	R	26364	W	26360	R	26364	J	26794	R	26794	W	26790	R	26794	J	27014	R	27014	W	27010	R	27014	J	27114	R	27114	W	27110	R	27114	J	27404	R	27404	W	27400	R	27404	J	27494	R	27504	W	27500	R	27504	J	27714	R	27714	W	27710	R	27714	J	28484	R	28484	W	28480	R	28484	J	28724	R	28724	W	28720	R	28724	J	29864	R	29864	W	29860	R	29864	J	30084	R	30084	W	30080	R	30083	J	30673	R	30673	W	30670	R	30674	J	32814	R	32814	W	32810	R	32814	J	33074	R	33074	W	33070	R	33074	J	33484	R	33486	N	33506	J	33504	W	33516	R	33517	N	33557	J	33566	W	33567	R	33567	E	34116	J	34116	R	34118	N	34128	J	34136	W	34138	R	34138	E	35176	J	35176	R	35179	N	35189	J	35186	W	35189	R	35189	E	35476	J	35476	R	354710	N	354910	J	35496	W	354910	R	354910	E	36296	J	36296	R	36296	E	36314	J	36314	R	363111	N	363111	J	36324	W	363211	R	36324	J	363411	E	36354	R	36354	W	36350	R	36354	J	39134	R	39134	W	39130	R	39144	J	39314	R	39314	W	39310	R	39314	J	39584	R	39584	W	39580	R	39584	J	39844	R	39844	W	39840	R	39844	J	40194	R	40194	W	40200	R	40204	J	40384	R	40384	W	40380	R	40384	J	40554	R	40554	W	40550	R	40554	J	40984	R	40984	W	40980	R	40984	J	40994	R	40994	W	40990	R	40994	J	41224	R	41224	W	41220	R	41224	J	41524	R	41524	W	41520	R	41524	J	41684	R	41684	W	41680	R	41684	J	41944	R	41944	W	41940	R	41944	J	42184	R	42184	W	42190	R	42194	J	42404	R	42404	W	42400	R	42404	J	42584	R	42584	W	42580	R	42584	J	42714	R	42714	W	42710	R	42714	J	42904	R	42904	W	42900	R	42904	J	43134	R	431312	N	431412	J	43144	W	431512	R	431513	N	431613	J	431714	N	431714	J	431712	W	431714	R	431714	J	433213	R	433213	J	434714	R	434714	J	436213	R	436213	J	437714	R	437714	J	439213	R	439213	J	440714	R	440714	J	442213	R	442213	J	443714	R	443714	J	445213	R	445213	J	446714	R	446714	J	448213	R	448213	J	449714	R	449714	J	451213	R	451213	W	452214	R	452213	J	462714	J	462713	R	462713	J	465614	R	465614	J	467113	R	467113	J	468614	R	468614	J	470113	R	470113	J	471614	R	471614	J	473113	R	473113	J	474614	R	474614	J	476113	R	476113	J	477614	R	477614	J	479113	R	479113	W	480214	R	480214	W	48170	R	481713	J	490313	R	490314	J	492613	J	492614	R	492614	W	492613	R	492613	W	50030	R	500314	J	502714	R	502713	J	511614	J	511613	R	511613	J	514414	R	514414	J	515913	R	515913	J	517414	R	517414	J	518913	R	518913	J	520414	R	520414	J	521913	R	521913	J	523414	R	523414	J	524913	R	524913	J	526414	R	526414	J	527913	R	527913	W	529114	R	529113	J	539614	J	539613	R	539613	J	542514	R	542514	J	544013	R	544013	J	545514	R	545514	J	547013	R	547013	J	548514	R	548514	W	548613	R	548613	W	55270	R	552714	J	558714	R	558714	W	55870	R	558713	J	562813	R	562813	E	562812	J	562812	R	562812	W	56280	R	562914	J	568814	R	568814	E	568812	J	568812	R	568812	E	56894	J	56894	R	568915	N	568915	J	56904	W	569015	R	56904	J	569215	E	56934	R	56934	W	56930	R	56934	J	60144	R	60144	W	60140	R	60144	J	60434	R	60434	W	60430	R	60434	J	60884	R	60884	W	60880	R	60884	J	61084	R	61084	W	61080	R	61084	J	62154	R	62154	W	62150	R	62154	J	62404	R	62404	W	62400	R	62404	J	62824	R	62824	W	62820	R	62824	J	63054	R	63054	W	63050	R	63054	J	64344	R	64344	W	64340	R	64344	J	64674	R	64674	W	64670	R	64674	J	65124	R	65124	W	65120	R	65124	J	65364	R	65364	W	65360	R	65364	J	68584	R	685816	N	686016	J	68604	W	686116	R	6861

stat_log.py 运行部分 切换进程结果

在这里插入图片描述


完结撒花


结束惹 恰饭去了 晚上8:44了

在这里插入图片描述

转载地址:https://love6.blog.csdn.net/article/details/117292470 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Leetcode 452. 用最少数量的箭引爆气球(DAY 125) ---- 贪心算法学习期
下一篇:Leetcode 991. 坏了的计算器(DAY 124)---- 贪心算法学习期

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年05月04日 02时54分52秒