[Principle Analysis]linux The chain list principle in the kernel practice [2]

Source: Internet
Author: User

Summary:

In this paper, the process of the evolution of the structure of their own list of linked lists slowly evolved to resemble the implementation of the Linux kernel chain list.

Body:

In this series 1, if the information in the Data_node exchange, that is, value is placed in front, the Head_node information is placed behind, then the node data will not be output normally.

typedef struct DATA_NODE{INT value;head_node h;} Data_node;

To find out why, the main reason is to see the implementation of the List_value function:

void List_value (data_node* d) {   data_node* dn = D;   do{     printf ("%d", dn->value);     DN = (data_node*) dn->h.next;   } while (Dn!=d);}

The above code is to force the pointer of Dn->h.next to Data_node to complete the Data_node first address of the determination, now data_node internal data exchange order, Head_node's first address is no longer the first address of Data_node, So something went wrong. Here the solution is also very straightforward: through the Head_node address reverse Data_node address, the basic idea: the address of the Head_node, minus its address in the Data_node offset, that is, the address of Data_node. Follow this idea to change the List_value code as follows:

void Show_value (head_node* ptr) {head_node* temp = ptr;unsigned long offset = (unsigned long) & ((data_node*) 0)->h; data_node* DN = (data_node*) ((unsigned long) PTR  -offset);d o{printf ("%d", dn->value);p tr = dn->h.next; unsigned long offset = (unsigned long) & ((data_node*) 0)->h;dn = (data_node*) ((unsigned long) PTR  -offset);} while (& (dn->h)! = temp);}

To offset, use the following statement: (Unsinged Long) & ((data_node*) 0)->h; Here the address symbol is not missing, because the latter part is only offset to H, the amount of the specific offset is also the address of H, because the address is starting from 0 The first address of the Data_node is obtained from the Head_node's first address minus its offset in data_node. The above code is not clear, we will repeat the part as a macro form, that is:

#define OFF ()  (unsigned long)  (& (data_node*) 0)->h) #define  entry (PTR)  (data_node*) (( unsigned long) PTR  -off ())

Then use the above macro to rewrite the Show_value function:

void Show_value (head_node* ptr) {head_node* temp = ptr;data_node* DN = entry (PTR);d o{printf ("%d", dn->value);p tr = dn-& GT;H.NEXT;DN = entry (PTR);} while (& (dn->h)! = temp);}

It looks a lot leaner, so we'll write a separate module for the data processing function:

void ShowMe (daat_node* dn) {    printf ("%d", Dn->value);}

Looking back at the above code, or can not meet our modular needs, the above code in the loop by the data processing module is fragmented, not very well modular, we want to see the code is the following, the loop part of the code as far as possible to focus on the outside of parentheses, the benefits: cyclic part of the code to improve the reusability, Modifying the processing function becomes easy;

data_node* dn; Loop code section {     showme (DN);}

There are three commonly used methods for the study of loops: for, while, the Do while;do while has been proven to be isolated by data processing functions, while words, judgment statements and operation statements are separated; Finally, we can only consider using for to achieve our assumptions above, the above Show_ Value is changed to the form based on the For loop:

data_node* dn;for (head_node* temp = ptr, DN = entry (PTR), & (Dn->h)!=temp; ptr = dn->h.next, DN = entry (PTR)) {Sho W_value (DN);}

This modification has a problem compiling on VS 2005, as long as the definition of head_node* temp is placed outside the loop. The code then becomes the following form:

void Show_value (head_node* ptr) {data_node* DN = null;head_node* temp;for (temp = ptr, DN = entry (PTR); & (Dn->h)!=tem P ptr = dn->h.next, DN = entry (PTR)) {printf ("%d", Dn->value);}}

After running the above code, it is found that there is no output, carefully checking the main is the statement:& (DN->H)!=temp; The statement does not satisfy the condition when the loop is first executed, because the current value of temp is the current address of dn->h. This means that the temp and DN belong to the same data node. Of course, when initializing, the DN can be pointed to the next node of PTR, but the problem is that the data of PTR current node cannot be output, causing the data to be lost. This is the problem for the For loop, in the original do while version, because it is the first output data, update ptr after the judgment, so there is no such problem. How do we change it here? A simple thought of a solution is to skip the first node, the first node does not have data, just the first node as a flag node, that is, the head node. Add code modifications to the head node:

head_node* lh = (head_node*) malloc (sizeof (Head_node)); lh->next = Lh;lh->prev = Lh;node_add (LH, & (D1->h)); Node_add (LH, & (D2->h)); Node_add (LH, & (D3->h));

The corresponding Show_value function should also be modified:

void Show_value (head_node* ptr) {data_node* DN = null;head_node* temp;for (temp = ptr, DN = entry (Ptr->next); & (DN-&G T;H)!=temp; ptr = dn->h.next, DN = entry (PTR)) {showme (DN);}}

The code of the call should also be modified: Show_value (LH), tested, the data in the above three nodes can be output, but it seems that the code in the Show_vlaue is still not clear enough, we can then Polish:

void Show_value (head_node* head) {data_node* DN = null;head_node* pos;for (pos = head->next, DN = entry (pos); pos!=head; pos = pos->next, DN = entry (pos)) {showme (DN);}}

The above code can see that the for loop operation and judgment are moved outside the curly braces, only the operation function is left inside the parentheses, and then we re-macro the For loop part of the code:

#define List_each_entry (Head, POS) for   (pos = head->next, DN = entry (pos); pos!=head; pos=pos->next, DN = entry ( POS))

Based on the above macro, we then modify the Show_value function:

void Show_value (head_node* head) {data_node* DN = null;head_node* pos;list_each_entry (Head, POS) {showme (DN);}}

Conclusion:

This article takes the link list in the Linux kernel code as the lighthouse, uses the natural evolution process, slowly modifies its own code to the class Linux implementation code according to its own demand.



[Principle Analysis]linux The chain list principle in the kernel practice [2]

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.