0
点赞
收藏
分享

微信扫一扫

操作系统原理分析实验


操作系统原理分析要点


进程的调度时机与进程切换机制

-------------

调度时机

中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();

内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;

用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度

---------

进程的切换

进程切换 任务切换 上下文切换

1 switch_to 宏 schedule() 进程描述符地址

2 进程切换-内核栈切换实施

A用户态(中断、异常、系统调用,用户栈保存在内核栈,ESP到栈底)--A内核态

A内核态(内核栈切换)--B内核态

B内核态(取出1用户栈信息、装载寄存器)--B用户态

====================================

i_addr[0]1483

i_addr[1]24

i_addr[2]225

i_addr[3]542

i_addr[4]2212

i_addr[5]98

i_addr[6]3321

i_addr[7]23

i_addr[8]123

i_addr[9]67---[n=10]

i_addr[10]326*

i_addr[11]756*

i_addr[12]226*

第326块

……

[11]109

[12]954

[13]952

……

第756块

[0]53**

[1]922**

……

第53块

……

[211]863

[212]335

……

第922块

……

[211]2312

[212]3276

……

假设某文件的i-node结构及各级索引表如上所示,如果物理块长度为X=1KB,块号Y=4B

1.该文件的读写指针指示地址为6820,给出该 地址所在的物理块号和块内地址

2.该文件的读写指针指示地址为22675,给出 该地址所在的物理块号和块内地址

3.该文件的读写指针指示地址为751155,给 出该地址所在的物理块号和块内地址

解:

a=log2(XKB/8bit)=log2(2^10)=10

0~9 有n=10

b=X KB/Y B=X*2^10/Y=2^8

(1)x1=6820

index=x1>>a=x1/(2^a)取整=6<n

w=x1&11……(a个1)=x1%(2^a)取余数=676

物理块号3321(PS:i_addr[6]3321)

块内地址676(PS:w)

(2)x1=22675

index=x1>>a=x1/(2^a)取整=22

w=x1&11……(a个1)=x1%(2^a)取余数=147<b

index=index-n=12 

物理块号954(PS:i_addr[10]326*[12]954 )

块内地址147(PS:w)

(3)x1=751155

index=x1>>a=x1/(2^a)取整=733

w=x1&11……(a个1)=x1%(2^a)取余数=563

index=index-n=723

index=index-b=467

index÷b=index2(商)……w2(余数) 

index2=1

w2=211

物理块号2321(PS:i_addr[11]756*[1]922**[211]2312)

块内地址563(PS:w)

=====================================

7 6 5 4 3 2 1 0

0_1_1_0_1_1_1_1

15 14 13 12 11 10 9 8

1__1___0__0__1__1_1_1

23 22 21 20 19 18 17 16

0__1__0__1__0__1___1__0

31 30 29 28 27 26 25 24

0__0__0__0__1__0___1__0

某静态页式存储管理中,已知内存共有X=32块 ,块长度为Y=4K=2^12=4096,(假设单位一样),当前位

示图如上,进程P的虚拟地址空间大小为ADD=35655。

1.当前有几个空闲块[PS:数一下位示图上有0] 14个

2.进程P共有几页[PS:ADD除以Y,商整数只入不舍 相当于 

(ADD+Y-1)/Y取整数部分]

(35655+4K-1)/4K=9页

 

3.根据位示图,写出进程P的页表

[0]4

[1]7

[2]12

[3]13

[4]16

[5]19

[6]21

[7]23

[8]24 

4.给定进程P的虚拟地址:9198和 ox9D8F,根据(3)分别计算对应的物理地址

十进制的9198:

页号p=9198/4K=2;页内地址w=9198%4K=1006

块号b=12(PS:[p]12)

物理地址=b*4K+1006=50158

十六进制ox9D8F:

页号p=1001 1101 1000 1111>>12=1001

p=9不小于9,越界

多了cr3和页目录介绍

=======================================================

实验一 并发程序设计  

 1.目的

在单处理器环境下,实现多任务的核心是并发程序设计,进程的并发执行提高了CPU的利用率,使得CPU与设备并行、设备与设备并行成为可能。但并发执行的一些进程之间需要互斥和同步的控制。

    在应用系统开发中,几乎都需要使用数据库系统,在多用户操作时,对数据库中一些表的操作也需要互斥或同步。


2.要求

题目:在BACC环境下,对程序并发执行的实验:(1)没有控制时正确的程序执行的结果不正确;(2)BACC中PV操作的并发控制的实现。

要求:

(1)学习Windows命令接口中部分基本命令的使用

(2)BACC的使用:

(3)BACC中PV操作的并发控制的实现。  

(4)将课堂和习题中的同步、互斥的并发程序设计的习题的设计与实现。

二、实验内容

1.pop ()和push (100)各执行一次的结果(堆栈)

有并发控制的(两种答案)

semaphore s=1;
int stack[20];
int top;
void pop(){
int free;
p(s);
free=stack[top];
top--;
cout<<"out:"<<free<<endl;
v(s);
}
void push(int free){
p(s);
top++;
stack[top]=free;
cout<<"in:"<<free<<endl;
v(s);
}

main()
{

int i;
for(i=0;i<20;i++)stack[i]=-1;
stack[0]=0;
stack[1]=156;
stack[2]=254;
stack[3]=129;
stack[4]=23;
top=4;
cobegin{
pop();push(100);}
cout<<"top_point="<<top<<endl;
for(i=0;i<=top;i++)
cout<<"stack["<<i<<"]="<<stack[i]<<endl;
}

2.同步关系

   假定有三个进程R、W1、W2共享一个缓冲区B,而B每次只能存放一个整数。当缓冲区中无数时,进程R可以从输入设备上读入一个整数并存入B中;若存到B中的数是奇数,则允许进程W1将其取出打印;若是偶数,则允许进程W2将其取出打印。另外规定:进程R必须等B中的数被取出打印后才能再存放下一个数,进程W1或W2对每次存入的数只能打印一次并且都不能从空的缓冲区中取数。请用PV操作实现R、W1和W2三个进程的并发执行。

semaphore S = 1, SO = 0, SE = 0;
int B;

void R()
{
int x;
cin >> x;
p(S);
B = x;
if (B % 2 == 1)
v(SO);
else v(SE);
}

void W1()
{
int y;
p(SO);
y = B;
v(S);
cout << "print odd:" << y << endl;
}

void W2()
{
int z;
p(SE);
z = B;
v(S);
cout << "print even:" << z << endl;
}

main()
{
cobegin{ R(); R(); W1(); W2(); }
}

实验二 进程通信  

一、目的与要求

  1.目的

进程通信是多任务协作的基础,具有广泛的应用。熟悉Linux的基于消息队列的进程通信的系统调用,并实现一个简单的C/S结构的实例。


 2.要求

题目:Linux进程通信及C/S结构应用。

(1)熟悉教材中有关进程通信方式。

(2)熟悉Linux的使用(常用shell命令、VI、CC等)。

(3)熟悉Linux的消息结构定义, msgget()、msgrcv(msgqid,…)、msgsnd(msgqid,…)的系统使用,C/S结构的工作过程 。

二、实验内容

 1.一个简单C/S结构 实现①a*X+b=0求x②反转字符串

msg_mycs.h:

#define MSGKEY 1183



struct msgform {
long mtype;
int source_pid;
double a,b;
char opcode;
double result;
char fanzhuan[128];
char return_msg[128];
}msg;

int msgsize=sizeof(struct msgform)-sizeof(long);

int msgqid;

B1.C:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "msg_mycs.h"

main()

{
struct msgform msg;
int pid;
int i;



msgqid = msgget(MSGKEY,0777);
pid = getpid();
msg.opcode != '1';
for(;msg.opcode!='q';){
printf("opcode=(1 for a*?+b=0; 2 forfanzhuan;q for EXIT)");
msg.opcode=getchar();
while(msg.opcode=='\n')msg.opcode=getchar();
if (msg.opcode == '1' || msg.opcode == '2')
{

if (msg.opcode == '1')
{
printf("a=");
scanf("%lf", &msg.a);
printf("b=");
scanf("%lf",&msg.b);
}
else{
printf("the string=");
scanf("%s", msg.fanzhuan);
}

msg.source_pid=pid;
msg.mtype=1;
msg.return_msg[0]=0;
msgsnd(msgqid,&msg,msgsize,0);
msgrcv(msgqid,&msg,msgsize,pid,0);
printf("client: receive from pid=%d\n",msg.source_pid);
if(msg.opcode=='1')
printf("%.2f* %.2f + %.2f = 0\n",msg.a,msg.result,msg.b);
else
printf("%s\n",msg.return_msg);
}

}

}

A1.C

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "msg_mycs.h"

main()
{

struct msgform msg;
int pid;
int i;



msgqid = msgget(MSGKEY,0777);

pid = getpid();
msg.opcode != '1';

for(;msg.opcode!='q';){
printf("opcode=(1 for a*?+b=0; 2 forfanzhuan;q for EXIT)");

msg.opcode=getchar();

while(msg.opcode=='\n')msg.opcode=getchar();

if (msg.opcode == '1' || msg.opcode == '2')
{

if (msg.opcode == '1')
{
printf("a=");
scanf("%lf", &msg.a);
printf("b=");
scanf("%lf",&msg.b);
}
else{
printf("the string=");
scanf("%s", msg.fanzhuan);
}


msg.source_pid=pid;
msg.mtype=1;
msg.return_msg[0]=0;
msgsnd(msgqid,&msg,msgsize,0);
msgrcv(msgqid,&msg,msgsize,pid,0);
printf("client: receive from pid=%d\n",msg.source_pid);
if(msg.opcode=='1')
printf("%.2f* %.2f + %.2f = 0\n",msg.a,msg.result,msg.b);
else
printf("%s\n",msg.return_msg);
}

}



}

 2.一个简单C/S结构的基金账户管理

msg_mycs.h:

#define MSGKEY 1183

struct msgform {

long mtype;
int source_pid;
char nameid[10],password[10];
char opcode;
double result;
char return_msg[100];

}msg;

int msgsize=sizeof(struct msgform)-sizeof(long);

int msgqid;

b2.c

#include <stdlib.h>   /*如果没有这个会提示貌似是 identifier or ‘(’ before 甚么甚么的错误*/

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#include <sys/ioctl.h>/*如果没有这个会提示 define NULL 的错误*/

#include "msg_mycs.h"

struct usr

{

char name[10];

char pass[10];

double money;

struct usr *next;

}*head;

int registerr(struct msgform m);/*这个自己定义的函数名,本来是register,应该是头文件里面有个这个名字的,所以我就弄了另一个就ok了*/

struct usr* findbyName(struct msgform m);

main()

{

int i,j;

extern cleanup();

for(i=0;i<20;i++)

signal(i,cleanup);

msgqid = msgget(MSGKEY,0777|IPC_CREAT);

head= NULL;

struct usr *pointlist;

pointlist = NULL;

for(;msg.opcode!='q';)

{

printf("server pid= %d is ready (msgqid=%d)... \n",getpid(),msgqid);

msgrcv(msgqid,&msg,msgsize,1,0);

printf("server: receive from pid=%d\n",msg.source_pid);

switch(msg.opcode){

case '1':

j=registerr(msg);

if (j == 0)strcpy(msg.return_msg, "the account already exists ");

else strcpy(msg.return_msg, "register successfull");

break;

case '2':

pointlist=findbyName(msg);

if (pointlist == NULL)strcpy(msg.return_msg, "the account you required doesnot exist or password error");

else strcpy(msg.return_msg, "sign in successfull");

break;

case '3':if (pointlist != NULL )

{

pointlist->money+=msg.result;

strcpy(msg.return_msg, "deposit successfull");

} else strcpy(msg.return_msg, "error,please ask for help");

break;

case '4':

if (pointlist != NULL)

{

if (msg.result > 0 && pointlist->money > msg.result)

{

pointlist->money -= msg.result;

msg.result=pointlist->money;

strcpy(msg.return_msg, "withdraw successfull");

}

else strcpy(msg.return_msg, " insufficient balance ");

}

else strcpy(msg.return_msg, "withdraw error ");

break;

case '5':

if (pointlist!= NULL )

{

msg.result=pointlist->money ;

strcpy(msg.return_msg, "account balance");

}

else strcpy(msg.return_msg, "operation error ");

break;

}

msg.mtype=msg.source_pid;

msg.source_pid=getpid();

msgsnd(msgqid,&msg,msgsize,0);

}

pointlist = NULL;

printf("server eixt by client pid=%d\n",msg.mtype);

}

struct usr* findbyName(struct msgform m)

{

struct usr * tmp_node;

tmp_node = head;

while (tmp_node!= NULL)

{

if ((strcmp(tmp_node->name, m.nameid) == 0) &&( strcmp(tmp_node->pass, m.password) == 0)){return tmp_node;

}tmp_node = tmp_node->next;

}

return NULL;

}

int registerr (struct msgform m)

{

struct usr* tmp_node;

tmp_node = head;

while (tmp_node != NULL)
{

if (strcmp(tmp_node->name, m.nameid) == 0)return 0;
tmp_node = tmp_node->next;

}

tmp_node = malloc(sizeof(struct usr));
strcpy(tmp_node->name, m.nameid);
strcpy(tmp_node->pass, m.password);
tmp_node->money = m.result;
tmp_node->next = head;
head = tmp_node;
return 1;

}

cleanup()

{

msgctl(msgqid,IPC_RMID,0);

exit(0);

}

A2.c     

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#include "msg_mycs.h"

main()

{

struct msgform msg;

int pid;

int i;

msgqid = msgget(MSGKEY,0777);

pid=getpid();
msg.opcode='1';

for(;msg.opcode!='q';){
printf("1:zhuce\n 2:dengru\n 3:cunk \n 4: quk \n 5:chaxun \n q:tuichu \n ");
msg.opcode=getchar();

while(msg.opcode=='\n')msg.opcode=getchar();
if(msg.opcode=='1'||msg.opcode=='2'){
printf("user:");
scanf("%s",&msg.nameid);
printf("password:");
scanf("%s",&msg.password);} else
if(msg.opcode=='3') { printf("cun monney:");
scanf("%lf",&msg.result);
} else if(msg.opcode=='4'){printf("qu monney:");
scanf("%lf",&msg.result);}
if(msg.opcode=='1'||msg.opcode=='2'||msg.opcode=='3'||msg.opcode=='4'||msg.opcode=='5')

{

msg.source_pid=pid;
msg.mtype=1;
msg.return_msg[0]=0;
msgsnd(msgqid,&msg,msgsize,0);
msgrcv(msgqid,&msg,msgsize,pid,0);
printf("client: receive from pid=%d\n",msg.source_pid);
switch (msg.opcode)
{
case '1':
case '2':
printf("%s\n", msg.return_msg);
break;
case '3':
case '4':
case '5':
printf("%s\n $=%lf\n", msg.return_msg, msg.result);
break;
}
}
}
}

 


举报

相关推荐

0 条评论