目标:
这次要为进程实现sleep功能和wakeup功能,所以我们需要添加两个队列,一个是运行队列runningList,还有一个则是等待队列waitingList。
链表的使用
提供的链表节点结构如下:
typedef struct ListHead
{
ListHead *prev;
ListHead *next;
}ListHead;
如何使用这个链表节点呢?毕竟平常创建的链表节点,里边可是会在节点定义里边添加value值的啊。
我们可以使用PCB和ListHead来新创建一个节点结构如下:
typedef struct PCBList
{
PCB *pcb;
ListHead listNode;
}PCBList;
关于这个链表,它提供了以下几个函数,
链表节点的初始化,链表节点的加入
void list_init(ListHead *list)
{
assert(list != NULL);
list->prev = list;
list->next = list;
list->value = 0;
}
void list_add(ListHead *prev, ListHead *next, ListHead *data)
{
assert(data != NULL);
data->prev = prev;
data->next = next;
if (NULL != prev)
{
prev->next = data;
}
if (NULL != next)
{
next->prev = data;
}
}
void list_add_before(ListHead *list, ListHead *data)
{
assert(list != NULL);
list_add(list->prev, list, data);
}
我看到这个双向链表节点的加入感觉好懵懵懂懂啊
,新节点加入之后,链表结构到底是怎么变化的呢?
比如我首先创建一个头结点ListHead head,之后初始化它,那么我们的双向链表就是如下图所示:
加入一个节点之后呢?
ListHead node1;
list_init(node1);
list_add_before(&head, &node1);
我们知道会有这样的操作:
list_add(head->prev, &head, &node1)
也即node1->prev = head->prev;
node1->next = &head;
head->prev->next = node1;
head->prev = node1;
感觉好混乱啊,画个图来看看吧:
首先head的prev和next都是指向自己的,为了表示更加清晰,我们使用一个单独的head->prev节点,当然了,此时head->prev == head。
接着node1节点加入,然后就是按照上面写的修改指向,也就是此时的中间图。
因为head->prev和head节点时同一个节点,所以合并之后就变成第三幅图了。
那么我再加入一个节点node2情况会怎么样呢?
node2->prev = head->prev;
node2->next = &head;
head->prev->next = node2;