在 PCB 实现过程中,在进入调度程序之前,链表是如何在就绪队列中实现的?

问题描述 投票:0回答:1
  1. 为什么Ready队列中使用链表?

  2. 如何使用?

  3. 栈和队列在其中是如何发挥作用的?

  4. 它如何影响调度程序和 PCB 执行?

从《Abraham Siberschatz 的操作系统概念》一书中引用了这段代码

// Define Process Control Block (PCB)
typedef struct PCB {
    int pid; // Process ID
    char state[10]; // Process state (e.g., "Ready", "Running", etc.)
    struct PCB* next; // Pointer to the next PCB in the ready queue
} PCB;

// Define Ready Queue structure with pointers to first and last PCB
typedef struct ReadyQueue {
    PCB* first; // Pointer to the first PCB in the ready queue
    PCB* last;  // Pointer to the last PCB in the ready queue
} ReadyQueue;

// Function to create a new PCB
PCB* createPCB(int pid, const char* state) {
    PCB* newPCB = (PCB*)malloc(sizeof(PCB)); // Allocate memory for the new PCB
    newPCB->pid = pid; // Assign process ID
    snprintf(newPCB->state, sizeof(newPCB->state), "%s", state); // Assign process state
    newPCB->next = NULL; // Set the next pointer to NULL initially
    return newPCB; // Return the pointer to the new PCB
}

// Function to initialize a ReadyQueue
ReadyQueue* initializeReadyQueue() {
    ReadyQueue* rq = (ReadyQueue*)malloc(sizeof(ReadyQueue)); // Allocate memory for the ready queue
    rq->first = NULL; // Set the first PCB pointer to NULL
    rq->last = NULL;  // Set the last PCB pointer to NULL
    return rq;
}

// Function to add a PCB to the ready queue (end of the list)
void enqueue(ReadyQueue* rq, PCB* pcb) {
    if (rq->last == NULL) { // If the queue is empty
        rq->first = pcb; // Set both first and last to the new PCB
        rq->last = pcb;
    } else { // If queue is not empty
        rq->last->next = pcb; // Link the new PCB to the end of the queue
        rq->last = pcb; // Update the last pointer to the new PCB
    }
}

// Function to remove a PCB from the ready queue (from the front of the list)
PCB* dequeue(ReadyQueue* rq) {
    if (rq->first == NULL) { // If the queue is empty
        printf("Ready queue is empty.\n");
        return NULL;
    }
    
    PCB* temp = rq->first; // Get the first PCB
    rq->first = rq->first->next; // Move the first pointer to the next PCB

    if (rq->first == NULL) { // If the queue is now empty after dequeue
        rq->last = NULL; // Update the last pointer to NULL
    }

    return temp; // Return the dequeued PCB
}
c data-structures linked-list operating-system queue
1个回答
0
投票

双线程程序的旧示例,使用链接列表作为具有 Windows 互斥体和信号量的线程之间的消息队列来复制文件。这类似于我在小型计算机和嵌入式设备(磁带驱动器、硬盘驱动器)的全盛时期所工作的多线程操作系统上实现队列的方式。上次我使用类似此示例代码的程序是为了捕获流式原始数据,该数据对于单个硬盘驱动器来说太快了,但可以通过在两个硬盘驱动器之间交替来处理,因此它使用了三个线程和队列,一组用于读取,并在两组之间交替进行写作。这个 Windows 示例和我所使用的操作系统的共同点是对链表队列使用互斥体和信号量。操作系统还包含一个时间参数,以便单个调用可以等待(互斥体和信号量)或时间。

/*----------------------------------------------------------------------*/
/*      mtcopy.c        multi-thread file copy demo                     */
/*                                                                      */
/*  Uses linked list fifo's to hold buffered data: LLIST.               */
/*  Uses mutexes for ownership of link lists.                           */
/*  Uses semaphores for list counts.                                    */
/*                                                                      */
/*  Uses the existing thread for file reads.                            */
/*  Creates a second  thread for file writes.                           */
/*                                                                      */
/*      Jeff Reid       2015MAY22    15:00                              */
/*----------------------------------------------------------------------*/
#include <windows.h>
#include <stdio.h>
#include <stddef.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <conio.h>

#define NBFR    64                      /* number of buffers */
#define BFRSZ   0x10000                 /* buffer size */

typedef struct _NODE                    /* node structure */
{
  struct _NODE *pNext;                  /* ptr to next node */
    BYTE       *pBfr;                   /* ptr to buffer */
    DWORD       dwCnt;                  /* # bytes in buffer */
}NODE;

typedef struct _LIST                    /* linked List structure */
{
    NODE       *pFirst;                 /* ptr to 1st  node */
    NODE       *pLast;                  /* ptr to last node */
    HANDLE      hMtxSem[2];             /* mutex and semaphore handles */
}LIST;
#define hMtx hMtxSem[0]                 /* mutex        == ownership */
#define hSem hMtxSem[1]                 /* semaphore    == list count */

/*----------------------------------------------------------------------*/
/*      data                                                            */
/*----------------------------------------------------------------------*/
static HANDLE   htT1;                   /* thread handles */
static LIST     llT0;                   /* thread 0 list */
static LIST     llT1;                   /* thread 1 list */
static NODE     aNode[NBFR];            /* array of nodes */
static DWORD    fExitThread;            /* flag to indicate thread exit */
static DWORD    dwThreadT1;             /* thread id's (not used) */
static DWORD    dwExitCode;             /* exit code */
static HANDLE   hSrc;                   /* file I/O */
static HANDLE   hDst;
static PBYTE    pMem;                   /* ptr to allocated memory */
/*----------------------------------------------------------------------*/
/*      code                                                            */
/*----------------------------------------------------------------------*/
static DWORD    WINAPI Thread0(LPVOID);
static DWORD    WINAPI Thread1(LPVOID);
static void     InitThread0List(void);
static NODE *   GetNode(LIST *);
static DWORD    PutNode(LIST *, NODE *);
/*----------------------------------------------------------------------*/
/*      main                                                            */
/*----------------------------------------------------------------------*/
DWORD main(DWORD argc, BYTE **argv)
{
    hSrc    = INVALID_HANDLE_VALUE;     /* init file handles to not open */
    hDst    = INVALID_HANDLE_VALUE;
    if(argc != 3){
        printf("usage is mtcopy <src> <dst>\n");
        goto exit0;}
    pMem = malloc(BFRSZ*NBFR);          /* allocate memory */
    if(!pMem){
        _cputs("can't allocate enough memory\r\n");
        goto exit0;}
    hSrc = CreateFile(argv[1],          /* open src file */
            GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
    if(hSrc == INVALID_HANDLE_VALUE){
        printf("Can't open %s\n", argv[1]);
        goto exit0;}
    hDst = CreateFile(argv[2],          /* open dst file */
        GENERIC_ALL , 0, NULL, CREATE_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, 0);
    if(hDst == INVALID_HANDLE_VALUE){
        printf("Can't create %s\n", argv[2]);
        goto exit0;}
    /*  create mutex and semaphore for each list */
    if((llT0.hSem = CreateSemaphore(NULL,0,NBFR+1,NULL))==NULL){
        _cputs("can't create semaphore\r\n");
        goto exit0;}
    if((llT0.hMtx = CreateMutex(NULL,FALSE,NULL))==NULL){
        _cputs("can't create mutex\r\n");
        goto exit0;}
    if((llT1.hSem = CreateSemaphore(NULL,0,NBFR+1,NULL))==NULL){
        _cputs("can't create semaphore\r\n");
        goto exit0;}
    if((llT1.hMtx = CreateMutex(NULL,FALSE,NULL))==NULL){
        _cputs("can't create mutex\r\n");
        goto exit0;}
    /*  create threads */
    htT1 = CreateThread(NULL, 0, Thread1, 0, 0, &dwThreadT1);
    if(!htT1){
        _cputs("can't create thread\r\n");
        goto exit0;}
    InitThread0List();                  /* init Thread 0 list */
    Thread0((LPVOID)NULL);              /* start Thread 0 */
exit0:
    if(htT1){                           /* close thread */
        WaitForSingleObject(htT1, INFINITE);
        CloseHandle(htT1);}
    if(llT1.hSem){                      /* close mutex, semaphore */
        CloseHandle(llT1.hSem);}
    if(llT1.hMtx){
        CloseHandle(llT1.hMtx);}
    if(llT0.hSem){
        CloseHandle(llT0.hSem);}
    if(llT0.hMtx){
        CloseHandle(llT0.hMtx);}
    if(hDst != INVALID_HANDLE_VALUE){   /* close files */
        CloseHandle(hDst);}
    if(hSrc != INVALID_HANDLE_VALUE){
        CloseHandle(hSrc);}
    if(pMem){                           /* free memory */
        free(pMem);}
    return(0);
}
/*----------------------------------------------------------------------*/
/*      Thread0         read bfr from file 0                            */
/*----------------------------------------------------------------------*/
static DWORD WINAPI Thread0(LPVOID lpvoid)
{
NODE *pNode;
    while(1){
        pNode = GetNode(&llT0);         /* get node */
        ReadFile(hSrc, pNode->pBfr, BFRSZ, &(pNode->dwCnt), NULL);
        PutNode(&llT1, pNode);          /* send node to thread 1 */
        if(pNode->dwCnt == 0){          /* exit if end of file */
            return(0);}}
}
/*----------------------------------------------------------------------*/
/*      Thread1         write bfr to file 1                             */
/*----------------------------------------------------------------------*/
static DWORD WINAPI Thread1(LPVOID lpvoid)
{
NODE *pNode;
DWORD dwWrite;
DWORD dwCnt = 1;
    while(dwCnt){
        pNode = GetNode(&llT1);         /* get node */
        dwCnt = pNode->dwCnt;           /* localize count */
        if(dwCnt)                       /* write data if count != 0 */
            WriteFile(hDst, pNode->pBfr, dwCnt, &dwWrite, NULL);
        PutNode(&llT0, pNode);}         /* return node to thread 0 */
    return(0);
}
/*----------------------------------------------------------------------*/
/*      InitThread0List init thread 0 list                              */
/*----------------------------------------------------------------------*/
static void InitThread0List(void)
{
BYTE * pBfr;
DWORD i;
    pBfr = pMem;
    for(i = 0; i < NBFR; i++){
        aNode[i].pBfr = pBfr;
        PutNode(&llT0, &aNode[i]);
        pBfr += BFRSZ;}
}
/*----------------------------------------------------------------------*/
/*      GetNode     get first node from list                            */
/*                                                                      */
/*  WaitForMultipleObjects eliminates any thread priority issues        */
/*----------------------------------------------------------------------*/
static NODE * GetNode(LIST * pList)
{
NODE * pNode;                           /* used for return value */
/*  wait for ownership, node, and decrement semaphore count */
    WaitForMultipleObjects(2, pList->hMtxSem, TRUE ,INFINITE);
    pNode = pList->pFirst;              /* set return value */
    pList->pFirst = pNode->pNext;       /* advance first ptr */
    if(pList->pFirst == NULL)           /* if emptied list */
        pList->pLast = NULL;            /*  reset last ptr as well */
    ReleaseMutex(pList->hMtx);          /* release ownership of list */
    return(pNode);
}
/*----------------------------------------------------------------------*/
/*      PutNode     append node to end of list                          */
/*      returns 0 if list was previously empty                          */
/*                                                                      */
/*  ReleaseSemaphore increments list count and enables pending thread   */
/*----------------------------------------------------------------------*/
static DWORD PutNode(LIST * pList, NODE * pNode)
{
DWORD dwPrevCount;
    /* wait for ownership of list */
    WaitForSingleObject(pList->hMtx, INFINITE);
    if(pList->pFirst == NULL)           /* if empty list */
        pList->pFirst = pNode;          /*   set first ptr */
    else                                /* else set tail node ptr */
        pList->pLast->pNext = pNode;
    pList->pLast = pNode;               /* set last ptr */
    pNode->pNext = NULL;                /* reset next ptr */
    /* increment semaphore list count */
    ReleaseSemaphore(pList->hSem,1,&dwPrevCount);
    ReleaseMutex(pList->hMtx);          /* release ownership of list */
    return(dwPrevCount);
}
© www.soinside.com 2019 - 2024. All rights reserved.