内核链表及使用

内核链表是操作系统内核中用于管理内存中数据结构的一种方式,特别是在Linux内核中。它提

拱了一种灵活且高效的方法来组织和管理数据,如进程、缓冲区、定时器等。内核链表的设计允许

快速插入、删除和遍历节点,这对于需要高效率和实时响应的内核操作至关重要。

内核链表:

可以给里面放不止一套相同类型的数据,但数据的对象不同

内核链表:

双向链表、有头链表,循环链表

内核链表的特点:

  1. 双向链表:大多数内核链表是双向循环链表,这意味着每个节点都有指向前一个和后一个节点的指针。这使得从链表中任意位置插入和删除节点都变得容易。

  2. 内存管理:内核链表通常用于管理内核空间的内存,因此它们需要高效且占用空间小。

  3. 并发控制:由于内核代码可能被多个处理器或线程同时访问,内核链表的实现通常需要考虑并发控制,如使用自旋锁或互斥锁。

  4. 性能优化:内核链表的设计通常针对性能进行了优化,以减少内存访问延迟和提高处理速度。

将节点放在存储数据的结构体中

怎么通过节点获取数据呢------->内核提供了两个宏:

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、接指针函数的返回值的函数,最好判空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值