一、单向链表
//list.h#ifndef LIST_H_
#define LIST_H_
#include <stdlib.h>
typedef struct ListElement_ {
void *data;
struct ListElement_ *next;
} ListElement;
typedef struct List_ {
int size;
int (*match) (const void *data1, const void *data2);
void (*destory) (void* data);
ListElement *head;
ListElement *tail;
} List;
void list_init(List *list, void (*destory) (void *data)); //初始化链表,每次使用前都要去初始化
void list_destory(List *list); //销毁链表
int list_ins_next(List *list, ListElement *element, const void *data); //在指定的元素画面插入一个元素,如果element为NULL,则在表头插入
int list_rem_next(List *list, ListElement *element, void *data); //移除指定元素的后面一个元素
#define list_size(list) ((list)->size)
#define list_head(list) ((list)->head)
#define list_tail(list) ((list)->tail)
#define list_is_head(list, element) ((element) == (list->head) ? 1 : 0)
#define list_is_tail(element) ((element)->next == NULL ? 1 : 0)
#define list_data(element) ((element)->data)
#define list_next(element) ((element)->next)
#endif
实现文件list.c
#include "list.h"
#include
#include
#include
void list_init(List *list, void (*destory)(void *data)) {
if (list == NULL) return;
list->size = 0;
list->match = NULL;
list->destory = destory;
list->head = NULL;
list->tail = NULL;
}
void list_destory(List *list) {
if (list == NULL) return;
void *data;
while (list_size(list) > 0) {
if (list_rem_next(list, NULL, (void **)&data) == 0 && list->destory != NULL) {
list->destory(data);
}
}
memset(list, 0, sizeof(list));
}
int list_ins_next(List *list, ListElement *elem, const void *data) {
if (!list) return -1;
ListElement *ins_elem = (ListElement*)malloc(sizeof(ListElement));
list_data(ins_elem) = data;
list_next(ins_elem) = NULL;
if (!elem) {
if (list_size(list) == 0) list_tail(list) = ins_elem;
list_next(ins_elem) = list_head(list);
list_head(list) = ins_elem;
} else {
if (list_next(elem) == NULL) list_tail(list) = ins_elem;
list_next(ins_elem) = list_next(elem);
list_next(elem) = ins_elem;
}
list->size++;
return 0;
}
int list_rem_next(List *list, ListElement *elem, void **data) {
if (!list || list_size(list) == 0) return -1;
ListElement *old_element;
if (!elem) {
*data = list_data(list_head(list));
old_element = list_head(list);
list_head(list) = list_next(list_head(list));
if (list_size(list) == 1) list->tail = NULL;
} else {
if (elem->next == NULL) return -1;
*data = list_data(list_next(elem));
old_element = (list_next(elem));
list_next(elem) = list_next(list_next(elem));
if (elem->next == NULL) list->tail = elem;
}
free(old_element);
list_size(list)--;
return 0;
}
二、单向链表的应用
单向链表可以应用于操作系统的虚拟内存中,我们知道程序使用的内存空间大于实际的物理内存。虚拟内存是一种地址空间的映射机制,它允许进程不必完全加载到物理内存中也可以得到运行。这种方式的优点:
- 进程可以使用比系统实际所允许的物理内存大得多的地址空间。
- 多个进程能够共享系统的内存以并发的方式执行。

模拟内存页表的代码:
#include "list.h"
//从空闲的页帧链表中获取空闲页帧号
int alloc_frame(List *list) {
if (list_size(list) == 0) return -1;
int *frame_number;
if (list_size(list)) {
list_rem_next(list, NULL, (void**)&frame_number);
}
return *frame_number;
}
//接受一个页帧号并将其放回空闲页帧链表中
int free_frame(List *list, int frame_number) {
int *data;
if ((data = (int*)malloc(sizeof(int))) == NULL) return -1;
*data = frame_number;
if (list_ins_next(list, NULL, data))
return -1;
return 0;
}
void init_page(List *list) {
int i;
for (i = 0; i < 10; ++i) {
int *j = (int*) malloc(sizeof(int));
*j = rand() % 50;
list_ins_next(list, NULL, j);
}
}
void print(List *list) {
int i = 0;
ListElement *elem = list->head;
printf("list size is : %d\n", list_size(list));
for (; i < list_size(list) && elem != NULL ; ++i) {
printf("%d\n", *(int*)elem->data);
elem = elem->next;
}
}
int real_mem[50] = {0,}; //模拟系统中真实的内存
int get_mem(int frame) { //获取真实的内存值
return real_mem[frame];
}
int main() {
List *list = (List*)malloc(sizeof(*list));
list_init(list, free);
init_page(list); //初始化一个页表
print(list);
int frame = alloc_frame(list);
//取得了页帧号,获取真实的物理内存
int use_mem = get_mem(frame);
//TODO: 使用这块内存
list_destory(list);
return 0;
}
本文详细介绍了单向链表的概念,并探讨了其在C语言中的具体应用,展示了如何利用链表来扩展进程地址空间并实现内存共享。
&spm=1001.2101.3001.5002&articleId=8301763&d=1&t=3&u=f64ef5fb15c1451faf41618a80c14d73)
2468

被折叠的 条评论
为什么被折叠?



