作業二:進程PCB管理與發送器

來源:互聯網
上載者:User
文章目錄
  • 作業描述
  • 背景知識
作業二:進程PCB管理與發送器

系統管理進程在系統中各種運行活動都離不開對於進程PCB的操作,本次作業以進程的PCB為管理目標,實現進程調度時狀態變化相應的操作。

作業描述

使用資料結構struct PCB表示進程,記錄進程的相關資訊;進程資訊包括:進程內部標識符pid、進程名pname、進程狀態pstatus、

進程已耗用時間ptime、進程隊列指標pnext。請設計合理的資料結構,容納這些資訊,以下是範例程式碼。

 

#define RUNNING0  /* 執行  */    #define READY1  /* 就緒  */    #define FINISHED2  /* 結束 */    #define EMPTY3  /* PCB表空閑  */        struct PCB    {    int  pid;        char pname[8];        int  pstatus;        int  ptime;        PCB *pnext;};

 

 

設定三個隊列(鏈表),分別是就緒隊列、執行隊列和空閑PCB隊列。

程式初始化的時候先建立空閑PCB隊列,然後根據使用者輸入的進程數量建立進程並構成進程就緒隊列。

使用鏈表表示進程所在隊列。

進程按著順序輪流執行,每個進程一次執行m個時間片,m大於等於1。

進程PCB中的ptime初始值是進程運行完畢需要的時間,初始值可以隨機賦值一個整數,運行過程中每運行一次則:

    ptime = ptime - m;    if (ptime<=0)         執行-->完成;  /* 進程從執行態轉變為完成 */

直到ptime小於或等於0表示該進程可以在最後一次分配的時間片中執行完畢。

編寫基本管理函數,包括添加insert_pcb()、刪除del_pcb()、修改mod_pcb()。

進程調度及狀態變化時螢幕列印相關資訊。

這裡是一個例子程式(點擊下載),如果你不太明白題目的意思,可以運行這個例子程式,看看輸出結果你是否能夠看明白。

背景知識

1. 進程式控制制塊PCB。PCB是進程的重要資料結構,包括了重要的控制資訊,如進程標識、處理機現場、進程狀態、資源清單等。

2. 隊列與鏈表。使用鏈表操作實現隊列中節點的添加、修改和刪除。

3. 進程狀態。進程的基本狀態包括執行、就緒和阻塞三種,引入掛起後,變為執行、活動就緒、活動阻塞、靜止就緒和靜止阻塞等。

進程在生命週期中的活動就是在這些狀態上進行變化。

 

 

/*----------------------------------------------------------------------------------------------------------------*/

實現如下:

下面代碼基本是基於進程式控制制塊的組織方式(a.連結方式 )- 來實現的。

程式實現比較簡化,如沒有阻塞隊列等。

基於的這種結構,即認為-系統開闢的PCB區為連續的儲存結構來儲存。

故以下代碼是基於靜態鏈表(空閑PCB隊列,就緒隊列)來實現的,

因為的這種結構,在用資料結構類比的前提下,若用動態指標(PCB若指標鏈式串連,則動態較好),反而可能顯得臃腫。

主要思路能顯得清晰即可。

代碼如下:

#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <iostream>using namespace std;#ifdef LINUX#include <unistd.h>#define SLEEP(N) sleep(N)#endif#ifdef WIN32#include <windows.h>#define SLEEP(N) Sleep(N)#endif#define NUM 6//預設系統PCB區有6個PCB int each_time = 1;int N = 0;char sname[6][3] = {"p1", "p2", "p3", "p4", "p5", "p6"}; typedef enum {RUNNING,READY,FINISHED,EMPTY}Pstatus; //記錄進程狀態的枚舉類型 typedef struct Process { int  pid;char pname[8];int  pstatus;int  ptime;int pnext;Process() {pid = -1;pstatus = EMPTY;ptime = 0;pnext = -1;memset(pname, 0, sizeof(pname));}}Process;Process PCB[NUM], Pre_PCB[NUM];typedef struct Pqueue {int top;int rear;}Pqueue;Pqueue ready, pre_ready;Pqueue pfree;int run, pre_run;void Creat_Pcb(int pid) {PCB[pid].pstatus = READY;strcpy(PCB[pid].pname, sname[N++]);PCB[pid].ptime = rand() % 8 + 1;PCB[pid].pnext = -1;}//分配PCB給進程 void Push_Pqueue(int pid, Pqueue &cur) {if(cur.top == -1) {cur.top = pid;} else {PCB[cur.rear].pnext = pid;}cur.rear = pid;PCB[cur.rear].pnext = -1;}//壓入隊列,就緒隊列或空閑隊列 int Pop_Pqueue(Pqueue &cur) {if(cur.top == -1) {printf("隊列為空白,ERROR。\n");return -1;}int pid = cur.top;cur.top = PCB[pid].pnext;if(cur.top == -1) {cur.rear = -1;}PCB[pid].pnext = -1;return pid;}//彈出隊列 void Del_Pcb(int pid) {PCB[pid].ptime = 0;PCB[pid].pnext = -1;Push_Pqueue(pid, pfree);}//回收PCB,恢複到空閑狀態 void Insert_Pcb() {if (pfree.top == -1) {puts("空閑隊列為空白, 建立進程失敗");return ; }int pid = Pop_Pqueue(pfree);//從空閑PCB隊列取出PCB Creat_Pcb(pid);//分配PCB給進程 Push_Pqueue(pid, ready);//進入就緒隊列 }//建立進程 void Print_Status(Process state[], Pqueue cur, int ran); void Modify_Pcb() {//進程調度 if (ready.top == -1) {puts("系統沒有進程可以調度");return ; }pre_run = run;pre_ready = ready;int pid = Pop_Pqueue(ready);run = pid;PCB[pid].pstatus = RUNNING;puts("上一步狀態:");Print_Status(Pre_PCB, pre_ready, pre_run);puts("目前狀態:");Print_Status(PCB, ready, run);//輸出狀態 for (int i = 0; i < N; i++) {Pre_PCB[i] = PCB[i];}//儲存目前狀態的前驅。 if (PCB[pid].ptime - each_time > 0) {PCB[pid].ptime -= each_time; PCB[pid].pstatus = READY;Push_Pqueue(pid, ready);} else {PCB[pid].ptime = 0;PCB[pid].pstatus = FINISHED;Del_Pcb(pid);}//修改PCB狀態,儲存現場(這裡僅ptime) } void Init_Pcb() {int i;N = 0;each_time = rand() % 6 + 1;//隨機產生時間片大小 for (i = 0; i < NUM; i++) {PCB[i].pid = i;PCB[i].pnext = i + 1;}PCB[NUM-1].pnext = -1;pfree.top = 0;pfree.rear = NUM - 1;ready.top = -1;ready.rear = -1; run = -1;}//系統PCB區的初始化狀態 void Print_Status(Process state[], Pqueue cur, int ran) {puts("╔═══════════════════════╗"); puts("║    進程名     進程狀態    進程剩餘執行時間   ║");for (int i = 0; i < N; i++) {printf("║\t%s\t", state[i].pname);switch(state[i].pstatus) {case RUNNING: printf(" RUNNING\t");break;case READY: printf(" READY\t\t");break;case FINISHED: printf(" FINISHED\t");break;default:break; }printf("%d\t\t║\n", state[i].ptime);} puts("╚═══════════════════════╝"); printf("╠═  Ready_queue :");for (int i = cur.top; i != -1; i = state[i].pnext) printf(" %s ->", state[i].pname);printf(" NULL\n");printf("╠═  Active_queue:");if (ran != -1) printf(" %s ->", state[ran].pname);puts(" NULL");}//輸出狀態函數 void speed(int v) {switch(v) {case 1: SLEEP(500);break;case 2: SLEEP(1600);break;case 3: SLEEP(2400);break;default: break;}}//自動示範模式的分檔(停頓間隔)函數 int Check_Input(char str[]) {    int i, k = 0;    int st = -1, ed = -1;    char stmp[110];   for (i = 0; str[i]; i++) if (str[i] != ' ') {st = i; break;}   for (i = strlen(str) - 1; i >= 0; i--) if (str[i] != ' ') {ed = i; break;} if (st == -1) return -2;    for (i = st; i <= ed; i++) {        if (!(str[i] >= '0' && str[i] <= '9')) {            return -1;        } else {            stmp[k++] = str[i];            }    }    int r = 1, sum = 0;    for (i = k - 1; i >= 0; i--, r *= 10) {        sum += (stmp[i] - '0') * r;    }    return sum;}//輸入處理,做簡單的排錯處理void solve() {int n;char str[110];puts("輸入進程的數量(範圍在[1-6]內):");while (gets(str)) {while ((n = Check_Input(str)) < 0 || n > 6) {if (n == -1 || n > 6) {//輸入檢查處理puts("ERROR, 請重新輸入");}gets(str); } Init_Pcb();//初始化 for (int i = 0; i < n; i++) {Insert_Pcb();}for (int i = 0; i < n; i++) {Pre_PCB[i] = PCB[i];}//儲存前一個狀態的資訊 puts("初始進程情況:"); Print_Status(PCB, pre_ready, run); printf("╠═  時間片大小為 %d\n", each_time);int mode = 1;int v = 1;puts("\n請選擇示範模式:1(自動)   2(手動)");gets(str); while (! ((mode = Check_Input(str)) >= 1 && mode <= 2) ) {if (mode != -2) {puts("ERROR, 請重新輸入");//輸入檢查處理}gets(str);} if (mode == 1) {puts("1:快速示範\t2:中速示範\t3:慢速示範");gets(str);while (! ((v = Check_Input(str)) >= 1 && v <= 3) ) {if (v != -2) {puts("ERROR, 請重新輸入");//輸入檢查處理}gets(str);}}while (true) {system("cls"); Modify_Pcb();//進程調度 if (ready.top == -1) {//就緒隊列空。 if (mode == 2) { puts("點擊前往下一步");system("pause");}break;}if (mode == 1) {speed(v);//自動模式停頓 } else {puts("點擊前往下一步");system("pause");//以完成手動模式手動翻頁 }}if (mode == 1) speed(v);//自動模式停頓 system("cls");puts("上一步狀態:");Print_Status(Pre_PCB, ready, run);puts("目前狀態:");for (int i = 0; i < n; i++) PCB[i].pstatus = FINISHED;run = -1;Print_Status(PCB, ready, run);//完成狀態 puts("congratulation!!!進程全部成功運行結束!");system("pause");system("cls");puts("輸入進程的數量(範圍在[1-6]內):");}}int main() {srand((unsigned)time(NULL));solve();return 0;}

以下是上面代碼的.exe可執行檔(傳不上去,rar壓縮檔)。

點擊 下載。

 

12.5號 - 重新寫了個PCB用指標鏈式串連的程式,偽介面簡單一些。

此程式的特點主要是簡單易懂一些,簡化了一些浮雲的處理;

歎自己平時都不用指標的,用起指標來就顯得比較生疏,過程中出現諸如記憶體不可讀很多次。

不過最後程式還算清晰,調度函數Modify_Pcb()相對上面程式而言寫的要清晰一些。

  (上面的寫的戳了,最後一次輸出要特殊到外面處理,這裡就不需要-)。

代碼如下:

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <time.h>#define NUM 6#define RUNNING 0  /* 執行  */    #define READY 1  /* 就緒  */    #define FINISHED 2  /* 結束 */    #define EMPTY 3  /* PCB表空閑  */   int each_time = 1;//預設時間片為1 int N = 0;char sname[6][3] = {"p1", "p2", "p3", "p4", "p5", "p6"};     typedef struct PCB {    char pname[8];        int  pstatus;        int  ptime;        PCB *pnext;}PCB, *QueuePtr;typedef struct {QueuePtr front;QueuePtr rear;}LinkQueue;  LinkQueue p_empty, p_ready, p_run, p_end;void InitQueue(LinkQueue &Q) {Q.front = Q.rear = (QueuePtr)malloc(sizeof(PCB));}//初始化隊列 void EnQueue(LinkQueue &Q, QueuePtr p) {Q.rear->pnext = p;Q.rear = p;p->pnext = NULL;}//壓入隊列 void DeQueue(LinkQueue &Q, QueuePtr &p) {if (Q.front == Q.rear) {printf("ERROR,隊列為空白!");}p = Q.front->pnext; Q.front->pnext = p->pnext;p->pnext = NULL;if (Q.rear == p) Q.rear = Q.front;}//出隊列,將出隊元素的結點指標用p儲存 void Insert_Pcb() {    QueuePtr p;   DeQueue(p_empty, p);//從空閑隊列取出PCB EnQueue(p_ready, p); //加入到就緒隊列 strcpy(p->pname, sname[N++]);p->pstatus = READY;p->ptime = rand() % 8 + 1;//初始化資訊,名字,狀態//進程執行時間(rand隨機產生,rand() %8+1後在1-8範圍)printf("建立進程%s,執行時間%d     <建立成功>\n", p->pname, p->ptime);}//建立進程 void Del_Pcb(QueuePtr &p) {p->ptime = 0;p->pstatus = FINISHED;p->pnext = NULL;EnQueue(p_end, p);}//刪除進程,加入到完成狀態隊列中。 void Modify_Pcb() {//進程調度 QueuePtr cur;puts("===============執行調度=============");if (p_run.front != p_run.rear) {//執行隊列不空 DeQueue(p_run, cur);//彈出執行進程 cur->ptime -= each_time;//執行一個時間片 printf("調度:進程%s     ", cur->pname);if (cur->ptime > 0) {//若執行未結束,經調度到就緒狀態 cur->pstatus = READY;printf("<執行 -> 就緒>.\n");EnQueue(p_ready, cur);}else {//執行結束 printf("<執行 -> 結束>.\n");Del_Pcb(cur);//加入到結束隊列 }}if (p_ready.front != p_ready.rear) {//就緒隊列不空 DeQueue(p_ready, cur);//彈出就緒隊列隊首元素 EnQueue(p_run, cur);//進入執行態 cur->pstatus = RUNNING;printf("調度:進程%s     <就緒 -> 執行>.\n", cur->pname);printf("調度:%s執行中...\n", cur->pname);//調度執行 printf("就緒隊列 : ");QueuePtr ready = p_ready.front->pnext;while (ready) {printf("%s<1>->", ready->pname);ready = ready->pnext;}//輸出就緒隊列 puts("NULL");printf("執行隊列 : ");printf("%s<0>->NULL\n\n", cur->pname);//輸出執行隊列 }}void Init_PCB() {InitQueue(p_empty);InitQueue(p_ready);InitQueue(p_run);InitQueue(p_end);//初始化隊列 for (int i = 0; i < NUM; i++) {QueuePtr p = (QueuePtr)malloc(sizeof(PCB)); p->pnext = NULL;EnQueue(p_empty, p);}//初始空閑隊列為6個空閑PCB }void solve() {int n;printf("進程數量?[1-6]:");scanf("%d", &n);if (n < 1 || n > 6) { puts("輸入資料不在1-6"); return ; } Init_PCB();//初始化隊列 for (int i = 0; i < n; i++) {Insert_Pcb();//建立進程 }while (true) {Modify_Pcb();//進程調度(若就緒隊列不空,調度後p_run不為空白) if (p_run.front == p_run.rear) {break;//沒有進程在執行時退出。 }}QueuePtr run;printf("結束隊列 : ");QueuePtr end = p_end.front->pnext;while (end) {printf("%s<1>->", end->pname);end = end->pnext;}puts("NULL");//輸出結束隊列(按結束次序) }int main() {srand((unsigned)time(NULL));//以時間做隨機種子solve();return 0;} 

 

原創文章如轉載請註明:轉自¥忘%風 {http://www.cnblogs.com/slave_wc}

本文地址: 作業二:進程PCB管理與發送器

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.