当前位置: 首页 > article >正文

内核链表及使用

内核链表是操作系统内核中用于管理内存中数据结构的一种方式,特别是在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、接指针函数的返回值的函数,最好判空


http://www.kler.cn/a/291882.html

相关文章:

  • Gin 框架中的路由
  • 基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
  • 问:说说SpringDAO及ORM的用法?
  • 【windows笔记】08-Windows中的各种快捷方式、符号链接、目录联接、硬链接的区别和使用方法
  • 小程序19-微信小程序的样式和组件介绍
  • DAY120java审计第三方组件依赖库挖掘FastjsonShiroLog4jH2DB
  • 使用matlab的热门问题
  • 5.1.数据结构-c/c++二叉树详解(上篇)(遍历,几种二叉树)
  • 【Spring Boot 3】【Web】全局异常处理
  • 【mac】brew 更新
  • psql常见报错解决
  • 探究 Eureka 在 Spring Boot 中的配置注入与统一管理机制(下)——第三节
  • wordpress发送邮件的方法?怎么配置功能?
  • 计算机考研真题知识点——2021(B)
  • Redis的Java客户端
  • if语句:if和else
  • 云计算实训40——部署nmt、部署project_exam_system项目
  • 触想内嵌式工业一体机应用于智能检票机改善旅游体验
  • 学学vue-1
  • c语言与c++的区别详解
  • [数据集][目标检测]智慧牧场猪只检测数据集VOC+YOLO格式16245张1类别
  • 理解Sigmoid激活函数原理和实现
  • Linux 硬件学习 s3c2440 arm920t蜂鸣器
  • Trollspeed网速悬浮窗,精简且强大
  • 【ArcGIS Pro原理第一期】各种空间插值原理:GPI、LPI、IDW等
  • Go异常处理机制