Try   HackMD

Linux 核心專題: kHTTPd 改進

執行人: williamlin0518
專題解說影片

任務簡介

改進 kHTTPd 的並行處理能力,予以量化並有效管理連線。

TODO: 依據第七次作業 開發 kHTTPd

著重 concurrency, workqueue, CMWQ
充分予以量化分析

Linux 核心設計: RCU 同步機制

a synchronization mechanism handle read-mostly situations

Key Concepts of RCU:

  • Reading without Locks

  • Grace Period

  • Deferred Updates


Workqueues in the Linux Kernel

1. Goals of cmwq

Make improve on original wq both concurrency and resource usage

Multi-threaded wq had one worker thread per CPU

  • Single MT wq would have N worker threads, N is CPUs in the system.
  • resource wastage

Single-threaded wq had one worker thread system-wide

  • limited concurrency

2. CMWQ Design

Unified Worker Pools

  • Shared pool of worker threads for all workqueues.

Separation of High Priority and Normal Tasks

  • separate pools for normal and high-priority tasks

透過 eBPF 觀察作業系統行為


解釋 drop-tcp-socket 核心模組運作原理


kecho

Trace the steps from a connection is initiated to when it is processed:

Request Handling Flow

1. Listening for Connections:

  1. kecho_init_module is called. Sets up the listening socket and starts the echo server daemon thread.
  2. create and set up a socket that listens on a specific port for incoming connections.

2. Accepting Connections:

  1. The echo_server_daemon function runs in a loop, handling the server logic. It uses kernel_accept to accept incoming connections on the listening socket.

3. Handling Connections (Work Item Execution):

  1. Inside create_work, a struct kecho instance is initialized and a work structure (struct work_struct) is prepared. This is enqueued into kecho_wq.
  2. echo_server_worker is the function assigned to this work structure. When the workqueue decides to execute this task, echo_server_worker processes the data from the connected socket
         +-------------------+ 
         | echo_server_daemon|
         | (Kernel Thread)   |
         +-------------------+
                    |
                    | listens for connections
                    V
          +----------------------------+
          |  Workqueue (kecho_wq)      |
          |  - Manages multiple works  |
          |    submitted for processing| \\
          +----------------------------+  \\
                   ||                      \\
                   ||                       \\
                   V                         V
       +--------------------------+     +--------------------------+
       | Worker 1 (struct kecho)  |     | Worker 2 (struct kecho)  |
       | - Handles specific       |     | - Handles specific       |
       |   connection A           |     |   connection B           |
       | - Contains:              |     | - Contains:              |
       |    * struct work_struct  |     |    * struct work_struct  |
       |    * struct socket*      |     |    * struct socket*      |
       |    * Other connection    |     |    * Other connection    |
       |      specific data       |     |      specific data       |
       +--------------------------+     +--------------------------+

Analysis Mechanism of kecho


在 khttpd 引入 CMWQ

william@william-System-Product-Name:~/linux2024/khttpd$ ./htstress -n 100000 -c 1 -t 4 http://localhost:8081/
0 requests
10000 requests
20000 requests
30000 requests
40000 requests
50000 requests
60000 requests
70000 requests
80000 requests
90000 requests

requests:      100000
good requests: 100000 [100%]
bad requests:  0 [0%]
socket errors: 0 [0%]
seconds:       1.614
requests/sec:  61959.059

  1. 宣告 daemon 全域變數,用來存放目前服務是否已停止和 worker 的 linked list
struct http_service daemon = {.is_stopped = false,
                              .worker = LIST_HEAD_INIT(daemon.worker)};
  1. 參考kecho ,建立代表 service 和 worker 的結構。
struct http_service {
    bool is_stopped;
    struct list_head worker;
};


struct khttpd {
    struct socket *sock;
    struct list_head list;
    struct work_struct http_work;
};
  1. daemon 函式中對應的 kthread_create 修改為以 create_work 建立新的任務,並利用 queue_work 將新增的任務加入 workqueue 中等待執行。
static struct work_struct *create_work(struct socket *sk)
{
    struct http_work *work;
    if (!(work = kmalloc(sizeof(struct http_work), GFP_KERNEL)))
        return NULL;

    work->socket = sk;
    
    INIT_WORK(&work->khttpd_work, http_server_worker_CMWQ);
    
    list_add(&work->node, &daemon_list.head);

    return &work->khttpd_work;
}
  1. error module not insert correctly

分析效能表現和提出改進方案