题目:fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;
#include
#include
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
#include
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
#include
#include
#include
#include /*子写父读,互斥访问*/
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
#include
#include
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
#include "curses.h"
#include
#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;
}
●最佳置换算法、 先进先出置换算法、最近最久未使 用置换算法●小组讨论 ●讨论结果分析(页面置换次数及缺页率)
#include
#include
#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;
}