ULK --- Chap3 Processes: Doubly linked lists

Before moving to and describing how the kernel keeps track of the various processes in the system,

we would like to emphasize the role of special data structures that implement doubly linked lists.

For each list, a set of primitives operations must be implemented: initializing the lists, inserting and

deleting an element, scanning the list, and so on. It would be both a waste of programmers‘ effort

and a waste of memory to replicate the primitive operations for each different list.

Therefore, the Linux kernel defines the list_head data structure, whose only fields next and prev

represent the forward and back pointers of a generic doubly linked list element, respectively. It is

important to note, however, that the pointers in a list_head field store the addresses of other list_heads

rather then the addresses of the whole data structure in which the list_head structure is included;

A new list is created by using the LIST_HEAD(list_name) macro. It declares a new variable named

list_name of  type list_head, which is a dummy first element that acts as a placeholder for the head

of the new list, and initializes the prev and next fields of the list_head data structure so as to point

to the list_name variable itself.

                         The Process List

The first example of a doubly linked list we will examine is the process list, a list that links together

all existing process descriptors. Each task_struct structure includes a tasks field of type list_head

whose prev and next fields point, respectively, to the previous and to the next task_struct element.

The head of the process list is the init_task task_struct descriptor; it is the process descriptor of the

so-called process 0 or swapper. The task->prev field of init_task points to the tasks field of the process

descriptor inserted last in the list.

The SET_LINK and REMOVE_LINK macros are used to insert and to remove a process descriptor

in the process list, respectively. These macros also take care of the parenthood relationship of the

process.

Another useful macro, called for_each_process, scans the whole process list. It is defined as follows.

The macro is the loop control statement after which the kernel programmer supplies the loop. Notice

how the init_task process descriptor just plays the role of list header. The macro starts by moving

past init_task to the next task and continues until it reaches init_task again (thanks to the circularity

of the list). At each interation, the variable passed as the argument of the macro contains the address

of the currently scanned process descriptor, as returned by the list_entry macro.

#define  for_each_process(p)         for (p = &init_task; (p = list_entry((p)->tasks.next,                                                              struct task_struct, tasks)                                                               ) != &init_task;)                        
时间: 2024-10-03 21:53:54

ULK --- Chap3 Processes: Doubly linked lists的相关文章

ULK --- Chap3 Processes: How Processes Are Organized

The runqueue lists group all processes in a  TASK_RUNNING state. When it comes to grouping processes in other states, the various states call for different types of treatment, with Linux opting for one of choices shown in the following list. Processe

ULK --- Chap3 Processes: Lists of Tasking_Running processes

When looking for a new process to run on a CPU, the kernel has to consider only the runnable processes (that is, the processes in the TASK_RUNNING state). Earlier Linux version put all runnable processes in the same list called runqueue. Because it w

ULK --- Chap3 Processes: Process Descriptor Handling

Processes are dynamic entities whose lifetimes range from a few milliseconds to months. Thus, the kernel must be able to handle many processes at the same time, and process descriptors are stored in dynamic memory rather than in the memory area perma

ULK --- Chap3 Processes

The concept of a process is fundamental to any multiprogramming operating system. A process is usually defined as an instance of a program in execution; thus, if 16 users are running vi at once, there are 16 separate processes (although they can shar

ULK --- Chap3 Processes: Relationships Among Processes

Processes created by a  program have a parent/child relationship. When a process creates multiple children, these children have sibling relationships. Several fields must be introduced in a process descriptor to represent these relationships; Process

ULK --- Chap3 Processes: Identifying a Process

As a general rule, each execution context that can be independently scheduled must have its own process descriptor; therefore, even lightweight processes, which share a large portion of their kernel data structures, have their own task_struct structu

[LeetCode] Flatten a Multilevel Doubly Linked List 压平一个多层的双向链表

You are given a doubly linked list which in addition to the next and previous pointers, it could have a child pointer, which may or may not point to a separate doubly linked list. These child lists may have one or more children of their own, and so o

Intersection of Two Linked Lists

Write a program to find the node at which the intersection of two singly linked lists begins. For example, the following two linked lists: A: a1 → a2 c1 → c2 → c3 B: b1 → b2 → b3 begin to intersect at node c1. Notes: If the two linked lists have no i

[C++]LeetCode: 60 Intersection of Two Linked Lists

题目: Write a program to find the node at which the intersection of two singly linked lists begins. For example, the following two linked lists: A: a1 → a2 c1 → c2 → c3 B: b1 → b2 → b3 begin to intersect at node c1. Notes: If the two linked lists have