操作系统原理分析实验

操作系统原理分析要点

https://www.cnblogs.com/huyufeng/p/5400639.html

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

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

调度时机

中断处理过程(包括时钟中断、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,越界

https://blog.csdn.net/u011209099/article/details/9248525 多了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
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值