contributed by < qwe661234
>
Doubly-linked list and its value is string.
Add new queue node to the end of the list by list_add
.
If malloc
fails to allocate space for string that store in new node, you should free the memory of new node. Otherwise, it would cause memory leak.
Expect for adding new queue node to the end of the list by list_add_tail
, other operations are the same as q_insert_head
.
Get first node of queue by list_first_entry
.
Check if the buffer size - 1 is larger than the length of copy string. Otherwise, it would overflow destination buffer.
Undefined behavior for strncpy
bufsize
'\0'
Except for getting first node of queue by list_last_entry
, other operations are the same as q_remove_head
.
If queue is singular, delete the only node in queue.
If queue is non-singular, use two pointer to get middle node. The first pointer is point to the first node and the second pointer is point to the last node. The first pointer iterate from the first to the the last node and the last pointer iterate oppositely. When these two pointers point to the same node or the firat pointer cross the second pointer, the node pointed by the second pointer would be the middle node.
Becasue these two pointers meet the terminal condition in the beginning, we use do while
.
A queue node would be delete in two condition:
Iterate the queue and record the number of iterated node. If the number is even, move current node to the position which is previos to previous node.
Except for the last node, move node to the queue tail from node is previous to the last node to the first node.
This version is more concise.
Sort the queue by merge sort.
I want to create another head to maintain when I divide the queue, but malloc
is disallowed in q_sort
. Therefore, I remove queue head and pass the first node and the last node as parameters.
Because the mergeSort
only return the first node of sorted queue, we should iterate sorted queue to find out the last node. Then, connect removed queue head to the first node and the last node of sorted queue.
All commands store in a command list, and it is a singly-linked list
ADD_COMMAD
automatically link command xxx
to its operation function do_xxx
You should explain why it works.
cmd_list
is the head of command list
what while
loop in funciton add_cmd
does is sorting commands in alphabetical order. The operaion like insertion sort, find out the suit position from the head of list and insert new command element into command list.
Follow the modern shuffle algorithm to shuffle queue.
0
~ n - 1
0
.n
means node number of tail node.When user call command shuffle, funciton do_shuffle
would be called.
Function ADD_COMAND
connect command parameter1
to do_parameter1
automatically, so when user call command shuffle
, then function do_shuffle
would be called.
parameter2
is the information of command. When user call command help
, the "| shuffle queue"
will show in the information of the command shuffle
.
The select system call's I/O event model is I/O multiplexer. When we call select, the fd set is copied from userspace to kernel space before iterating through all socket fd. If all of the socket fd fail to satisfy the condition, the kernel thread will release CPU resources; otherwise, the kernel thread will be woken up when the event occurs. Even if the select system call returns, we must still determine which socket fd is ready.
The select system call is used in this program to monitor the file-reading and connection events. When an event occurs, we use the function FD_ISSET
to determine which socket fd is ready. If the event is a connection event, we will use the accept system call to establish a connection with the client and respond to its request.
Epoll is more flexible than select. Epoll manages multiple socket fds using an epoll fd, and there is no limit to the number of fds in epoll. Furthermore, epoll copies the socket fd in userspace to the event table in kernel space, allowing userspace and kernel space to watch the same memory content by only one copy. When the socket fd is ready, epoll triggers the fd via the callback function, allowing us to learn which socket fd is ready without iterating, reducing the time complexity of this operation to O(1).
To replace select with epoll, we must first modify the function do_web
. The first step is to create an epoll instance using the function epoll_create
. Next, because the server socket fd web_fd
is our polling target, we add it to epoll with function epoll_ctl
. In this case, we use the EPOLL_CTL_ADD
operator, which performs the same function as FD_SET
by adding the fd to epoll and causing epoll to monitor its I/O event.
We must modify cmd_select
after we have modified do_web
. The function epoll_wait
is used to determine whether or not events occur; its return value is the number of the ready event, and event information is stored in a data structure called struct epoll_event
. We usually use a for loop to iterate through all of the ready events and handle them appropriately.