C: Linux内置链表在内核数据结构中的使用

Ase*_*ian 5 c kernel linux-kernel

我正在尝试向我的linux内核添加系统调用,当我修改task_struct(通过添加链表)时,使用内置链表会很有利,并且task_struct已经有相当多的struct list_head了在那里用于其他目的。为了统一,我想坚持使用这种数据结构。

我的问题是我真的不完全理解如何使用这个结构。例如,我看到他们有“struct list_head Children”。然而,这个结构的实现很简单,就是“*next”和“*last”。

我在网上查看了示例,每个人都说,好吧

struct node{
    int data;
    struct list_head list;
}; 
Run Code Online (Sandbox Code Playgroud)

但这是否表明我应该包含在我的 task_struct 中的数据结构应该是

struct node list;
Run Code Online (Sandbox Code Playgroud)

我不太明白如果我使用 list_head,我将如何初始化结构以包含我希望它包含的数据。

本质上,我想添加系统调用的链接列表,并以 char* (可读格式)链接列表的形式将它们添加到进程中。

目前,获取系统调用信息的语义并不重要......我只需要弄清楚如何让链表与task_struct一起工作。

编辑:例如我想做的事情:

我已经获得了函数执行的系统调用的列表。我将它们保存在单独的 char* 变量中。我想在进程 task_struct 中添加一个列表来跟踪所有这些系统调用。

例如

进程“abc”调用 printf ~> 相当于“WriteScreen” getchar ~> 相当于“ReadKey”

我现在有一段包含这两个字符串的用户态代码。我调用一个系统调用,我将编写该系统调用(每个标记一次),以使用这些系统调用“标记”进程。

两次调用后,'abc'的task_struct有一个列表

abc->task_struct->tag_list

该列表包含“WriteScreen”和“ReadKey”。

稍后我将使用这些标签来打印调用了 WriteScreen、ReadKey 等的进程列表。这些的实现将在我了解如何使用列表来正确存储附加到进程的字符串后进行。

rsl*_*mos 4

因此,您想要完成的是每个进程的列表,而不是创建进程列表(task_struct)。

这意味着每个进程都有自己的列表,即自己的列表头。

除了下一个/上一个指针之外,该列表还将存储单个数据,实际上是一个字符串(可以是字符串本身或指向其他地方的字符串的指针)。

因此,列表节点将是:

struct my_node {
    struct list_head list;
    char data[100]; // arbitrarily set to 100; could be also char*
}
Run Code Online (Sandbox Code Playgroud)

task_struct 应该增加一个新的列表头:

struct task_struct {
  // many members that contains info about a process
  ...

  struct list_head my_list;
}
Run Code Online (Sandbox Code Playgroud)

是的。您会注意到这两种情况(当进程属于列表时,以及当列表属于进程时)成员将是相同的;只是它的用途不同。

现在,当创建一个进程时,您应该初始化列表头(因为每个进程都会有一个新列表):

struct task_struct *new_process;
INIT_LIST_HEAD(&new_process->my_list);
Run Code Online (Sandbox Code Playgroud)

插入一个新节点(假设你已经创建了它,即分配了内存并初始化了它的数据):

struct my_node *node; 
struct task_struct *a_process;

[... my_node initialized ...]
[... a_proccess obtained somehow ...]

list_add_tail(&node->list, &a_process->my_list);
Run Code Online (Sandbox Code Playgroud)

迭代元素:

struct my_node *p;
struct task_struct *a_process

// list is the member name (yes, the member name) of your list inside my_node
list_for_each_entry(p, &a_process->my_list, list) {
  // do whatever you want with p
}
Run Code Online (Sandbox Code Playgroud)

编辑:

但请注意,您可以使用其他方法来完成您想要做的事情,而无需诉诸复杂的链表。

例如,您可以分配一个字符数组,并通过用一些字符(逗号、句点等)分隔字符串来对字符串列表进行编码。这边走:

"WriteScreen,ReadKey\0"
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您应该注意缓冲区限制,以免溢出。另一方面,您不必负责分配和释放列表的节点。