It mainly transplanted the list and rbtree in the kernel. These two data structures can also be used in user-state programs.
At the same time, cpputest is used to test the transplanted code. (The test code is actually using the two data structures)
The kernel code is as follows: (kernel version v3.2 debian 7.5 source code)
The above code is simplified and only common functions are left. At the same time, the kernel-related parts are deleted.
Main content:
- List introduction (Circular two-way linked list)
- Rbtree Introduction
1. list introduction (Circular two-way linked list)1.1 Introduction
The usage of linked lists in Linux is somewhat different from that in general data structures.
In the Linux kernel, to ensure the universality of the linked list, the node Structure of the linked list is extracted separately, that is, the structure of the linked list is defined separately from the data of the linked list.
In general, the linked list introduced in the data structure is defined by the data of the linked list and the structure of the linked list.
Note:For more information, see section 1.2 In http://www.cnblogs.com/wang_yb/archive/2013/04/16/3023892.html on my previous blog.
The important point in this section is: after the linked list structure is separated from the data, how does one obtain data through the linked list node structure?
Functions with safe or macros can be used in multiple threads.
1.2 modify part
1.3 list. h external interface
No. |
Main functions |
Description |
| 1. |
List_add |
Append a node after the head |
| 2. |
List_add_tail |
Append a node before the head, that is, append a node to the end. |
| 3. |
List_del |
Delete a node and set next and prev of the node to NULL. |
| 4. |
List_del_init |
Delete a node and initialize the deleted Node |
| 5. |
List_replace |
Replace a node |
| 6. |
List_replace_init |
Replace a node and initialize the replaced node. |
| 7. |
List_move |
Move the node to the head |
| 8. |
List_move_tail |
Before moving the node to the head |
| 9. |
List_is_last |
Judge whether the node is the last in the linked list |
| 10. |
List_empty |
Judge whether the linked list is empty (that is, whether there are only head nodes) |
| 11. |
List_is_singular |
Judge whether there is only one node in the Linked List (except the head) |
| 12. |
List_cut_position |
Truncates one linked list into two linked lists. |
| 13. |
List_splice |
Merge the two linked lists into one linked list, and add all the nodes in @ list (excluding list) to the head. |
| 14. |
List_splice_tail |
Merge two linked lists into one linked list. All nodes in @ list (excluding list) are added to the head. |
| 15. |
List_splice_init |
Same as list_splice, @ list will be initialized at last |
| 16. |
List_splice_tail_init |
Same as list_splice_tail, @ list will be initialized at last |
No. |
Major macros |
Description |
| 1. |
List_entry |
Get struct containing this node |
| 2. |
List_first_entry |
Obtain the first struct containing this node |
| 3. |
List_for_each |
One node after the head node starts to cycle backward |
| 4. |
List_for_each_prev |
Starts the forward loop from a node before the head node |
| 5. |
List_for_each_safe |
The secure version of list_for_each, that is, it can run normally even if other threads Delete nodes during the loop. |
| 6. |
List_for_each_prev_safe |
Security version of list_for_each_prev |
| 7. |
List_for_each_entry |
Same as list_for_each, but different parameters |
| 8. |
List_for_each_entry_reverse |
Same as list_for_each_prev, but different parameters |
| 9. |
List_for_each_entry_continue |
Similar to list_for_each_entry, but not from the beginning (head) |
| 10. |
List_for_each_entry_continue_reverse |
Similar to list_for_each_entry_reverse, but not from the beginning (head) |
| 11. |
List_for_each_entry_from |
Starts from the specified position and loops backward. |
| 12. |
List_for_each_entry_safe |
Security version of list_for_each_entry |
| 13. |
List_for_each_entry_safe_continue |
Secure version of list_for_each_entry_continue |
| 14. |
List_for_each_entry_safe_from |
Security version of list_for_each_entry_from |
| 15. |
List_for_each_entry_safe_reverse |
Security version of list_for_each_entry_reverse |
1.4 Use example-test all list operations in list. h
Construct the following scenario to test all list operations listed above:
1. Construct the struct used for testing: (To make the test results clear, struct should be as simple as possible)
struct test_struct {int num; struct list_head head;};
2. test functions one by one using the test framework cppUTest
3. Macro-related tests are not currently available
4. running the test is very simple (the premise is to install cpputest)
make./test_list -v
2. rbtree Introduction1.1 Introduction
The red/black tree is a self-balancing Binary Search Tree. The red and black trees are ordered.
Note:For more information, see section 4th in http://www.cnblogs.com/wang_yb/archive/2013/04/16/3023892.html on my previous blog.
Here, I just want to add that although the red/black tree is somewhat complicated, its search, insertion, and deletion operations are quite efficient. The search, insert, and delete time complexity is O (log n) n, which is the number of elements in the tree.
1.2 modify part
To make rbtree easier, the following content is deleted temporarily:
1.3 rbtree. h external interface
Note:The external interface of rbtree does not include the interface for inserting node. It is only used to change the node color after the node is inserted.
It may be because the node sequence varies with the specific struct, so it cannot be implemented in a unified manner.
No. |
Main functions |
Description |
| 1. |
Rb_set_parent |
Set the address of the parent node |
| 2. |
Rb_set_color |
Set node color |
| 3. |
Rb_init_node |
Initialize a node |
| 4. |
Rb_insert_color |
Set the color of the newly inserted Node |
| 5. |
Rb_erase |
Delete a node |
| 6. |
Rb_next |
Returns the next node of the current node. |
| 7. |
Rb_prev |
Returns the previous node of the current node. |
| 8. |
Rb_first |
Returns the first leaf node (that is, the leftmost leaf node) |
| 9. |
Rb_last |
Returns the last leaf node (that is, the rightmost leaf node) |
| 10. |
Rb_replace_node |
Replace a node in the rbtree (just a simple replacement, the color of the replacement is incorrect, and the Data Order is incorrect) |
No. |
Major macros |
Description |
| 1. |
Rb_parent |
Obtain the address of the parent node |
| 2. |
Rb_color |
Node color |
| 3. |
Rb_is_red |
Red node or not |
| 4. |
Rb_is_black |
Black node or not |
| 5. |
Rb_set_red |
Set the node to red |
| 6. |
Rb_set_black |
Set the node to black |
| 7. |
RB_ROOT |
Initialize the root node |
| 8. |
Rb_entry |
Get struct containing rbtree node |
| 9. |
RB_EMPTY_ROOT |
Determine if only the root node exists |
| 10. |
RB_EMPTY_NODE |
Judge whether the node has just been initialized and has not been added to the tree |
| 11. |
RB_CLEAR_NODE |
Set the parent node of the node to point to itself. |
1.4 supplement to rbtree. c
The functions in rbtree. c are relatively simple. The complex ones are rb_insert_color and rb_erase.
These two functions also involve other undisclosed functions _ rb_rotate_left, _ rb_rotate_right, _ rb_erase_color
1. _ rb_rotate_left: Left-hand, that is, the parameter node is the center point, and it is rotated counterclockwise. You can adjust the height of the right subtree from the left-hand side.
The following figure shows the left and right pointers of struct rb_node when the left is left.
This is the most complicated situation, that is, the left and right subtree of all related nodes is not empty.
Struct test_struct {int num;
Struct rb_node node ;};
2. test functions one by one using the test framework cppUTest
3. Macro-related tests are not currently available
4. running the test is very simple (the premise is to install cpputest)
make./test_rbtree -v
Download related test code