进程运行轨迹的跟踪
来源:互联网 发布:淘宝笔记本电脑 编辑:程序博客网 时间:2024/05/21 05:05
一、源代码
/* process.c Linux下多进程程序,父进程循环创建NUM_CPROC个子进程,每个子进程执行cpuio_bound程序,父进程循 环打印子进程的PID,之后阻塞等待子进程结束返回。*/#include<stdio.h>#include<unistd.h>#include<time.h>#include<sys/times.h>#include<sys/types.h>#define NUM_CPROC 50#define LAST_TIME 25 #define RATE (LAST_TIME/NUM_CPROC)#define HZ 100void cpuio_bound(int last,int cpu_time,int io_time);int main(int argc, char *argv[]){ pid_t n_cproc[NUM_CPROC]; int i; for(i=0;i<NUM_CPROC;i++){ n_cproc[i]=fork();//创建子进程 if(n_cproc[i]==0){ cpuio_bound(LAST_TIME, RATE*i, LAST_TIME-RATE*i);//子进程执行cpuio_bound程序 return 0; }else if(n_cproc[i]<0){ printf("Failed to fork child process %d!", i+1);//创建失败 return -1; } } for(i=0;i<NUM_CPROC;i++) printf("Child PID: %d\n", n_cproc[i]);//打印子进程PID wait(NULL);//等待子进程结束(阻塞) return 0;}//由子进程调用,执行last秒,其中cpu操作花费cpu_time秒,io操作花费io_time秒。void cpuio_bound(int last,int cpu_time,int io_time){ clock_t beg_time,end_time; int sleep_time; double num; while(last>0){ //模拟CPU操作,执行cpu_time秒 beg_time=times(NULL); num=1.012345 do{ num*=1.010101 end_time=times(NULL); }while(((end_time-beg_time)/HZ)<cpu_time); last-=(end_time-beg_time)/HZ; if(last<0) break;//模拟IO操作,执行io_time秒 sleep_time=0; while(sleep_time<io_time){ sleep(1); sleep_time++; } last-=sleep_time; }}
/* cal_time.sh 上面的多进程程序写完可以在实体机上先用脚本测一下运行时间*/#!/bin/bashstart=$(date "+%s")./processend=$(date "+%s")time=$((end-start))echo "time used:$time seconds"#输出:time used:25 seconds#本来以为时间会很长(51个进程每个运行25秒),但实际上一共用时25seconds。#这就是多进程的魅力啊
/* linux-0.11/init/main.c 为了更早的记录追踪进程的状态信息和生命周期,在任务0切换到用户模式下立刻创建文件描述符0,1,2,3分 别和stdin,stdout,stderr,/var/process.log关联。之后创建子进程1,将继承这些文件描述符。我 们在追踪的时候就可以直接在内核空间fprintk进程状态到文件描述符3上,即写入process.log里面。*/ move_to_user_mode();//切换到用户模式 setup((void *) &drive_info);//加载文件系统 (void) open("/dev/tty0",O_RDWR,0);//打开/dev/tty0,建立文件描述符0和/dev/tty0的关联 (void) dup(0); //让文件描述符1也和/dev/tty0关联 (void) dup(0); //让文件描述符2也和/dev/tty0关联 //在文件描述符3上打开/var/process.log文件(无则创建,有则清空,只写打开,UGO权限为读写) (void) open("/var/process.log", O_CREAT|O_TRUNC|O_WRONLY,0666); if (!fork()) { //创建进程1,执行init函数 init(); }
//linux-0.11/kernel/fork.c//copy_process复制进程 p->start_time = jiffies;//设置子进程开始运行时间(当前滴答数) fprintk(3,"%d\tN\t%d\n",p->pid,jiffies);//打印N (新建)标志 ... p->state = TASK_RUNNING;//子进程处于可执行状态,时间片一切换到即可执行 fprintk(3,"%d\tJ\t%d\n",p->pid,jiffies);//打印J(就绪)标志
//linux-0.11/kernel/sched.c//schedule调度函数if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&(*p)->state==TASK_INTERRUPTIBLE){ (*p)->state=TASK_RUNNING;//可中断睡眠任务得到信号之后置为就绪状态 fprintk(3,"%d\tJ\t%d\n",(*p)->pid,jiffies);}...if(current->pid!=task[next]->pid){ if(current->state==TASK_RUNNING) //当前执行的进程时间片用完了,设为就绪状态 fprintk(3,"%d\tJ\t%d\n",current->pid,jiffies); //切换到下一个进程,设置下一个进程状态为R(运行)状态 fprintk(3,"%d\tR\t%d\n",task[next]->pid,jiffies); } switch_to(next);int sys_pause(void){ //转换当前任务状态为可中断的等待状态 current->state = TASK_INTERRUPTIBLE; if(current->pid!=0) fprintk(3,"%d\tW\t%d\n",current->pid,jiffies);//打印W(阻塞)标志 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,"%d\tW\t%d\n",current->pid,jiffies); schedule(); //schedule执行别的进程,只有当进程被唤醒重新执行时才会返回执行后续的语句,把比它早进入等 //待队列的一个进程唤醒,置为就绪状态。 if (tmp){ tmp->state=0; fprintk(3,"%d\tJ\t%d\n",tmp->pid,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,"%d\tW\t%d\n",current->pid,jiffies); schedule(); //只有当进程被唤醒才会返回这里 if (*p && *p != current) { (**p).state=0; //进程被唤醒且不是当前任务时置为就绪状态 fprintk(3,"%d\tJ\t%d\n",(*p)->pid,jiffies); goto repeat; } *p=NULL; if (tmp){ tmp->state=0; //队列空了,如果tmp不为NULL,亦置为就绪状态,原因同上。 fprintk(3,"%d\tJ\t%d\n",tmp->pid,jiffies); }}void wake_up(struct task_struct **p){ if (p && *p) { (**p).state=0;//进程被唤醒置为就绪状态 fprintk(3,"%d\tJ\t%d\n",(*p)->pid,jiffies); *p=NULL; }}
//linux-0.11/kernel/exit.c//do_exit执行退出current->state = TASK_ZOMBIE;//设置当前进程为僵死状态fprintk(3,"%d\tE\t%d\n",current->pid,jiffies);//打印E(退出)标志//sys_waitpidif (flag) {//flag被置位说明子进程既不是停止也不是僵死 if (options & WNOHANG) return 0;//没有子进程处于退出或者终止态就返回 current->state=TASK_INTERRUPTIBLE;//设置子进程为中断睡眠状态 fprintk(3,"%d\tW\t%d\n",current->pid,jiffies); schedule(); if (!(current->signal &= ~(1<<(SIGCHLD-1)))) goto repeat; else return -EINTR; }
二、运行结果
linux-0.11编译运行process.c结果如图:
我们会发现/var/下面多了一个process.log文件,拷贝到实体机上查看
//开始阶段进程状态大多数为新建、就绪、运行、阻塞
//后面开始有进程终止退出
用Python脚本处理日志文件
//这里我们排除了ID为0,1,2,3,4,5,57,58的进程,因为它们不是我们process.c创建的进程,为了后续时间片
//修改之后的比较,我们选择排除它们。
三、修改时间片
/* 进程时间片的设置只存在于进程创建和调度中,这里我们选择将时间片分别设置为原来的一半和两倍,观察 结果。*///linux-0.11/kernel/fork.c p->counter = p->priority; p->counter = p->priority/2;//时间片减半 p->counter = p->priority*2;//时间片加倍//Linux-0.11/kernel/sched.c //就绪进程的counter均为0,则重新给所有进程的counter减半并加上优先级 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) if (*p) (*p)->counter = ((*p)->counter >> 1) + (*p)->priority; for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) if (*p) (*p)->counter = ((*p)->counter >> 1) + (*p)->priority/2;//减半 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) if (*p) (*p)->counter = ((*p)->counter >> 1) + (*p)->priority*2;//加倍
重复上面的运行步骤,得到结果
//时间片减半
//时间片加倍
四、结果分析
当时间片分别减半、正常、加倍的时候,CPU burst和IO burst几乎没有什么变化,有变化的只是Turnaround 时间和waiting 时间,这里我们统计一下平均值。
这里我们很容易发现随着时间片的增长,进程的周转时间和等待时间增加。这是因为时间片长了,进程不容易切换到其他进程,即响应其他进程的速度变慢,其他进程等待时间增长(如果是交互式的话即前台响应变慢会更明显),但时间片变长可以减少进程切换次数,增加CPU执行指令的吞吐量。
五、参考资料
- HIT-OSLAB-MANUAL进程运行轨迹的跟踪
- UNIX系统中struct tms 分析
- Linux 进程状态
- What is meant by CPU Burst and I/O Burst?
0 0
- 进程运行轨迹的跟踪
- 进程运行轨迹的跟踪与统计
- 实验4 进程运行轨迹的跟踪与统计
- 哈工大操作系统试验3 进程运行轨迹的跟踪与统计
- 操作系统原理与实践4--进程运行轨迹的跟踪与统计
- 操作系统之进程轨迹跟踪
- 跟踪导弹轨迹的向量计算
- 轨迹跟踪——二维轨迹跟踪
- GPS轨迹 跟踪路径
- HTML 5 APIs 是如何跟踪用户轨迹的
- Android——BroadCaseReceiver,跟踪轨迹获取稳定的GPS
- Linux 进程查看 跟踪 运行总结
- python绘制铅球的运行轨迹
- 轨迹,你的轨迹
- MapKit画出运行轨迹
- 路径与轨迹、路径规划与轨迹规划、路径跟踪与轨迹跟踪
- 使用数组设置小车运行的轨迹(方便)
- CreateProcess进程创建的内核跟踪分析
- 我的编码规范
- Spring注入依赖对象
- VS2010水晶报表组件下载地址
- ios支付宝集成遇到的问题?
- 【Android图像处理】图像处理之-放大镜特效
- 进程运行轨迹的跟踪
- c++指针类型转换
- Extjs4 封装dropzonejs组件 2016.12.29
- php模拟get提交
- java基础学习总结——java读取properties文件总结
- 小弟有几个iOS开发问题,望大侠给予解决,谢谢!
- 请问各位大神,在OC中,这是个什么语法格式。
- Android 反编译:加固前后对比
- 新人求助,为什么我用了SDWebImage加载cell的图片,但是cell滚动还是卡