Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The second part of this project involves modifying the kernel module so that it

ID: 3877461 • Letter: T

Question

The second part of this project involves modifying the kernel module so that it uses the kernel linked-list data structure. In Section 1.10, we covered various data structures that are common in operating systems (At the bottom of this document).The Linux kernel provides several of these structures.Here, we explore using the circular, doubly linked list that is available to kernel developers. Much of what we discuss is available in the Linux source code— in this instance, the include le <linux/list.h>—and we recommend that you examine this le as you proceed through the following steps. Initially, you must dene a struct containing the elements that are to be inserted in the linked list.The following C struct denes birthdays:

struct birthday {

int day;

int month;

int year;

struct list_head list;

}

Notice the member struct list head list. The list head structure is dened in the include le <linux/types.h>. Its intention is to embed the linked lis twithin the nodesthat comprise the list.This list head structure is quite simple—it merely holds two members, next and prev,that point to the next and previous entries in the list. By embedding the linked list within the structure,Linux makes it possible to manage the data structure with a series of macro functions.


Inserting Elements into the Linked List
We can declare a list head object,which we use as a reference to the head of the list by using the LIST_HEAD() macro
static LIST_HEAD(birthday list);
This macro denes and initializes the variable birthday list,which is of type struct list head.
We create and initialize instances of struct birthday as follows:
struct birthday *person;
person = kmalloc(sizeof(*person), GFP KERNEL);

person->day = 2;

person->month= 8;

person->year = 1995;

INIT LIST_HEAD(&person->list);
The kmalloc() function is the kernel equivalent of the user-level malloc() function for allocating memory,except that kernel memory is being allocated. (TheGFP KERNELag indicates routine kernel memory allocation.)The macro INIT LIST HEAD() initializes the list member in struct birthday.Wecan then add this instance to the end of the linked list using the list add tail() macro:
list_add_tail(&person->list, &birthday list);
Traversing the LinkedList
Traversing the list involves using the list_for_each_entry() Macro, which accepts three parameters:

• A pointer to the structure being iterated over

• A pointer to the head of the list being iterated over

• The name of the variable containing the list head structure
Thefollowingcode illustrates this macro:
struct birthday *ptr;

list_for_each_entry(ptr, &birthday list, list) {

/* on each iteration ptr points */

/* to the next birthday struct */

}

Removing Elements from the Linked List
Removing elements from the list involves using the list_del() macro,which is passed a pointer to struct list_head
list_del(struct list_head *element)
This removes element from the list while maintaining the structure of the remainder of the list. Perhaps the simplest approach for removing all elements from a linked list is to remove each element as you traverse the list. The macro list for each entry safe() behaves much like list for each entry()
except that it is passed an additional argument that maintains the value of the next pointer of the item being deleted. (This is necessary for preserving the structure of the list.)

The following code example illustrates this macro:
struct birthday *ptr, *next

list_for_each_entry_safe(ptr,next,&birthday list,list) {

/* on each iteration ptr points */

/* to the next birthday struct */

list del(&ptr->list);

kfree(ptr);

}

Notice that after deleting each element,were turn memory that was previously allocated with kmalloc() back to the kernel with the call to kfree(). Careful memory management—which includes releasing memory to prevent memory leaks—is crucial when developing kernel-level code.


Part II Assignment
In the module entry point,create a linked list containing ve struct birthday elements.Traverse the linked list and output its contents to the kernel log buffer. Invoke the dmesg command to ensure the list is properly constructed once the kernel module has been loaded. In the module exit point,delete the elements from the linked list and return the free memory back to the kernel.Again, invoke the dmesg command to check that the list has been removed once the kernel module has been unloaded.

Kernel module simple.c

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/module.h>

/* This function is called when the module is loaded. */

int simple init(void) {

printk(KERN INFO "Loading Module ");

return 0;

}

/* This function is called when the module is removed. */

void simple exit(void) {

printk(KERN INFO "Removing Module ");

}

/* Macros for registering module entry and exit points. */

module init(simple init);

module exit(simple exit);

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Simple Module");

MODULE_AUTHOR("SGG")

Explanation / Answer

Linux Kernel Programming– Linked List

Linux piece has connected rundown as an implicit information structure characterized in/lib/modules/$(uname - r)/manufacture/incorporate/linux/list.h. Contrasted and basic usage of connected rundown, the Linux piece rendition enables one to inserted the pre-characterized connected rundown hub into any information structure to shape a connected rundown.

0. Correlation of Common Linked List and Linux Kernel Linked List

Assume we need to actualize a connected rundown of information structure Person. The normal execution is as underneath,

struct Person {

singe name[30];

unsigned int weight;

unsigned singe sex;

struct Person* prev;

struct Person* next;

};

The comparing Linux portion execution would be,

struct Person {

burn name[30];

unsigned int weight;

unsigned burn sexual orientation;

struct list_head list;/* bit's rundown structure */

};

The list_head structure is characterized in list.h,

struct list_head {

struct list_head *next, *prev;

};

The Linux usage is a round connected rundown. The insights about how to make and utilize a connected rundown is secured underneath.

1. Make a Linked List in Linux Kernel Programming

1.1 Create a rundown head

The initial step is to make a rundown head, which focuses to the leader of the connected rundown. There're two strategies. Take after the case above, we can do,

struct Person personList;

LIST_HEAD_INIT(&personList.list);

Or on the other hand

LIST_HEAD(personList);

The two bits of code accomplish similar impacts.

1.2 Create list hub

There're two approaches to make another hub of the information structure Person we characterized previously. To make a hub powerfully,

struct Person* aNewPersonPointer;

aNewPersonPointer = kmalloc(sizeof(*aNewPersonPointer), GFP_KERNEL);

strcpy(aNewPersonPointer->name, "roman10");

aNewPersonPointer->weight = 130;

aNewPersonPointer->gender = 1;

INIT_LIST_HEAD(&aNewPersonPointer->list);

Or then again you can make a hub statically,

struct Person aNewPerson = {

.name = strcpy(aNewPerson.name, "roman10"),

.weight = 130,

.sexual orientation = 1,

.list = LIST_HEAD_INIT(aNewPerson.list),

};

1.3 Add a rundown hub

Linux bit gives the accompanying capacity to include a connected rundown hub,

void list_add(struct list_head *new, struct list_head *head);

You can pass any rundown hub as head, the new hub will be embedded quickly after the head. On the off chance that you pass the last component as head, this capacity can be utilized to actualize a stack. Take after tht past case,

list_add(&aNewPerson->list, &personList.list);

There's another capacity to include a connected rundown hub,

void list_add_tail(struct list_head *new, struct list_head *head);

Thus, you can pass any hub as head, the new hub will be embedded just before the head. On the off chance that you pass the main hub as head, the new hub will be embedded before the primary hub. As the Linux execution of connected rundown is roundabout, it's identical to embeddings the new hub after the last hub. In this manner, this capacity can be utilized to execute a line.

Take after the past case,

list_add_tail(&aNewPerson->list, &personList.list);

2. Erase a Node from the List

Linux portion gives a capacity to erase a hub from the rundown,

void list_del(struct list_head *entry);

It will erase the section hub from the rundown. This capacity expels the passage hub from the connected rundown by disengage prev and next pointers from the rundown, however it doesn't free any memory space distributed for section hub. Take after the case above,

list_del(&aNewPerson->list);

3. Connected List Traversal

The list.h header characterizes a full scale list_for_each(pos, head) for connected rundown traversal. The two pos and head are pointers to the list_head. pos is utilized as a circle cursor, and head is the head hub of the connected rundown. In our case,

struct list_head *node;

struct Person *aPerson;

list_for_each(node, &personList.list) {

/get to the rundown hub through hub

aPerson = list_entry(node, struct Person, list);

}

list_entry is a large scale of 3 inputs,

list_entry(ptr, type, part)

where ptr is a pointer to list_head, type is the structure that list_head is inserted in, for our situation, struct Person, and part is the name of the list_head inside the characterized structure, list for our situation.

A less demanding approach to circle through the connected rundown is likewise given, which joins the circle and list_entry work,

list_for_each_entry(pos, head, part)

In our illustration,

struct Person *aPerson;

list_for_each_entry(aPerson, &personList.list, list) {

/get to the part from aPerson

}

There's a third method to circle through the connected rundown, used to circle through the rundown while expelling hub from it.

list_for_each_entry_safe(pos, n, head, part)

where n is another pointer to client characterized structure utilized as transitory stockpiling. In our case,

struct Person *aPerson, *tempPerson;

list_for_each_entry_safe(aPerson, tempPerson, &personList.list, list) {

/get to the part from aPerson

list_del(&aPerson->list);

kfree(aPerson);

}

4. Different Functions

There're numerous different capacities characterized in list.h, including move list hub starting with one connected rundown then onto the next, join two connected rundown, and so on. One can allude to list.h header petition for more point by point data.

5. Test Program

The following is a portion module that demonstrates the fundamental utilization of the capacities secured previously,

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/list.h>

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("hello");