李熙堃 LEE SHE KUN P76111597
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 2023q1 Homework6 (ktcp) ###### tags: `linux2023` contributed by < `JoshuaLee0321` > ## 自我檢查清單 - [x] 給定的 `kecho` 已使用 CMWQ,請陳述其優勢和用法 :::success 我想要先提到一個在 `workqueue.h` 中的笑話,在 `linux-hwe-5.19-headers-5.19.0-41/include/linux/workqueue.h` 的第 343 行,有一個定義了 `WQ_MAX_ACTIVE = 512` 註解上這樣打: `/* I like 512, better ideas? */` 相當的有幽默感。 ### CMWQ 用法 使用方法其實沒有到很難 ```graphviz digraph G { rankdir=LR node[shape=rectangle] "wq = alloc_workqueue()" -> "queue_work(wq, job)" -> "destroy_workqueue(wq)" "queue_work(wq, job)" -> "queue_work(wq, job)" [label="while working"] } ``` 根據上面的流程圖可以看到,先行宣告一個 `struct workqueue_struct *wq`,在 `alloc_workqueu()` 時設定好此 `wq` 的行為模式,接下來只需要給他工作即可 #### CMWQ FLAGS 根據 `workqueue.h` 中有一個 `enum` 對於各個 `FLAG` 的定義以及它的名稱,不難猜出要這些參數有甚麼用處。以下來一一介紹: ```c WQ_UNBOUND /* 各工作不會被綁定在特定 CPU 上執行 */ WQ_FREEZABLE /* 跟電源相關的 flag ,當系統進入冬眠時,有下這個 flag 的 WQ 會完成當前所有 work 並且不啟動新的 work 直到系統解除冬眠 */ WQ_MEM_RECLAIM /* 若有這個參數,系統會創建 rescuer thread,當檢測到會產生死結時,出手相助 */ WQ_HIGHPRI /* 此 wq 有高優先權 */ WQ_CPU_INTENSIVE /* 此 wq 會特別消耗 CPU ,在 2 中提到: * Runnable CPU intensive work items will not prevent * other work items in the same worker-pool from starting * execution * 也就是說,他可以算是優先權相對較低的工作 */ WQ_SYSFS /* 在 linux file system 中可以看到此 wq */ WQ_POWER_EFFICIENT /* 當此 work 很吃資源的時候,想省電可以下這個參數 */ ``` 參考資料: 1. [CMWQ概述](http://www.wowotech.net/irq_subsystem/cmwq-intro.html) 2. [為甚麼 WQ_CPU_INTENSIVE 對 unbound 工作隊獵沒有意義](https://tjtech.me/why-cpu-intensive-work-is-meaningless-for-unbound-wq.html) 3. [sysfs](https://man7.org/linux/man-pages/man5/sysfs.5.html) ### CMWQ 優勢 相比於其他自行定義的 queue,如果程式設計者創造出太多 thread,這些 thread 每一個都有一個自己獨立的 PID,有機會導致 kernel space 中的 process 數量太多,而 user space 根本沒有辦法調度任何 process 另外在很多情況下,queue 中的 process 都是需要被[異步處理](https://en.wikipedia.org/wiki/Asynchronous_I/O),而通常自己設計的 queue 無法達成這個效果 *********** 相比之下,CMWQ明確的劃分了前後端的實作 ![](https://i.imgur.com/ocd9tIB.png) 讓用戶不需要關心如何分配每個 thread 在任何時間上的需不需要被執行,並且提出 `thread pool` 機制,讓所有進程都可以存取到共享的 `thread` ::: - [ ] 搭配閱讀《Demystifying the Linux CPU Scheduler》第 1 章和第 2 章,描述 CPU 排程器和 workqueue/CMWQ 的互動,應探究相關 Linux 核心原始程式碼 - [ ] 研讀〈[Linux 核心設計: RCU 同步機制](https://hackmd.io/@sysprog/linux-rcu)〉並測試相關 Linux 核心模組以理解其用法 - [ ] 如何測試網頁伺服器的效能,針對多核處理器場景調整 - [ ] 如何利用 [Ftrace](https://docs.kernel.org/trace/ftrace.html) 找出 `khttpd` 核心模組的效能瓶頸,該如何設計相關實驗學習。搭配閱讀《Demystifying the Linux CPU Scheduler》第 6 章 - [x] 解釋 `drop-tcp-socket` 核心模組運作原理。`TIME-WAIT` sockets 又是什麼? :::success ### 讀了許久無法理解,想要請問老師該怎麼去理解這份 kernel module #### 參考資料 1. [what is net_generic function](https://stackoverflow.com/questions/20189858/what-is-net-generic-function-in-linux-include-net-net-namespace-h) 2. [`char array[0] 1`](https://blog.csdn.net/zhinanpolang/article/details/110433515) 3. [`char array[0] 2`](https://blog.csdn.net/weixin_30335575/article/details/99294723?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-99294723-blog-110433515.235%5Ev32%5Epc_relevant_increate_t0_download_v2_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-99294723-blog-110433515.235%5Ev32%5Epc_relevant_increate_t0_download_v2_base&utm_relevant_index=2) ::: - [ ] 研讀 [透過 eBPF 觀察作業系統行為](https://hackmd.io/@sysprog/linux-ebpf),如何用 eBPF 測量 kthread / CMWQ 關鍵操作的執行成本? > 參照 [eBPF 教程](https://github.com/eunomia-bpf/bpf-developer-tutorial) - [ ] 參照〈[測試 Linux 核心的虛擬化環境](https://hackmd.io/@sysprog/linux-virtme)〉和〈[建構 User-Mode Linux 的實驗環境](https://hackmd.io/@sysprog/user-mode-linux-env)〉,在原生的 Linux 系統中,利用 UML 或 `virtme` 建構虛擬化執行環境,搭配 GDB 追蹤 `khttpd` 核心模組 ## 在 khttp 中引入 cmwq 參照 [kecho](https://hackmd.io/@sysprog/linux2020-kecho) 的程式碼,可以發現為了在核心中有效管理每一個 thread,可以看到在 `echo_server.h` 中存在 ```c struct echo_service { bool is_stopped; struct list_head worker; }; ``` 同理,我也在 `http_server.h` 中新增了同樣的結構方便管理每一個 caller ```c struct khttp_service { bool is_stopped; struct list_head worker; } ``` 再來是修改原本的 `http_server_worker.c` 在原本的 `kecho` 當中必須要有幾個制式的流程: 1. alloc_work() 2. create_work() 3. `process listhead of daemon` 4. queue_work() 5. free_work() 所以我們必須要照著上面的流程更改原本的程式碼。 ```c= struct workqueue_struct *khttp_wq; ... static int __init khttpd_init(void) { ... khttp_wq = alloc_workqueue(MODULE_NAME, 0, 0); /* workqueue allocated */ http_server = kthread_run(http_server_daemon, &param, KBUILD_MODNAME); ... } ``` 首先更改 `main.c` 中的全域變數 `khttp_wq` 當作我們的佇列 (由以上第 1 行紀錄) 再來在第六行的地方初始化剛剛宣告的佇列。 > 由於我覺得在 `http_server.c` 又有一個新的結構體,這樣導致我要更改每一個結構體時必須要到不同的檔案中修改,於是我把所有有關結構體的宣告都移動到 `http_server.h` 中 ```c= ... struct http_request { struct socket *socket; enum http_method method; char request_url[128]; int complete; struct list_head worker; struct work_struct http_work; }; ... ``` * `http_server.c` 中的 `struct http_request` 移動到 `http_server.h` 並且在第 6, 7 行新增了鏈結串列節點以及 CMWQ 的結構。 接下來更改 `http_server.c`,首先,先實作 `create_work` 以及 `free_work`,兩者皆參考 [`kecho-echo_server.c`](https://github.com/sysprog21/kecho/blob/master/echo_server.c) 中的對應函式實作 ```c static struct work_struct *create_work(struct socket *sk) { struct http_request *work; if( !(work = kmalloc(sizeof(struct http_request), GFP_KERNEL))) return NULL; work->socket = sk; /* initalize work */ INIT_WORK(&work->http_work, http_server_worker); /* add work->node into daemon list*/ list_add(&work->worker, &daemon.head); /* return the specific work */ return &work->http_work; } static void free_work(void) { struct http_request *l, *tar; list_for_each_entry_safe(tar, l, &daemon.head, worker) { kernel_sock_shutdown(tar->socket, SHUT_RDWR); flush_work(&tar->http_work); sock_release(tar->socket); kfree(tar); } } ``` 再來根據 [`kecho-echo_server.c`](https://github.com/sysprog21/kecho/blob/master/echo_server.c) 中可以發現,其傳遞參數的方法是由 [`container_of`](https://hackmd.io/@sysprog/linux-macro-containerof) 的方法把 `struct work_struct` 當作參數放入 `khttp_worker` 中,所以在 `khttp` 中也必須要做一樣的事情,並且把相對傳遞參數的方法改掉 ```c= /* change void *arg into struct work_struct*/ static void http_server_worker(struct work_struct *work) { struct http_request *worker = container_of(work, struct http_request, http_work); ... realloc: buf = kzalloc(RECV_BUFFER_SIZE, GFP_KERNEL); if (!buf) { pr_err("can't allocate memory!\n"); goto realloc; } http_parser_init(&parser, HTTP_REQUEST); parser.data = &worker->socket; while (!kthread_should_stop()) { int ret = http_server_recv(worker->socket, buf, RECV_BUFFER_SIZE - 1); if (ret <= 0) { if (ret) pr_err("recv error: %d\n", ret); break; } if (!http_parser_execute(&parser, &setting, buf, ret)) continue; if (worker->complete && !http_should_keep_alive(&parser)) break; memset(buf, 0, RECV_BUFFER_SIZE); } kernel_sock_shutdown(worker->socket, SHUT_RDWR); kfree(buf); } ``` 可以看到在第 7 行增加了 `realloc` 的標籤,由於先前的函數在失敗之後就直接回傳 -1 當作失敗,並且重複使用 thread,在這邊因為沒有辦法回傳,所以我選擇的方法為重複 `kzalloc` 直到成功為止。另外可以看到第 4 行已經利用 `container_of` 取出結構體,並且在第 15, 18, 32 行取代成 `worker->socket`。 經過以下的改動,我已經把 CMWQ 實作在 `khttp` 中了,以下為兩者之間用 [`hstress.c`](https://github.com/sysprog21/khttpd/blob/master/htstress.c) 的比較 > 以下數據皆使用 `./htstress localhost:8081 -n 100000 -c 10` 來做區別 * `khttpd without CMWQ` ![](https://hackmd.io/_uploads/rkaIBJOVn.png) * `khttpd with CMWQ` ![](https://hackmd.io/_uploads/Hk89Hk_E3.png) 可以看到,在實作了 `CMWQ` 之後,速度從原本的 4.6 秒降低至 4.01 秒。 ## 提供目錄檔案存取功能,提供基本的 directory listing 功能 ### 利用額外的終端機監控資訊 * 在實作 khttpd 時,時常不清楚內部回傳值到底如何,尤其當我想要觀察 `http_server_worker` 時,我總是不知道裡面有哪些參數是可以使用的 此時我發現可以利用額外的一個終端機不停監控內核中的資訊,使用以下 command ```bash sudo dmesg -wH ``` 另外在修改了 `http_server_worker` 中的一小部分: ```diff static void http_server_worker(struct work_struct *work) { ... while (!kthread_should_stop()) { ... + pr_info("buf = %s", buf); ... } ... } ``` 這樣一來就可以隨時得知 `buf` 中的資訊 ![](https://hackmd.io/_uploads/ByDhkmfHn.png) :::info ##### 題外話 `favicon.ico` * 在把 buf 列印出來後,我發現路徑中一直出現 `favicon.ico` 這個關鍵字,查了之後才發現許多瀏覽器都會發送此類型的靜態 `request` 參考資料: [**favicon.ico**](https://www.cisco.com/c/zh_tw/support/docs/security/web-security-appliance/117995-qna-wsa-00.pdf) ::: # 問題 - [ ] 目前怎麼找都沒有找到一個好的方法把 directory 內的東西列出來,想要請問老師有甚麼關鍵字可以搜尋的 :::success 在 kernel 中並不存在 process 的概念,如果要做出 directory listing 的功能,必須要給每一個連線者專屬的記憶體空間,讓他可以去訪問當前她想要的東西 ::: - [ ]

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully