浏览代码

核心数据结构,双向链表

simon 10 月之前
父节点
当前提交
2f608ddf9f
共有 3 个文件被更改,包括 165 次插入1 次删除
  1. 108 0
      lib/kernel/list.c
  2. 53 0
      lib/kernel/list.h
  3. 4 1
      makefile

+ 108 - 0
lib/kernel/list.c

@@ -0,0 +1,108 @@
+#include "list.h"
+#include "../../kernel/interrupt.h"
+
+// 初始化双向链表list
+void list_init(struct list *plist)
+{
+    plist->head.prev = NULL;
+    plist->head.next = &plist->tail;
+    plist->tail.prev = &plist->head;
+    plist->tail.next = NULL;
+}
+// 将链表元素elem 插入在元素before之前
+void list_insert_before(struct list_elem *before, struct list_elem *elem)
+{
+    enum intr_status old_status = intr_disable(); // 关中断
+
+    before->prev->next = elem; // before 暂时脱离链表
+
+    elem->prev = before->prev;
+    elem->next = before;
+
+    before->prev = elem; // before重新回到链表
+
+    intr_set_status(old_status); // 恢复中断
+}
+// 将元素elem添加到链表plist队首,类似栈push操作
+void list_push(struct list *plist, struct list_elem *elem)
+{
+    list_insert_before(plist->head.next, elem); // 在队头插入elem
+}
+void list_iterate(struct list *plist);
+// 添加元素到链表队尾
+void list_append(struct list *plist, struct list_elem *elem)
+{
+    list_insert_before(&plist->tail, elem); // 在队尾的前面插入
+}
+// 从链表中删除元素pelem
+void list_remove(struct list_elem *pelem)
+{
+    enum intr_status old_status = intr_disable(); // 关中断
+
+    pelem->prev->next = pelem->next;
+    pelem->next->prev = pelem->prev;
+
+    intr_set_status(old_status); // 恢复中断
+}
+// 将链表第一个元素弹出并返回
+struct list_elem *list_pop(struct list *plist)
+{
+    struct list_elem *elem = plist->head.next;
+    list_remove(elem);
+    return elem;
+}
+// 判断链表是否为空,空返回true,否则返回false
+bool list_empty(struct list *plist)
+{
+    return (plist->head.next == &plist->tail ? true : false);
+}
+// 返回链表长度
+uint32_t list_len(struct list *plist)
+{
+    struct list_elem *elem = plist->head.next;
+    uint32_t length = 0;
+    while (elem != &plist->tail)
+    {
+        length++;
+        elem = elem->next;
+    }
+    return length;
+}
+// 把列表plist中的每个元素elem和arg传给func,
+// func 判断是否符合条件
+// 如果找到符合条件的元素返回元素指针,否则返回NULL
+struct list_elem *list_traversal(struct list *plist, trav_func func, int arg)
+{
+    struct list_elem *elem = plist->head.next;
+
+    // 如果链表为空,直接返回NULL
+    if (list_empty(plist))
+    {
+        return NULL;
+    }
+
+    while (elem != &plist->tail)
+    {
+        if (func(elem, arg))
+        {
+            // func返回true,直接返回元素指针
+            return elem;
+        }
+        elem = elem->next;
+    }
+    return NULL;
+}
+// 查找元素是否在链表中,成功返回true,失败返回false
+bool elem_find(struct list *plist, struct list_elem *obj_elem)
+{
+    struct list_elem *elem = plist->head.next;
+    while (elem != &plist->tail)
+    {
+        if (elem == obj_elem)
+        {
+            return true;
+        }
+        elem = elem->next;
+    }
+    return false;
+}

+ 53 - 0
lib/kernel/list.h

@@ -0,0 +1,53 @@
+// 双向链表结构
+#ifndef __LIB_KERNEL_LIST_H
+#define __LIB_KERNEL_LIST_H
+#include "../stdint.h"
+
+#define offset(struct_type, member) (int)(&((struct_type *)0)->member)
+
+#define node2entry(struct_type, struct_member_name, node_ptr) \
+    (struct_type *)((int)node_ptr - offset(struct_type, struct_member_name))
+
+// 链表节点, 节点中不需要数据成员, 只要求前驱和后继指针
+struct list_elem
+{
+    struct list_elem *prev; // 前驱节点
+    struct list_elem *next; // 后继节点
+};
+
+// 链表结构, 用来实现队列
+struct list
+{
+    struct list_elem head; // 链表头, 链表起始元素, 不是第一个元素
+    struct list_elem tail; // 链表尾, 链表终止元素, 不是最后一个元素
+};
+
+// 自定义函数类型 trav_func, 用于在list_traversal中做回调函数
+typedef bool trav_func(struct list_elem *, int arg);
+
+/****************************** function声明 ******************************/
+// 初始化双向链表list
+void list_init(struct list *);
+// 将链表元素elem 插入在元素before之前
+void list_insert_before(struct list_elem *before, struct list_elem *elem);
+// 将元素elem添加到链表plist队首,类似栈push操作
+void list_push(struct list *plist, struct list_elem *elem);
+void list_iterate(struct list *plist);
+void list_append(struct list *plist, struct list_elem *elem);
+// 从链表中删除元素pelem
+void list_remove(struct list_elem *pelem);
+// 将链表第一个元素弹出并返回
+struct list_elem *list_pop(struct list *plist);
+// 判断链表是否为空,空返回true,否则返回false
+bool list_empty(struct list *plist);
+// 返回链表长度
+uint32_t list_len(struct list *plist);
+// 把列表plist中的每个元素elem和arg传给func,
+// func 判断是否符合条件
+// 如果找到符合条件的元素返回元素指针,否则返回NULL
+struct list_elem *list_traversal(struct list *plist, trav_func func, int arg);
+// 查找元素是否在链表中,成功返回true,失败返回false
+bool elem_find(struct list *plist, struct list_elem *obj_elem);
+/****************************** function声明  END ******************************/
+
+#endif // __LIB_KERNEL_LIST_H

+ 4 - 1
makefile

@@ -13,7 +13,7 @@ LDFLAGS = -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_BIN_DIR)/kernel.map
 OBJS = $(BUID_O_DIR)/main.o $(BUID_O_DIR)/init.o $(BUID_O_DIR)/interrupt.o  \
 	$(BUID_O_DIR)/timer.o $(BUID_O_DIR)/kernel.o $(BUID_O_DIR)/print.o   \
 	$(BUID_O_DIR)/debug.o $(BUID_O_DIR)/string.o $(BUID_O_DIR)/bitmap.o  \
-	$(BUID_O_DIR)/memory.o $(BUID_O_DIR)/thread.o
+	$(BUID_O_DIR)/memory.o $(BUID_O_DIR)/thread.o $(BUID_O_DIR)/list.o
 
 ################################ C 代码编译 ################################
 $(BUID_O_DIR)/main.o: kernel/main.c lib/kernel/print.h lib/stdint.h kernel/init.h
@@ -43,6 +43,9 @@ $(BUID_O_DIR)/memory.o: kernel/memory.c kernel/memory.h lib/stdint.h lib/kernel/
 $(BUID_O_DIR)/thread.o: thread/thread.c thread/thread.h
 	$(CC) $(CFLAGS) $< -o $@
 
+$(BUID_O_DIR)/list.o: lib/kernel/list.c lib/kernel/list.h lib/stdint.h kernel/interrupt.h
+	$(CC) $(CFLAGS) $< -o $@
+
 ################################ 汇编代码编译 ################################
 $(BUID_O_DIR)/kernel.o: kernel/kernel.S
 	$(AS) $(ASFLAGS) $< -o $@