实验一:创建程序
题目:fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值: 1)在父进程中,fork返回新创建子进程的进程ID; 2)在子进程中,fork返回0; 3)如果出现错误,fork返回一个负值;
#include<stdio.h> #include<unistd.h> int main() { int p1,p2; while((p1=fork())==-1); /*创建子进程p1*/ if(p1==0) /*子进程创建成功*/ printf("child1!"); else { while((p2=fork())==-1); /*创建子进程p2*/ if(p2==0) /*子进程创建成功*/ printf("child2! \n"); else printf("parent! \n"); } return 0; }
实验二:进程控制
修改已编好的程序, 将每个进程的输出由单个字符改为一句话,再观察程序执行时屏幕. 上出现的现象,并分析其原因。如果在程序中。使用系统调用lockf(来给每个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。
#include<unistd.h> #include<stdio.h> int main() { int p1,p2,i; while((p1=fork())==-1);//创建子进程p1,这个是一个技巧,直到创建子进程成功为止 if(p1==0){//当P1为0则创建进程成功 lockf(1,1,0); for(i=0;i<50;i++)//循环50次来输出 child进程 printf("child %d\n",i); lockf(1,0,0); } else //p1创建失败则执行下面的 { while((p2=fork())==-1);//判断p2进程创建失败,则执行空语句。 if(p2==0){//如果p2创建成功,执行以下 lockf(1,1,0);//加锁第一个参数为stdout(标准输出设备描述符 for(i=0;i<50;i++) printf("son %d\n",i); lockf(1,0,0);} //解锁 else {lockf(1,1,0); for(i=0;i<50;i++) printf("daughter %d\n",i); lockf(1,0,0); } } }
实验三:进程管理
1. 目的和要求: 通过实验理解进程的概念,进程的组成( PcB 结构),进程的并发执行和操作系统进行进程管理的相关原语(主要是进程的创建、执行、撤消)。 2. 实验内容 用 c 语言编程模拟进程管理,至少要有:创建新的进程;查看运行进程;换出某个进程;杀死运行进程以及进程之间通信等功能。
#include "stdio.h" #include "curses.h" #include "stdlib.h" struct PCB_type { int pid; int priority; int size; char content[10]; int state; /* 0表示不在内存,1表示在内存,2表示挂起*/ }; struct PCB_type storage[20]; int num=0,hang_up=0,bj,i,j,pid;/*定义相关参数变量*/ /*********************创建新进程*************************/ void create() { if(num>=20) /*判断是否有存储空间*/ printf("\n 内存已满,请删除或挂起其他程序"); else{ for(i=0;i<20;i++) if(storage[i].state==0) break; /*按顺序在内存中寻找创建新进程的空间*/ printf("\n请输入新建进程的pid值\n"); scanf("%d",&storage[i].pid); for(j=0;j<i;j++) /*判断是否之前已存储相同pid进程*/ if(storage[j].pid==storage[i].pid) { printf("\n该进程已存在于内存中"); return; } printf("\n请输入新进程的优先级 \n" ); scanf("%d",&storage[i].priority); printf("\n请输入新进程的大小\n" ); scanf("%d",&storage[i].size); printf("\n请输入新进程的内容\n" ); scanf("%s",&storage[i].content); storage[i].state=1; /*将进程状态设为1,表示在内存中*/ num++;/*内存中进程数目加一*/ } } /********************查看当前运行进程**************************/ void run() { bj=0; for(i=0;i<20;i++) if(storage[i].state==1) /*若进程状态设为1,表示在内存中,输出查看*/ {printf("\n pid=%d",storage[i].pid); printf(" priority=%d",storage[i].priority); printf(" size=%d",storage[i].size); printf(" content=%s",storage[i].content); bj=1;/*存在于内存中的进程标记为1 */ } if(bj==0) printf("\n当前没有运行该进程\n" );/*标记为0,表示该进程未创建于内存中*/ } /********************换出进程***************************/ void swap_out() {if(num==0) /*num=0,表示内存中无进程*/ { printf("\n当前没有运行的进程\n" ); return; } printf("\n请输入要换出的进程的pid值\n" ); scanf("%d",&pid); bj=0; for(i=0;i<20;i++) { if(pid==storage[i].pid) { if(storage[i].state==1) {storage[i].state=2; /*将该进程的状态设为挂起*/ hang_up++; printf("\n该进程已成功挂起换出\n" ); } else if(storage[i].state==0) printf("\n要换出的进程不存在\n" ); else printf("\n要换出的进程已经被挂起\n" ); bj=1;break; } } if(bj==0) printf("\n要换出的进程不存在\n" ); } /********************杀死进程***************************/ void kill() { if(num==0) { printf("\n当前没有运行的进程\n" ); return; } printf("\n请输入要杀死的进程的pid值\n" ); scanf("%d",&pid); bj=0; for(i=0;i<20;i++) { if(pid==storage[i].pid) { if(storage[i].state==1) {storage[i].state=0; /*将该进程的状态设为不在内存中*/ num--; /*内存中的进程数目减少一个*/ printf("\n该进程已成功杀死\n" ); } else if(storage[i].state==0) printf("\n要杀死的进程不存在\n" ); else printf("\n要杀死的进程已经被挂起\n" );/*剩余状态为2,挂起*/ bj=1;break; } } if(bj==0) printf("\n要杀死的进程不存在\n" ); } /********************唤醒进程***************************/ void rouse() { if(num==0) { printf("当前没有运行的进程\n"); return; } if(hang_up==0) /*hang_up=0,表示没有挂起的进程*/ { printf("\n当前没有换出的进程\n"); return; } printf("\n请输入要唤醒的进程的pid值:\n"); scanf("%d",&pid); for(i=0;i<20;i++){ if(pid==storage[i].pid) { if(storage[i].state==2) {storage[i].state=1; /*将该进程的状态设为挂起*/ hang_up--; num++; printf("\n该进程已成功唤醒\n" ); } else if(storage[i].state==0) printf("\n要唤醒的进程不存在\n" ); else printf("\n要唤醒的进程已经在内存中\n" ); } } } /********************主程序***************************/ int main() {int serial,n=1,i; for(i=0;i<20;i++) storage[i].state=0; /*使所有进程都初始设为不在内存中*/ while(n){ printf("\n**********************************************"); printf("\n* 进程演示系统 *"); printf("\n**********************************************"); printf("\n 1.创建新的进程 2.查看运行进程"); printf("\n 3.换出某个进程 4.杀死运行进程"); printf("\n 5.唤醒某个进程 6.退出程序 "); printf("\n**********************************************"); printf("\n请选择(1~6):"); scanf("%d",&serial); switch(serial) { case 1: create( ); break; case 2 :run(); break; case 3 :swap_out();break; case 4 :kill();break; case 5 :rouse();break; case 6 :exit(0); default: n=0; break; } } return 0; }
实验四:进程通信
1. 编制一个程序,使其实现进程的软中断通信。 2. 要求:使用系统调用 fork ()创建两个子进程,再用系统调用 signal ()让父进程捕捉键盘上来的中断信号(即 DEL 键)当捕捉到中断信号后,父进程用系统调用 kill ()向两个进程发出信号子进程捕捉到信号后分别输出下列信息后终止; 3. Child Process 1 is Killed by Parent! 4. Child Process 2 is Killed by Parent! 5. 父进程等待两个子进程终止后,输出如信息后终止: 6. Parent Process is killed! 7. 在上面的程序中增加语句 signal ( SIGINT SIG _IGN ),和signal ( SIGQUIT SIG _IGN )
#include <unistd.h> #include <signal.h> #include <stdio.h> #include<stdlib.h> #include <sys/wait.h> /*子写父读,互斥访问*/ int pid1,pid2; int main( ) { int fd[2]; char inpipe[100]; pipe(fd); /*创建一个管道*/ while ((pid1=fork( ))==-1); if(pid1==0) { lockf(fd[1],1,0); sleep(3); write(fd[1],"Child 1 is sending a message!\n",30); /*向管道写长为50字节的串*/ lockf(fd[1],0,0); //文件描述 锁定和解锁 0表示从文件的当前位置到文件尾。 exit(0); } else { while((pid2=fork( ))==-1); if(pid2==0) { int i=0; lockf(fd[1],1,0); /*互斥*/ sleep(3); write(fd[1],"Child 2 is sending a message! \n",30); while(++i){ write(fd[1],"Child 2 is sending a message! ",30); //printf("%dKb\n",15*i/1024); } lockf(fd[1],0,0); exit(0); } else { printf("父进程准备读取管道中的内容!\n"); wait(0); /*同步 阻塞父进程*/ /*从管道中读长为15字节的串*/ read(fd[0],inpipe,30); printf("%s ",inpipe); read(fd[0],inpipe,30); printf("%s\n",inpipe); exit(0); } } }
实验五:进程调度算法
1. 进程调度算法 2. 小组讨论 3. 讨论结果分析先来先去进程调度算法
#include<iostream> #include<string> #include<queue> using namespace std; typedef struct pcb { string pName; //进程名 float arriveTime;//到达时间 float serviceTime;//服务时间 float estimatedRunningtime;//估计运行时间 float startTime;//开始运行时间 float finishTime;//完成运行时间 float turnaroundTime;//周转时间 float weightedTuraroundTime;//带权周转时间 char state;//状态 bool operator<(const pcb &a)const { return arriveTime > a.arriveTime; } }PCB; void createProcess(priority_queue<PCB> &p, int n) {//创建n个进程 cout << endl << endl << "创建进程" << endl; PCB r;//工作结点 for (int i = 0; i<n; i++) { cout << "请输入第" << i + 1 << "个进程的名字、到达时间、服务时间(例如:A 12 8):"; cin >> r.pName; cin >> r.arriveTime; cin >> r.serviceTime; r.startTime = 0; r.finishTime = 0; r.estimatedRunningtime = r.serviceTime; r.turnaroundTime = 0; r.weightedTuraroundTime = 0; p.push(r); } } void printProcess(priority_queue<PCB> p) {//输出所有进程的信息 PCB q; cout << "进程名\t到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间" << endl; while (p.size() != 0) { q = p.top(); cout << q.pName << "\t" << q.arriveTime << "\t " << q.serviceTime << "\t "; cout << q.startTime << "\t " << q.finishTime << "\t " << q.turnaroundTime << "\t " << q.weightedTuraroundTime << endl; p.pop(); } cout << endl << endl; } void runProcess(priority_queue<PCB> &p, priority_queue<PCB> &q, int n) {//运行进程 PCB s; float finishTimeOfPriorProcess; for (int i = 0; i<n; i++) { s = p.top(); if (i == 0) {//当前进程是第一个进程 while (s.estimatedRunningtime != 0) {//输出当前运行进程的信息 cout << "正在运行的进程" << endl; cout << "进程名\t到达时间 服务时间 已运行时间 还剩运行时间" << endl; cout << s.pName << "\t" << s.arriveTime << "\t " << s.serviceTime << "\t "; cout << s.serviceTime - s.estimatedRunningtime << "\t " << s.estimatedRunningtime << endl; s.estimatedRunningtime--; //当前进程的估计运行时间减1 } s.startTime = s.arriveTime; s.finishTime = s.startTime + s.serviceTime; s.turnaroundTime = s.finishTime - s.arriveTime; s.weightedTuraroundTime = float(s.turnaroundTime*1.0 / s.serviceTime); s.state = 'C'; finishTimeOfPriorProcess = s.finishTime; } else {//当前进程不是第一个进程 while (s.estimatedRunningtime != 0) { cout << "正在运行的进程" << endl; cout << "进程名\t到达时间 服务时间 已运行时间 还剩运行时间" << endl; cout << s.pName << "\t" << s.arriveTime << "\t " << s.serviceTime << "\t "; cout << s.serviceTime - s.estimatedRunningtime << "\t " << s.estimatedRunningtime << endl; s.estimatedRunningtime--;//当前进程的估计运行时间减1 } s.startTime = finishTimeOfPriorProcess>s.arriveTime ? finishTimeOfPriorProcess : s.arriveTime; s.finishTime = s.startTime + s.serviceTime; s.turnaroundTime = s.finishTime - s.arriveTime; s.weightedTuraroundTime = float(s.turnaroundTime*1.0 / s.serviceTime); s.state = 'C'; finishTimeOfPriorProcess = s.finishTime; } q.push(s); p.pop(); cout << "进程" << s.pName << "执行结束之后就绪队列中的进程" << endl; printProcess(p); } cout<< endl << endl; } int main() { priority_queue<PCB> p,q; int n; cout << "请输入进程的个数:"; cin >> n; createProcess(p, n); runProcess(p, q, n); cout << "所有进程执行结束之后的相关情况" << endl << endl; printProcess(q); getchar(); getchar(); return 0; }
实验六:动态分区存储管理的内存分配回收
1. 实验目的 通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解,熟悉可变分区存 储管理的内存分配和回收。 2. 实验内容 ①确定内存空间分配表; ②采用最优适应算法完成内存空间的分配和回收; ③编写主函数对所做工作进行测试。
#include <stdio.h> #include "curses.h" #include<string.h> #define MAX 100 struct partition{ char pn[10]; int begin; int size; int end; char status; }; typedef struct partition PART; PART p[MAX]; int n; void init() { p[0].begin = 0; p[0].end = 100; strcpy(p[0].pn, "SYSTEM"); p[0].size = 100; p[0].status = 'u'; p[1].begin = 100; p[1].end = 1000; strcpy(p[1].pn, "-----"); p[1].size = p[1].end - p[1].begin; p[1].status = 'f'; n = 2; } void show() { int x = 1; int i; printf("空闲区表Free:\n"); printf("\tNo.\tproname\tbegin\tsize\tstatus\n"); for(i = 0; i < n; i++) { if(p[i].status=='f') printf("\tNo.%d\t%s\t%4d\t%4d\t%4c\n", x++, p[i].pn, p[i].begin, p[i].size, p[i].status); } printf("\n\n=========================================================\n"); printf("已分配分区表Used:\n"); printf("\tNo.\tproname\tbegin\tsize\tstatus\n"); for(i = 0, x = 1; i < n; i++) { if(p[i].status=='u') printf("\tNo.%d\t%s\t%4d\t%4d\t%4c\n", x++, p[i].pn, p[i].begin, p[i].size, p[i].status); } printf("\n\n=========================================================\n"); printf("内存使用情况:\nprintf sorted by address:\n"); printf("\tNo.\tproname\tbegin\tsize\tstatus\n"); printf("\t--------------------------------------\n"); for(i = 0, x = 1; i < n; i++) { printf("\tNo.%d\t%s\t%4d\t%4d\t%4c\n", x++, p[i].pn, p[i].begin, p[i].size, p[i].status); } } void input() { int x = 1; while(x) { printf("\n\n请输入进程名称:"); scanf("%s", &p[n].pn); for(int i = 0; i < n; i++) { x = 0; if(strcmp(p[n].pn, p[i].pn) == 0) { x = 1; printf("进程名称已存在,请重新输入!"); break; } } } x = 1; while(x) { printf("\n请输入进程需要的空间大小:"); scanf("%d", &p[n].size); for(int i = 0; i < n; i++) { if(p[i].size >=p[n].size) { x = 0; break; } } if(x) printf("找不到适合的空间,请重新输入!"); } } void caculate(int i) { int x=0; p[i].end = p[i].begin+p[i].size; p[i-1].end=p[i-1].begin+p[i-1].size; if(p[i+1].status=='f' && p[i].end==p[i+1].begin) { x=1; p[i+1].begin=p[i].begin; p[i+1].size=p[i].size+p[i+1].size; for(int j=i;j<n;j++) { p[j]=p[j+1]; } n=n-1; } if(p[i-1].status=='f' && p[i-1].end==p[i].begin) { x=1; p[i].begin=p[i-1].begin; p[i].size=p[i-1].size+p[i].size; strcpy(p[i].pn, "-----"); p[i].status = 'f'; for(int k=i;k<n;k++) { p[k-1]=p[k]; } n=n-1; } if(x==0) { strcpy(p[i].pn, "-----"); p[i].status = 'f'; } } void recycle() { char name[50]; int x = 1; while(x) { printf("\n请输入进程名称:"); scanf("%s", &name); for(int i = 0; i < n; i++) { if(strcmp(name, p[i].pn) == 0) { x = 0; caculate(i); break; } } if(x==1) { printf("没找到请重新输入\n"); } } } void first() { PART temp[MAX]; for(int i = 0;i < n; i++) { if(p[i].status=='f') { if(p[i].size >= p[n].size) { temp[0]=p[i]; p[i]=p[n]; p[n]=temp[0]; p[i].end=p[n].begin+p[i].size; p[i].status='u'; p[i].begin=p[n].begin; p[n].begin=p[i].end; p[n].end=temp[0].end; p[n].status='f'; p[n].size=p[n].size-p[i].size; n++; break; } } } } void best() { int min=10000; int a; PART temp[MAX]; for(int i=0;i<n;i++) { if(p[i].status=='f' && p[i].size >= p[n].size) { if(p[i].size < min) { min = p[i].size; a=i; } } } if(p[a].size >= p[n].size) { temp[0]=p[a]; p[a]=p[n]; p[n]=temp[0]; p[a].end=p[n].begin+p[a].size; p[a].status='u'; p[a].begin=p[n].begin; p[n].begin=p[a].end; p[n].end=temp[0].end; p[n].status='f'; p[n].size=p[n].size-p[a].size; n++; } } void bad() { int max=0; int a; PART temp[MAX]; for(int i=0;i<n;i++) { if(p[i].status=='f') { if(p[i].size > max) { max = p[i].size; a=i; } } } if(p[a].size >= p[n].size) { temp[0]=p[a]; p[a]=p[n]; p[n]=temp[0]; p[a].end=p[n].begin+p[a].size; p[a].status='u'; p[a].begin=p[n].begin; p[n].begin=p[a].end; p[n].end=temp[0].end; p[n].status='f'; p[n].size=p[n].size-p[a].size; n++; } } int show_menu() { int x; printf("\n(1)首次适应算法"); // printf("\n(2)循环首次适应算法"); printf("\n(2)最佳适应算法"); printf("\n(3)最坏适应算法"); printf("\n请选择一种分配方式:"); scanf("%d", &x); while(x < 1 || x > 4) { printf("\n输入错误!"); printf("\n请选择一种分配方式:"); scanf("%d", &x); } return x; } int main(void) { int choose1,choose2; printf("初始化:设置内存总容量为 1000k\n系统从低地址部分开始占用 100k\n\n"); init(); show(); while(1) { printf("请选择:1.分配内存 2.回收内存 3.结束\n"); scanf("%d",&choose1); if(choose1==1) { input(); choose2=show_menu(); if(choose2==1) { first(); } if(choose2==2) { best(); } if(choose2==3) { bad(); } show(); } if(choose1==2) { recycle(); show(); } if(choose1==3) break; } return 0; }
实验7页面置换算法
●最佳置换算法、 先进先出置换算法、最近最久未使 用置换算法●小组讨论 ●讨论结果分析(页面置换次数及缺页率)
#include<iostream> #include <string> #define maxPage 100 using namespace std; int phyBlockNum; int show(int * block,int ispageL) { string str[2]= {" 否"," 是"}; for(int i=0; i<phyBlockNum; i++) { if(block[i]==-1) cout<<" \t"; else cout<<block[i]<<"\t"; } cout<<str[ispageL]<<endl; } bool inblock(int *block,int page) { for(int i=0; i<phyBlockNum; i++) { if(page==block[i]) return 1; } return 0; } void FIFO(int* block,int* page) { for(int i=0; i<phyBlockNum; i++) block[i]=-1; int i,j=0,temp; cout<<"页号\t"; cout<<"是否缺页\n"; for(i=0; page[i]!=-1; i++) { temp=page[i]; cout<<temp<<"\t"; if(!inblock(block,temp)) { block[(j++)% phyBlockNum]=temp; temp=1; } else temp=0; show(block,temp); } cout<<"FIFO算法的缺页率为"<<(double)j/(double)i<<endl; } void OPT(int* block,int* page) { for(int i=0; i<phyBlockNum; i++) block[i]=-1; int i,pageL=0,temp,max,* ntime; ntime=new int(phyBlockNum); for(i=0; i<phyBlockNum; i++) ntime[i]=-1; cout<<"页号\t"; for(i=0; i<phyBlockNum; i++) cout<<"页块"<<i<<"\t"; cout<<"是否缺页\n"; for(i=0; block[phyBlockNum-1]==-1; i++) { temp=page[i]; cout<<temp<<"\t"; if(!inblock(block,temp)) { block[pageL++]=temp; temp=1; } else temp=0; show(block,temp); } for(; page[i]!=-1; i++) { temp=page[i]; cout<<temp<<"\t"; max=0; for(int k=0; k<phyBlockNum; k++) { for(int m=i; page[m]!=-1; m++) { if(page[m]==block[k]) { ntime[k]=m; break; } else if(page[m+1]==-1) ntime[k]=m+1; } } for(int j=1; j<phyBlockNum; j++) max=ntime[max]<ntime[j]?j:max; if(!inblock(block,temp)) { block[max]=temp; pageL++; temp=1; } else temp=0; show(block,temp); } cout<<"OPT算法的缺页率为"<<(double)pageL/(double)i<<endl; } void LRU(int* block,int* page) { for(int i=0; i<phyBlockNum; i++) block[i]=-1; int i,pageL=0,temp,min,* ntime; ntime=new int(phyBlockNum); for(i=0; i<phyBlockNum; i++) ntime[i]=-1; cout<<"页号\t"; for(i=0; i<phyBlockNum; i++) cout<<"页块"<<i<<"\t"; cout<<"是否缺页\n"; for(i=0; block[phyBlockNum-1]==-1; i++) { temp=page[i]; cout<<temp<<"\t"; if(!inblock(block,temp)) { block[pageL++]=temp; temp=1; } else temp=0; show(block,temp); } for(; page[i]!=-1; i++) { temp=page[i]; min=0; for(int k=0; k<phyBlockNum; k++) { for(int m=i; m>=0; m--) { if(page[m]==block[k]) { ntime[k]=m; break; } else if(m==0) ntime[k]=-1; } } for(int j=1; j<phyBlockNum; j++) min=ntime[min]>ntime[j]?j:min; cout<<temp<<"\t"; if(!inblock(block,temp)) { block[min]=temp; pageL++; temp=1; } else temp=0; show(block,temp); } cout<<"LRU算法的缺页率为"<<(double)pageL/(double)i<<endl; } int main() { int * Block; int pageQue[maxPage]; cout<<"输入分配给改作业的物理块数:"; cin>>phyBlockNum; Block=new int(phyBlockNum); cout<<"输入一组页面访问顺序,输入-1结束:"; for(int i=0; i<maxPage; i++) { cin>>pageQue[i]; if(pageQue[i]==-1) break; } cout<<"\n-----------------OPT算法-----------------\n"; OPT(Block,pageQue); cout<<"\n-----------------FIFO算法----------------\n"; FIFO(Block,pageQue); cout<<"\n-----------------LRU算法-----------------\n"; LRU(Block,pageQue); return 0; }
8.