contributed by < Eric Lin >
lab0 is a homework of the course Linux 核心設計/實作 by jserv
This lab aims to assessing one's C Programming Skills. Some of the skills tested are:
Check C Programming Lab for more information.
Source: cprogramminglab
The file queue.h
and list.h
contains declarations of the following structures:
list_head
is a circular doubly-linked list for queue contents.element_t
has fields value
and list
, storing a pointer to a string and a structure of queue list.In the starter code, the queue contains only a single field of typelist_head
, but you can add other fields list
which is intruded in element_t
.
In the picture above is a singly-linked list rather than a doubly-linked list in our case of implementing queue.
Check the benefits of using intrusive-linked-lists.
From man page:
The macro
offsetof()
returns the offset of the field member from the start of the structure type.
(TYPE *)0
: casting the value 0 to the pointer type Type *
. Which places a struct object at memory address zero.&((TYPE *)0)->MEMBER
: getting the address of struct field MEMBER
of this struct object. Since the address of struct object is 0, the the address of MEMBER
is the offset in bytes.size_t
which has the same size as a pointer.container_of()
is a macro defined in <linux/kernel.h>
.
From kernel doc:
What
container_of()
does is to obtain a pointer to the containing struct from a pointer to a member by a simple subtraction using the offsetof() macro from standard C, which allows something similar to object oriented behaviours.
Notice that the contained member must not be a pointer, but an actual member for this to work.
According to C99 Standard in chapter 6.5.6 Additive operators
- For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
- When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression.
It is neccessary to do (char *)
cast in this macro to ensure that pointer arithmetic operates on a byte level basis. When you subtract an offset from a pointer, you are moving the pointer backward by the number of bytes indicated by the offset. However, the actual size of the structure might be different due to padding and alignment requirements.
For this point, We can see the following example:
result:
In the example, when we apply the container_of
macro, the addresses of s1
and s2
match. However, when wrong_container_of
macro is applied, 16 bytes(sizeof(float) * 4 == 16
) of offset has been conduct, the addresses of two don't match.
Return NULL if a failing call to malloc().
Traverse elements linked to
list_head
and free each of them.
strdup
returns a pointer to a new string which is a duplicate of the string s. A terminating null byte ('\0') is also added.
Return NULL if
head
is NULL or empty.
Get the first element in queue by
list_first_entry
strncpy
copies the string pointed to byele->value
.
Traverse each list in
head
and count them byi
.
Move the head node forward and the tail node backward untill reaching the middle node.
Traverse list and swap their next and prev.
Recursive quick sort.
First convert the list to non-circular by
end->next = NULL
to creating a stop condition.
If current value is not greater than the next value, delete the node.
In the end, convert the list back to circular list by linking the end and the head node.
Extract each link list from queue and join them in the first queue.
Do quick sort.