---
tags: Linux Kernel
---
# 提交第一份 Patch 到 Linux Kernel
contributed by < [steven1lung](https://github.com/steven1lung) >
## 我自己的心得
在看老師的書 Demystifying the Linux CPU Scheduler 的時候,突然好奇說每一個任務的 loading 是如何運算的,畢竟排程器上的任務如此多,計算出 load 然後依據每個 CPU 的狀態去做 task migration 應該是很重要的課題。所以我就跑去 [pelt.c ](https://elixir.bootlin.com/linux/latest/source/kernel/sched/pelt.c) 看了一下實際的運算是如何做到的。
> pelt 全名是 Per Entity Load Tracking
在看程式碼的時候,發現有個地方的中括號打反了變成 `[1002..1024[`,我就想說試試看發人生第一個 patch。
結果自己在摸索如何發 patch 花了好多時間...,轉眼間就早上了。所以就記錄了一下自己發 patch 的過程來紀念逝去的時間。雖然這個 patch 最後是我誤會中括號的用法,所以並沒有被採納,但跟這些厲害的人交流讓人有點興奮><
> 結果發現反過來的中括號是法文的用法,是我自己搞錯 xD
我發的 patch 在[這裡](https://lore.kernel.org/lkml/3193fcc9-c672-19d9-a2e2-ad67809dd20b@infradead.org/T/)。
## 前言
Linux Kernel 的開發跟維護方法是透過信件來溝通跟 review,Linux Kernel 有一個龐大的 mail server,每天收到近千個信件提交 patches,格式不正確或是表達不好的 patch 很常會被忽略,連回覆都不會有,所以要如何寫好一個好的 patch 充滿學問。
> “Only wimps use tape backup. REAL men just upload their important stuff on ftp and let the rest of the world mirror it.” --Linus Torvalds
## 準備提交 Patch 會使用到的 Email Client
* git send-email
* mutt
git 其實就有提供一個命令:`git send-email` 來做到發出信件的功能,或是也有很多人會使用 `mutt` 來幫忙發 plain text mail。我自己是 send patches 時會使用 `git send-email`,如果只是回覆 comment 之類就會用 mutt。
> 這邊要小心如果回覆 patch 的 comment 的時候使用 gmail 或是手機內建的信箱,要記得信件不要使用到 html,會被 lkml 認為是 spam 或病毒,就會被退回。
### git send-email
使用之前還需要到 `~/.gitconfig` 裡先設定一些 smtp 的資料:
```
$ vi ~/.gitconfig
```
然後在最後面加上:
```
[sendemail]
smtpencryption=tls
smtpserver=smtp.gmail.com
smtpuser=你的信箱@xxxx.com
smtpserverport=587
smtpPass=你的APP密碼
```
> APP 密碼的設定方式在下面有說明。
### mutt
mutt 是一個很多開發者都會使用到 mail client,Greg Kroah-Hartman 也是使用這個!他也有在網路上分享自己的 workflow,詳情可以看[這裡](http://kroah.com/log/blog/2019/08/14/patch-workflow-with-mutt-2019/)。
mutt 並不是內建的,所以事先需要安裝:
```
$ sudo apt install mutt # Debian
$ sudo dnf install mutt # Fedora
$ brew install mutt # Macos
```
接著一樣要去設定一些 smtp 的參數:
```
$ vi ~/.muttrc
```
把以下的資料填好並且儲存:
```
set ssl_starttls=yes
set ssl_force_tls=yes
set imap_user = "你的信箱@XXXX.com"
set imap_pass = "你的APP密碼"
set from="你的信箱@XXXX.com"
set realname="FIRST_NAME LAST_NAME"
set folder = "imaps://imap.gmail.com/"
set spoolfile = "imaps://imap.gmail.com/INBOX"
set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
set header_cache = "~/.mutt/cache/headers"
set message_cachedir = "~/.mutt/cache/bodies"
set certificate_file = "~/.mutt/certificates"
set smtp_url = "smtps://你的信箱@XXX.com:你的APP密碼@smtp.gmail.com:465/"
set record="~/mail/sent"
set move = no
set imap_keepalive = 900
```
### App 密碼設定
因為我信箱是使用 gmail,這邊就放我是如何設定 gmail 的。其中 `你的APP密碼` 需要到 gmail 裡面設定一個給應用程式的密碼,步驟如下:
> https://support.google.com/mail/answer/185833?hl=en
1. 開啟 google 的 2FA 認證
> 到 [這裡](https://myaccount.google.com/security?rapt=AEjHL4Ma9vPuhKss9SEbsfcQQAYyuW0pwsA_mMKLb2w6XyJJucvD-5MgBKAW5_O8KOD4tnetMuUtSxfGiGvzFqhnkC-wnUkwpA) 的 「登入 Google」點選兩步驟驗證,並且完成設定。
2. 建立應用程式密碼
> 「開啟兩步驟驗證」的下方有一個「應用程式密碼」,點進去後選擇「郵件」跟「其他」,名字就取一個自己會認得的就可以,完成後會顯示密碼,複製貼到 `.gitconfig` 或是 `.muttrc` 就可以了。
## 在本地端建立一個 Repo
如果直接去 github 上 clone 會花很長的時間,這裡我是到 [release](https://github.com/torvalds/linux/tags) 找最新的檔案下載,之後再解壓縮就好了。
這裡舉我下載的 `linux-5.19-rc1.tar.gz` 為例,載完後將檔案解壓縮到想要開發的目錄下:
```
$ tar -zxvf linux-5.19-rc1.tar.gz
```
之後就可以進去設定 git:
```
$ cd linux-5.19-rc1
$ git init
$ git add .
$ git commit -m "origin"
$ git checkout -b my-patch
```
> 如果是第一次使用 git 也要記得先`git config` 設定一下名字跟信箱喔!
之後就可以進行修改了!
## Commit Message
完成自己的修改後就可以新增 commit:
```
$ git commit -asv
```
-a:加入剛剛修改並且有 track 的檔案
-s:commit 會加上 `Signed-off-by: <你的名字> <你的信箱@XXX.com>`
-v:verbose,會列出你的修改,看著寫 commit message 會比較方便
### commit message 格式
Patch 的格式都有嚴格的限制,沒有寫過的同學可以去看你編輯的檔案之前 commit 是如何寫的比較有概念。
簡單來說就是會分成:標題、內容描述、自己的簽名,中間都會空一行:
```
subsystemName: short description
# blank line
patch content description
# blank line
Signed-off-by: "name" <email>
```
## 建立 Patch
完成 commit 就可以建立等等要寄出去的 patch 了:
```
$ git format-patch master
```
建立好的 patch 要先通過一些 scripts 裡面的檢查:
```
$ ./scripts/checkpatch.pl ./patch_name.patch
```
如果你的 patch 有問題,會有提示訊息跟你說是哪裡需要修改,修改完後可以使用:
```
$ git commit -a --amend
$ git format-patch master
```
## 寄送 Patch
接著就要找出 maintainer 是誰,並且將 patch 寄給他,這邊舉修改 docs 為例:
```
$ ./scripts/get_maintainer.pl ./patch_name.patch
Jonathan Corbet <corbet@lwn.net> (maintainer:DOCUMENTATION)
linux-doc@vger.kernel.org (open list:DOCUMENTATION)
linux-kernel@vger.kernel.org (open list)
```
從輸出就可以看到要寄給的人了,通常裡面的人都會要 CC 到。
使用 `git send-email`:
```
$ git send-email --to corbet@lwn.net \
--cc linux-doc@vger.kernel.org \
--cc linux-kernel@vger.kernel.org \
./patch_name.patch
```
使用 `mutt`:
```
$ mutt -H ./patch_name.patch
```
## 後續
之後就可以到 [lkml.org](https://lkml.org/) 看看有沒有出現你的 patch 了,靜靜等待 review 就好了。
### 後記
之後在看 UML (User Mode Linux) 的時候找到一個錯字,也順手送了一個 patch 過去,document 的維護者 Jonathon 還恭喜我發送第一個 kernel patch,人真的很好 xD
> Jonathon 的[回覆](https://lore.kernel.org/all/20220621072910.4704-1-1030steven@gmail.com/t/)