1. 程式人生 > >⊙-→棒棒糖ing .____`

⊙-→棒棒糖ing .____`

作業系統原理分析要點

程序的排程時機與程序切換機制

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

排程時機

中斷處理過程(包括時鐘中斷、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,越界

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

實驗一 併發程式設計  

 1.目的

在單處理器環境下,實現多工的核心是併發程式設計,程序的併發執行提高了CPU的利用率,使得CPU與裝置並行、裝置與裝置並行成為可能。但併發執行的一些程序之間需要互斥和同步的控制。

    在應用系統開發中,幾乎都需要使用資料庫系統,在多使用者操作時,對資料庫中一些表的操作也需要互斥或同步。

2.要求

題目:在BACC環境下,對程式併發執行的實驗:(1)沒有控制時正確的程式執行的結果不正確;(2)BACC中PV操作的併發控制的實現。

要求:

(1)學習Windows命令介面中部分基本命令的使用

(2)BACC的使用:

(3)BACC中PV操作的併發控制的實現。  

(4)將課堂和習題中的同步、互斥的併發程式設計的習題的設計與實現。

有併發控制的(兩種答案)

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②反轉字串


#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結構的基金賬戶管理


#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;
          }
         }
    } 
}