It is recommended to use the kernel list only after you know the one-way and two-way circular lists. Do not use the kernel list first

Kernel linked list. H file

#ifndef __DLIST_H
#define __DLIST_H

```mermaid
graph TD
Start --> Stop
Copy the code

/* This file is from Linux Kernel (include/linux/list.h)

  • and modified by simply removing hardware prefetching of list items.
  • Here by copyright, credits attributed to wherever they belong.
  • Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)

* /

/ *

  • Simple doubly linked list implementation.
  • Some of the internal functions (” __xxx “) are useful when
  • manipulating whole lists rather than single entries, as
  • sometimes we already know the next/prev entries and we can
  • generate better code by using them directly rather than
  • using the generic single-entry routines.

/ / *

  • container_of – cast a member of a structure out to the containing structure
  • @ptr: the pointer to the member.
  • @type: the type of the container struct this is embedded in.
  • @member: the name of the member within the struct.

*/ #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char )__mptr – offsetof(type,member) ); } /

  • These are non-NULL pointers that will result in page faults
  • under normal circumstances, used to verify that nobody uses
  • non-initialized list entries.

*/ #define LIST_POISON1 ((void *) 0x00100100) #define LIST_POISON2 ((void *) 0x00200)

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

#define LIST_HEAD_INIT(name) {&(name), &(name)}

#define LIST_HEAD(name)

struct list_head name = LIST_HEAD_INIT(name)

#define INIT_LIST_HEAD(PTR) do {(PTR)->next = (PTR); (ptr)->prev = (ptr); } while (0)

/ *

  • Insert a new entry between two known consecutive entries.
  • This is only for internal list manipulation where we know
  • the prev/next entries already!

* /

Static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new;

}

/ * *

  • List_add – Add a new entry
  • @new: new entry to be added
  • @head: list head to add it after
  • Insert a new entry after the specified head.
  • This is good for implementing stacks.

Static list_add(struct list_head *new, struct list_head *head) {__list_add(new, struct list_head *head) head, head->next); }

/ * *

  • List_add_tail – Add a new entry
  • @new: new entry to be added
  • @head: list head to add it before
  • Insert a new entry before the specified head.
  • This is useful for implementing queues.

Static list_add_tail(struct list_head *new, struct list_head *head) {__list_add(new, struct list_head *head) head->prev, head); }

/ *

  • Delete a list entry by making the prev/next entries
  • point to each other.
  • This is only for internal list manipulation where we know
  • the prev/next entries already!

Static inline void __list_del(struct list_head *prev, struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; }

/ * *

  • List_del — Deletes entry from list.
  • @entry: the element to delete from the list.
  • Note: list_empty on entry does not return true after this, the entry is in an undefined state.

*/ / get the entry node: Static inline void list_del(struct list_head *entry) {__list_del(entry->prev, entry->next); entry->next = (void *) 0; entry->prev = (void *) 0; }

/ * *

  • List_del_init – Deletes entry from list and reinitialize it.
  • @entry: the element to delete from the list.

*/ / get the entry node: Static inline void list_del_init(struct list_head *entry) {__list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); }

/ * *

  • List_move — delete from one list and add as another’s head
  • @list: the entry to move
  • @head: the head that will precede our entry

Static list_head (struct list_head *list, struct list_head *list) struct list_head *head) { __list_del(list->prev, list->next); list_add(list, head); }

/ * *

  • List_move_tail — delete from one list and add as another’s tail
  • @list: the entry to move
  • @head: the head that will follow our entry

Static list_head (struct list_head *list) static list_head (struct list_head *list) struct list_head *head) { __list_del(list->prev, list->next); list_add_tail(list, head); }

/ * *

  • List_empty – tests whether a list is empty
  • @head: the list to test.

Static list_empty(struct list_head *head) {return list_head ->next == head; }

// List: 1 2 3 4 5 6 7 // head: 11 22 33 44 // result :head: 1 2 3 4 5 6 7 11 22 33 44 static inline void __list_splice(struct list_head *list, struct list_head *head) { struct list_head *first = list->next; struct list_head *last = list->prev; struct list_head *at = head->next;

first->prev = head;
head->next = first;

last->next = at;
at->prev = last;
Copy the code

}

/ * *

  • List_splice — join two lists
  • @list: the new list to add.
  • @head: the place to add it in the first list.

*/ static inline void list_splice(struct list_head *list, struct list_head *head) { if (! list_empty(list)) __list_splice(list, head); }

/ * *

  • List_splice_init — join two lists and reinitialise the emptied list.
  • @list: the new list to add.
  • @head: the place to add it in the first list.
  • The list at @list is reinitialised

*/ static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head); INIT_LIST_HEAD(list); } }

/ * *

  • List_entry – Get the struct for this entry
  • @ptr: the &struct list_head pointer.
  • @type: the type of the struct this is embedded in.
  • @member: the name of the list_struct within the struct.

*/ / small pointer PTR, large structure type type, small structure inside the large structure member name list // small pointer address, #define list_entry(PTR, type, member) ((type *)((char *)(PTR)-(unsigned long)(&(type *)0)->member))) #define list_entry(PTR, type, member) ((char *)(PTR)->member))

/ * *

  • list_for_each – iterate over a list
  • @pos: the &struct list_head to use as a loop counter.
  • @head: the head for your list.

* /

#define list_for_each(pos, head) for (pos = (head)->next; #define list_for_each(pos, head)->next; pos ! = (head); pos = pos->next)

/ * *

  • list_for_each_prev – iterate over a list backwards
  • @pos: the &struct list_head to use as a loop counter.
  • @head: the head for your list.

#define list_for_each_prev(pos, head) for (pos = (head)->prev; pos ! = (head); pos = pos->prev)

/ * *

  • list_for_each_safe – iterate over a list safe against removal of list entry
  • @pos: the &struct list_head to use as a loop counter.
  • @n: another &struct list_head to use as temporary storage
  • @head: the head for your list.

*/ // a safe traversal to prevent node deletion in the loop body, #define list_for_each_safe(pos, n, head) for (pos = (head)->next, n = pos->next; pos ! = (head); pos = n, n = pos->next)

/ * *

  • list_for_each_entry – iterate over list of given type
  • @pos: the type * to use as a loop counter.
  • @head: the head for your list.
  • @member: the name of the list_struct within the struct.

*/ / get a pointer to a large structure: //pos is a large structure pointer variable in traversal, #define list_for_each_entry(pos, head, member) for (pos = list_entry((head)->next, typeof(*pos), member); &pos->member ! = (head); pos = list_entry(pos->member.next, typeof(*pos), member))

/ * *

  • List_for_each_entry_safe – Iterate over list of given type safe against removal of list entry
  • @pos: the type * to use as a loop counter.
  • @n: another type * to use as temporary storage
  • @head: the head for your list.
  • @member: the name of the list_struct within the struct.

*/ #define list_for_each_entry_safe(pos, n, head, member) for (pos = list_entry((head)->next, typeof(*pos), member), n = list_entry(pos->member.next, typeof(*pos), member); &pos->member ! = (head); pos = n, n = list_entry(n->member.next, typeof(*n), member))

#endif

Railway management system based on Linux

Please see the link below for the project code (the blogger also made efforts @@)

Simple application of a few small procedures

While learning, you can refer to the comments to understand the code, and the code blogger has run it himself

#include "list.h"
#include <stdio.h>
#include <stdlib.h>

typedef int Datatype;

// Data node structure declaration
typedef struct node// Large structure: store data {
	Datatype data;
	struct list_head list;		// small structure: store precursor pointer and successor pointer
}Node, *Link;

Link init_list(a);
Link create_node(Datatype data);
void display(Link head);
void delete_node(Link head, Datatype data);
Link find_node(Link head, Datatype data);

// Initialize the linked list
Link init_list(a)
{
	// Create a node
	Link head = malloc(sizeof(Node));
	// Create pure linked lists
	if(head ! =NULL)
	{
		INIT_LIST_HEAD(&(head->list));
	}
	return head;
}

// Create a node
Link create_node(Datatype data)
{
	Link new = malloc(sizeof(Node));
	if (new! =NULL)
	{
		new->data = data;
		new->list.prev = NULL;
		new->list.next = NULL;
	}
	return new;
}

/ / traverse
void display(Link head)
{
	Link Node_p = NULL;
	Link N = NULL;
	list_for_each_entry_safe(Node_p, N, &(head->list), list)
	{
		printf("%d ", Node_p->data);
	}
	printf("\n");
}

// Delete a node
void delete_node(Link head, Datatype data)
{
	Link Node_p = NULL;
	Link N = NULL;
	list_for_each_entry_safe(Node_p, N, &(head->list), list)
	{
		if (Node_p->data == data)
		{
			list_del(&(Node_p->list));// Delete a node
			free(Node_p); }}printf("No such object \n");

	// Link Node_p = find_node(head, data);
	// if (Node_p == NULL)
	/ / {
	// printf(" no such object \n");
	// }
	// else
	/ / {
	// list_del(&(Node_p->list)); // Delete a node
	// free(Node_p);
	// }
}

// Find the node
Link find_node(Link head, Datatype data)
{
	Link Node_p = NULL;
	Link N = NULL;
	list_for_each_entry_safe(Node_p, N, &(head->list), list)
	{
		if (Node_p->data == data)
		{
			returnNode_p; }}return NULL;
}

int main(int argc, char const *argv[])
{
	// Initialize an empty linked list
	Link head = init_list();

	// Create node in insert
	int i;
	for (i = 0; i < 5; ++i)
	{	
		Link new = create_node(i+1);	
		list_add_tail(&(new->list), &(head->list));
	}

	/ / traverse
	display(head);

	return 0;
}
Copy the code

```c
#include "list.h"
#include <stdio.h>
#include <stdlib.h>

// Data node structure declaration
struct node// Large structure: store data {
	int data;
	struct list_head list;		// small structure: store precursor pointer and successor pointer
};

int main(int argc, char const *argv[])
{
	// Create a node
	struct node *head = malloc(sizeof(struct node));
	struct node *head1 = malloc(sizeof(struct node));
	// Create pure linked lists
	if(head ! =NULL)
	{
		INIT_LIST_HEAD(&(head->list));
	}
	if(head1 ! =NULL)
	{
		INIT_LIST_HEAD(&(head1->list));
	}
	int i;
	for (i = 0; i < 5; ++i)
	{
		struct node *new = malloc(sizeof(struct node));
		if (new! =NULL)
		{
			new->data = i+1;
			new->list.prev = NULL;
			new->list.next = NULL;
		}
		else
		{
			i--;
			continue;
		}

		// Insert a node into the list
		/ / head
		// list_add(&(new->list), &(head->list));
		/ / end plug
		list_add_tail(&(new->list), &(head->list));
	}

	for (i = 0; i < 5; ++i)
	{
		struct node *new = malloc(sizeof(struct node));
		if (new! =NULL)
		{
			new->data = i+11;
			new->list.prev = NULL;
			new->list.next = NULL;
		}
		else
		{
			i--;
			continue;
		}

		// Insert a node into the list
		/ / head
		// list_add(&(new->list), &(head->list));
		/ / end plug
		list_add_tail(&(new->list), &(head1->list));
	}
	create_node(head,11);

	/ / traverse

	struct list_head *pos = NULL;
	struct list_head *n = NULL;

	struct node *Node_p = NULL;
	struct node *N = NULL;

	/ / the first
	// list_for_each(pos, &(head->list))
	/ / {
	// struct node *p = list_entry(pos, struct node, list);
	// printf("%d ", p->data);
	// }
	// printf("\n");

	/ / the second
	// list_for_each_prev(pos, &(head->list))
	/ / {
	// struct node *p = list_entry(pos, struct node, list);
	// printf("%d ", p->data);
		
	// }
	// printf("\n");

	/ / the third kind
	// list_for_each_safe(pos, n, &(head->list))
	/ / {
	// struct node *p = list_entry(pos, struct node, list);
	// if (p->data == 3)
	// 	{
	// list_del(&(p->list));
	/ /}
	// else
	// printf("%d ", p->data);
	// }
	// printf("\n");

	/ / the fourth
	// list_for_each_entry(Node_p, &(head->list), list)
	/ / {
	// printf("%d ", Node_p->data);
	// }
	// printf("\n");

	/ / 5 kinds
	// list_for_each_entry_safe(Node_p, N, &(head->list), list)
	/ / {
	// if (Node_p->data == 3)
	// 	{
	// // list_del(&(Node_p->list)); // Delete a node
	// // free(Node_p);

	// list_del_init(&(Node_p->list));
	/ /}
	// else
	// printf("%d ", Node_p->data);
	// }
	// printf("\n");

	// Move the node
	struct node *N1 = NULL;
	struct node *N2 = NULL;
	list_for_each_entry_safe(Node_p, N, &(head->list), list)
	{
		if (Node_p->data == 2)
		{
			N1 = Node_p;
		}
		if (Node_p->data == 4)
		{
			N2 = Node_p;
		}
	}

	list_move(&(N1->list), &(N2->list));
	list_move_tail(&(N1->list), &(N2->list));

	list_for_each_entry_safe(Node_p, N, &(head->list), list)
	{
		printf("%d ", Node_p->data);	
	}
	printf("\n");


	// merge linked lists
	list_splice(&(head->list), &(head1->list));

	list_for_each_entry_safe(Node_p, N, &(head1->list), list)
	{
		printf("%d ", Node_p->data);	
	}
	printf("\n");


	return 0;
}
Copy the code
#include "list.h" #include <stdio.h> #include <stdlib.h> typedef int Datatype; Typedef struct node {Datatype data; struct list_head list; }Node, *Link; // initialize the linked list Link init_list() {// Create a Node Link head = malloc(sizeof(Node)); // create a pure linked list if (head! = NULL ) { INIT_LIST_HEAD( &( head->list ) ) ; } return head ; } // create a node Link head = malloc(sizeof(struct node)); // Add data int a to the data field in the large structure; Link new = malloc( sizeof( struct node ) ); if ( new ! = NULL ) { new->data = a ; new->list.prev = NULL ; new->list.next = NULL ; } / / head list_add (& (new - > list), & (head - > list)); // list_add_tail(&(new -> list), &(head -> list)); Link create_node(Datatype data) {Link new = malloc(sizeof(Node)); if ( new ! = NULL ) { new->data = data ; new->list.prev = NULL ; new->list.next = NULL ; } return new ; } void display(Link head) {Link Node_p = NULL; Link N = NULL; list_for_each_entry_safe(Node_p, N, &(head->list), list) { printf("%d ", Node_p->data); } printf("\n"); } void delete_node(Link head, Datatype data) {Link Node_p = NULL; Link N = NULL ; list_for_each_entry_safe(Node_p, N, &(head->list), list) { if ( Node_p->data == data ) { list_del(&(Node_p->list)); // Delete node free(Node_p); }} printf(" no such object \n"); // Link Node_p = find_node(head, data); / / if / / (Node_p = = NULL) {/ / printf (" no the \ n "); // } // else // { // list_del(&(Node_p->list)); // Delete node // free(Node_p); Link find_node(Link head, Datatype data) {Link Node_p = NULL; Link N = NULL; list_for_each_entry_safe( Node_p , N , &( head -> list ) , list ) { if ( Node_p -> data == data ) { return Node_p ; } } return NULL ; } // Link N1 = NULL; Link N2 = NULL ; list_for_each_entry_safe( Node_p , N , &( head -> list ), list ) { if ( Node_p -> data == 2 ) { N1 = Node_p ; } if ( Node_p -> data == 4 ) { N2 = Node_p ; } // list_move(&(N1 -> list), &(N2 -> list)); List_move_tail (&(N1 -> list), &(N2 -> list)); List_splice (&(head -> list), &(head1 -> list)); list_for_each_entry_safe( Node_p , N , &( head1 -> list ) , list ) { printf( "%d", Node_p -> data ) ; } printf("\n"); / / 123456789Copy the code