详解C语言内核中的链表与结构体

详解C语言内核中的链表与结构体

1. 链表的概念

链表是一种线性数据结构,由多个节点组成,每个节点包含了两部分内容:数据和指针。

链表有多种类型,但其中最常见的是单向链表和双向链表。在单向链表中,每个节点只包含一个指针,它指向下一个节点;在双向链表中,每个节点包含两个指针,一个指向上一个节点,一个指向下一个节点。

链表的特点是可以动态地添加或删除节点,是一种非常灵活的数据结构。它可以用来实现其他数据结构,比如栈和队列等。

2. 结构体的概念

结构体是一种用户自定义类型,可以包含多个不同类型的变量,这些变量可以是基本类型,也可以是其他结构体类型。结构体可以用来表示一个实体,比如人或汽车等。

结构体的定义语法如下:

struct <结构体名> {
    <成员1类型> <成员1名>;
    <成员2类型> <成员2名>;
    ...
};

结构体成员可以通过.运算符来访问,比如:

struct person {
    char name[20];
    int age;
};

struct person p;
strcpy(p.name, "Tom");
p.age = 25;

3. 链表和结构体的结合使用

链表和结构体可以结合使用,使得链表中每个节点都可以包含一个结构体实体。这种结构体称为链表节点的数据域,它包含了节点的数据信息。

链表节点又包含了一个指针,指向下一个节点。这个指针称为链表节点的指针域。使用指针可以方便的连接多个节点,形成链表。如下示例所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct student {
    int id;
    char name[20];
    struct student *next; // 指向下一个节点的指针
};

int main() 
{
    // 创建三个学生结构体
    struct student *head = NULL, *p, *prev;
    int i;

    for (i = 0; i < 3; i++) {
        p = (struct student*)malloc(sizeof(struct student));
        p->id = i + 1;
        sprintf(p->name, "student%d", i + 1);
        p->next = NULL;
        // 构建链表
        if (head == NULL) {
            head = p;
        } else {
            prev->next = p;
        }
        prev = p;
    }

    // 遍历链表
    p = head;
    while (p != NULL) {
        printf("id=%d, name=%s\n", p->id, p->name);
        p = p->next;
    }

    // 释放链表
    p = head;
    while (p != NULL) {
        prev = p;
        p = p->next;
        free(prev);
    }

    return 0;
}

代码中先定义了一个学生结构体,包含了学生的ID、姓名和指向下一个节点的指针。然后创建了三个学生结构体,并链接到一起,形成链表。最后遍历链表,输出每个学生的信息。

注意到,在构建链表的过程中,需要记录上一个节点的指针prev,供下一个节点链接使用。

4. 在Linux内核中的链表

在Linux内核中,经常使用带有链表结构的数据结构。为了避免每次都重新实现链表,Linux内核提供了一个链表库,定义了基于链表的一些常见操作,包括创建、添加、删除和遍历等。

这个库定义在include/linux/list.h头文件中。在这个头文件中,定义了几个重要的结构体:

struct list_head {
    struct list_head *prev, *next;
};

struct hlist_head {
    struct hlist_node *first;
};

struct hlist_node {
    struct hlist_node *next, **pprev;
};

其中最重要的是list_head结构体,它被用作链表节点的指针域。由于链表节点需要包含在其他的结构体内,我们可以通过内嵌结构体来实现,例如:

struct student {
    int id;
    char name[20];
    struct list_head list; // 链表指针域
};

这里我们定义了一个含有链表指针的学生结构体,可以用它作为链表节点的数据域。在这个结构体中,使用了list_head结构体作为链表节点的指针域。这个list_head结构体包含了两个指针,分别指向上一个节点和下一个节点。

与普通链表类似,Linux内核中的链表可以使用一系列函数进行操作。下面展示如何创建一个包含链表节点的内核对象:

#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/module.h>

struct student {
    int id;
    char name[20];
    struct list_head list;
};

struct student stu1 = {
    .id = 1,
    .name = "Tom",
    .list = LIST_HEAD_INIT(stu1.list)
};

struct student stu2 = {
    .id = 2,
    .name = "Jerry",
    .list = LIST_HEAD_INIT(stu2.list)
};

struct student stu3 = {
    .id = 3,
    .name = "Mike",
    .list = LIST_HEAD_INIT(stu3.list)
};

static int __init hello_init(void)
{
    printk("Hello, world!\n");

    // 链接学生对象到链表
    INIT_LIST_HEAD(&stu1.list);
    list_add_tail(&stu2.list, &stu1.list);
    list_add_tail(&stu3.list, &stu1.list);

    // 遍历链表
    struct list_head *pos;
    struct student *stu;

    list_for_each(pos, &stu1.list) {
        stu = list_entry(pos, struct student, list);
        printk("id=%d, name=%s\n", stu->id, stu->name);
    }

    return 0;
}

static void __exit hello_exit(void)
{
    printk("Goodbye, world!\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

本示例中定义了三个学生对象,然后将它们通过链表链接起来,并遍历整个链表,输出每个学生的信息。

在本示例中,INIT_LIST_HEAD和list_add_tail函数用于初始化并添加链表元素,list_for_each和list_entry函数用于遍历链表。

总结

通过本文,我们详细讲解了在C语言中使用链表和结构体的基础知识,并介绍了Linux内核中的链表库,方便编写高可靠性的内核代码。本文中的示例可以帮助您更深入了解链表和结构体的使用方法,供读者参考。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解C语言内核中的链表与结构体 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言编程简单却重要的数据结构顺序表全面讲解

    C语言编程简单却重要的数据结构顺序表全面讲解 什么是顺序表? 顺序表是一种线性表,指的是一组有限元素的有限序列,其元素的逻辑顺序与它们在分配到的内存地址上的物理顺序相同或者等价。也就是说,顺序表中的元素按照其在内存中的位置依次存放。 顺序表的实现方式 顺序表的实现方式一般是使用数组,数组中的每一个元素对应着顺序表中的一个元素,位置相对应。 顺序表的优点 支持…

    数据结构 2023年5月17日
    00
  • 多维度深入分析Redis的5种基本数据结构

    多维度深入分析Redis的5种基本数据结构 Redis是一种高性能、内存数据存储系统,它支持多种数据结构,包括字符串、哈希表、列表、集合和有序集合。其中,每种数据结构都具有不同的特性和用途,本文将对这五种基本数据结构进行深入分析。 1. 字符串(string) 字符串是最基本的数据结构,一个字符串可以存储任意二进制数据,例如一个jpg图片或者一个序列化的对象…

    数据结构 2023年5月17日
    00
  • Java数据结构之哈夫曼树概述及实现

    Java数据结构之哈夫曼树概述及实现 哈夫曼树概述 哈夫曼树(Huffman Tree),也称为最优树(Optimal Binary Tree),是一种带权路径长度最短的二叉树,也就是最小权重的前缀编码树。其基本思想是采用频率作为节点的权值,将频率较小的节点放在左子树上,频率较大的节点放在右子树上,从而形成一棵权值最小的二叉树。 实现过程 实现哈夫曼树需要以…

    数据结构 2023年5月17日
    00
  • Huffman实现

    Huffman编码树 秒懂:【算法】Huffman编码_哔哩哔哩_bilibili 约定:字符x的编码长度 就是其对应叶节点的深度; 在一个字符集中,每个字符出现的次数有多有少,那么若都采用固定长度编码的话,那么编码长度会非常大,并且搜索时间复杂度都非常高;若采用非固定编码,出现次数多的字符编码长度小一些,并且放在树深度小的地方,提高搜索时间效率;这样带权平…

    算法与数据结构 2023年4月17日
    00
  • C++实现数据结构的顺序表详解

    C++实现数据结构的顺序表详解 介绍 在进行程序开发时,常常需要对数据进行存储和操作。其中一种数据结构是顺序表,它提供了一种在内存中线性存储数据的方法,能够方便地对数据进行插入、删除、查找等操作。本文将详细介绍如何使用C++实现数据结构的顺序表,帮助读者掌握顺序表的创建、插入、删除、查找等操作。 创建顺序表 顺序表可以使用数组来实现。下面的代码展示了如何创建…

    数据结构 2023年5月17日
    00
  • golang中set数据结构的使用示例

    Golang中Set数据结构的使用示例 Set是一种无序的、元素不重复的数据结构。通过使用map来实现,map中的key即为Set中的元素,value则可以用来存储某种状态(比如计数)。 Set数据结构的定义 type Set struct { m map[interface{}]bool } Set数据结构的初始化 func NewSet() *Set {…

    数据结构 2023年5月17日
    00
  • C语言数据结构系列队列篇

    C语言数据结构系列队列篇攻略 简介 队列(Queue)是一种先进先出(First In First Out, FIFO)的线性数据结构,类似于排队买票的过程。本篇攻略将带您从以下三个方面深入浅出地了解C语言数据结构系列队列篇: 队列的特点; 队列的实现; 队列的应用。 队列的特点 队列有两个特殊的端点,队头(front)和队尾(rear)。队头指示队列的头部…

    数据结构 2023年5月17日
    00
  • Halcon学习教程(一) 之提取十字线中心 图像分割

      原文作者:aircraft   原文链接:https://www.cnblogs.com/DOMLX/p/17266405.html      废话不多说,因为毕业后工作原因比较忙,好久没更新博客了,直接上图。。。     上图有个十字线,我们要提取出十字线的中心(Hhhh这个线是我随手画的 没画直!!) 第一步:肯定是读取图像进行灰度提取处理啦。   …

    算法与数据结构 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部