Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,295 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/README.rst
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
Linux內核6.x版本 <http://kernel.org/>
=========================================
以下是Linux版本6的發行註記。仔細閱讀它們,
它們會告訴你這些都是什麼,解釋如何安裝內核,以及遇到問題時該如何做。
什麼是Linux?
---------------
Linux是Unix操作系統的克隆版本,由Linus Torvalds在一個鬆散的網絡黑客
(Hacker,無貶義)團隊的幫助下從頭開始編寫。它旨在實現兼容POSIX和
單一UNIX規範。
它具有在現代成熟的Unix中應當具有的所有功能,包括真正的多任務處理、虛擬內存、
共享庫、按需加載、共享的寫時拷貝(COW)可執行文件、恰當的內存管理以及包括
IPv4和IPv6在內的複合網絡棧。
Linux在GNU通用公共許可證,版本2(GNU GPLv2)下分發,詳見隨附的COPYING文件。
它能在什麼樣的硬件上運行?
-----------------------------
雖然Linux最初是爲32位的x86 PC機(386或更高版本)開發的,但今天它也能運行在
(至少)Compaq Alpha AXP、Sun SPARC與UltraSPARC、Motorola 68000、PowerPC、
PowerPC64、ARM、Hitachi SuperH、Cell、IBM S/390、MIPS、HP PA-RISC、Intel
IA-64、DEC VAX、AMD x86-64 Xtensa和ARC架構上。
Linux很容易移植到大多數通用的32位或64位體系架構,只要它們有一個分頁內存管理
單元(PMMU)和一個移植的GNU C編譯器(gcc;GNU Compiler Collection,GCC的一
部分)。Linux也被移植到許多沒有PMMU的體系架構中,儘管功能顯然受到了一定的
限制。
Linux也被移植到了其自己上。現在可以將內核作爲用戶空間應用程序運行——這被
稱爲用戶模式Linux(UML)。
文檔
-----
因特網上和書籍上都有大量的電子文檔,既有Linux專屬文檔,也有與一般UNIX問題相關
的文檔。我建議在任何Linux FTP站點上查找LDP(Linux文檔項目)書籍的文檔子目錄。
本自述文件並不是關於系統的文檔:有更好的可用資源。
- 因特網上和書籍上都有大量的(電子)文檔,既有Linux專屬文檔,也有與普通
UNIX問題相關的文檔。我建議在任何有LDP(Linux文檔項目)書籍的Linux FTP
站點上查找文檔子目錄。本自述文件並不是關於系統的文檔:有更好的可用資源。
- 文檔/子目錄中有各種自述文件:例如,這些文件通常包含一些特定驅動程序的
內核安裝說明。請閱讀
:ref:`Documentation/process/changes.rst <changes>` 文件,它包含了升級內核
可能會導致的問題的相關信息。
安裝內核源代碼
---------------
- 如果您要安裝完整的源代碼,請把內核tar檔案包放在您有權限的目錄中(例如您
的主目錄)並將其解包::
xz -cd linux-6.x.tar.xz | tar xvf -
將“X”替換成最新內核的版本號。
【不要】使用 /usr/src/linux 目錄!這裏有一組庫頭文件使用的內核頭文件
(通常是不完整的)。它們應該與庫匹配,而不是被內核的變化搞得一團糟。
- 您還可以通過打補丁在6.x版本之間升級。補丁以xz格式分發。要通過打補丁進行
安裝,請獲取所有較新的補丁文件,進入內核源代碼(linux-6.x)的目錄並
執行::
xz -cd ../patch-6.x.xz | patch -p1
請【按順序】替換所有大於當前源代碼樹版本的“x”,這樣就可以了。您可能想要
刪除備份文件(文件名類似xxx~ 或 xxx.orig),並確保沒有失敗的補丁(文件名
類似xxx# 或 xxx.rej)。如果有,不是你就是我犯了錯誤。
與6.x內核的補丁不同,6.x.y內核(也稱爲穩定版內核)的補丁不是增量的,而是
直接應用於基本的6.x內核。例如,如果您的基本內核是6.0,並且希望應用6.0.3
補丁,則不應先應用6.0.1和6.0.2的補丁。類似地,如果您運行的是6.0.2內核,
並且希望跳轉到6.0.3,那麼在應用6.0.3補丁之前,必須首先撤銷6.0.2補丁
(即patch -R)。更多關於這方面的內容,請閱讀
:ref:`Documentation/process/applying-patches.rst <applying_patches>` 。
或者,腳本 patch-kernel 可以用來自動化這個過程。它能確定當前內核版本並
應用找到的所有補丁::
linux/scripts/patch-kernel linux
上面命令中的第一個參數是內核源代碼的位置。補丁是在當前目錄應用的,但是
可以將另一個目錄指定爲第二個參數。
- 確保沒有過時的 .o 文件和依賴項::
cd linux
make mrproper
現在您應該已經正確安裝了源代碼。
軟件要求
---------
編譯和運行6.x內核需要各種軟件包的最新版本。請參考
:ref:`Documentation/process/changes.rst <changes>`
來了解最低版本要求以及如何升級軟件包。請注意,使用過舊版本的這些包可能會
導致很難追蹤的間接錯誤,因此不要以爲在生成或操作過程中出現明顯問題時可以
只更新包。
爲內核建立目錄
---------------
編譯內核時,默認情況下所有輸出文件都將與內核源代碼放在一起。使用
``make O=output/dir`` 選項可以爲輸出文件(包括 .config)指定備用位置。
例如::
kernel source code: /usr/src/linux-6.x
build directory: /home/name/build/kernel
要配置和構建內核,請使用::
cd /usr/src/linux-6.x
make O=/home/name/build/kernel menuconfig
make O=/home/name/build/kernel
sudo make O=/home/name/build/kernel modules_install install
請注意:如果使用了 ``O=output/dir`` 選項,那麼它必須用於make的所有調用。
配置內核
---------
即使只升級一個小版本,也不要跳過此步驟。每個版本中都會添加新的配置選項,
如果配置文件沒有按預定設置,就會出現奇怪的問題。如果您想以最少的工作量
將現有配置升級到新版本,請使用 ``make oldconfig`` ,它只會詢問您新配置
選項的答案。
- 其他配置命令包括::
"make config" 純文本界面。
"make menuconfig" 基於文本的彩色菜單、選項列表和對話框。
"make nconfig" 增強的基於文本的彩色菜單。
"make xconfig" 基於Qt的配置工具。
"make gconfig" 基於GTK的配置工具。
"make oldconfig" 基於現有的 ./.config 文件選擇所有選項,並詢問
新配置選項。
"make olddefconfig"
類似上一個,但不詢問直接將新選項設置爲默認值。
"make defconfig" 根據體系架構,使用arch/$arch/defconfig或
arch/$arch/configs/${PLATFORM}_defconfig中的
默認選項值創建./.config文件。
"make ${PLATFORM}_defconfig"
使用arch/$arch/configs/${PLATFORM}_defconfig中
的默認選項值創建一個./.config文件。
用“make help”來獲取您體系架構中所有可用平臺的列表。
"make allyesconfig"
通過儘可能將選項值設置爲“y”,創建一個
./.config文件。
"make allmodconfig"
通過儘可能將選項值設置爲“m”,創建一個
./.config文件。
"make allnoconfig" 通過儘可能將選項值設置爲“n”,創建一個
./.config文件。
"make randconfig" 通過隨機設置選項值來創建./.config文件。
"make localmodconfig" 基於當前配置和加載的模塊(lsmod)創建配置。禁用
已加載的模塊不需要的任何模塊選項。
要爲另一臺計算機創建localmodconfig,請將該計算機
的lsmod存儲到一個文件中,並將其作爲lsmod參數傳入。
此外,通過在參數LMC_KEEP中指定模塊的路徑,可以將
模塊保留在某些文件夾或kconfig文件中。
target$ lsmod > /tmp/mylsmod
target$ scp /tmp/mylsmod host:/tmp
host$ make LSMOD=/tmp/mylsmod \
LMC_KEEP="drivers/usb:drivers/gpu:fs" \
localmodconfig
上述方法在交叉編譯時也適用。
"make localyesconfig" 與localmodconfig類似,只是它會將所有模塊選項轉換
爲內置(=y)。你可以同時通過LMC_KEEP保留模塊。
"make kvm_guest.config"
爲kvm客戶機內核支持啓用其他選項。
"make xen.config" 爲xen dom0客戶機內核支持啓用其他選項。
"make tinyconfig" 配置儘可能小的內核。
更多關於使用Linux內核配置工具的信息,見文檔
Documentation/kbuild/kconfig.rst。
- ``make config`` 注意事項:
- 包含不必要的驅動程序會使內核變大,並且在某些情況下會導致問題:
探測不存在的控制器卡可能會混淆其他控制器。
- 如果存在協處理器,則編譯了數學仿真的內核仍將使用協處理器:在
這種情況下,數學仿真永遠不會被使用。內核會稍微大一點,但不管
是否有數學協處理器,都可以在不同的機器上工作。
- “kernel hacking”配置細節通常會導致更大或更慢的內核(或兩者
兼而有之),甚至可以通過配置一些例程來主動嘗試破壞壞代碼以發現
內核問題,從而降低內核的穩定性(kmalloc())。因此,您可能應該
用於研究“開發”、“實驗”或“調試”特性相關問題。
編譯內核
---------
- 確保您至少有gcc 5.1可用。
有關更多信息,請參閱 :ref:`Documentation/process/changes.rst <changes>` 。
- 執行 ``make`` 來創建壓縮內核映像。如果您安裝了lilo以適配內核makefile,
那麼也可以進行 ``make install`` ,但是您可能需要先檢查特定的lilo設置。
實際安裝必須以root身份執行,但任何正常構建都不需要。
無須徒然使用root身份。
- 如果您將內核的任何部分配置爲模塊,那麼還必須執行 ``make modules_install`` 。
- 詳細的內核編譯/生成輸出:
通常,內核構建系統在相當安靜的模式下運行(但不是完全安靜)。但是有時您或
其他內核開發人員需要看到編譯、鏈接或其他命令的執行過程。爲此,可使用
“verbose(詳細)”構建模式。
向 ``make`` 命令傳遞 ``V=1`` 來實現,例如::
make V=1 all
如需構建系統也給出內個目標重建的願意,請使用 ``V=2`` 。默認爲 ``V=0`` 。
- 準備一個備份內核以防出錯。對於開發版本尤其如此,因爲每個新版本都包含
尚未調試的新代碼。也要確保保留與該內核對應的模塊的備份。如果要安裝
與工作內核版本號相同的新內核,請在進行 ``make modules_install`` 安裝
之前備份modules目錄。
或者,在編譯之前,使用內核配置選項“LOCALVERSION”向常規內核版本附加
一個唯一的後綴。LOCALVERSION可以在“General Setup”菜單中設置。
- 爲了引導新內核,您需要將內核映像(例如編譯後的
.../linux/arch/x86/boot/bzImage)複製到常規可引導內核的位置。
- 不再支持在沒有LILO等啓動裝載程序幫助的情況下直接從軟盤引導內核。
如果從硬盤引導Linux,很可能使用LILO,它使用/etc/lilo.conf文件中
指定的內核映像文件。內核映像文件通常是/vmlinuz、/boot/vmlinuz、
/bzImage或/boot/bzImage。使用新內核前,請保存舊映像的副本,並複製
新映像覆蓋舊映像。然後您【必須重新運行LILO】來更新加載映射!否則,
將無法啓動新的內核映像。
重新安裝LILO通常需要運行/sbin/LILO。您可能希望編輯/etc/lilo.conf
文件爲舊內核映像指定一個條目(例如/vmlinux.old)防止新的不能正常
工作。有關更多信息,請參閱LILO文檔。
重新安裝LILO之後,您應該就已經準備好了。關閉系統,重新啓動,盡情
享受吧!
如果需要更改內核映像中的默認根設備、視頻模式等,請在適當的地方使用
啓動裝載程序的引導選項。無需重新編譯內核即可更改這些參數。
- 使用新內核重新啓動並享受它吧。
若遇到問題
-----------
如果您發現了一些可能由於內核缺陷所導致的問題,請參閱:
Documentation/translations/zh_CN/admin-guide/reporting-issues.rst 。
想要理解內核錯誤報告,請參閱:
Documentation/translations/zh_CN/admin-guide/bug-hunting.rst 。
更多用GDB調試內核的信息,請參閱:
Documentation/translations/zh_CN/dev-tools/gdb-kernel-debugging.rst
和 Documentation/process/debugging/kgdb.rst 。
@@ -0,0 +1,294 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/bootconfig.rst
:譯者: 吳想成 Wu XiangCheng <bobwxc@email.cn>
========
引導配置
========
:作者: Masami Hiramatsu <mhiramat@kernel.org>
概述
====
引導配置擴展了現有的內核命令行,以一種更有效率的方式在引導內核時進一步支持
鍵值數據。這允許管理員傳遞一份結構化關鍵字的配置文件。
配置文件語法
============
引導配置文件的語法採用非常簡單的鍵值結構。每個關鍵字由點連接的單詞組成,鍵
和值由 ``=`` 連接。值以分號( ``;`` )或換行符( ``\n`` )結尾。數組值中每
個元素由逗號( ``,`` )分隔。::
KEY[.WORD[...]] = VALUE[, VALUE2[...]][;]
與內核命令行語法不同,逗號和 ``=`` 周圍允許有空格。
關鍵字只允許包含字母、數字、連字符( ``-`` )和下劃線( ``_`` )。值可包含
可打印字符和空格,但分號( ``;`` )、換行符( ``\n`` )、逗號( ``,`` )、
井號( ``#`` )和右大括號( ``}`` )等分隔符除外。
如果你需要在值中使用這些分隔符,可以用雙引號( ``"VALUE"`` )或單引號
( ``'VALUE'`` )括起來。注意,引號無法轉義。
鍵的值可以爲空或不存在。這些鍵用於檢查該鍵是否存在(類似布爾值)。
鍵值語法
--------
引導配置文件語法允許用戶通過大括號合併鍵名部分相同的關鍵字。例如::
foo.bar.baz = value1
foo.bar.qux.quux = value2
也可以寫成::
foo.bar {
baz = value1
qux.quux = value2
}
或者更緊湊一些,寫成::
foo.bar { baz = value1; qux.quux = value2 }
在這兩種樣式中,引導解析時相同的關鍵字都會自動合併。因此可以追加類似的樹或
鍵值。
相同關鍵字的值
--------------
禁止兩個或多個值或數組共享同一個關鍵字。例如::
foo = bar, baz
foo = qux # !錯誤! 我們不可以重定義相同的關鍵字
如果你想要更新值,必須顯式使用覆蓋操作符 ``:=`` 。例如::
foo = bar, baz
foo := qux
這樣 ``foo`` 關鍵字的值就變成了 ``qux`` 。這對於通過添加(部分)自定義引導
配置來覆蓋默認值非常有用,免於解析默認引導配置。
如果你想對現有關鍵字追加值作爲數組成員,可以使用 ``+=`` 操作符。例如::
foo = bar, baz
foo += qux
這樣, ``foo`` 關鍵字就同時擁有了 ``bar`` , ``baz`` 和 ``qux`` 。
此外,父關鍵字下可同時存在值和子關鍵字。
例如,下列配置是可行的。::
foo = value1
foo.bar = value2
foo := value3 # 這會更新foo的值。
注意,裸值不能直接放進結構化關鍵字中,必須在大括號外定義它。例如::
foo {
bar = value1
bar {
baz = value2
qux = value3
}
}
同時,關鍵字下值節點的順序是固定的。如果值和子關鍵字同時存在,值永遠是該關
鍵字的第一個子節點。因此如果用戶先指定子關鍵字,如::
foo.bar = value1
foo = value2
則在程序(和/proc/bootconfig)中,它會按如下顯示::
foo = value2
foo.bar = value1
註釋
----
配置語法接受shell腳本風格的註釋。註釋以井號( ``#`` )開始,到換行符
( ``\n`` )結束。
::
# comment line
foo = value # value is set to foo.
bar = 1, # 1st element
2, # 2nd element
3 # 3rd element
會被解析爲::
foo = value
bar = 1, 2, 3
注意你不能把註釋放在值和分隔符( ``,`` 或 ``;`` )之間。如下配置語法是錯誤的::
key = 1 # comment
,2
/proc/bootconfig
================
/proc/bootconfig是引導配置的用戶空間接口。與/proc/cmdline不同,此文件內容以
鍵值列表樣式顯示。
每個鍵值對一行,樣式如下::
KEY[.WORDS...] = "[VALUE]"[,"VALUE2"...]
用引導配置引導內核
==================
用引導配置引導內核有兩種方法:將引導配置附加到initrd鏡像或直接嵌入內核中。
*initrd: initial RAM disk,初始內存磁盤*
將引導配置附加到initrd
----------------------
由於默認情況下引導配置文件是用initrd加載的,因此它將被添加到initrd(initramfs)
鏡像文件的末尾,其中包含填充、大小、校驗值和12字節幻數,如下所示::
[initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]
大小和校驗值爲小端序存放的32位無符號值。
當引導配置被加到initrd鏡像時,整個文件大小會對齊到4字節。空字符( ``\0`` )
會填補對齊空隙。因此 ``size`` 就是引導配置文件的長度+填充的字節。
Linux內核在內存中解碼initrd鏡像的最後部分以獲取引導配置數據。由於這種“揹負式”
的方法,只要引導加載器傳遞了正確的initrd文件大小,就無需更改或更新引導加載器
和內核鏡像本身。如果引導加載器意外傳遞了更長的大小,內核將無法找到引導配置數
據。
Linux內核在tools/bootconfig下提供了 ``bootconfig`` 命令來完成此操作,管理員
可以用它從initrd鏡像中刪除或追加配置文件。你可以用以下命令來構建它::
# make -C tools/bootconfig
要向initrd鏡像添加你的引導配置文件,請按如下命令操作(舊數據會自動移除)::
# tools/bootconfig/bootconfig -a your-config /boot/initrd.img-X.Y.Z
要從鏡像中移除配置,可以使用-d選項::
# tools/bootconfig/bootconfig -d /boot/initrd.img-X.Y.Z
然後在內核命令行上添加 ``bootconfig`` 告訴內核去initrd文件末尾尋找內核配置。
將引導配置嵌入內核
------------------
如果你不能使用initrd,也可以通過Kconfig選項將引導配置文件嵌入內核中。在此情
況下,你需要用以下選項重新編譯內核::
CONFIG_BOOT_CONFIG_EMBED=y
CONFIG_BOOT_CONFIG_EMBED_FILE="/引導配置/文件/的/路徑"
``CONFIG_BOOT_CONFIG_EMBED_FILE`` 需要從源碼樹或對象樹開始的引導配置文件的
絕對/相對路徑。內核會將其嵌入作爲默認引導配置。
與將引導配置附加到initrd一樣,你也需要在內核命令行上添加 ``bootconfig`` 告訴
內核去啓用內嵌的引導配置。
注意,即使你已經設置了此選項,仍可用附加到initrd的其他引導配置覆蓋內嵌的引導
配置。
通過引導配置傳遞內核參數
========================
除了內核命令行,引導配置也可以用於傳遞內核參數。所有 ``kernel`` 關鍵字下的鍵
值對都將直接傳遞給內核命令行。此外, ``init`` 下的鍵值對將通過命令行傳遞給
init進程。參數按以下順序與用戶給定的內核命令行字符串相連,因此命令行參數可以
覆蓋引導配置參數(這取決於子系統如何處理參數,但通常前面的參數將被後面的參數
覆蓋)::
[bootconfig params][cmdline params] -- [bootconfig init params][cmdline init params]
如果引導配置文件給出的kernel/init參數是::
kernel {
root = 01234567-89ab-cdef-0123-456789abcd
}
init {
splash
}
這將被複制到內核命令行字符串中,如下所示::
root="01234567-89ab-cdef-0123-456789abcd" -- splash
如果用戶給出的其他命令行是::
ro bootconfig -- quiet
則最後的內核命令行如下::
root="01234567-89ab-cdef-0123-456789abcd" ro bootconfig -- splash quiet
配置文件的限制
==============
當前最大的配置大小是32KB,關鍵字總數(不是鍵值條目)必須少於1024個節點。
注意:這不是條目數而是節點數,條目必須消耗超過2個節點(一個關鍵字和一個值)。
所以從理論上講最多512個鍵值對。如果關鍵字平均包含3個單詞,則可有256個鍵值對。
在大多數情況下,配置項的數量將少於100個條目,小於8KB,因此這應該足夠了。如果
節點數超過1024,解析器將返回錯誤,即使文件大小小於32KB。(請注意,此最大尺寸
不包括填充的空字符。)
無論如何,因爲 ``bootconfig`` 命令在附加啓動配置到initrd映像時會驗證它,用戶
可以在引導之前注意到它。
引導配置API
===========
用戶可以查詢或遍歷鍵值對,也可以查找(前綴)根關鍵字節點,並在查找該節點下的
鍵值。
如果您有一個關鍵字字符串,則可以直接使用 xbc_find_value() 查詢該鍵的值。如果
你想知道引導配置裏有哪些關鍵字,可以使用 xbc_for_each_key_value() 迭代鍵值對。
請注意,您需要使用 xbc_array_for_each_value() 訪問數組的值,例如::
vnode = NULL;
xbc_find_value("key.word", &vnode);
if (vnode && xbc_node_is_array(vnode))
xbc_array_for_each_value(vnode, value) {
printk("%s ", value);
}
如果您想查找具有前綴字符串的鍵,可以使用 xbc_find_node() 通過前綴字符串查找
節點,然後用 xbc_node_for_each_key_value() 迭代前綴節點下的鍵。
但最典型的用法是獲取前綴下的命名值或前綴下的命名數組,例如::
root = xbc_find_node("key.prefix");
value = xbc_node_find_value(root, "option", &vnode);
...
xbc_node_for_each_array_value(root, "array-option", value, anode) {
...
}
這將訪問值“key.prefix.option”的值和“key.prefix.array-option”的數組。
鎖是不需要的,因爲在初始化之後配置只讀。如果需要修改,必須複製所有數據和關鍵字。
函數與結構體
============
相關定義的kernel-doc參見:
- include/linux/bootconfig.h
- lib/bootconfig.c
@@ -0,0 +1,85 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/bug-bisect`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
二分(bisect)缺陷
+++++++++++++++++++
(英文版)最後更新:2016年10月28日
引言
=====
始終嘗試由來自kernel.org的源代碼構建的最新內核。如果您沒有信心這樣做,請將
錯誤報告給您的發行版供應商,而不是內核開發人員。
找到缺陷(bug)並不總是那麼容易,不過仍然得去找。如果你找不到它,不要放棄。
儘可能多的向相關維護人員報告您發現的信息。請參閱MAINTAINERS文件以瞭解您所
關注的子系統的維護人員。
在提交錯誤報告之前,請閱讀“Documentation/admin-guide/reporting-issues.rst”。
設備未出現(Devices not appearing)
====================================
這通常是由udev/systemd引起的。在將其歸咎於內核之前先檢查一下。
查找導致缺陷的補丁
===================
使用 ``git`` 提供的工具可以很容易地找到缺陷,只要缺陷是可復現的。
操作步驟:
- 從git源代碼構建內核
- 以此開始二分 [#f1]_::
$ git bisect start
- 標記損壞的變更集::
$ git bisect bad [commit]
- 標記正常工作的變更集::
$ git bisect good [commit]
- 重新構建內核並測試
- 使用以下任一與git bisect進行交互::
$ git bisect good
或::
$ git bisect bad
這取決於您測試的變更集上是否有缺陷
- 在一些交互之後,git bisect將給出可能導致缺陷的變更集。
- 例如,如果您知道當前版本有問題,而4.8版本是正常的,則可以執行以下操作::
$ git bisect start
$ git bisect bad # Current version is bad
$ git bisect good v4.8
.. [#f1] 您可以(可選地)在開始git bisect的時候提供good或bad參數
``git bisect start [BAD] [GOOD]``
如需進一步參考,請閱讀:
- ``git-bisect`` 的手冊頁
- `Fighting regressions with git bisect(用git bisect解決迴歸)
<https://www.kernel.org/pub/software/scm/git/docs/git-bisect-lk2009.html>`_
- `Fully automated bisecting with "git bisect run"(使用git bisect run
來全自動二分) <https://lwn.net/Articles/317154>`_
- `Using Git bisect to figure out when brokenness was introduced
(使用Git二分來找出何時引入了錯誤) <http://webchick.net/node/99>`_
@@ -0,0 +1,334 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/bug-hunting`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
追蹤缺陷
=========
內核錯誤報告通常附帶如下堆棧轉儲::
------------[ cut here ]------------
WARNING: CPU: 1 PID: 28102 at kernel/module.c:1108 module_put+0x57/0x70
Modules linked in: dvb_usb_gp8psk(-) dvb_usb dvb_core nvidia_drm(PO) nvidia_modeset(PO) snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd soundcore nvidia(PO) [last unloaded: rc_core]
CPU: 1 PID: 28102 Comm: rmmod Tainted: P WC O 4.8.4-build.1 #1
Hardware name: MSI MS-7309/MS-7309, BIOS V1.12 02/23/2009
00000000 c12ba080 00000000 00000000 c103ed6a c1616014 00000001 00006dc6
c1615862 00000454 c109e8a7 c109e8a7 00000009 ffffffff 00000000 f13f6a10
f5f5a600 c103ee33 00000009 00000000 00000000 c109e8a7 f80ca4d0 c109f617
Call Trace:
[<c12ba080>] ? dump_stack+0x44/0x64
[<c103ed6a>] ? __warn+0xfa/0x120
[<c109e8a7>] ? module_put+0x57/0x70
[<c109e8a7>] ? module_put+0x57/0x70
[<c103ee33>] ? warn_slowpath_null+0x23/0x30
[<c109e8a7>] ? module_put+0x57/0x70
[<f80ca4d0>] ? gp8psk_fe_set_frontend+0x460/0x460 [dvb_usb_gp8psk]
[<c109f617>] ? symbol_put_addr+0x27/0x50
[<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
[<f80bb3bf>] ? dvb_usb_exit+0x2f/0xd0 [dvb_usb]
[<c13d03bc>] ? usb_disable_endpoint+0x7c/0xb0
[<f80bb48a>] ? dvb_usb_device_exit+0x2a/0x50 [dvb_usb]
[<c13d2882>] ? usb_unbind_interface+0x62/0x250
[<c136b514>] ? __pm_runtime_idle+0x44/0x70
[<c13620d8>] ? __device_release_driver+0x78/0x120
[<c1362907>] ? driver_detach+0x87/0x90
[<c1361c48>] ? bus_remove_driver+0x38/0x90
[<c13d1c18>] ? usb_deregister+0x58/0xb0
[<c109fbb0>] ? SyS_delete_module+0x130/0x1f0
[<c1055654>] ? task_work_run+0x64/0x80
[<c1000fa5>] ? exit_to_usermode_loop+0x85/0x90
[<c10013f0>] ? do_fast_syscall_32+0x80/0x130
[<c1549f43>] ? sysenter_past_esp+0x40/0x6a
---[ end trace 6ebc60ef3981792f ]---
這樣的堆棧跟蹤提供了足夠的信息來識別內核源代碼中發生錯誤的那一行。根據問題的
嚴重性,它還可能包含 **“Oops”** 一詞,比如::
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<c06969d4>] iret_exc+0x7d0/0xa59
*pdpt = 000000002258a001 *pde = 0000000000000000
Oops: 0002 [#1] PREEMPT SMP
...
儘管有 **Oops** 或其他類型的堆棧跟蹤,但通常需要找到出問題的行來識別和處理缺
陷。在本章中,我們將參考“Oops”來了解需要分析的各種堆棧跟蹤。
如果內核是用 ``CONFIG_DEBUG_INFO`` 編譯的,那麼可以使用文件:
`scripts/decode_stacktrace.sh` 。
鏈接的模塊
-----------
受到污染或正在加載/卸載的模塊用“(…)”標記,污染標誌在
`Documentation/admin-guide/tainted-kernels.rst` 文件中進行了描述,“正在被加
載”用“+”標註,“正在被卸載”用“-”標註。
Oops消息在哪?
---------------
通常,Oops文本由klogd從內核緩衝區讀取,然後交給 ``syslogd`` ,後者將其寫入
syslog文件,通常是 ``/var/log/messages`` (取決於 ``/etc/syslog.conf`` )。
在使用systemd的系統上,它也可以由 ``journald`` 守護進程存儲,並通過運行
``journalctl`` 命令進行訪問。
有時 ``klogd`` 會掛掉,這種情況下您可以運行 ``dmesg > file`` 從內核緩衝區
讀取數據並保存它。或者您可以 ``cat /proc/kmsg > file`` ,但是您必須適時
中斷以停止傳輸,因爲 ``kmsg`` 是一個“永無止境的文件”。
如果機器嚴重崩潰,無法輸入命令或磁盤不可用,那還有三個選項:
(1) 手動複製屏幕上的文本,並在機器重新啓動後輸入。很難受,但這是突然崩潰下
唯一的選擇。或者你可以用數碼相機拍下屏幕——雖然不那麼好,但總比什麼都沒
有好。如果消息滾動超出控制檯頂部,使用更高分辨率(例如 ``vga=791`` )
引導啓動將允許您閱讀更多文本。(警告:這需要 ``vesafb`` ,因此對“早期”
的Oppses沒有幫助)
(2) 從串口終端啓動(參見
:ref:`Documentation/admin-guide/serial-console.rst <serial_console>` ),
在另一臺機器上運行調制解調器然後用你喜歡的通信程序捕獲輸出。
Minicom運行良好。
(3) 使用Kdump(參閱 Documentation/admin-guide/kdump/kdump.rst ),使用
Documentation/admin-guide/kdump/gdbmacros.txt 中的dmesg gdbmacro從舊內存
中提取內核環形緩衝區。
找到缺陷位置
-------------
如果你能指出缺陷在內核源代碼中的位置,則報告缺陷的效果會非常好。這有兩種方法。
通常來說使用 ``gdb`` 會比較容易,不過內核需要用調試信息來預編譯。
gdb
^^^^
GNU 調試器(GNU debugger, ``gdb`` )是從 ``vmlinux`` 文件中找出OOPS的確切
文件和行號的最佳方法。
在使用 ``CONFIG_DEBUG_INFO`` 編譯的內核上使用gdb效果最好。可通過運行以下命令
進行設置::
$ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
在用 ``CONFIG_DEBUG_INFO`` 編譯的內核上,你可以直接從OOPS複製EIP值::
EIP: 0060:[<c021e50e>] Not tainted VLI
並使用GDB來將其翻譯成可讀形式::
$ gdb vmlinux
(gdb) l *0xc021e50e
如果沒有啓用 ``CONFIG_DEBUG_INFO`` ,則使用OOPS的函數偏移::
EIP is at vt_ioctl+0xda8/0x1482
並在啓用 ``CONFIG_DEBUG_INFO`` 的情況下重新編譯內核::
$ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
$ make vmlinux
$ gdb vmlinux
(gdb) l *vt_ioctl+0xda8
0x1888 is in vt_ioctl (drivers/tty/vt/vt_ioctl.c:293).
288 {
289 struct vc_data *vc = NULL;
290 int ret = 0;
291
292 console_lock();
293 if (VT_BUSY(vc_num))
294 ret = -EBUSY;
295 else if (vc_num)
296 vc = vc_deallocate(vc_num);
297 console_unlock();
或者若您想要更詳細的顯示::
(gdb) p vt_ioctl
$1 = {int (struct tty_struct *, unsigned int, unsigned long)} 0xae0 <vt_ioctl>
(gdb) l *0xae0+0xda8
您也可以使用對象文件作爲替代::
$ make drivers/tty/
$ gdb drivers/tty/vt/vt_ioctl.o
(gdb) l *vt_ioctl+0xda8
如果你有調用跟蹤,類似::
Call Trace:
[<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
[<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
[<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
...
這表明問題可能在 :jbd: 模塊中。您可以在gdb中加載該模塊並列出相關代碼::
$ gdb fs/jbd/jbd.ko
(gdb) l *log_wait_commit+0xa3
.. note::
您還可以對堆棧跟蹤處的任何函數調用執行相同的操作,例如::
[<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
上述調用發生的位置可以通過以下方式看到::
$ gdb drivers/media/usb/dvb-usb/dvb-usb.o
(gdb) l *dvb_usb_adapter_frontend_exit+0x3a
objdump
^^^^^^^^
要調試內核,請使用objdump並從崩潰輸出中查找十六進制偏移,以找到有效的代碼/匯
編行。如果沒有調試符號,您將看到所示例程的彙編程序代碼,但是如果內核有調試
符號,C代碼也將可見(調試符號可以在內核配置菜單的hacking項中啓用)。例如::
$ objdump -r -S -l --disassemble net/ipv4/tcp.o
.. note::
您需要處於內核樹的頂層以便此獲得您的C文件。
如果您無法訪問源代碼,仍然可以使用以下方法調試一些崩潰轉儲(如Dave Miller的
示例崩潰轉儲輸出所示)::
EIP is at +0x14/0x4c0
...
Code: 44 24 04 e8 6f 05 00 00 e9 e8 fe ff ff 8d 76 00 8d bc 27 00 00
00 00 55 57 56 53 81 ec bc 00 00 00 8b ac 24 d0 00 00 00 8b 5d 08
<8b> 83 3c 01 00 00 89 44 24 14 8b 45 28 85 c0 89 44 24 18 0f 85
Put the bytes into a "foo.s" file like this:
.text
.globl foo
foo:
.byte .... /* bytes from Code: part of OOPS dump */
Compile it with "gcc -c -o foo.o foo.s" then look at the output of
"objdump --disassemble foo.o".
Output:
ip_queue_xmit:
push %ebp
push %edi
push %esi
push %ebx
sub $0xbc, %esp
mov 0xd0(%esp), %ebp ! %ebp = arg0 (skb)
mov 0x8(%ebp), %ebx ! %ebx = skb->sk
mov 0x13c(%ebx), %eax ! %eax = inet_sk(sk)->opt
`scripts/decodecode` 文件可以用來自動完成大部分工作,這取決於正在調試的CPU
體系結構。
報告缺陷
---------
一旦你通過定位缺陷找到了其發生的地方,你可以嘗試自己修復它或者向上遊報告它。
爲了向上遊報告,您應該找出用於開發受影響代碼的郵件列表。這可以使用 ``get_maintainer.pl`` 。
例如,您在gspca的sonixj.c文件中發現一個缺陷,則可以通過以下方法找到它的維護者::
$ ./scripts/get_maintainer.pl -f drivers/media/usb/gspca/sonixj.c
Hans Verkuil <hverkuil@kernel.org> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%)
Mauro Carvalho Chehab <mchehab@kernel.org> (maintainer:MEDIA INPUT INFRASTRUCTURE (V4L/DVB),commit_signer:1/1=100%)
Tejun Heo <tj@kernel.org> (commit_signer:1/1=100%)
Bhaktipriya Shridhar <bhaktipriya96@gmail.com> (commit_signer:1/1=100%,authored:1/1=100%,added_lines:4/4=100%,removed_lines:9/9=100%)
linux-media@vger.kernel.org (open list:GSPCA USB WEBCAM DRIVER)
linux-kernel@vger.kernel.org (open list)
請注意它將指出:
- 最後接觸源代碼的開發人員(如果這是在git樹中完成的)。在上面的例子中是Tejun
和Bhaktipriya(在這個特定的案例中,沒有人真正參與這個文件的開發);
- 驅動維護人員(Hans Verkuil);
- 子系統維護人員(Mauro Carvalho Chehab);
- 驅動程序和/或子系統郵件列表(linux-media@vger.kernel.org);
- Linux內核郵件列表(linux-kernel@vger.kernel.org)。
通常,修復缺陷的最快方法是將它報告給用於開發相關代碼的郵件列表(linux-media
ML),抄送驅動程序維護者(Hans)。
如果你完全不知道該把報告寄給誰,且 ``get_maintainer.pl`` 也沒有提供任何有用
的信息,請發送到linux-kernel@vger.kernel.org。
感謝您的幫助,這使Linux儘可能穩定:-)
修復缺陷
---------
如果你懂得編程,你不僅可以通過報告錯誤來幫助我們,還可以提供一個解決方案。
畢竟,開源就是分享你的工作,你不想因爲你的天才而被認可嗎?
如果你決定這樣做,請在制定解決方案後將其提交到上游。
請務必閱讀
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>` ,
以幫助您的代碼被接受。
---------------------------------------------------------------------------
用 ``klogd`` 進行Oops跟蹤的注意事項
------------------------------------
爲了幫助Linus和其他內核開發人員, ``klogd`` 對保護故障的處理提供了大量支持。
爲了完整支持地址解析,至少應該使用 ``sysklogd`` 包的1.3-pl3版本。
當發生保護故障時, ``klogd`` 守護進程會自動將內核日誌消息中的重要地址轉換爲
它們的等效符號。然後通過 ``klogd`` 使用的任何報告機制來轉發這個已翻譯的內核
消息。保護錯誤消息可以直接從消息文件中剪切出來並轉發給內核開發人員。
``klogd`` 執行兩種類型的地址解析,靜態翻譯和動態翻譯。靜態翻譯使用System.map
文件。爲了進行靜態轉換, ``klogd`` 守護進程必須能夠在守護進程初始化時找到系
統映射文件。有關 ``klogd`` 如何搜索映射文件的信息,請參見klogd手冊頁。
當使用內核可加載模塊時,動態地址轉換非常重要。由於內核模塊的內存是從內核的
動態內存池中分配的,因此無論是模塊的開頭還是模塊中的函數和符號都沒有固定的
位置。
內核支持系統調用,允許程序確定加載哪些模塊及其在內存中的位置。klogd守護進程
使用這些系統調用構建了一個符號表,可用於調試可加載內核模塊中發生的保護錯誤。
klogd至少會提供產生保護故障的模塊的名稱。如果可加載模塊的開發人員選擇從模塊
導出符號信息,則可能會有其他可用的符號信息。
由於內核模塊環境可以是動態的,因此當模塊環境發生變化時,必須有一種通知
``klogd`` 守護進程的機制。有一些可用的命令行選項允許klogd向當前正在執行的守
護進程發出信號示意應該刷新符號信息。有關更多信息,請參閱 ``klogd`` 手冊頁。
sysklogd發行版附帶了一個補丁,它修改了 ``modules-2.0.0`` 包,以便在加載或
卸載模塊時自動向klogd發送信號。應用此補丁基本上可無縫支持調試內核可加載模塊
發生的保護故障。
以下是 ``klogd`` 處理的可加載模塊中的保護故障示例::
Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
Aug 29 09:51:01 blizard kernel: *pde = 00000000
Aug 29 09:51:01 blizard kernel: Oops: 0002
Aug 29 09:51:01 blizard kernel: CPU: 0
Aug 29 09:51:01 blizard kernel: EIP: 0010:[oops:_oops+16/3868]
Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
Aug 29 09:51:01 blizard kernel: eax: 315e97cc ebx: 003a6f80 ecx: 001be77b edx: 00237c0c
Aug 29 09:51:01 blizard kernel: esi: 00000000 edi: bffffdb3 ebp: 00589f90 esp: 00589f8c
Aug 29 09:51:01 blizard kernel: ds: 0018 es: 0018 fs: 002b gs: 002b ss: 0018
Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
Aug 29 09:51:01 blizard kernel: 00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
Aug 29 09:51:01 blizard kernel: bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
@@ -0,0 +1,16 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Translator: 胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
清除 WARN_ONCE
--------------
WARN_ONCE / WARN_ON_ONCE / printk_once 僅僅打印一次消息.
echo 1 > /sys/kernel/debug/clear_warn_once
可以清除這種狀態並且再次允許打印一次告警信息,這對於運行測試集後重現問題
很有用。
@@ -0,0 +1,112 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Translator: 胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
========
CPU 負載
========
Linux通過``/proc/stat``和``/proc/uptime``導出各種信息,用戶空間工具
如top(1)使用這些信息計算系統花費在某個特定狀態的平均時間。
例如:
$ iostat
Linux 2.6.18.3-exp (linmac) 02/20/2007
avg-cpu: %user %nice %system %iowait %steal %idle
10.01 0.00 2.92 5.44 0.00 81.63
...
這裏系統認爲在默認採樣週期內有10.01%的時間工作在用戶空間,2.92%的時
間用在系統空間,總體上有81.63%的時間是空閒的。
大多數情況下``/proc/stat``的信息幾乎真實反映了系統信息,然而,由於內
核採集這些數據的方式/時間的特點,有時這些信息根本不可靠。
那麼這些信息是如何被蒐集的呢?每當時間中斷觸發時,內核查看此刻運行的
進程類型,並增加與此類型/狀態進程對應的計數器的值。這種方法的問題是
在兩次時間中斷之間系統(進程)能夠在多種狀態之間切換多次,而計數器只
增加最後一種狀態下的計數。
舉例
---
假設系統有一個進程以如下方式週期性地佔用cpu::
兩個時鐘中斷之間的時間線
|-----------------------|
^ ^
|_ 開始運行 |
|_ 開始睡眠
(很快會被喚醒)
在上面的情況下,根據``/proc/stat``的信息(由於當系統處於空閒狀態時,
時間中斷經常會發生)系統的負載將會是0
大家能夠想象內核的這種行爲會發生在許多情況下,這將導致``/proc/stat``
中存在相當古怪的信息::
/* gcc -o hog smallhog.c */
#include <time.h>
#include <limits.h>
#include <signal.h>
#include <sys/time.h>
#define HIST 10
static volatile sig_atomic_t stop;
static void sighandler (int signr)
{
(void) signr;
stop = 1;
}
static unsigned long hog (unsigned long niters)
{
stop = 0;
while (!stop && --niters);
return niters;
}
int main (void)
{
int i;
struct itimerval it = { .it_interval = { .tv_sec = 0, .tv_usec = 1 },
.it_value = { .tv_sec = 0, .tv_usec = 1 } };
sigset_t set;
unsigned long v[HIST];
double tmp = 0.0;
unsigned long n;
signal (SIGALRM, &sighandler);
setitimer (ITIMER_REAL, &it, NULL);
hog (ULONG_MAX);
for (i = 0; i < HIST; ++i) v[i] = ULONG_MAX - hog (ULONG_MAX);
for (i = 0; i < HIST; ++i) tmp += v[i];
tmp /= HIST;
n = tmp - (tmp / 3.0);
sigemptyset (&set);
sigaddset (&set, SIGALRM);
for (;;) {
hog (n);
sigwait (&set, &i);
}
return 0;
}
參考
---
- https://lore.kernel.org/r/loom.20070212T063225-663@post.gmane.org
- Documentation/filesystems/proc.rst (1.8)
謝謝
---
Con Kolivas, Pavel Machek
@@ -0,0 +1,97 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/cputopology.rst
:翻譯:
唐藝舟 Tang Yizhou <tangyeechou@gmail.com>
==========================
如何通過sysfs將CPU拓撲導出
==========================
CPU拓撲信息通過sysfs導出。顯示的項(屬性)和某些架構的/proc/cpuinfo輸出相似。它們位於
/sys/devices/system/cpu/cpuX/topology/。請閱讀ABI文件:
Documentation/ABI/stable/sysfs-devices-system-cpu。
drivers/base/topology.c是體系結構中性的,它導出了這些屬性。然而,die、cluster、book、
draw這些層次結構相關的文件僅在體系結構提供了下文描述的宏的條件下被創建。
對於支持這個特性的體系結構,它必須在include/asm-XXX/topology.h中定義這些宏中的一部分::
#define topology_physical_package_id(cpu)
#define topology_die_id(cpu)
#define topology_cluster_id(cpu)
#define topology_core_id(cpu)
#define topology_book_id(cpu)
#define topology_drawer_id(cpu)
#define topology_sibling_cpumask(cpu)
#define topology_core_cpumask(cpu)
#define topology_cluster_cpumask(cpu)
#define topology_die_cpumask(cpu)
#define topology_book_cpumask(cpu)
#define topology_drawer_cpumask(cpu)
``**_id macros`` 的類型是int。
``**_cpumask macros`` 的類型是 ``(const) struct cpumask *`` 。後者和恰當的
``**_siblings`` sysfs屬性對應(除了topology_sibling_cpumask(),它和thread_siblings
對應)。
爲了在所有體系結構上保持一致,include/linux/topology.h提供了上述所有宏的默認定義,以防
它們未在include/asm-XXX/topology.h中定義:
1) topology_physical_package_id: -1
2) topology_die_id: -1
3) topology_cluster_id: -1
4) topology_core_id: 0
5) topology_book_id: -1
6) topology_drawer_id: -1
7) topology_sibling_cpumask: 僅入參CPU
8) topology_core_cpumask: 僅入參CPU
9) topology_cluster_cpumask: 僅入參CPU
10) topology_die_cpumask: 僅入參CPU
11) topology_book_cpumask: 僅入參CPU
12) topology_drawer_cpumask: 僅入參CPU
此外,CPU拓撲信息由/sys/devices/system/cpu提供,包含下述文件。輸出對應的內部數據源放在
方括號("[]")中。
=========== ==================================================================
kernel_max: 內核配置允許的最大CPU下標值。[NR_CPUS-1]
offline: 由於熱插拔移除或者超過內核允許的CPU上限(上文描述的kernel_max)
導致未上線的CPU。[~cpu_online_mask + cpus >= NR_CPUS]
online: 在線的CPU,可供調度使用。[cpu_online_mask]
possible: 已被分配資源的CPU,如果它們CPU實際存在,可以上線。
[cpu_possible_mask]
present: 被系統識別實際存在的CPU。[cpu_present_mask]
=========== ==================================================================
上述輸出的格式和cpulist_parse()兼容[參見 <linux/cpumask.h>]。下面給些例子。
在本例中,系統中有64個CPU,但是CPU 32-63超過了kernel_max值,因爲NR_CPUS配置項是32,
取值範圍被限制爲0..31。此外注意CPU2和4-31未上線,但是可以上線,因爲它們同時存在於
present和possible::
kernel_max: 31
offline: 2,4-31,32-63
online: 0-1,3
possible: 0-31
present: 0-31
在本例中,NR_CPUS配置項是128,但內核啓動時設置possible_cpus=144。系統中有4個CPU,
CPU2被手動設置下線(也是唯一一個可以上線的CPU)::
kernel_max: 127
offline: 2,4-127,128-143
online: 0-1,3
possible: 0-127
present: 0-3
閱讀Documentation/core-api/cpu_hotplug.rst可瞭解開機參數possible_cpus=NUM,同時還
可以瞭解各種cpumask的信息。
@@ -0,0 +1,136 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/index`
:Translator: Alex Shi <alex.shi@linux.alibaba.com>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
Linux 內核用戶和管理員指南
==========================
下面是一組隨時間添加到內核中的面向用戶的文檔的集合。到目前爲止,還沒有一個
整體的順序或組織 - 這些材料不是一個單一的,連貫的文件!幸運的話,情況會隨着
時間的推移而迅速改善。
這個初始部分包含總體信息,包括描述內核的README, 關於內核參數的文檔等。
.. toctree::
:maxdepth: 1
README
Todolist:
* kernel-parameters
* devices
* sysctl/index
本節介紹CPU漏洞及其緩解措施。
Todolist:
* hw-vuln/index
下面的一組文檔,針對的是試圖跟蹤問題和bug的用戶。
.. toctree::
:maxdepth: 1
reporting-issues
reporting-regressions
security-bugs
bug-hunting
bug-bisect
tainted-kernels
init
Todolist:
* ramoops
* dynamic-debug-howto
* kdump/index
* perf/index
這是應用程序開發人員感興趣的章節的開始。可以在這裏找到涵蓋內核ABI各個
方面的文檔。
Todolist:
* sysfs-rules
本手冊的其餘部分包括各種指南,介紹如何根據您的喜好配置內核的特定行爲。
.. toctree::
:maxdepth: 1
bootconfig
clearing-warn-once
cpu-load
cputopology
lockup-watchdogs
unicode
sysrq
mm/index
Todolist:
* acpi/index
* aoe/index
* auxdisplay/index
* bcache
* binderfs
* binfmt-misc
* blockdev/index
* braille-console
* btmrvl
* cgroup-v1/index
* cgroup-v2
* cifs/index
* dell_rbu
* device-mapper/index
* edid
* efi-stub
* ext4
* nfs/index
* gpio/index
* highuid
* hw_random
* initrd
* iostats
* java
* jfs
* kernel-per-CPU-kthreads
* laptops/index
* lcd-panel-cgram
* ldm
* LSM/index
* md
* media/index
* module-signing
* mono
* namespaces/index
* numastat
* parport
* perf-security
* pm/index
* pnp
* rapidio
* ras
* rtc
* serial-console
* svga
* thunderbolt
* ufs
* vga-softcursor
* video-output
* xfs
.. only:: subproject and html
Indices
=======
* :ref:`genindex`
@@ -0,0 +1,58 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/init`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
解釋“No working init found.”啓動掛起消息
=========================================
:作者:
Andreas Mohr <andi at lisas period de>
Cristian Souza <cristianmsbr at gmail period com>
本文檔提供了加載初始化二進制(init binary)失敗的一些高層級原因(大致按執行
順序列出)。
1) **無法掛載根文件系統Unable to mount root FS** :請設置“debug”內核參數(在
引導加載程序bootloader配置文件或CONFIG_CMDLINE)以獲取更詳細的內核消息。
2) **初始化二進制不存在於根文件系統上init binary doesn't exist on rootfs** :
確保您的根文件系統類型正確(並且 ``root=`` 內核參數指向正確的分區);擁有
所需的驅動程序,例如SCSI或USB等存儲硬件;文件系統(ext3、jffs2等)是內建的
(或者作爲模塊由initrd預加載)。
3) **控制檯設備損壞Broken console device** : ``console= setup`` 中可能存在
衝突 --> 初始控制檯不可用(initial console unavailable)。例如,由於串行
IRQ問題(如缺少基於中斷的配置)導致的某些串行控制檯不可靠。嘗試使用不同的
``console= device`` 或像 ``netconsole=`` 。
4) **二進制存在但依賴項不可用Binary exists but dependencies not available** :
例如初始化二進制的必需庫依賴項,像 ``/lib/ld-linux.so.2`` 丟失或損壞。使用
``readelf -d <INIT>|grep NEEDED`` 找出需要哪些庫。
5) **無法加載二進制Binary cannot be loaded** :請確保二進制的體系結構與您的
硬件匹配。例如i386不匹配x86_64,或者嘗試在ARM硬件上加載x86。如果您嘗試在
此處加載非二進制文件(shell腳本?),您應該確保腳本在其工作頭(shebang
header)行 ``#!/...`` 中指定能正常工作的解釋器(包括其庫依賴項)。在處理
腳本之前,最好先測試一個簡單的非腳本二進制文件,比如 ``/bin/sh`` ,並確認
它能成功執行。要了解更多信息,請將代碼添加到 ``init/main.c`` 以顯示
kernel_execve()的返回值。
當您發現新的失敗原因時,請擴展本解釋(畢竟加載初始化二進制是一個 **關鍵** 且
艱難的過渡步驟,需要儘可能無痛地進行),然後向LKML提交一個補丁。
待辦事項:
- 通過一個可以存儲 ``kernel_execve()`` 結果值的結構體數組實現各種
``run_init_process()`` 調用,並在失敗時通過迭代 **所有** 結果來記錄一切
(非常重要的可用性修復)。
- 試着使實現本身在一般情況下更有幫助,例如在受影響的地方提供額外的錯誤消息。
@@ -0,0 +1,67 @@
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/lockup-watchdogs.rst
:Translator: Hailong Liu <liu.hailong6@zte.com.cn>
.. _tw_lockup-watchdogs:
=================================================
Softlockup與hardlockup檢測機制(又名:nmi_watchdog)
=================================================
Linux中內核實現了一種用以檢測系統發生softlockup和hardlockup的看門狗機制。
Softlockup是一種會引發系統在內核態中一直循環超過20秒(詳見下面“實現”小節)導致
其他任務沒有機會得到運行的BUG。一旦檢測到'softlockup'發生,默認情況下系統會打
印當前堆棧跟蹤信息並進入鎖定狀態。也可配置使其在檢測到'softlockup'後進入panic
狀態;通過sysctl命令設置“kernel.softlockup_panic”、使用內核啓動參數
“softlockup_panic”(詳見Documentation/admin-guide/kernel-parameters.rst)以及使
能內核編譯選項“BOOTPARAM_SOFTLOCKUP_PANIC”都可實現這種配置。
而'hardlockup'是一種會引發系統在內核態一直循環超過10秒鐘(詳見"實現"小節)導致其
他中斷沒有機會運行的缺陷。與'softlockup'情況類似,除了使用sysctl命令設置
'hardlockup_panic'、使能內核選項“BOOTPARAM_HARDLOCKUP_PANIC”以及使用內核參數
"nmi_watchdog"(詳見:”Documentation/admin-guide/kernel-parameters.rst“)外,一旦檢
測到'hardlockup'默認情況下系統打印當前堆棧跟蹤信息,然後進入鎖定狀態。
這個panic選項也可以與panic_timeout結合使用(這個panic_timeout是通過稍具迷惑性的
sysctl命令"kernel.panic"來設置),使系統在panic指定時間後自動重啓。
實現
====
Softlockup和hardlockup分別建立在hrtimer(高精度定時器)和perf兩個子系統上而實現。
這也就意味着理論上任何架構只要實現了這兩個子系統就支持這兩種檢測機制。
Hrtimer用於週期性產生中斷並喚醒watchdog線程;NMI perf事件則以”watchdog_thresh“
(編譯時默認初始化爲10秒,也可通過”watchdog_thresh“這個sysctl接口來進行配置修改)
爲間隔週期產生以檢測 hardlockups。如果一個CPU在這個時間段內沒有檢測到hrtimer中
斷髮生,'hardlockup 檢測器'(即NMI perf事件處理函數)將會視系統配置而選擇產生內核
警告或者直接panic。
而watchdog線程本質上是一個高優先級內核線程,每調度一次就對時間戳進行一次更新。
如果時間戳在2*watchdog_thresh(這個是softlockup的觸發門限)這段時間都未更新,那麼
"softlocup 檢測器"(內部hrtimer定時器回調函數)會將相關的調試信息打印到系統日誌中,
然後如果系統配置了進入panic流程則進入panic,否則內核繼續執行。
Hrtimer定時器的週期是2*watchdog_thresh/5,也就是說在hardlockup被觸發前hrtimer有
2~3次機會產生時鐘中斷。
如上所述,內核相當於爲系統管理員提供了一個可調節hrtimer定時器和perf事件週期長度
的調節旋鈕。如何通過這個旋鈕爲特定使用場景配置一個合理的週期值要對lockups檢測的
響應速度和lockups檢測開銷這二者之間進行權衡。
默認情況下所有在線cpu上都會運行一個watchdog線程。不過在內核配置了”NO_HZ_FULL“的
情況下watchdog線程默認只會運行在管家(housekeeping)cpu上,而”nohz_full“啓動參數指
定的cpu上則不會有watchdog線程運行。試想,如果我們允許watchdog線程在”nohz_full“指
定的cpu上運行,這些cpu上必須得運行時鐘定時器來激發watchdog線程調度;這樣一來就會
使”nohz_full“保護用戶程序免受內核干擾的功能失效。當然,副作用就是”nohz_full“指定
的cpu即使在內核產生了lockup問題我們也無法檢測到。不過,至少我們可以允許watchdog
線程在管家(non-tickless)核上繼續運行以便我們能繼續正常的監測這些cpus上的lockups
事件。
不論哪種情況都可以通過sysctl命令kernel.watchdog_cpumask來對沒有運行watchdog線程
的cpu集合進行調節。對於nohz_full而言,如果nohz_full cpu上有異常掛住的情況,通過
這種方式打開這些cpu上的watchdog進行調試可能會有所作用。
@@ -0,0 +1,30 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/index.rst
:翻譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
:校譯:
============
監測數據訪問
============
:doc:`DAMON </mm/damon/index>` 允許輕量級的數據訪問監測。使用DAMON,
用戶可以分析他們系統的內存訪問模式,並優化它們。
.. toctree::
:maxdepth: 2
start
usage
reclaim
lru_sort
@@ -0,0 +1,264 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/lru_sort.rst
:翻譯:
臧雷剛 Leigang Zang <zangleigang@hisilicon.com>
:校譯:
==================
基於DAMON的LRU排序
==================
基於DAMON的LRU排序是一個靜態的內核模塊,旨在用於以主動的、輕量級的數據訪問模型
爲基礎的頁面優先級處理的LRU鏈表上,以使得LRU上的數據訪問模型更爲可信。
哪裏需要主動的LRU排序
=====================
在一個大型系統中,以頁爲粒度的訪問檢測會有比較顯著的開銷,LRU通常不會主動去排序,
而是對部分特殊事件進行部分的、響應式的排序,例如:特殊的用戶請求,系統調用或者
內存壓力。這導致,在有些場景下,LRU不能夠完美的作爲一個可信的數據訪問模型,比如
在內存壓力下對目標內存進行回收。
因爲DAMON能夠儘可能準確的識別數據訪問模型,同時只引起用戶指定範圍的開銷,主動的
執行DAMON_LRU_SORT讓LRU變得更爲可信是有益的,而且這隻需要較少和可控的開銷。
這是如何工作的
==============
DAMON_LRU_SORT使用DAMON尋找熱頁(範圍內的頁面訪問頻率高於用戶指定的閾值)和冷頁
(範圍內的頁面在超過用戶指定的時間無訪問),並提高熱頁和降低冷頁在LRU中的優先級。
爲了避免在排序過程佔用更多的CPU計算資源,可以設置一個CPU佔用時間的約束值。在約
束下,分別提升或者降低更多的熱頁和冷頁。系統管理員也可以配置三個內存水位以控制
在何種條件下自動激活或者停止這種機制。
冷熱閾值和CPU約束的默認值是比較保守的。這意味着,在默認參數下,模塊可以廣泛且無
負作用的使用在常見環境中,同時在只消耗一小部分CPU時間的情況下,給有內存壓力的系
統提供一定水平的冷熱識別。
接口:模塊參數
==============
使用此特性,你首先需要確認你的系統中運行的內核在編譯時啓用了
``CONFIG_DAMON_LRU_SORT=y``.
爲了讓系統管理員打開或者關閉並且調節指定的系統,DAMON_LRU_SORT設計了模塊參數。
這意味着,你可以添加 ``damon_lru_sort.<parameter>=<value>`` 到內核的啓動命令行
參數,或者在 ``/sys/modules/damon_lru_sort/parameters/<parameter>`` 寫入正確的
值。
下邊是每個參數的描述
enabled
-------
打開或者關閉DAMON_LRU_SORT.
你可以通過設置這個參數爲 ``Y`` 來打開DAMON_LRU_SORT。設置爲 ``N`` 關閉
DAMON_LRU_SORT。注意,在基於水位的激活的情況下,DAMON_LRU_SORT有可能不會真正去
監測或者做LRU排序。對這種情況,參考下方關於水位的描述。
commit_inputs
-------------
讓DAMON_LRU_SORT再次讀取輸入參數,除了 ``enabled`` 。
在DAMON_LRU_SORT運行時,新的輸入參數默認不會被應用。一旦這個參數被設置爲 ``Y``
,DAMON_LRU_SORT會再次讀取除了 ``enabled`` 之外的參數。讀取完成後,這個參數會被
設置爲 ``N`` 。如果在讀取時發現有無效參數,DAMON_LRU_SORT會被關閉。
hot_thres_access_freq
---------------------
熱點內存區域的訪問頻率閾值,千分比。
如果一個內存區域的訪問頻率大於等於這個值,DAMON_LRU_SORT把這個區域看作熱區,並
在LRU上把這個區域標記爲已訪問,因些在內存壓力下這部分內存不會被回收。默認爲50%。
cold_min_age
------------
用於識別冷內存區域的時間閾值,單位是微秒。
如果一個內存區域在這個時間內未被訪問過,DAMON_LRU_SORT把這個區域看作冷區,並在
LRU上把這個區域標記爲未訪問,因此在內存壓力下這些內存會首先被回收。默認值爲120
秒。
quota_ms
--------
嘗試LRU鏈表排序的時間限制,單位是毫秒。
DAMON_LRU_SORT在一個時間窗口內(quota_reset_interval_ms)內最多嘗試這麼長時間來
對LRU進行排序。這個可以用來作爲CPU計算資源的約束。如果值爲0,則表示無限制。
默認10毫秒。
quota_reset_interval_ms
-----------------------
配額計時重置週期,毫秒。
配額計時重置週期。即,在quota_reset_interval_ms毫秒內,DAMON_LRU_SORT對LRU進行
排序不會超過quota_ms或者quota_sz。
默認1秒。
wmarks_interval
---------------
水位的檢查週期,單位是微秒。
當DAMON_LRU_SORT使能但是由於水位而不活躍時檢查水位前最小的等待時間。默認值5秒。
wmarks_high
-----------
空閒內存高水位,千分比。
如果空閒內存水位高於這個值,DAMON_LRU_SORT停止工作,不做任何事,除了週期性的檢
查水位。默認200(20%)。
wmarks_mid
----------
空閒內存中間水位,千分比。
如果空閒內存水位在這個值與低水位之間,DAMON_LRU_SORT開始工作,開始檢測並對LRU鏈
表進行排序。默認150(15%)。
wmarks_low
----------
空閒內存低水位,千分比。
如果空閒內存小於這個值,DAMON_LRU_SORT不再工作,不做任何事,除了週期性的檢查水
線。默認50(5%)。
sample_interval
---------------
監測的採樣週期,微秒。
DAMON對冷內存監測的採樣週期。更多細節請參考DAMON文檔 (:doc:`usage`) 。默認5
毫秒。
aggr_interval
-------------
監測的收集週期,微秒。
DAMON對冷內存進行收集的時間週期。更多細節請參考DAMON文檔 (:doc:`usage`) 。默認
100毫秒。
min_nr_regions
--------------
最小監測區域數量。
對冷內存區域監測的最小數量。這個值可以作爲監測質量的下限。不過,這個值設置的過
大會增加開銷。更多細節請參考DAMON文檔 (:doc:`usage`) 。默認值爲10。
max_nr_regions
--------------
最大監測區域數量。
對冷內存區域監測的最大數量。這個值可以作爲監測質量的上限。然而,這個值設置的過
低會導致監測結果變差。更多細節請參考DAMON文檔 (:doc:`usage`) 。默認值爲1000。
monitor_region_start
--------------------
目標內存區域的起始物理地址。
DAMON_LRU_SORT要處理的目標內存區域的起始物理地址。默認,使用系統最大內存。
monitor_region_end
------------------
目標內存區域的結束物理地址。
DAMON_LRU_SORT要處理的目標內存區域的結束物理地址。默認,使用系統最大內存。
kdamond_pid
-----------
DAMON線程的PID。
如果DAMON_LRU_SORT是使能的,這個表示任務線程的PID。其它情況爲-1。
nr_lru_sort_tried_hot_regions
-----------------------------
被嘗試進行LRU排序的熱內存區域的數量。
bytes_lru_sort_tried_hot_regions
--------------------------------
被嘗試進行LRU排序的熱內存區域的大小(字節)。
nr_lru_sorted_hot_regions
-------------------------
成功進行LRU排序的熱內存區域的數量。
bytes_lru_sorted_hot_regions
----------------------------
成功進行LRU排序的熱內存區域的大小(字節)。
nr_hot_quota_exceeds
--------------------
熱區域時間約束超過限制的次數。
nr_lru_sort_tried_cold_regions
------------------------------
被嘗試進行LRU排序的冷內存區域的數量。
bytes_lru_sort_tried_cold_regions
---------------------------------
被嘗試進行LRU排序的冷內存區域的大小(字節)。
nr_lru_sorted_cold_regions
--------------------------
成功進行LRU排序的冷內存區域的數量。
bytes_lru_sorted_cold_regions
-----------------------------
成功進行LRU排序的冷內存區域的大小(字節)。
nr_cold_quota_exceeds
---------------------
冷區域時間約束超過限制的次數。
Example
=======
如下是一個運行時的命令示例,使DAMON_LRU_SORT查找訪問頻率超過50%的區域並對其進行
LRU的優先級的提升,同時降低那些超過120秒無人訪問的內存區域的優先級。優先級的處
理被限制在最多1%的CPU以避免DAMON_LRU_SORT消費過多CPU時間。在系統空閒內存超過50%
時DAMON_LRU_SORT停止工作,並在低於40%時重新開始工作。如果DAMON_RECLAIM沒有取得
進展且空閒內存低於20%,再次讓DAMON_LRU_SORT停止工作,以此回退到以LRU鏈表爲基礎
以頁面爲單位的內存回收上。 ::
# cd /sys/modules/damon_lru_sort/parameters
# echo 500 > hot_thres_access_freq
# echo 120000000 > cold_min_age
# echo 10 > quota_ms
# echo 1000 > quota_reset_interval_ms
# echo 500 > wmarks_high
# echo 400 > wmarks_mid
# echo 200 > wmarks_low
# echo Y > enabled
@@ -0,0 +1,229 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/reclaim.rst
:翻譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
:校譯:
===============
基於DAMON的回收
===============
基於DAMON的回收(DAMON_RECLAIM)是一個靜態的內核模塊,旨在用於輕度內存壓力下的主動和輕
量級的回收。它的目的不是取代基於LRU列表的頁面回收,而是有選擇地用於不同程度的內存壓力和要
求。
哪些地方需要主動回收?
======================
在一般的內存超量使用(over-committed systems,虛擬化相關術語)的系統上,主動回收冷頁
有助於節省內存和減少延遲高峯,這些延遲是由直接回收進程或kswapd的CPU消耗引起的,同時只產
生最小的性能下降 [1]_ [2]_ 。
基於空閒頁報告 [3]_ 的內存過度承諾的虛擬化系統就是很好的例子。在這樣的系統中,客戶機
向主機報告他們的空閒內存,而主機則將報告的內存重新分配給其他客戶。因此,系統的內存得到了充
分的利用。然而,客戶可能不那麼節省內存,主要是因爲一些內核子系統和用戶空間應用程序被設計爲
使用盡可能多的內存。然後,客戶機可能只向主機報告少量的內存是空閒的,導致系統的內存利用率下降。
在客戶中運行主動回收可以緩解這個問題。
它是如何工作的?
================
DAMON_RECLAIM找到在特定時間內沒有被訪問的內存區域並分頁。爲了避免它在分頁操作中消耗過多
的CPU,可以配置一個速度限制。在這個速度限制下,它首先分頁出那些沒有被訪問過的內存區域。系
統管理員還可以配置在什麼情況下這個方案應該自動激活和停用三個內存壓力水位。
接口: 模塊參數
==============
要使用這個功能,你首先要確保你的系統運行在一個以 ``CONFIG_DAMON_RECLAIM=y`` 構建的內
核上。
爲了讓系統管理員啓用或禁用它,併爲給定的系統進行調整,DAMON_RECLAIM利用了模塊參數。也就
是說,你可以把 ``damon_reclaim.<parameter>=<value>`` 放在內核啓動命令行上,或者把
適當的值寫入 ``/sys/module/damon_reclaim/parameters/<parameter>`` 文件。
下面是每個參數的描述。
enabled
-------
啓用或禁用DAMON_RECLAIM。
你可以通過把這個參數的值設置爲 ``Y`` 來啓用DAMON_RCLAIM,把它設置爲 ``N`` 可以禁用
DAMON_RECLAIM。注意,由於基於水位的激活條件,DAMON_RECLAIM不能進行真正的監測和回收。
這一點請參考下面關於水位參數的描述。
min_age
-------
識別冷內存區域的時間閾值,單位是微秒。
如果一個內存區域在這個時間或更長的時間內沒有被訪問,DAMON_RECLAIM會將該區域識別爲冷的,
並回收它。
默認爲120秒。
quota_ms
--------
回收的時間限制,以毫秒爲單位。
DAMON_RECLAIM 試圖在一個時間窗口(quota_reset_interval_ms)內只使用到這個時間,以
嘗試回收冷頁。這可以用來限制DAMON_RECLAIM的CPU消耗。如果該值爲零,則該限制被禁用。
默認爲10ms。
quota_sz
--------
回收的內存大小限制,單位爲字節。
DAMON_RECLAIM 收取在一個時間窗口(quota_reset_interval_ms)內試圖回收的內存量,並
使其不超過這個限制。這可以用來限制CPU和IO的消耗。如果該值爲零,則限制被禁用。
默認情況下是128 MiB。
quota_reset_interval_ms
-----------------------
時間/大小配額收取重置間隔,單位爲毫秒。
時間(quota_ms)和大小(quota_sz)的配額的目標重置間隔。也就是說,DAMON_RECLAIM在
嘗試回收‘不’超過quota_ms毫秒或quota_sz字節的內存。
默認爲1秒。
wmarks_interval
---------------
當DAMON_RECLAIM被啓用但由於其水位規則而不活躍時,在檢查水位之前的最小等待時間。
wmarks_high
-----------
高水位的可用內存率(每千字節)。
如果系統的可用內存(以每千字節爲單位)高於這個數值,DAMON_RECLAIM就會變得不活躍,所以
它什麼也不做,只是定期檢查水位。
wmarks_mid
----------
中間水位的可用內存率(每千字節)。
如果系統的空閒內存(以每千字節爲單位)在這個和低水位線之間,DAMON_RECLAIM就會被激活,
因此開始監測和回收。
wmarks_low
----------
低水位的可用內存率(每千字節)。
如果系統的空閒內存(以每千字節爲單位)低於這個數值,DAMON_RECLAIM就會變得不活躍,所以
它除了定期檢查水位外什麼都不做。在這種情況下,系統會退回到基於LRU列表的頁面粒度回收邏輯。
sample_interval
---------------
監測的採樣間隔,單位是微秒。
DAMON用於監測冷內存的採樣間隔。更多細節請參考DAMON文檔 (:doc:`usage`) 。
aggr_interval
-------------
監測的聚集間隔,單位是微秒。
DAMON對冷內存監測的聚集間隔。更多細節請參考DAMON文檔 (:doc:`usage`)。
min_nr_regions
--------------
監測區域的最小數量。
DAMON用於冷內存監測的最小監測區域數。這可以用來設置監測質量的下限。但是,設
置的太高可能會導致監測開銷的增加。更多細節請參考DAMON文檔 (:doc:`usage`) 。
max_nr_regions
--------------
監測區域的最大數量。
DAMON用於冷內存監測的最大監測區域數。這可以用來設置監測開銷的上限值。但是,
設置得太低可能會導致監測質量不好。更多細節請參考DAMON文檔 (:doc:`usage`) 。
monitor_region_start
--------------------
目標內存區域的物理地址起點。
DAMON_RECLAIM將對其進行工作的內存區域的起始物理地址。也就是說,DAMON_RECLAIM
將在這個區域中找到冷的內存區域並進行回收。默認情況下,該區域使用最大系統內存區。
monitor_region_end
------------------
目標內存區域的結束物理地址。
DAMON_RECLAIM將對其進行工作的內存區域的末端物理地址。也就是說,DAMON_RECLAIM將
在這個區域內找到冷的內存區域並進行回收。默認情況下,該區域使用最大系統內存區。
kdamond_pid
-----------
DAMON線程的PID。
如果DAMON_RECLAIM被啓用,這將成爲工作線程的PID。否則,爲-1。
nr_reclaim_tried_regions
------------------------
試圖通過DAMON_RECLAIM回收的內存區域的數量。
bytes_reclaim_tried_regions
---------------------------
試圖通過DAMON_RECLAIM回收的內存區域的總字節數。
nr_reclaimed_regions
--------------------
通過DAMON_RECLAIM成功回收的內存區域的數量。
bytes_reclaimed_regions
-----------------------
通過DAMON_RECLAIM成功回收的內存區域的總字節數。
nr_quota_exceeds
----------------
超過時間/空間配額限制的次數。
例子
====
下面的運行示例命令使DAMON_RECLAIM找到30秒或更長時間沒有訪問的內存區域並“回收”?
爲了避免DAMON_RECLAIM在分頁操作中消耗過多的CPU時間,回收被限制在每秒1GiB以內。
它還要求DAMON_RECLAIM在系統的可用內存率超過50%時不做任何事情,但如果它低於40%時
就開始真正的工作。如果DAMON_RECLAIM沒有取得進展,因此空閒內存率低於20%,它會要求
DAMON_RECLAIM再次什麼都不做,這樣我們就可以退回到基於LRU列表的頁面粒度回收了::
# cd /sys/module/damon_reclaim/parameters
# echo 30000000 > min_age
# echo $((1 * 1024 * 1024 * 1024)) > quota_sz
# echo 1000 > quota_reset_interval_ms
# echo 500 > wmarks_high
# echo 400 > wmarks_mid
# echo 200 > wmarks_low
# echo Y > enabled
.. [1] https://research.google/pubs/pub48551/
.. [2] https://lwn.net/Articles/787611/
.. [3] https://www.kernel.org/doc/html/latest/mm/free_page_reporting.html
@@ -0,0 +1,125 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/start.rst
:翻譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
:校譯:
========
入門指南
========
本文通過演示DAMON的默認用戶空間工具,簡要地介紹瞭如何使用DAMON。請注意,爲了簡潔
起見,本文檔只描述了它的部分功能。更多細節請參考該工具的使用文檔。
`doc <https://github.com/damonitor/damo/blob/next/USAGE.md>`_ .
前提條件
========
內核
----
首先,你要確保你當前系統中跑的內核構建時選定了這個功能選項 ``CONFIG_DAMON_*=y``.
用戶空間工具
------------
在演示中,我們將使用DAMON的默認用戶空間工具,稱爲DAMON Operator(DAMO)。它可以在
https://github.com/damonitor/damo找到。下面的例子假設DAMO在你的$PATH上。當然,但
這並不是強制性的。
因爲DAMO使用了DAMON的sysfs接口(詳情請參考:doc:`usage`),你應該確保
:doc:`sysfs </filesystems/sysfs>` 被掛載。
記錄數據訪問模式
================
下面的命令記錄了一個程序的內存訪問模式,並將監測結果保存到文件中。 ::
$ git clone https://github.com/sjp38/masim
$ cd masim; make; ./masim ./configs/zigzag.cfg &
$ sudo damo record -o damon.data $(pidof masim)
命令的前兩行下載了一個人工內存訪問生成器程序並在後臺運行。生成器將重複地逐一訪問兩個
100 MiB大小的內存區域。你可以用你的真實工作負載來代替它。最後一行要求 ``damo`` 將
訪問模式記錄在 ``damon.data`` 文件中。
將記錄的模式可視化
==================
你可以在heatmap中直觀地看到這種模式,顯示哪個內存區域(X軸)何時被訪問(Y軸)以及訪
問的頻率(數字)。::
$ sudo damo report heats --heatmap stdout
22222222222222222222222222222222222222211111111111111111111111111111111111111100
44444444444444444444444444444444444444434444444444444444444444444444444444443200
44444444444444444444444444444444444444433444444444444444444444444444444444444200
33333333333333333333333333333333333333344555555555555555555555555555555555555200
33333333333333333333333333333333333344444444444444444444444444444444444444444200
22222222222222222222222222222222222223355555555555555555555555555555555555555200
00000000000000000000000000000000000000288888888888888888888888888888888888888400
00000000000000000000000000000000000000288888888888888888888888888888888888888400
33333333333333333333333333333333333333355555555555555555555555555555555555555200
88888888888888888888888888888888888888600000000000000000000000000000000000000000
88888888888888888888888888888888888888600000000000000000000000000000000000000000
33333333333333333333333333333333333333444444444444444444444444444444444444443200
00000000000000000000000000000000000000288888888888888888888888888888888888888400
[...]
# access_frequency: 0 1 2 3 4 5 6 7 8 9
# x-axis: space (139728247021568-139728453431248: 196.848 MiB)
# y-axis: time (15256597248362-15326899978162: 1 m 10.303 s)
# resolution: 80x40 (2.461 MiB and 1.758 s for each character)
你也可以直觀地看到工作集的大小分佈,按大小排序。::
$ sudo damo report wss --range 0 101 10
# <percentile> <wss>
# target_id 18446632103789443072
# avr: 107.708 MiB
0 0 B | |
10 95.328 MiB |**************************** |
20 95.332 MiB |**************************** |
30 95.340 MiB |**************************** |
40 95.387 MiB |**************************** |
50 95.387 MiB |**************************** |
60 95.398 MiB |**************************** |
70 95.398 MiB |**************************** |
80 95.504 MiB |**************************** |
90 190.703 MiB |********************************************************* |
100 196.875 MiB |***********************************************************|
在上述命令中使用 ``--sortby`` 選項,可以顯示工作集的大小是如何按時間順序變化的。::
$ sudo damo report wss --range 0 101 10 --sortby time
# <percentile> <wss>
# target_id 18446632103789443072
# avr: 107.708 MiB
0 3.051 MiB | |
10 190.703 MiB |***********************************************************|
20 95.336 MiB |***************************** |
30 95.328 MiB |***************************** |
40 95.387 MiB |***************************** |
50 95.332 MiB |***************************** |
60 95.320 MiB |***************************** |
70 95.398 MiB |***************************** |
80 95.398 MiB |***************************** |
90 95.340 MiB |***************************** |
100 95.398 MiB |***************************** |
數據訪問模式感知的內存管理
==========================
以下三個命令使每一個大小>=4K的內存區域在你的工作負載中沒有被訪問>=60秒,就會被換掉。 ::
$ echo "#min-size max-size min-acc max-acc min-age max-age action" > test_scheme
$ echo "4K max 0 0 60s max pageout" >> test_scheme
$ damo schemes -c test_scheme <pid of your workload>
@@ -0,0 +1,346 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/usage.rst
:翻譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
:校譯:
========
詳細用法
========
DAMON 爲不同的用戶提供了下面這些接口。
- *DAMON用戶空間工具。*
`這 <https://github.com/damonitor/damo>`_ 爲有這特權的人, 如系統管理員,希望有一個剛好
可以工作的人性化界面。
使用它,用戶可以以人性化的方式使用DAMON的主要功能。不過,它可能不會爲特殊情況進行高度調整。
它同時支持虛擬和物理地址空間的監測。更多細節,請參考它的 `使用文檔
<https://github.com/damonitor/damo/blob/next/USAGE.md>`_。
- *sysfs接口。*
:ref:`這 <sysfs_interface>` 是爲那些希望更高級的使用DAMON的特權用戶空間程序員準備的。
使用它,用戶可以通過讀取和寫入特殊的sysfs文件來使用DAMON的主要功能。因此,你可以編寫和使
用你個性化的DAMON sysfs包裝程序,代替你讀/寫sysfs文件。 `DAMON用戶空間工具
<https://github.com/damonitor/damo>`_ 就是這種程序的一個例子 它同時支持虛擬和物理地址
空間的監測。
- *內核空間編程接口。*
:doc:`這 </mm/damon/api>` 這是爲內核空間程序員準備的。使用它,用戶可以通過爲你編寫內
核空間的DAMON應用程序,最靈活有效地利用DAMON的每一個功能。你甚至可以爲各種地址空間擴展DAMON。
詳細情況請參考接口 :doc:`文件 </mm/damon/api>`。
sysfs接口
=========
DAMON的sysfs接口是在定義 ``CONFIG_DAMON_SYSFS`` 時建立的。它在其sysfs目錄下創建多
個目錄和文件, ``<sysfs>/kernel/mm/damon/`` 。你可以通過對該目錄下的文件進行寫入和
讀取來控制DAMON。
對於一個簡短的例子,用戶可以監測一個給定工作負載的虛擬地址空間,如下所示::
# cd /sys/kernel/mm/damon/admin/
# echo 1 > kdamonds/nr_kdamonds && echo 1 > kdamonds/0/contexts/nr_contexts
# echo vaddr > kdamonds/0/contexts/0/operations
# echo 1 > kdamonds/0/contexts/0/targets/nr_targets
# echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid_target
# echo on > kdamonds/0/state
文件層次結構
------------
DAMON sysfs接口的文件層次結構如下圖所示。在下圖中,父子關係用縮進表示,每個目錄有
``/`` 後綴,每個目錄中的文件用逗號(",")分開。 ::
/sys/kernel/mm/damon/admin
│ kdamonds/nr_kdamonds
│ │ 0/state,pid
│ │ │ contexts/nr_contexts
│ │ │ │ 0/operations
│ │ │ │ │ monitoring_attrs/
│ │ │ │ │ │ intervals/sample_us,aggr_us,update_us
│ │ │ │ │ │ nr_regions/min,max
│ │ │ │ │ targets/nr_targets
│ │ │ │ │ │ 0/pid_target
│ │ │ │ │ │ │ regions/nr_regions
│ │ │ │ │ │ │ │ 0/start,end
│ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ ...
│ │ │ │ │ schemes/nr_schemes
│ │ │ │ │ │ 0/action
│ │ │ │ │ │ │ access_pattern/
│ │ │ │ │ │ │ │ sz/min,max
│ │ │ │ │ │ │ │ nr_accesses/min,max
│ │ │ │ │ │ │ │ age/min,max
│ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms
│ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil
│ │ │ │ │ │ │ watermarks/metric,interval_us,high,mid,low
│ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds
│ │ │ │ │ │ │ tried_regions/
│ │ │ │ │ │ │ │ 0/start,end,nr_accesses,age
│ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ ...
│ │ │ │ ...
│ │ ...
根
--
DAMON sysfs接口的根是 ``<sysfs>/kernel/mm/damon/`` ,它有一個名爲 ``admin`` 的
目錄。該目錄包含特權用戶空間程序控制DAMON的文件。擁有根權限的用戶空間工具或deamons可以
使用這個目錄。
kdamonds/
---------
與監測相關的信息包括請求規格和結果被稱爲DAMON上下文。DAMON用一個叫做kdamond的內核線程
執行每個上下文,多個kdamonds可以並行運行。
在 ``admin`` 目錄下,有一個目錄,即``kdamonds``,它有控制kdamonds的文件存在。在開始
時,這個目錄只有一個文件,``nr_kdamonds``。向該文件寫入一個數字(``N``),就會創建名爲
``0`` 到 ``N-1`` 的子目錄數量。每個目錄代表每個kdamond。
kdamonds/<N>/
-------------
在每個kdamond目錄中,存在兩個文件(``state`` 和 ``pid`` )和一個目錄( ``contexts`` )。
讀取 ``state`` 時,如果kdamond當前正在運行,則返回 ``on`` ,如果沒有運行則返回 ``off`` 。
寫入 ``on`` 或 ``off`` 使kdamond處於狀態。向 ``state`` 文件寫 ``update_schemes_stats`` ,
更新kdamond的每個基於DAMON的操作方案的統計文件的內容。關於統計信息的細節,請參考
:ref:`stats section <sysfs_schemes_stats>`. 將 ``update_schemes_tried_regions`` 寫到
``state`` 文件,爲kdamond的每個基於DAMON的操作方案,更新基於DAMON的操作方案動作的嘗試區域目錄。
將`clear_schemes_tried_regions`寫入`state`文件,清除kdamond的每個基於DAMON的操作方案的動作
嘗試區域目錄。 關於基於DAMON的操作方案動作嘗試區域目錄的細節,請參考:ref:tried_regions 部分
<sysfs_schemes_tried_regions>`。
如果狀態爲 ``on``,讀取 ``pid`` 顯示kdamond線程的pid。
``contexts`` 目錄包含控制這個kdamond要執行的監測上下文的文件。
kdamonds/<N>/contexts/
----------------------
在開始時,這個目錄只有一個文件,即 ``nr_contexts`` 。向該文件寫入一個數字( ``N`` ),就會創
建名爲``0`` 到 ``N-1`` 的子目錄數量。每個目錄代表每個監測背景。目前,每個kdamond只支持
一個上下文,所以只有 ``0`` 或 ``1`` 可以被寫入文件。
contexts/<N>/
-------------
在每個上下文目錄中,存在一個文件(``operations``)和三個目錄(``monitoring_attrs``,
``targets``, 和 ``schemes``)。
DAMON支持多種類型的監測操作,包括對虛擬地址空間和物理地址空間的監測。你可以通過向文件
中寫入以下關鍵詞之一,並從文件中讀取,來設置和獲取DAMON將爲上下文使用何種類型的監測操作。
- vaddr: 監測特定進程的虛擬地址空間
- paddr: 監視系統的物理地址空間
contexts/<N>/monitoring_attrs/
------------------------------
用於指定監測屬性的文件,包括所需的監測質量和效率,都在 ``monitoring_attrs`` 目錄中。
具體來說,這個目錄下有兩個目錄,即 ``intervals`` 和 ``nr_regions`` 。
在 ``intervals`` 目錄下,存在DAMON的採樣間隔(``sample_us``)、聚集間隔(``aggr_us``)
和更新間隔(``update_us``)三個文件。你可以通過寫入和讀出這些文件來設置和獲取微秒級的值。
在 ``nr_regions`` 目錄下,有兩個文件分別用於DAMON監測區域的下限和上限(``min`` 和 ``max`` ),
這兩個文件控制着監測的開銷。你可以通過向這些文件的寫入和讀出來設置和獲取這些值。
關於間隔和監測區域範圍的更多細節,請參考設計文件 (:doc:`/mm/damon/design`)。
contexts/<N>/targets/
---------------------
在開始時,這個目錄只有一個文件 ``nr_targets`` 。向該文件寫入一個數字(``N``),就可以創建
名爲 ``0`` 到 ``N-1`` 的子目錄的數量。每個目錄代表每個監測目標。
targets/<N>/
------------
在每個目標目錄中,存在一個文件(``pid_target``)和一個目錄(``regions``)。
如果你把 ``vaddr`` 寫到 ``contexts/<N>/operations`` 中,每個目標應該是一個進程。你
可以通過將進程的pid寫到 ``pid_target`` 文件中來指定DAMON的進程。
targets/<N>/regions
-------------------
當使用 ``vaddr`` 監測操作集時( ``vaddr`` 被寫入 ``contexts/<N>/operations`` 文
件),DAMON自動設置和更新監測目標區域,這樣就可以覆蓋目標進程的整個內存映射。然而,用戶可
能希望將初始監測區域設置爲特定的地址範圍。
相反,當使用 ``paddr`` 監測操作集時,DAMON不會自動設置和更新監測目標區域( ``paddr``
被寫入 ``contexts/<N>/operations`` 中)。因此,在這種情況下,用戶應該自己設置監測目標
區域。
在這種情況下,用戶可以按照自己的意願明確設置初始監測目標區域,將適當的值寫入該目錄下的文件。
開始時,這個目錄只有一個文件, ``nr_regions`` 。向該文件寫入一個數字(``N``),就可以創
建名爲 ``0`` 到 ``N-1`` 的子目錄。每個目錄代表每個初始監測目標區域。
regions/<N>/
------------
在每個區域目錄中,你會發現兩個文件( ``start`` 和 ``end`` )。你可以通過向文件寫入
和從文件中讀出,分別設置和獲得初始監測目標區域的起始和結束地址。
每個區域不應該與其他區域重疊。 目錄“N”的“結束”應等於或小於目錄“N+1”的“開始”。
contexts/<N>/schemes/
---------------------
對於一版的基於DAMON的數據訪問感知的內存管理優化,用戶通常希望系統對特定訪問模式的內存區
域應用內存管理操作。DAMON從用戶那裏接收這種形式化的操作方案,並將這些方案應用於目標內存
區域。用戶可以通過讀取和寫入這個目錄下的文件來獲得和設置這些方案。
在開始時,這個目錄只有一個文件,``nr_schemes``。向該文件寫入一個數字(``N``),就可以
創建名爲``0``到``N-1``的子目錄的數量。每個目錄代表每個基於DAMON的操作方案。
schemes/<N>/
------------
在每個方案目錄中,存在五個目錄(``access_pattern``、``quotas``、``watermarks``、
``stats`` 和 ``tried_regions``)和一個文件(``action``)。
``action`` 文件用於設置和獲取你想應用於具有特定訪問模式的內存區域的動作。可以寫入文件
和從文件中讀取的關鍵詞及其含義如下。
- ``willneed``: 對有 ``MADV_WILLNEED`` 的區域調用 ``madvise()`` 。
- ``cold``: 對具有 ``MADV_COLD`` 的區域調用 ``madvise()`` 。
- ``pageout``: 爲具有 ``MADV_PAGEOUT`` 的區域調用 ``madvise()`` 。
- ``hugepage``: 爲帶有 ``MADV_HUGEPAGE`` 的區域調用 ``madvise()`` 。
- ``nohugepage``: 爲帶有 ``MADV_NOHUGEPAGE`` 的區域調用 ``madvise()``。
- ``lru_prio``: 在其LRU列表上對區域進行優先排序。
- ``lru_deprio``: 對區域的LRU列表進行降低優先處理。
- ``stat``: 什麼都不做,只計算統計數據
schemes/<N>/access_pattern/
---------------------------
每個基於DAMON的操作方案的目標訪問模式由三個範圍構成,包括以字節爲單位的區域大小、每個
聚合區間的監測訪問次數和區域年齡的聚合區間數。
在 ``access_pattern`` 目錄下,存在三個目錄( ``sz``, ``nr_accesses``, 和 ``age`` ),
每個目錄有兩個文件(``min`` 和 ``max`` )。你可以通過向 ``sz``, ``nr_accesses``, 和
``age`` 目錄下的 ``min`` 和 ``max`` 文件分別寫入和讀取來設置和獲取給定方案的訪問模式。
schemes/<N>/quotas/
-------------------
每個 ``動作`` 的最佳 ``目標訪問模式`` 取決於工作負載,所以不容易找到。更糟糕的是,將某些動作
的方案設置得過於激進會造成嚴重的開銷。爲了避免這種開銷,用戶可以爲每個方案限制時間和大小配額。
具體來說,用戶可以要求DAMON儘量只使用特定的時間(``時間配額``)來應用動作,並且在給定的時間間
隔(``重置間隔``)內,只對具有目標訪問模式的內存區域應用動作,而不使用特定數量(``大小配額``)。
當預計超過配額限制時,DAMON會根據 ``目標訪問模式`` 的大小、訪問頻率和年齡,對找到的內存區域
進行優先排序。爲了進行個性化的優先排序,用戶可以爲這三個屬性設置權重。
在 ``quotas`` 目錄下,存在三個文件(``ms``, ``bytes``, ``reset_interval_ms``)和一個
目錄(``weights``),其中有三個文件(``sz_permil``, ``nr_accesses_permil``, 和
``age_permil``)。
你可以設置以毫秒爲單位的 ``時間配額`` ,以字節爲單位的 ``大小配額`` ,以及以毫秒爲單位的 ``重
置間隔`` ,分別向這三個文件寫入數值。你還可以通過向 ``weights`` 目錄下的三個文件寫入數值來設
置大小、訪問頻率和年齡的優先權,單位爲千分之一。
schemes/<N>/watermarks/
-----------------------
爲了便於根據系統狀態激活和停用每個方案,DAMON提供了一個稱爲水位的功能。該功能接收五個值,稱爲
``度量`` 、``間隔`` 、``高`` 、``中`` 、``低`` 。``度量值`` 是指可以測量的系統度量值,如
自由內存比率。如果系統的度量值 ``高`` 於memoent的高值或 ``低`` 於低值,則該方案被停用。如果
該值低於 ``中`` ,則該方案被激活。
在水位目錄下,存在五個文件(``metric``, ``interval_us``,``high``, ``mid``, and ``low``)
用於設置每個值。你可以通過向這些文件的寫入來分別設置和獲取這五個值。
可以寫入 ``metric`` 文件的關鍵詞和含義如下。
- none: 忽略水位
- free_mem_rate: 系統的自由內存率(千分比)。
``interval`` 應以微秒爲單位寫入。
schemes/<N>/stats/
------------------
DAMON統計每個方案被嘗試應用的區域的總數量和字節數,每個方案被成功應用的區域的兩個數字,以及
超過配額限制的總數量。這些統計數據可用於在線分析或調整方案。
可以通過讀取 ``stats`` 目錄下的文件(``nr_tried``, ``sz_tried``, ``nr_applied``,
``sz_applied``, 和 ``qt_exceeds``))分別檢索這些統計數據。這些文件不是實時更新的,所以
你應該要求DAMON sysfs接口通過在相關的 ``kdamonds/<N>/state`` 文件中寫入一個特殊的關鍵字
``update_schemes_stats`` 來更新統計信息的文件內容。
schemes/<N>/tried_regions/
--------------------------
當一個特殊的關鍵字 ``update_schemes_tried_regions`` 被寫入相關的 ``kdamonds/<N>/state``
文件時,DAMON會在這個目錄下創建從 ``0`` 開始命名的整數目錄。每個目錄包含的文件暴露了關於每個
內存區域的詳細信息,在下一個 :ref:`聚集區間 <sysfs_monitoring_attrs>`,相應的方案的 ``動作``
已經嘗試在這個目錄下應用。這些信息包括地址範圍、``nr_accesses`` 以及區域的 ``年齡`` 。
當另一個特殊的關鍵字 ``clear_schemes_tried_regions`` 被寫入相關的 ``kdamonds/<N>/state``
文件時,這些目錄將被刪除。
tried_regions/<N>/
------------------
在每個區域目錄中,你會發現四個文件(``start``, ``end``, ``nr_accesses``, and ``age``)。
讀取這些文件將顯示相應的基於DAMON的操作方案 ``動作`` 試圖應用的區域的開始和結束地址、``nr_accesses``
和 ``年齡`` 。
用例
~~~~
下面的命令應用了一個方案:”如果一個大小爲[4KiB, 8KiB]的內存區域在[10, 20]的聚合時間間隔內
顯示出每一個聚合時間間隔[0, 5]的訪問量,請分頁該區域。對於分頁,每秒最多隻能使用10ms,而且每
秒分頁不能超過1GiB。在這一限制下,首先分頁出具有較長年齡的內存區域。另外,每5秒鐘檢查一次系統
的可用內存率,當可用內存率低於50%時開始監測和分頁,但如果可用內存率大於60%,或低於30%,則停
止監測。“ ::
# cd <sysfs>/kernel/mm/damon/admin
# # populate directories
# echo 1 > kdamonds/nr_kdamonds; echo 1 > kdamonds/0/contexts/nr_contexts;
# echo 1 > kdamonds/0/contexts/0/schemes/nr_schemes
# cd kdamonds/0/contexts/0/schemes/0
# # set the basic access pattern and the action
# echo 4096 > access_pattern/sz/min
# echo 8192 > access_pattern/sz/max
# echo 0 > access_pattern/nr_accesses/min
# echo 5 > access_pattern/nr_accesses/max
# echo 10 > access_pattern/age/min
# echo 20 > access_pattern/age/max
# echo pageout > action
# # set quotas
# echo 10 > quotas/ms
# echo $((1024*1024*1024)) > quotas/bytes
# echo 1000 > quotas/reset_interval_ms
# # set watermark
# echo free_mem_rate > watermarks/metric
# echo 5000000 > watermarks/interval_us
# echo 600 > watermarks/high
# echo 500 > watermarks/mid
# echo 300 > watermarks/low
請注意,我們強烈建議使用用戶空間的工具,如 `damo <https://github.com/damonitor/damo>`_ ,
而不是像上面那樣手動讀寫文件。以上只是一個例子。
監測結果的監測點
================
DAMON通過一個tracepoint ``damon:damon_aggregated`` 提供監測結果. 當監測開啓時,你可
以記錄追蹤點事件,並使用追蹤點支持工具如perf顯示結果。比如說::
# echo on > monitor_on_DEPRECATED
# perf record -e damon:damon_aggregated &
# sleep 5
# kill 9 $(pidof perf)
# echo off > monitor_on_DEPRECATED
# perf script
@@ -0,0 +1,50 @@
.. include:: ../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/index.rst
:翻譯:
徐鑫 xu xin <xu.xin16@zte.com.cn>
========
內存管理
========
Linux內存管理子系統,顧名思義,是負責系統中的內存管理。它包括了虛擬內存與請求
分頁的實現,內核內部結構和用戶空間程序的內存分配、將文件映射到進程地址空間以
及許多其他很酷的事情。
Linux內存管理是一個具有許多可配置設置的複雜系統, 且這些設置中的大多數都可以通
過 ``/proc`` 文件系統獲得,並且可以使用 ``sysctl`` 進行查詢和調整。這些API接
口被描述在Documentation/admin-guide/sysctl/vm.rst文件和 `man 5 proc`_ 中。
.. _man 5 proc: http://man7.org/linux/man-pages/man5/proc.5.html
Linux內存管理有它自己的術語,如果你還不熟悉它,請考慮閱讀下面參考:
Documentation/admin-guide/mm/concepts.rst.
在此目錄下,我們詳細描述瞭如何與Linux內存管理中的各種機制交互。
.. toctree::
:maxdepth: 1
damon/index
ksm
Todolist:
* concepts
* cma_debugfs
* hugetlbpage
* idle_page_tracking
* memory-hotplug
* nommu-mmap
* numa_memory_policy
* numaperf
* pagemap
* soft-dirty
* swap_numa
* transhuge
* userfaultfd
* zswap
@@ -0,0 +1,199 @@
.. include:: ../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/ksm.rst
:翻譯:
徐鑫 xu xin <xu.xin16@zte.com.cn>
============
內核同頁合併
============
概述
====
KSM是一種能節省內存的數據去重功能,由CONFIG_KSM=y啓用,並在2.6.32版本時被添
加到Linux內核。詳見 ``mm/ksm.c`` 的實現,以及http://lwn.net/Articles/306704
和https://lwn.net/Articles/330589
KSM最初目的是爲了與KVM(即著名的內核共享內存)一起使用而開發的,通過共享虛擬機
之間的公共數據,將更多虛擬機放入物理內存。但它對於任何會生成多個相同數據實例的
應用程序都是很有用的。
KSM的守護進程ksmd會定期掃描那些已註冊的用戶內存區域,查找內容相同的頁面,這些
頁面可以被單個寫保護頁面替換(如果進程以後想要更新其內容,將自動複製)。使用:
引用:`sysfs intraface <ksm_sysfs>` 接口來配置KSM守護程序在單個過程中所掃描的頁
數以及兩個過程之間的間隔時間。
KSM只合並匿名(私有)頁面,從不合並頁緩存(文件)頁面。KSM的合併頁面最初只能被
鎖定在內核內存中,但現在可以就像其他用戶頁面一樣被換出(但當它們被交換回來時共
享會被破壞: ksmd必須重新發現它們的身份並再次合併)。
以madvise控制KSM
================
KSM僅在特定的地址空間區域時運行,即應用程序通過使用如下所示的madvise(2)系統調
用來請求某塊地址成爲可能的合併候選者的地址空間::
int madvise(addr, length, MADV_MERGEABLE)
應用程序當然也可以通過調用::
int madvise(addr, length, MADV_UNMERGEABLE)
來取消該請求,並恢復爲非共享頁面:此時KSM將去除合併在該範圍內的任何合併頁。注意:
這個去除合併的調用可能突然需要的內存量超過實際可用的內存量-那麼可能會出現EAGAIN
失敗,但更可能會喚醒OOM killer。
如果KSM未被配置到正在運行的內核中,則madvise MADV_MERGEABLE 和 MADV_UNMERGEABLE
的調用只會以EINVAL 失敗。如果正在運行的內核是用CONFIG_KSM=y方式構建的,那麼這些
調用通常會成功:即使KSM守護程序當前沒有運行,MADV_MERGEABLE 仍然會在KSM守護程序
啓動時註冊範圍,即使該範圍不能包含KSM實際可以合併的任何頁面,即使MADV_UNMERGEABLE
應用於從未標記爲MADV_MERGEABLE的範圍。
如果一塊內存區域必須被拆分爲至少一個新的MADV_MERGEABLE區域或MADV_UNMERGEABLE區域,
當該進程將超過 ``vm.max_map_count`` 的設定,則madvise可能返回ENOMEM。(請參閱文檔
Documentation/admin-guide/sysctl/vm.rst)。
與其他madvise調用一樣,它們在用戶地址空間的映射區域上使用:如果指定的範圍包含未
映射的間隙(儘管在中間的映射區域工作),它們將報告ENOMEM,如果沒有足夠的內存用於
內部結構,則可能會因EAGAIN而失敗。
KSM守護進程sysfs接口
====================
KSM守護進程可以由``/sys/kernel/mm/ksm/`` 中的sysfs文件控制,所有人都可以讀取,但
只能由root用戶寫入。各接口解釋如下:
pages_to_scan
ksmd進程進入睡眠前要掃描的頁數。
例如, ``echo 100 > /sys/kernel/mm/ksm/pages_to_scan``
默認值:100(該值被選擇用於演示目的)
sleep_millisecs
ksmd在下次掃描前應休眠多少毫秒
例如, ``echo 20 > /sys/kernel/mm/ksm/sleep_millisecs``
默認值:20(該值被選擇用於演示目的)
merge_across_nodes
指定是否可以合併來自不同NUMA節點的頁面。當設置爲0時,ksm僅合併在物理上位
於同一NUMA節點的內存區域中的頁面。這降低了訪問共享頁面的延遲。在有明顯的
NUMA距離上,具有更多節點的系統可能受益於設置該值爲0時的更低延遲。而對於
需要對內存使用量最小化的較小系統來說,設置該值爲1(默認設置)則可能會受
益於更大共享頁面。在決定使用哪種設置之前,您可能希望比較系統在每種設置下
的性能。 ``merge_across_nodes`` 僅當系統中沒有ksm共享頁面時,才能被更改設
置:首先將接口`run` 設置爲2從而對頁進行去合併,然後在修改
``merge_across_nodes`` 後再將‘run’又設置爲1,以根據新設置來重新合併。
默認值:1(如早期的發佈版本一樣合併跨站點)
run
* 設置爲0可停止ksmd運行,但保留合併頁面,
* 設置爲1可運行ksmd,例如, ``echo 1 > /sys/kernel/mm/ksm/run`` ,
* 設置爲2可停止ksmd運行,並且對所有目前已合併的頁進行去合併,但保留可合併
區域以供下次運行。
默認值:0(必須設置爲1才能激活KSM,除非禁用了CONFIG_SYSFS)
use_zero_pages
指定是否應當特殊處理空頁(即那些僅含zero的已分配頁)。當該值設置爲1時,
空頁與內核零頁合併,而不是像通常情況下那樣空頁自身彼此合併。這可以根據
工作負載的不同,在具有着色零頁的架構上可以提高性能。啓用此設置時應小心,
因爲它可能會降低某些工作負載的KSM性能,比如,當待合併的候選頁面的校驗和
與空頁面的校驗和恰好匹配的時候。此設置可隨時更改,僅對那些更改後再合併
的頁面有效。
默認值:0(如同早期版本的KSM正常表現)
max_page_sharing
單個KSM頁面允許的最大共享站點數。這將強制執行重複數據消除限制,以避免涉
及遍歷共享KSM頁面的虛擬映射的虛擬內存操作的高延遲。最小值爲2,因爲新創
建的KSM頁面將至少有兩個共享者。該值越高,KSM合併內存的速度越快,去重
因子也越高,但是對於任何給定的KSM頁面,虛擬映射的最壞情況遍歷的速度也會
越慢。減慢了這種遍歷速度就意味着在交換、壓縮、NUMA平衡和頁面遷移期間,
某些虛擬內存操作將有更高的延遲,從而降低這些虛擬內存操作調用者的響應能力。
其他任務如果不涉及執行虛擬映射遍歷的VM操作,其任務調度延遲不受此參數的影
響,因爲這些遍歷本身是調度友好的。
stable_node_chains_prune_millisecs
指定KSM檢查特定頁面的元數據的頻率(即那些達到過時信息數據去重限制標準的
頁面)單位是毫秒。較小的毫秒值將以更低的延遲來釋放KSM元數據,但它們將使
ksmd在掃描期間使用更多CPU。如果還沒有一個KSM頁面達到 ``max_page_sharing``
標準,那就沒有什麼用。
KSM與MADV_MERGEABLE的工作有效性體現於 ``/sys/kernel/mm/ksm/`` 路徑下的接口:
pages_shared
表示多少共享頁正在被使用
pages_sharing
表示還有多少站點正在共享這些共享頁,即節省了多少
pages_unshared
表示有多少頁是唯一的,但被反覆檢查以進行合併
pages_volatile
表示有多少頁因變化太快而無法放在tree中
full_scans
表示所有可合併區域已掃描多少次
stable_node_chains
達到 ``max_page_sharing`` 限制的KSM頁數
stable_node_dups
重複的KSM頁數
比值 ``pages_sharing/pages_shared`` 的最大值受限制於 ``max_page_sharing``
的設定。要想增加該比值,則相應地要增加 ``max_page_sharing`` 的值。
監測KSM的收益
=============
KSM可以通過合併相同的頁面來節省內存,但也會消耗額外的內存,因爲它需要生成一些rmap_items
來保存每個掃描頁面的簡要rmap信息。其中有些頁面可能會被合併,但有些頁面在被檢查幾次
後可能無法被合併,這些都是無益的內存消耗。
1) 如何確定KSM在全系統範圍內是節省內存還是消耗內存?這裏有一個簡單的近似計算方法供參考::
general_profit =~ pages_sharing * sizeof(page) - (all_rmap_items) *
sizeof(rmap_item);
其中all_rmap_items可以通過對 ``pages_sharing`` 、 ``pages_shared`` 、 ``pages_unshared``
和 ``pages_volatile`` 的求和而輕鬆獲得。
2) 單一進程中KSM的收益也可以通過以下近似的計算得到::
process_profit =~ ksm_merging_pages * sizeof(page) -
ksm_rmap_items * sizeof(rmap_item).
其中ksm_merging_pages顯示在 ``/proc/<pid>/`` 目錄下,而ksm_rmap_items
顯示在 ``/proc/<pid>/ksm_stat`` 。
從應用的角度來看, ``ksm_rmap_items`` 和 ``ksm_merging_pages`` 的高比例意
味着不好的madvise-applied策略,所以開發者或管理員必須重新考慮如何改變madvis策
略。舉個例子供參考,一個頁面的大小通常是4K,而rmap_item的大小在32位CPU架構上分
別是32B,在64位CPU架構上是64B。所以如果 ``ksm_rmap_items/ksm_merging_pages``
的比例在64位CPU上超過64,或者在32位CPU上超過128,那麼應用程序的madvise策略應
該被放棄,因爲ksm收益大約爲零或負值。
監控KSM事件
===========
在/proc/vmstat中有一些計數器,可以用來監控KSM事件。KSM可能有助於節省內存,這是
一種權衡,因爲它可能會在KSM COW或複製中的交換上遭受延遲。這些事件可以幫助用戶評估
是否或如何使用KSM。例如,如果cow_ksm增加得太快,用戶可以減少madvise(, , MADV_MERGEABLE)
的範圍。
cow_ksm
在每次KSM頁面觸發寫時拷貝(COW)時都會被遞增,當用戶試圖寫入KSM頁面時,
我們必須做一個拷貝。
ksm_swpin_copy
在換入時,每次KSM頁被複制時都會被遞增。請注意,KSM頁在換入時可能會被複
制,因爲do_swap_page()不能做所有的鎖,而需要重組一個跨anon_vma的KSM頁。
--
Izik Eidus,
Hugh Dickins, 2009年11月17日。
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,371 @@
.. SPDX-License-Identifier: (GPL-2.0+ OR CC-BY-4.0)
.. 【重分發信息參見本文件結尾】
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/reporting-regressions.rst
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
============
報告迴歸問題
============
“*我們拒絕出現迴歸*”是Linux內核開發的首要規則;Linux的發起者和領軍開發者Linus
Torvalds立下了此規則並確保它被落實。
本文檔描述了這條規則對用戶的意義,以及Linux內核開發模型如何確保解決所有被報告
的迴歸;關於內核開發者如何處理的方面參見 Documentation/process/handling-regressions.rst 。
本文重點(亦即“太長不看”)
==========================
#. 如果某程序在原先的Linux內核上運行良好,但在較新版本上效果更差、或者根本不
能用,那麼你就碰見迴歸問題了。注意,新內核需要使用類似配置編譯;更多相關細
節參見下方。
#. 按照 Documentation/translations/zh_CN/admin-guide/reporting-issues.rst 中
所說的報告你的問題,該文檔已經包含了所有關於迴歸的重要方面,爲了方便起見也
複製到了下面。兩個重點:在報告主題中使用“[REGRESSION]”開頭並抄送或轉發到
`迴歸郵件列表 <https://lore.kernel.org/regressions/>`_
(regressions@lists.linux.dev)。
#. 可選但是建議:在發送或轉發報告時,指明該回歸發生的起點,以便Linux內核迴歸
追蹤機器人“regzbot”可以追蹤此問題::
#regzbot introduced v5.13..v5.14-rc1
與用戶相關的所有Linux內核迴歸細節
=================================
基本重點
--------
什麼是“迴歸”以及什麼是“無迴歸規則”?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果某程序/實例在原先的Linux內核上運行良好,但在較新版本上效果更差、或者根本
不能用,那麼你就碰見迴歸問題了。“無迴歸規則”不允許出現這種情況。如果偶然發
生了,導致問題的開發者應當迅速修復問題。
也就是說,若Linux 5.13中的WiFi驅動程序運行良好,但是在5.14版本上卻不能用、速
度明顯變慢或出現錯誤,那就出現了迴歸。如果某正常工作的應用程序突然在新內核上
出現不穩定,這也是迴歸;這些問題可能是由於procfs、sysfs或Linux提供給用戶空間
軟件的許多其他接口之一的變化。但請記住,前述例子中的5.14需要使用類似於5.13的
配置構建。這可以用 ``make olddefconfig`` 實現,詳細解釋見下。
注意本節第一句話中的“實例”:即使開發者需要遵循“無迴歸”規則,但仍可自由地改
變內核的任何方面,甚至是導出到用戶空間的API或ABI,只要別破壞現有的應用程序或
用例。
還需注意,“無迴歸”規則只限制內核提供給用戶空間的接口。它不適用於內核內部接
口,比如一些外部開發的驅動程序用來插入鉤子到內核的模塊API。
如何報告迴歸?
~~~~~~~~~~~~~~
只需按照 Documentation/translations/zh_CN/admin-guide/reporting-issues.rst 中
所說的報告你的問題,該文檔已經包含了要點。下面幾點概述了一下只在迴歸中重要的
方面:
* 在檢查可加入討論的現有報告時,別忘了搜索 `Linux迴歸郵件列表
<https://lore.kernel.org/regressions/>`_ 和 `regzbot網頁界面
<https://linux-regtracking.leemhuis.info/regzbot/>`_ 。
* 在報告主題的開頭加上“[REGRESSION]”。
* 在你的報告中明確最後一個正常工作的內核版本和首個出問題的版本。如若可能,
用二分法嘗試找出導致迴歸的變更,更多細節見下。
* 記得把報告發到Linux迴歸郵件列表(regressions@lists.linux.dev)。
* 如果通過郵件報告迴歸,請抄送回歸列表。
* 如果你使用某些缺陷追蹤器報告迴歸,請通過郵件轉發已提交的報告到迴歸列表,
並抄送維護者以及出問題的相關子系統的郵件列表。
如果是穩定版或長期支持版系列(如v5.15.3…v5.15.5)的迴歸,請記得抄送
`Linux穩定版郵件列表 <https://lore.kernel.org/stable/>`_ (stable@vger.kernel.org)。
如果你成功地執行了二分,請抄送肇事提交的信息中所有簽了“Signed-off-by:”的人。
在抄送你的報告到列表時,也請記得通知前述的Linux內核迴歸追蹤機器人。只需在郵件
中包含如下片段::
#regzbot introduced: v5.13..v5.14-rc1
Regzbot會就將你的郵件視爲在某個特定版本區間的迴歸報告。上例中即linux v5.13仍
然正常,而Linux 5.14-rc1是首個您遇到問題的版本。如果你執行了二分以查找導致回
歸的提交,請使用指定肇事提交的id代替::
#regzbot introduced: 1f2e3d4c5d
添加這樣的“regzbot命令”對你是有好處的,它會確保報告不會被忽略。如果你省略了
它,Linux內核的迴歸跟蹤者會把你的迴歸告訴regzbot,只要你發送了一個副本到迴歸
郵件列表。但是迴歸跟蹤者只有一個人,有時不得不休息或甚至偶爾享受可以遠離電腦
的時光(聽起來很瘋狂)。因此,依賴此人手動將回歸添加到 `已追蹤且尚未解決的
Linux內核迴歸列表 <https://linux-regtracking.leemhuis.info/regzbot/>`_ 和
regzbot發送的每週迴歸報告,可能會出現延遲。 這樣的延誤會導致Linus Torvalds
在決定“繼續開發還是發佈新版本?”時忽略嚴重的迴歸。
真的修復了所有的迴歸嗎?
~~~~~~~~~~~~~~~~~~~~~~~~
幾乎所有都是,只要引起問題的變更(肇事提交)被可靠定位。也有些迴歸可以不用這
樣,但通常是必須的。
誰需要找出迴歸的根本原因?
~~~~~~~~~~~~~~~~~~~~~~~~~~
受影響代碼區域的開發者應該自行嘗試定位問題所在。但僅靠他們的努力往往是不可
能做到的,很多問題只發生在開發者的無法接觸的其他特定外部環境中——例如特定的
硬件平臺、固件、Linux發行版、系統的配置或應用程序。這就是爲什麼最終往往是報
告者定位肇事提交;有時用戶甚至需要再運行額外測試以查明確切的根本原因。開發
者應該提供建議和可能的幫助,以使普通用戶更容易完成該流程。
如何找到罪魁禍首?
~~~~~~~~~~~~~~~~~~
如 Documentation/translations/zh_CN/admin-guide/reporting-issues.rst (簡要)
和 Documentation/translations/zh_CN/admin-guide/bug-bisect.rst (詳細)中所
述,執行二分。聽起來工作量很大,但大部分情況下很快就能找到罪魁禍首。如果這很
困難或可靠地重現問題很耗時,請考慮與其他受影響的用戶合作,一起縮小搜索範圍。
當出現迴歸時我可以向誰尋求建議?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
發送郵件到迴歸郵件列表(regressions@lists.linux.dev)同時抄送Linux內核的迴歸
跟蹤者(regressions@leemhuis.info);如果問題需要保密處理,可以省略列表。
關於迴歸的更多細節
------------------
“無迴歸規則”的目標是什麼?
~~~~~~~~~~~~~~~~~~~~~~~~~~
用戶應該放心升級內核版本,而不必擔心有程序可能崩潰。這符合內核開發者的利益,
可以使更新有吸引力:他們不希望用戶停留在停止維護或超過一年半的穩定/長期Linux
版本系列上。這也符合所有人的利益,因爲 `那些系列可能含有已知的缺陷、安全問題
或其他後續版本已經修復的問題
<http://www.kroah.com/log/blog/2018/08/24/what-stable-kernel-should-i-use/>`_ 。
此外,內核開發者希望使用戶測試最新的預發行版或常規發行版變得簡單而有吸引力。
這同樣符合所有人的利益,如果新版本出來後很快就有相關報告,會使追蹤和修復問題
更容易。
實際中“無迴歸”規則真的可行嗎?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
這不是句玩笑話,請見Linux創建者和主要開發人員Linus Torvalds在郵件列表中的許
多發言,其中一些在 Documentation/process/handling-regressions.rst 中被引用。
此規則的例外情況極爲罕見;之前當開發者認爲某個特定的情況有必要援引例外時,
基本都被證明錯了。
誰來確保“無迴歸”被落實?
~~~~~~~~~~~~~~~~~~~~~~~~
照看和支撐樹的子系統維護者應該關心這一點——例如,Linus Torvalds之於主線,
Greg Kroah-Hartman等人之於各種穩定/長期系列。
他們都得到了別人的幫助,以確保迴歸報告不會被遺漏。其中之一是Thorsten
Leemhuis,他目前擔任Linux內核的“迴歸跟蹤者”;爲了做好這項工作,他使用了
regzbot——Linux內核迴歸跟蹤機器人。所以這就是爲什麼要抄送或轉發你的報告到
迴歸郵件列表來通知這些人,已經最好在你的郵件中包含“regzbot命令”來立即追蹤它。
迴歸通常多久能修復?
~~~~~~~~~~~~~~~~~~~~
開發者應該儘快修復任何被報告的迴歸,以提供及時爲受影響的用戶提供解決方案,並
防止更多用戶遇到問題;然而,開發人員需要花足夠的時間和注意力確保迴歸修復不會
造成額外的損害。
因此,答案取決於各種因素,如迴歸的影響、存在時長或出現於哪個Linux版本系列。
但最終,大多數的迴歸應該在兩週內修復。
當問題可以通過升級某些軟件解決時,是迴歸嗎?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
基本都是。如果開發人員告訴您其他情況,請諮詢上述迴歸跟蹤者。
當新內核變慢或能耗增加,是迴歸嗎?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
是的,但有一些差別。在微型基準測試中變慢5%不太可能被視爲迴歸,除非它也會對
廣泛基準測試的結果產生超過1%的影響。如果有疑問,請尋求建議。
當更新Linux時外部內核模塊崩潰了,是迴歸嗎?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
不,因爲“無迴歸”規則僅限於Linux內核提供給用戶空間的接口和服務。因此,它不包括
構建或運行外部開發的內核模塊,因爲它們在內核空間中運行與掛進內核使用的內部接
口偶爾會變化。
如何處理安全修復引起的迴歸?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在極爲罕見的情況下,安全問題無法在不引起迴歸的情況下修復;這些修復都被放棄了,
因爲它們終究會引起問題。幸運的是這種兩難境地基本都可以避免,受影響區域的主要
開發者以及Linus Torvalds本人通常都會努力在不引入迴歸的情況下解決安全問題。
如果你仍然面臨此種情況,請查看郵件列表檔案是否有人盡力避免過迴歸。如果沒有,
請報告它;如有疑問,請如上所述尋求建議。
當修復迴歸時不可避免會引入另一個,如何處理?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
很遺憾這種事確實會出現,但幸運的是並不經常出現;如果發生了,受影響代碼區的資
深開發者應當調查該問題以找到避免迴歸的解決方法,至少避免它們的影響。如果你遇
到這樣的情況,如上所述:檢查之前的討論是否有人已經盡了最大努力,如有疑問請尋
求建議。
小提示:如果人們在每個開發週期中定期給出主線預發佈(即v5.15-rc1或-rc3)以供
測試,則可以避免這種情況。爲了更好地解釋,可以設想一個在Linux v5.14和v5.15-rc1
之間集成的更改,該更改導致了迴歸,但同時是應用於5.15-rc1的其他改進的強依賴。
如果有人在5.15發佈之前就發現並報告了這個問題,那麼所有更改都可以直接撤銷,從
而解決迴歸問題。而就在幾天或幾周後,此解決方案變成了不可能,因爲一些軟件可能
已經開始依賴於後續更改之一:撤銷所有更改將導致上述用戶軟件出現迴歸,這是不可
接受的。
若我所依賴的功能在數月前被移除了,是迴歸嗎?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
是的,但如前節所述,通常很難修復此類迴歸。因此需要逐案處理。這也是定期測試主
線預發佈對所有人有好處的另一個原因。
如果我似乎是唯一受影響的人,是否仍適用“無迴歸”規則?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
適用,但僅限於實際使用:Linux開發人員希望能夠自由地取消那些只能在閣樓和博物
館中找到的硬件的支持。
請注意,有時爲了取得進展,不得不出現迴歸——後者也是防止Linux停滯不前所必需
的。因此如果迴歸所影響的用戶很少,那麼爲了他們和其他人更大的利益,還是讓事情
過去吧。尤其是存在某種規避迴歸的簡單方法,例如更新一些軟件或者使用專門爲此目
的創建的內核參數。
迴歸規則是否也適用於staging樹中的代碼?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
不,參見 `適用於所有staging代碼配置選項的幫助文本
<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/staging/Kconfig>`_ ,
其早已聲明::
請注意:這些驅動正在積極開發中,可能無法正常工作,並可能包含會在不久的
將來發生變化的用戶接口。
雖然staging開發人員通常堅持“無迴歸”的原則,但有時爲了取得進展也會違背它。這就
是爲什麼當staging樹的WiFi驅動被基本推倒重來時,有些用戶不得不處理迴歸(通常可
以忽略)。
爲什麼較新版本必須“使用相似配置編譯”?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
因爲Linux內核開發人員有時會集成已知的會導致迴歸的變更,但使它們成爲可選的,並
在內核的默認配置下禁用它們。這一技巧允許進步,否則“無迴歸”規則將導致停滯。
例如,試想一個新的可以阻止惡意軟件濫用某個內核的接口的安全特性,同時又需要滿足
另一個很罕見的應用程序。上述的方法可使兩方都滿意:使用這些應用程序的人可以關閉
新的安全功能,而其他不會遇到麻煩的人可以啓用它。
如何創建與舊內核相似的配置?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
用一個已知良好的內核啓動機器,並用 ``make olddefconfig`` 配置新版的Linux。這
會讓內核的構建腳本從正在運行的內核中摘錄配置文件(“.config”文件),作爲即將編
譯的新版本的基礎配置;同時將所有新的配置選項設爲默認值,以禁用可能導致迴歸的
新功能。
如何報告在預編譯的普通內核中發現的迴歸?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
您需要確保新的內核是用與舊版相似的配置編譯(見上文),因爲那些構建它們的人可
能啓用了一些已知的與新內核不兼容的特性。如有疑問,請向內核的提供者報告問題並
尋求建議。
用“regzbot”追蹤迴歸的更多信息
-----------------------------
什麼是迴歸追蹤?爲啥我需要關心它?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
像“無迴歸”這樣的規則需要有人來確保它們被遵守,否則會被有意/無意打破。歷史證
明瞭這一點對於Linux內核開發也適用。這就是爲什麼Linux內核的迴歸跟蹤者Thorsten
Leemhuis,,和另一些人盡力關注所有的迴歸直到他們解決。他們從未爲此獲得報酬,
因此這項工作是在盡最大努力的基礎上完成的。
爲什麼/如何使用機器人追蹤Linux內核迴歸?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
由於Linux內核開發過程的分佈式和鬆散結構,完全手動跟蹤迴歸已經被證明是相當困難
的。因此Linux內核的迴歸跟蹤者開發了regzbot來促進這項工作,其長期目標是儘可能爲
所有相關人員自動化迴歸跟蹤。
Regzbot通過監視跟蹤的迴歸報告的回覆來工作。此外,它還查找用“Link:”標籤引用這
些報告的補丁;對這些補丁的回覆也會被跟蹤。結合這些數據,可以很好地瞭解當前修
復過程的狀態。
如何查看regzbot當前追蹤的迴歸?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
參見 `regzbot在線 <https://linux-regtracking.leemhuis.info/regzbot/>`_ 。
何種問題可以由regzbot追蹤?
~~~~~~~~~~~~~~~~~~~~~~~~~~~
該機器人只爲了跟蹤迴歸,因此請不要讓regzbot涉及常規問題。但是對於Linux內核的
迴歸跟蹤者來說,讓regzbot跟蹤嚴重問題也可以,如有關掛起、損壞數據或內部錯誤
(Panic、Oops、BUG()、warning…)的報告。
如何修改被追蹤迴歸的相關信息?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在直接或間接回復報告郵件時使用“regzbot命令”即可。最簡單的方法是:在“已發送”文
件夾或郵件列表存檔中找到報告,然後使用郵件客戶端的“全部回覆”功能對其進行回覆。
在該郵件中的獨立段落中可使用以下命令之一(即使用空行將這些命令中的一個或多個與
其餘郵件文本分隔開)。
* 更新迴歸引入起點,例如在執行二分之後::
#regzbot introduced: 1f2e3d4c5d
* 設置或更新標題::
#regzbot title: foo
* 監視討論或bugzilla.kernel.org上有關討論或修復的工單::
#regzbot monitor: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/
#regzbot monitor: https://bugzilla.kernel.org/show_bug.cgi?id=123456789
* 標記一個有更多相關細節的地方,例如有關但主題不同的郵件列表帖子或缺陷追蹤器中的工單::
#regzbot link: https://bugzilla.kernel.org/show_bug.cgi?id=123456789
* 標記迴歸已失效::
#regzbot invalid: wasn't a regression, problem has always existed
Regzbot還支持其他一些主要由開發人員或迴歸追蹤人員使用的命令。命令的更多細節請
參考 `入門指南 <https://gitlab.com/knurd42/regzbot/-/blob/main/docs/getting_started.md>`_
和 `參考手冊 <https://gitlab.com/knurd42/regzbot/-/blob/main/docs/reference.md>`_ 。
..
正文結束
..
如本文件開頭所述,本文以GPL-2.0+或CC-BY-4.0許可發行。如您想僅在CC-BY-4.0許
可下重分發本文,請用“Linux內核開發者”作爲作者,並用如下鏈接作爲來源:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/translations/zh_CN/admin-guide/reporting-regressions.rst
..
注意:本RST文件內容只有在來自Linux內核源代碼時是使用CC-BY-4.0許可的,因爲經
過處理的版本(如經內核的構建系統)可能包含來自使用更嚴格許可證的文件的內容。
@@ -0,0 +1,78 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../process/security-bugs`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
安全缺陷
=========
Linux內核開發人員非常重視安全性。因此我們想知道何時發現了安全漏洞,以便儘快
修復和披露。請向Linux內核安全團隊報告安全漏洞。
聯絡
-----
可以通過電子郵件<security@kernel.org>聯繫Linux內核安全團隊。這是一個安全人員
的私有列表,他們將幫助驗證錯誤報告並開發和發佈修復程序。如果您已經有了一個
修復,請將其包含在您的報告中,這樣可以大大加快進程。安全團隊可能會從區域維護
人員那裏獲得額外的幫助,以理解和修復安全漏洞。
與任何缺陷一樣,提供的信息越多,診斷和修復就越容易。如果您不清楚哪些信息有用,
請查看“Documentation/translations/zh_CN/admin-guide/reporting-issues.rst”中
概述的步驟。任何利用漏洞的攻擊代碼都非常有用,未經報告者同意不會對外發布,除
非已經公開。
請儘可能發送無附件的純文本電子郵件。如果所有的細節都藏在附件裏,那麼就很難對
一個複雜的問題進行上下文引用的討論。把它想象成一個
:doc:`常規的補丁提交 <../process/submitting-patches>` (即使你還沒有補丁):
描述問題和影響,列出復現步驟,然後給出一個建議的解決方案,所有這些都是純文本的。
披露和限制信息
---------------
安全列表不是公開渠道。爲此,請參見下面的協作。
一旦開發出了健壯的補丁,發佈過程就開始了。對公開的缺陷的修復會立即發佈。
儘管我們傾向於在未公開缺陷的修復可用時即發佈補丁,但應報告者或受影響方的請求,
這可能會被推遲到發佈過程開始後的7日內,如果根據缺陷的嚴重性需要更多的時間,
則可額外延長到14天。推遲發佈修復的唯一有效原因是爲了適應QA的邏輯和需要發佈
協調的大規模部署。
雖然可能與受信任的個人共享受限信息以開發修復,但未經報告者許可,此類信息不會
與修復程序一起發佈或發佈在任何其他披露渠道上。這包括但不限於原始錯誤報告和
後續討論(如有)、漏洞、CVE信息或報告者的身份。
換句話說,我們唯一感興趣的是修復缺陷。提交給安全列表的所有其他資料以及對報告
的任何後續討論,即使在解除限制之後,也將永久保密。
協調
------
對敏感缺陷(例如那些可能導致權限提升的缺陷)的修復可能需要與私有郵件列表
<linux-distros@vs.openwall.org>進行協調,以便分發供應商做好準備,在公開披露
上游補丁時發佈一個已修復的內核。發行版將需要一些時間來測試建議的補丁,通常
會要求至少幾天的限制,而供應商更新發布更傾向於週二至週四。若合適,安全團隊
可以協助這種協調,或者報告者可以從一開始就包括linux發行版。在這種情況下,請
記住在電子郵件主題行前面加上“[vs]”,如linux發行版wiki中所述:
<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>。
CVE分配
--------
安全團隊通常不分配CVE,我們也不需要它們來進行報告或修復,因爲這會使過程不必
要的複雜化,並可能耽誤缺陷處理。如果報告者希望在公開披露之前分配一個CVE編號,
他們需要聯繫上述的私有linux-distros列表。當在提供補丁之前已有這樣的CVE編號時,
如報告者願意,最好在提交消息中提及它。
保密協議
---------
Linux內核安全團隊不是一個正式的機構實體,因此無法簽訂任何保密協議。
@@ -0,0 +1,281 @@
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/sysrq.rst
:翻譯:
黃軍華 Junhua Huang <huang.junhua@zte.com.cn>
:校譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
.. _tw_admin-guide_sysrq:
Linux 魔法系統請求鍵駭客
========================
針對 sysrq.c 的文檔說明
什麼是魔法 SysRq 鍵?
~~~~~~~~~~~~~~~~~~~~~
它是一個你可以輸入的具有魔法般的組合鍵。
無論內核在做什麼,內核都會響應 SysRq 鍵的輸入,除非內核完全卡死。
如何使能魔法 SysRq 鍵?
~~~~~~~~~~~~~~~~~~~~~~~
在配置內核時,我們需要設置 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' 爲 'Y'。
當運行一個編譯進 sysrq 功能的內核時,/proc/sys/kernel/sysrq 控制着被
SysRq 鍵調用的功能許可。這個文件的默認值由 CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE
配置符號設定,文件本身默認設置爲 1。以下是 /proc/sys/kernel/sysrq 中可能的
值列表:
- 0 - 完全不使能 SysRq 鍵
- 1 - 使能 SysRq 鍵的全部功能
- >1 - 對於允許的 SysRq 鍵功能的比特掩碼(參見下面更詳細的功能描述)::
2 = 0x2 - 使能對控制檯日誌記錄級別的控制
4 = 0x4 - 使能對鍵盤的控制 (SAK, unraw)
8 = 0x8 - 使能對進程的調試導出等
16 = 0x10 - 使能同步命令
32 = 0x20 - 使能重新掛載只讀
64 = 0x40 - 使能對進程的信號操作 (term, kill, oom-kill)
128 = 0x80 - 允許重啓、斷電
256 = 0x100 - 允許讓所有實時任務變普通任務
你可以通過如下命令把值設置到這個文件中::
echo "number" >/proc/sys/kernel/sysrq
這裏被寫入的 number 可以是 10 進制數,或者是帶着 0x 前綴的 16 進制數。
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必須是以 16 進制數寫入。
注意,``/proc/sys/kernel/sysrq`` 的值隻影響通過鍵盤觸發 SySRq 的調用,對於
通過 ``/proc/sysrq-trigger`` 的任何操作調用都是允許的
(通過具有系統權限的用戶)。
如何使用魔法 SysRq 鍵?
~~~~~~~~~~~~~~~~~~~~~~~
在 x86 架構上
你可以按下鍵盤組合鍵 `ALT-SysRq-<command key>`。
.. note::
一些鍵盤可能沒有標識 'SySRq' 鍵。'SySRq' 鍵也被當做 'Print Screen'鍵。
同時有些鍵盤無法處理同時按下這麼多鍵,因此你可以先按下鍵盤 `Alt` 鍵,
然後按下鍵盤 `SysRq` 鍵,再釋放鍵盤 `SysRq` 鍵,之後按下鍵盤上命令鍵
`<command key>`,最後釋放所有鍵。
在 SPARC 架構上
你可以按下鍵盤組合鍵 `ALT-STOP-<command key>` 。
在串行控制檯(只針對 PC 類型的標準串口)
你可以發一個 ``BREAK`` ,然後在 5 秒內發送一個命令鍵,
發送 ``BREAK`` 兩次將被翻譯爲一個正常的 BREAK 操作。
在 PowerPC 架構上
按下鍵盤組合鍵 `ALT - Print Screen` (或者 `F13`) - `<命令鍵>` 。
`Print Screen` (或者 `F13`) - `<命令鍵>` 或許也能實現。
在其他架構上
如果你知道其他架構的組合鍵,請告訴我,我可以把它們添加到這部分。
在所有架構上
寫一個字符到 /proc/sysrq-trigger 文件,例如::
echo t > /proc/sysrq-trigger
這個命令鍵 `<command key>` 是區分大小寫的。
什麼是命令鍵?
~~~~~~~~~~~~~~
=========== ================================================================
命令鍵 功能
=========== ================================================================
``b`` 將立即重啓系統,不會同步或者卸載磁盤。
``c`` 將執行系統 crash,如果配置了系統 crashdump,將執行 crashdump。
``d`` 顯示所有持有的鎖。
``e`` 發送 SIGTERM 信號給所有進程,除了 init 進程。
``f`` 將調用 oom killer 殺掉一個過度佔用內存的進程,如果什麼任務都沒殺,
也不會 panic。
``g`` kgdb 使用(內核調試器)。
``h`` 將會顯示幫助。(實際上除了這裏列舉的鍵,其他的都將顯示幫助,
但是 ``h`` 容易記住):-)
``i`` 發送 SIGKILL 給所有進程,除了 init 進程。
``j`` 強制性的 “解凍它” - 用於被 FIFREEZE ioctl 操作凍住的文件系統。
``k`` 安全訪問祕鑰(SAK)殺掉在當前虛擬控制檯的所有程序,注意:參考
下面 SAK 節重要論述。
``l`` 顯示所有活動 cpu 的棧回溯。
``m`` 將導出當前內存信息到你的控制檯。
``n`` 用於使所有實時任務變成普通任務。
``o`` 將關閉系統(如果配置和支持的話)。
``p`` 將導出當前寄存器和標誌位到控制檯。
``q`` 將導出每個 cpu 上所有已裝備的高精度定時器(不是完整的
time_list 文件顯示的 timers)和所有時鐘事件設備的詳細信息。
``r`` 關閉鍵盤的原始模式,設置爲轉換模式。
``s`` 將嘗試同步所有的已掛載文件系統。
``t`` 將導出當前所有任務列表和它們的信息到控制檯。
``u`` 將嘗試重新掛載已掛載文件系統爲只讀。
``v`` 強制恢復幀緩存控制檯。
``v`` 觸發 ETM 緩存導出 [ARM 架構特有]
``w`` 導出處於不可中斷狀態(阻塞)的任務。
``x`` 在 ppc/powerpc 架構上用於 xmon 接口。
在 sparc64 架構上用於顯示全局的 PMU(性能監控單元)寄存器。
在 MIPS 架構上導出所有的 tlb 條目。
``y`` 顯示全局 cpu 寄存器 [SPARC-64 架構特有]
``z`` 導出 ftrace 緩存信息
``0``-``9`` 設置控制檯日誌級別,該級別控制什麼樣的內核信息將被打印到你的
控制檯。(比如 ``0`` ,將使得只有緊急信息,像 PANICs or OOPSes
才能到你的控制檯。)
=========== ================================================================
好了,我能用他們做什麼呢?
~~~~~~~~~~~~~~~~~~~~~~~~~~
嗯,當你的 X 服務端或者 svgalib 程序崩潰,unraw(r) 非原始模式命令鍵是非常
方便的。
sak(k)(安全訪問祕鑰)在你嘗試登陸的同時,又想確保當前控制檯沒有可以獲取你的
密碼的特洛伊木馬程序運行時是有用的。它會殺掉給定控制檯的所有程序,這樣你
就可以確認當前的登陸提示程序是實際來自 init 進程的程序,而不是某些特洛伊
木馬程序。
.. important::
在其實際的形式中,在兼容 C2 安全標準的系統上,它不是一個真正的 SAK,
它也不應該誤認爲此。
似乎其他人發現其可以作爲(系統終端聯機鍵)當你想退出一個程序,
同時不會讓你切換控制檯的方法。(比如,X 服務端或者 svgalib 程序)
``reboot(b)`` 是個好方法,當你不能關閉機器時,它等同於按下"復位"按鈕。
``crash(c)`` 可以用於手動觸發一個 crashdump,當系統卡住時。
注意當 crashdump 機制不可用時,這個只是觸發一個內核 crash。
``sync(s)`` 在拔掉可移動介質之前,或者在使用不提供優雅關機的
救援 shell 之後很方便 -- 它將確保你的數據被安全地寫入磁盤。注意,在你看到
屏幕上出現 "OK" 和 "Done" 之前,同步還沒有發生。
``umount(u)`` 可以用來標記文件系統正常卸載,從正在運行的系統角度來看,它們將
被重新掛載爲只讀。這個重新掛載動作直到你看到 "OK" 和 "Done" 信息出現在屏幕上
纔算完成。
日誌級別 ``0`` - ``9`` 用於當你的控制檯被大量的內核信息衝擊,你不想看見的時候。
選擇 ``0`` 將禁止除了最緊急的內核信息外的所有的內核信息輸出到控制檯。(但是如果
syslogd/klogd 進程是運行的,它們仍將被記錄。)
``term(e)`` 和 ``kill(i)`` 用於當你有些有點失控的進程,你無法通過其他方式殺掉
它們的時候,特別是它正在創建其他進程。
"just thaw ``it(j)`` " 用於當你的系統由於一個 FIFREEZE ioctl 調用而產生的文件
系統凍結,而導致的不響應時。
有的時候 SysRq 鍵在使用它之後,看起來像是“卡住”了,我能做些什麼?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
這也會發生在我這,我發現輕敲鍵盤兩側的 shift、alt 和 control 鍵,然後再次敲擊
一個無效的 SysRq 鍵序列可以解決問題。(比如,像鍵盤組合鍵 `alt-sysrq-z` )
切換到另一個虛擬控制檯(鍵盤操作 `ALT+Fn` ),然後再切回來應該也有幫助。
我敲擊了 SysRq 鍵,但像是什麼都沒發生,發生了什麼錯誤?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
有一些鍵盤對於 SysRq 鍵設置了不同的鍵值,而不是提前定義的 99
(查看在 ``include/uapi/linux/input-event-codes.h`` 文件中 ``KEY_SYSRQ`` 的定義)
或者就根本沒有 SysRq 鍵。在這些場景下,執行 ``showkey -s`` 命令來找到一個合適
的掃描碼序列,然後使用 ``setkeycodes <sequence> 99`` 命令映射這個序列值到通用
的 SysRq 鍵編碼上(比如 ``setkeycodes e05b 99`` )。最好將這個命令放在啓動腳本
中。
哦,順便說一句,你十秒鐘不輸入任何東西就將退出 “showkey”。
我想添加一個 SysRq 鍵事件到一個模塊中,如何去做呢?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
爲了註冊一個基礎函數到這個表中,首先你必須包含 ``include/linux/sysrq.h`` 頭
文件,這個頭文件定義了你所需要的所有東西。然後你必須創建一個 ``sysrq_key_op``
結構體,然後初始化它,使用如下內容,A) 你將使用的這個鍵的處理函數, B) 一個
help_msg 字符串,在 SysRq 鍵打印幫助信息時將打印出來,C) 一個 action_msg 字
符串,就在你的處理函數調用前打印出來。你的處理函數必須符合在 'sysrq.h' 文件中
的函數原型。
在 ``sysrq_key_op`` 結構體被創建後,你可以調用內核函數
``register_sysrq_key(int key, const struct sysrq_key_op *op_p);``,
該函數在表中的 'key' 對應位置內容是空的情況下,將通過 ``op_p`` 指針註冊這個操作
函數到表中 'key' 對應位置上。在模塊卸載的時候,你必須調用
``unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)`` 函數,該函數
只有在當前該鍵對應的處理函數被註冊到了 'key' 對應位置時,纔會移除 'op_p' 指針
對應的鍵值操作函數。這是爲了防止在你註冊之後,該位置被改寫的情況。
魔法 SysRq 鍵系統的工作原理是將鍵對應操作函數註冊到鍵的操作查找表,
該表定義在 'drivers/tty/sysrq.c' 文件中。
該鍵表有許多在編譯時候就註冊進去的操作函數,但是是可變的。
並且有兩個函數作爲操作該表的接口被導出::
register_sysrq_key 和 unregister_sysrq_key.
當然,永遠不要在表中留下無效指針,即,當你的模塊存在調用 register_sysrq_key()
函數,它一定要調用 unregister_sysrq_key() 來清除它使用過的 SysRq 鍵表條目。
表中的空指針是安全的。:)
如果對於某種原因,在 handle_sysrq 調用的處理函數中,你認爲有必要調用
handle_sysrq 函數時,你必須意識到當前你處於一個鎖中(你同時也處於一箇中斷處理
函數中,這意味着不能睡眠)。所以這時你必須使用 ``__handle_sysrq_nolock`` 替代。
當我敲擊一個 SysRq 組合鍵時,只有標題打印出現在控制檯?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SysRq 鍵的輸出和所有其他控制檯輸出一樣,受制於控制檯日誌級別控制。
這意味着,如果內核以發行版內核中常見的 "quiet" 方式啓動,則輸出可能不會出現在實際
的控制檯上,即使它會出現在 dmesg 緩存中,也可以通過 dmesg 命令和 ``/proc/kmsg``
文件的消費訪問到。作爲一個特例,來自 sysrq 命令的標題行將被傳遞給所有控制檯
使用者,就好像當前日誌級別是最大的一樣。如果只發出標題頭,則幾乎可以肯定內核日誌
級別太低。如果你需要控制檯上的輸出,那麼你將需要臨時提高控制檯日誌級別,通過使用
鍵盤組合鍵 `alt-sysrq-8` 或者::
echo 8 > /proc/sysrq-trigger
在觸發了你感興趣的 SysRq 鍵命令後,記得恢復日誌級別到正常情況。
我有很多問題時,可以請教誰?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
請教在內核郵件列表上的人,郵箱:
linux-kernel@vger.kernel.org
致謝
~~~~
- Mydraal <vulpyne@vulpyne.net> 撰寫了該文件
- Adam Sulmicki <adam@cfar.umd.edu> 進行了更新
- Jeremy M. Dolan <jmd@turbogeek.org> 在 2001/01/28 10:15:59 進行了更新
- Crutcher Dunnavant <crutcher+kernel@datastacks.com> 添加鍵註冊部分
@@ -0,0 +1,161 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: :doc:`../../../admin-guide/tainted-kernels`
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
受污染的內核
-------------
當發生一些在稍後調查問題時可能相關的事件時,內核會將自己標記爲“受污染
(tainted)”的。不用太過擔心,大多數情況下運行受污染的內核沒有問題;這些信息
主要在有人想調查某個問題時纔有意義的,因爲問題的真正原因可能是導致內核受污染
的事件。這就是爲什麼來自受污染內核的缺陷報告常常被開發人員忽略,因此請嘗試用
未受污染的內核重現問題。
請注意,即使在您消除導致污染的原因(亦即卸載專有內核模塊)之後,內核仍將保持
污染狀態,以表示內核仍然不可信。這也是爲什麼內核在注意到內部問題(“kernel
bug”)、可恢復錯誤(“kernel oops”)或不可恢復錯誤(“kernel panic”)時會打印
受污染狀態,並將有關此的調試信息寫入日誌 ``dmesg`` 輸出。也可以通過
``/proc/`` 中的文件在運行時檢查受污染的狀態。
BUG、Oops或Panics消息中的污染標誌
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在頂部以“CPU:”開頭的一行中可以找到受污染的狀態;內核是否受到污染和原因會顯示
在進程ID(“PID:”)和觸發事件命令的縮寫名稱(“Comm:”)之後::
BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
Oops: 0002 [#1] SMP PTI
CPU: 0 PID: 4424 Comm: insmod Tainted: P W O 4.20.0-0.rc6.fc30 #1
Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
RIP: 0010:my_oops_init+0x13/0x1000 [kpanic]
[...]
如果內核在事件發生時沒有被污染,您將在那裏看到“Not-tainted:”;如果被污染,那
麼它將是“Tainted:”以及字母或空格。在上面的例子中,它看起來是這樣的::
Tainted: P W O
下表解釋了這些字符的含義。在本例中,由於加載了專有模塊( ``P`` ),出現了
警告( ``W`` ),並且加載了外部構建的模塊( ``O`` ),所以內核早些時候受到
了污染。要解碼其他字符,請使用下表。
解碼運行時的污染狀態
~~~~~~~~~~~~~~~~~~~~~
在運行時,您可以通過讀取 ``cat /proc/sys/kernel/tainted`` 來查詢受污染狀態。
如果返回 ``0`` ,則內核沒有受到污染;任何其他數字都表示受到污染的原因。解碼
這個數字的最簡單方法是使用腳本 ``tools/debugging/kernel-chktaint`` ,您的
發行版可能會將其作爲名爲 ``linux-tools`` 或 ``kernel-tools`` 的包的一部分提
供;如果沒有,您可以從
`git.kernel.org <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/tools/debugging/kernel-chktaint>`_
網站下載此腳本並用 ``sh kernel-chktaint`` 執行,它會在上面引用的日誌中有類似
語句的機器上打印這樣的內容::
Kernel is Tainted for following reasons:
* Proprietary module was loaded (#0)
* Kernel issued warning (#9)
* Externally-built ('out-of-tree') module was loaded (#12)
See Documentation/admin-guide/tainted-kernels.rst in the Linux kernel or
https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html for
a more details explanation of the various taint flags.
Raw taint value as int/string: 4609/'P W O '
你也可以試着自己解碼這個數字。如果內核被污染的原因只有一個,那麼這很簡單,
在本例中您可以通過下表找到數字。如果你需要解碼有多個原因的數字,因爲它是一
個位域(bitfield),其中每個位表示一個特定類型的污染的存在或不存在,最好讓
前面提到的腳本來處理。但是如果您需要快速看一下,可以使用這個shell命令來檢查
設置了哪些位::
$ for i in $(seq 18); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done
污染狀態代碼表
~~~~~~~~~~~~~~~
=== ===== ====== ========================================================
位 日誌 數字 內核被污染的原因
=== ===== ====== ========================================================
0 G/P 1 已加載專用模塊
1 _/F 2 模塊被強制加載
2 _/S 4 內核運行在不合規範的系統上
3 _/R 8 模塊被強制卸載
4 _/M 16 處理器報告了機器檢測異常(MCE)
5 _/B 32 引用了錯誤的頁或某些意外的頁標誌
6 _/U 64 用戶空間應用程序請求的污染
7 _/D 128 內核最近死機了,即曾出現OOPS或BUG
8 _/A 256 ACPI表被用戶覆蓋
9 _/W 512 內核發出警告
10 _/C 1024 已加載staging驅動程序
11 _/I 2048 已應用平臺固件缺陷的解決方案
12 _/O 4096 已加載外部構建(“樹外”)模塊
13 _/E 8192 已加載未簽名的模塊
14 _/L 16384 發生軟鎖定
15 _/K 32768 內核已實時打補丁
16 _/X 65536 備用污染,爲發行版定義並使用
17 _/T 131072 內核是用結構隨機化插件構建的
=== ===== ====== ========================================================
注:字符 ``_`` 表示空白,以便於閱讀表。
污染的更詳細解釋
~~~~~~~~~~~~~~~~~
0) ``G`` 加載的所有模塊都有GPL或兼容許可證, ``P`` 加載了任何專有模塊。
沒有MODULE_LICENSE(模塊許可證)或MODULE_LICENSE未被insmod認可爲GPL
兼容的模塊被認爲是專有的。
1) ``F`` 任何模塊被 ``insmod -f`` 強制加載, ``' '`` 所有模塊正常加載。
2) ``S`` 內核運行在不合規範的處理器或系統上:硬件已運行在不受支持的配置中,
因此無法保證正確執行。內核將被污染,例如:
- 在x86上:PAE是通過intel CPU(如Pentium M)上的forcepae強制執行的,這些
CPU不報告PAE,但可能有功能實現,SMP內核在非官方支持的SMP Athlon CPU上
運行,MSR被暴露到用戶空間中。
- 在arm上:在某些CPU(如Keystone 2)上運行的內核,沒有啓用某些內核特性。
- 在arm64上:CPU之間存在不匹配的硬件特性,引導加載程序以不同的模式引導CPU。
- 某些驅動程序正在被用在不受支持的體系結構上(例如x86_64以外的其他系統
上的scsi/snic,非x86/x86_64/itanium上的scsi/ips,已經損壞了arm64上
irqchip/irq-gic的固件設置…)。
3) ``R`` 模塊被 ``rmmod -f`` 強制卸載, ``' '`` 所有模塊都正常卸載。
4) ``M`` 任何處理器報告了機器檢測異常, ``' '`` 未發生機器檢測異常。
5) ``B`` 頁面釋放函數發現錯誤的頁面引用或某些意外的頁面標誌。這表示硬件問題
或內核錯誤;日誌中應該有其他信息指示發生此污染的原因。
6) ``U`` 用戶或用戶應用程序特意請求設置受污染標誌,否則應爲 ``' '`` 。
7) ``D`` 內核最近死機了,即出現了OOPS或BUG。
8) ``A`` ACPI表被重寫。
9) ``W`` 內核之前已發出過警告(儘管有些警告可能會設置更具體的污染標誌)。
10) ``C`` 已加載staging驅動程序。
11) ``I`` 內核正在處理平臺固件(BIOS或類似軟件)中的嚴重錯誤。
12) ``O`` 已加載外部構建(“樹外”)模塊。
13) ``E`` 在支持模塊簽名的內核中加載了未簽名的模塊。
14) ``L`` 系統上先前發生過軟鎖定。
15) ``K`` 內核已經實時打了補丁。
16) ``X`` 備用污染,由Linux發行版定義和使用。
17) ``T`` 內核構建時使用了randstruct插件,它可以有意生成非常不尋常的內核結構
佈局(甚至是性能病態的佈局),這在調試時非常有用。於構建時設置。
@@ -0,0 +1,174 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/unicode.rst
:譯者:
吳想成 Wu XiangCheng <bobwxc@email.cn>
胡皓文 Hu Haowen <2023002089@link.tyut.edu.cn>
Unicode(統一碼)支持
======================
(英文版)上次更新:2005-01-17,版本號 1.4
此文檔由H. Peter Anvin <unicode@lanana.org>管理,是Linux註冊名稱與編號管理局
(Linux Assigned Names And Numbers Authority,LANANA)項目的一部分。
現行版本請見:
http://www.lanana.org/docs/unicode/admin-guide/unicode.rst
簡介
-----
Linux內核代碼已被重寫以使用Unicode來將字符映射到字體。下載一個Unicode到字體
(Unicode-to-font)表,八位字符集與UTF-8模式都將改用此字體來顯示。
這微妙地改變了八位字符表的語義。現在的四個字符表是:
=============== =============================== ================
映射代號 映射名稱 Escape代碼 (G0)
=============== =============================== ================
LAT1_MAP Latin-1 (ISO 8859-1) ESC ( B
GRAF_MAP DEC VT100 pseudographics ESC ( 0
IBMPC_MAP IBM code page 437 ESC ( U
USER_MAP User defined ESC ( K
=============== =============================== ================
特別是 ESC ( U 不再是“直通字體”,因爲字體可能與IBM字符集完全不同。
例如,即使加載了一個Latin-1字體,也允許使用塊圖形(block graphics)。
請注意,儘管這些代碼與ISO 2022類似,但這些代碼及其用途都與ISO 2022不匹配;
Linux有兩個八位代碼(G0和G1),而ISO 2022有四個七位代碼(G0-G3)。
根據Unicode標準/ISO 10646,U+F000到U+F8FF被保留用於操作系統範圍內的分配
(Unicode標準將其稱爲“團體區域(Corporate Zone)”,因爲這對於Linux是不準確
的,所以我們稱之爲“Linux區域”)。選擇U+F000作爲起點,因爲它允許直接映射
區域以2的大倍數開始(以防需要1024或2048個字符的字體)。這就留下U+E000到
U+EFFF作爲最終用戶區。
[v1.2]:Unicodes範圍從U+F000到U+F7FF已經被硬編碼爲直接映射到加載的字體,
繞過了翻譯表。用戶定義的映射現在默認爲U+F000到U+F0FF,模擬前述行爲。實際上,
此範圍可能較短;例如,vgacon只能處理256字符(U+F000..U+F0FF)或512字符
(U+F000..U+F1FF)字體。
Linux 區域中定義的實際字符
---------------------------
此外,還定義了Unicode 1.1.4中不存在的以下字符;這些字符由DEC VT圖形映射使用。
[v1.2]此用法已過時,不應再使用;請參見下文。
====== ======================================
U+F800 DEC VT GRAPHICS HORIZONTAL LINE SCAN 1
U+F801 DEC VT GRAPHICS HORIZONTAL LINE SCAN 3
U+F803 DEC VT GRAPHICS HORIZONTAL LINE SCAN 7
U+F804 DEC VT GRAPHICS HORIZONTAL LINE SCAN 9
====== ======================================
DEC VT220使用6x10字符矩陣,這些字符在DEC VT圖形字符集中形成一個平滑的過渡。
我省略了掃描5行,因爲它也被用作塊圖形字符,因此被編碼爲U+2500 FORMS LIGHT
HORIZONTAL。
[v1.3]:這些字符已正式添加到Unicode 3.2.0中;它們在U+23BA、U+23BB、U+23BC、
U+23BD處添加。Linux現在使用新值。
[v1.2]:添加了以下字符來表示常見的鍵盤符號,這些符號不太可能被添加到Unicode
中,因爲它們非常討厭地取決於特定供應商。當然,這是糟糕設計的一個好例子。
====== ======================================
U+F810 KEYBOARD SYMBOL FLYING FLAG
U+F811 KEYBOARD SYMBOL PULLDOWN MENU
U+F812 KEYBOARD SYMBOL OPEN APPLE
U+F813 KEYBOARD SYMBOL SOLID APPLE
====== ======================================
克林貢(Klingon)語支持
------------------------
1996年,Linux是世界上第一個添加對人工語言克林貢支持的操作系統,克林貢是由
Marc Okrand爲《星際迷航》電視連續劇創造的。這種編碼後來被徵募Unicode註冊表
(ConScript Unicode Registry,CSUR)採用,並建議(但最終被拒絕)納入Unicode
平面一。不過,它仍然是Linux區域中的Linux/CSUR私有分配。
這種編碼已經得到克林貢語言研究所(Klingon Language Institute)的認可。
有關更多信息,請聯繫他們:
http://www.kli.org/
由於Linux CZ開頭部分的字符大多是dingbats/symbols/forms類型,而且這是一種
語言,因此根據標準Unicode慣例,我將它放置在16單元的邊界上。
.. note::
這個範圍現在由徵募Unicode註冊表正式管理。規範性引用文件爲:
https://www.evertype.com/standards/csur/klingon.html
克林貢語有一個26個字符的字母表,一個10位數的位置數字書寫系統,從左到右
,從上到下書寫。
克林貢字母的幾種字形已經被提出。但是由於這組符號看起來始終是一致的,只有實際
的形狀不同,因此按照標準Unicode慣例,這些差異被認爲是字體變體。
====== =======================================================
U+F8D0 KLINGON LETTER A
U+F8D1 KLINGON LETTER B
U+F8D2 KLINGON LETTER CH
U+F8D3 KLINGON LETTER D
U+F8D4 KLINGON LETTER E
U+F8D5 KLINGON LETTER GH
U+F8D6 KLINGON LETTER H
U+F8D7 KLINGON LETTER I
U+F8D8 KLINGON LETTER J
U+F8D9 KLINGON LETTER L
U+F8DA KLINGON LETTER M
U+F8DB KLINGON LETTER N
U+F8DC KLINGON LETTER NG
U+F8DD KLINGON LETTER O
U+F8DE KLINGON LETTER P
U+F8DF KLINGON LETTER Q
- Written <q> in standard Okrand Latin transliteration
U+F8E0 KLINGON LETTER QH
- Written <Q> in standard Okrand Latin transliteration
U+F8E1 KLINGON LETTER R
U+F8E2 KLINGON LETTER S
U+F8E3 KLINGON LETTER T
U+F8E4 KLINGON LETTER TLH
U+F8E5 KLINGON LETTER U
U+F8E6 KLINGON LETTER V
U+F8E7 KLINGON LETTER W
U+F8E8 KLINGON LETTER Y
U+F8E9 KLINGON LETTER GLOTTAL STOP
U+F8F0 KLINGON DIGIT ZERO
U+F8F1 KLINGON DIGIT ONE
U+F8F2 KLINGON DIGIT TWO
U+F8F3 KLINGON DIGIT THREE
U+F8F4 KLINGON DIGIT FOUR
U+F8F5 KLINGON DIGIT FIVE
U+F8F6 KLINGON DIGIT SIX
U+F8F7 KLINGON DIGIT SEVEN
U+F8F8 KLINGON DIGIT EIGHT
U+F8F9 KLINGON DIGIT NINE
U+F8FD KLINGON COMMA
U+F8FE KLINGON FULL STOP
U+F8FF KLINGON SYMBOL FOR EMPIRE
====== =======================================================
其他虛構和人工字母
-------------------
自從分配了克林貢Linux Unicode塊之後,John Cowan <jcowan@reutershealth.com>
和 Michael Everson <everson@evertype.com> 建立了一個虛構和人工字母的註冊表。
徵募Unicode註冊表請訪問:
https://www.evertype.com/standards/csur/
所使用的範圍位於最終用戶區域的低端,因此無法進行規範化分配,但建議希望對虛構
字母進行編碼的人員使用這些代碼,以實現互操作性。對於克林貢語,CSUR採用了Linux
編碼。CSUR的人正在推動將Tengwar和Cirth添加到Unicode平面一;將克林貢添加到
Unicode平面一被拒絕,因此上述編碼仍然是官方的。