内核链表及使用
内核链表是操作系统内核中用于管理内存中数据结构的一种方式,特别是在Linux内核中。它提
拱了一种灵活且高效的方法来组织和管理数据,如进程、缓冲区、定时器等。内核链表的设计允许
快速插入、删除和遍历节点,这对于需要高效率和实时响应的内核操作至关重要。
内核链表:
可以给里面放不止一套相同类型的数据,但数据的对象不同
内核链表:
双向链表、有头链表,循环链表
内核链表的特点:
-
双向链表:大多数内核链表是双向循环链表,这意味着每个节点都有指向前一个和后一个节点的指针。这使得从链表中任意位置插入和删除节点都变得容易。
-
内存管理:内核链表通常用于管理内核空间的内存,因此它们需要高效且占用空间小。
-
并发控制:由于内核代码可能被多个处理器或线程同时访问,内核链表的实现通常需要考虑并发控制,如使用自旋锁或互斥锁。
-
性能优化:内核链表的设计通常针对性能进行了优化,以减少内存访问延迟和提高处理速度。
将节点放在存储数据的结构体中
怎么通过节点获取数据呢------->内核提供了两个宏:
offset of:获取结构体成员到结构体开头的偏移量
contianer_of:通过偏移量获取结构体首地址
构建一个类内核链表实现航班及乘客查询(即将节点放在结构体中)
航班部分:
struct passager * create_passager(char *name,int flt_num,int sit_num,char card)
{
struct passager *p = malloc(sizeof(struct passager));
if(NULL == p)
{
return NULL;
}
strcpy(p->name,name);
p->flt_num = flt_num;
p->sit_num = sit_num;
p->card = card;
return p;
}
void print_passager(void *pnode)
{
struct passager *p = (struct passager *)pnode;
printf("%s %d %d %c\n",p->name,p->flt_num,p->sit_num,p->card);
}
struct flight * create_flight(int plane_name,char *src,char *dst)
{
struct flight *p = malloc(sizeof(struct flight));
if(NULL == p)
{
return NULL;
}
p->plane_name = plane_name;
strcpy(p->src,src);
strcpy(p->dst,dst);
return p;
}
void print_flight(void *pnode)
{
struct flight * p = (struct flight *)pnode;
printf("%d %s %s\n",p->plane_name,p->src,p->dst);
}
uav_t* creat_pthread(char *name,void *(*pfun)(void *))
{
uav_t * thread = malloc(sizeof(uav_t));
if(thread == NULL)
{
perror("malloc fail\n");
return NULL;
}
strcpy(thread->name,name);
pthread_t tid;
int ret = pthread_create(&tid,NULL,pfun,NULL);
if(ret != 0)
{
perror("pthread_create fail\n");
return NULL;
}
thread->pfun = pfun;
return thread;
}
创建航班节点
Klink_t *create_klink()
{
Klink_t *pknode = malloc(sizeof(Klink_t));
if(NULL == pknode)
{
return NULL;
}
pknode->phead = NULL;
pknode->clen = 0;
pthread_mutex_init(&(pknode->mutex), NULL);
return pknode;
}
头插
int push_link_head(Klink_t *plink,void *p)
{
Knode_t *pnode = (Knode_t *)p;
pnode->pnext = NULL;
pnode->ppre = NULL;
pnode->pnext = plink->phead;
if(plink->phead != NULL)
{
plink->phead->ppre = pnode;
}
plink->phead = pnode;
plink->clen++;
return 0;
}
遍历
void klink_for_each(Klink_t *plink, void (*pfun)(void *))
{
Knode_t *pnode = plink->phead;
while (pnode != NULL)
{
pfun(pnode);
pnode = pnode->pnext;
}
printf("\n");
}
结构体的第一个成员的地址即为结构体的首地址
函数指针:指向函数的指针
指向函数的指针,它允许将函数作为参数传递给其他函数,或者将函数赋值给指针变量
函数:返回值 函数名(形参表)
去掉变量名剩下类型名-->
函数指针:返回值 (*函数指针名)(形参表);
使用:函数指针可以作为参数传递给其他函数,这在实现回调函数时非常有用
函数指针(实参)
例如,假设有一个返回 int
类型,接受两个 int
类型参数的函数,其对应的函数指针声明如下:
int (*func_ptr)(int, int);
指针函数:返回值为指针的函数
这是一种函数,它的返回类型是指针类型。这种函数调用结束后,返回一个指向某种数据类型的指针。在C语言中非常常见,尤其是在处理数组、字符串和动态内存分配时。
1、返回的指针指向的空间不能是一块临时的空间
(返回的指针不能指向一个局部变量的空间)
2、malloc
全局变量
静态变量
3、接指针函数的返回值的函数,最好判空