模塊化的Kernel
現在我們隊Kernel是做什么的已經有了一些了解,讓我們再來簡單看下它的物理組成。早期版本的Linux Kernel是整體式的,也就是說所有的部件都靜態地連接成一個(很大的)執行文件。
相比較而言,現在的Linux Kernel是模塊化的:許多功能包含在模塊內,然后動態地載入kernel中。這使得kernel的內核很小,而且在運行kernel時可以不必reboot就能載入和替代模塊。
Kernel的內核在boot time時從位于/boot 目錄的一個文件加載進存儲中,通常這個/boot 目錄會被叫做KERNELVERSION,KERNELVERSION與kernel版本有關。(如果你想知道你的kernel版本是什么,運行命令行顯示系統信息-r。)kernel的模塊位于目錄/lib/modules/KERNELVERSION之下,所有的組件都會在kernel安裝時被拷貝。
管理模塊
大部分情況下,Linux管理它的模塊不需要你的幫忙,但是如果必要的時候有命令行可以來手動檢查和管理模塊。比如,為了查清楚當前到底哪個模塊在載入kernel。這里有一個輸出的例子:
# lsmod
pcspkr????????????? 4224? 0?
hci_usb??????????? 18204? 2?
psmouse??????????? 38920? 0?
bluetooth????????? 55908? 7 rfcomm,l2cap,hci_usb
yenta_socket?????? 27532? 5?
rsrc_nonstatic???? 14080? 1 yenta_socket
isofs????????????? 36284? 0?
輸出的內容包括:模塊的名字、大小、使用次數和依賴于它的模塊列表。使用次數對防止卸載當前活躍的模塊非常總要。Linux只允許使用次數為零的模塊被移除。
你可以使用modprobe來手動加載和卸載模塊,(還有兩個命令行叫做insmod和rmmod,但modprobe更易于使用因為它自動移除了模塊依賴)。比如lsmod的輸出在我們的電腦上顯示了一個名叫isofs的卸載模塊,它的使用次數是零而且沒有依賴模塊,(isofs是一個模塊,它支持CD上使用的ISO系統文件格式)這種情況下,kernel會允許我們卸載模塊:
# modprobe -r isofs
現在,isofs不再顯示在Ismod的輸出中,kernel由此節省了36,284字節的存儲。如果你放入CD并且讓它自動安裝,kernel將自動重新載入isofs模塊,而且isofs的使用次數增加到1次。如果這時候你還試圖移除模塊,就不會成功了因為它正在被使用:
# modprobe -r isofs?
FATAL: Module isofs is in use.
????
Lsmod只是列出了當前被載入的模塊,modprobe則將列出所有可用的模塊,它實際上輸出了/lib/modules/KERNELVERSION目錄下所有的模塊,名單會很長!
實際上,使用modprobe來手動加載一個模塊并不常見,但確實可以通過modprobe命令行來對模塊設置參數,例如:
# modprobe usbcore blinkenlights=1
我們并不是在創建blinkenlights,而是usbcore模塊的實參數。
那么如何知道一個模塊會接受什么參數呢?一個比較好的方法是使用modinfo命令,它列出了關于模塊的種種信息。這里有一個關于模塊snd-hda-intel的例子
# modinfo snd-hda-intel?
filename:?????? /lib/modules/2.6.20-16-generic/kernel/sound/pci/hda/snd-hda-intel.ko
description:??? Intel HDA driver
license:??????? GPL
srcversion:???? A3552B2DF3A932D88FFC00C
alias:????????? pci:v000010DEd0000055Dsv*sd*bc*sc*i*
alias:????????? pci:v000010DEd0000055Csv*sd*bc*sc*i*
depends:??????? snd-pcm,snd-page-alloc,snd-hda-codec,snd
vermagic:?????? 2.6.20-16-generic SMP mod_unload 586?
parm:?????????? index:Index value for Intel HD audio interface. (int)
parm:?????????? id:ID string for Intel HD audio interface. (charp)
parm:?????????? model:Use the given board model. (charp)
parm:?????????? position_fix:Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size). (int)
parm:?????????? probe_mask:Bitmask to probe codecs (default = -1). (int)
parm:?????????? single_cmd:Use single command to communicate with codecs (for debugging only). (bool)
parm:?????????? enable_msi:Enable Message Signaled Interrupt (MSI) (int)
parm:?????????? enable:bool
對我們來說比較有興趣的以"parm"開頭的那些部分:顯示了模塊所接受的參數。這些描述都比較簡明,如果想要更多的信息,那就安裝kernel的源代碼,在類似于/usr/src/KERNELVERSION/Documentation的目錄下你會找到。
里面會有一些有趣的東西,比如文件/usr/src/KERNELVERSION/Documentation/sound/alsa/ALSA-Configuration.txt描述的是被許多ALSA聲音模塊承認的參數;/usr/src/KERNELVERSION/Documentation/kernel-parameters.txt這個文件也很有用。
前幾天在Ubuntu論壇有一個例子,說的是如何將參數傳遞到一個模塊(詳見https://help.ubuntu.com/community/HdaIntelSoundHowto)。實際上問題的關鍵是snd-hda-intel參數在正確驅動聲音硬件時需要一點操作,而且在boot time加載時會中止。解決方法的一部分是將probe_mask=1選項賦給模塊,如果你是手動加載模塊,你需要輸入:
# modprobe snd-hda-intel probe_mask=1
更有可能,你在文件/etc/modprobe.conf中放置這樣類似的一行:options snd-hda-intel probe_mask=1
這"告訴"modprobe每次在加載snd-hda-intel模塊時包含probe_mask=1選項。現在的有些Linux版本將這一信息分離進/etc/modprobe.d下的不同文件中了,而不是放入modprobe.conf中。
/proc系統文件
Linux kernel同樣通過/proc系統文件來展示了許多細節。為了說明/proc,我們首先需要擴展我們對于文件的理解。除了認為文件就是存儲在硬盤或者CD或者存儲空間上的持久信息之外,我們還應當把它理解為任何可以通過傳統系統調用如:打開、讀、寫、關閉等訪問的信息,當然它也可以被常見的程序訪問。
/proc之下的"文件"完全是kernel虛擬的一個部分,給我們一個視角可以看到kernel內部的數據結構。實際上,許多Linux的報告工具均能夠很好地呈現在/proc下的文件中尋到的格式化版本的信息。比如,一列/proc/modules將展示一列當前加載的模塊。
同樣的,/proc/meminfo提供了關于虛擬存儲系統當前狀態的更多細節信息,而類如vmstat的工具則是以一種更加可理解的方式提供了相同的一些信息;/proc/net/arp顯示了系統ARP cache的當前內容,從命令行來說,arp -a顯示的也是相同的信息。
尤其有意思的是/proc/sys下的"文件"。/proc/sys/net/ipv4/ip_forward下的設置告訴我們kernel是否將轉發IP數據包,也就是說是否扮演網關的作用?,F在,kernel告訴我們這是關閉的:
# cat /proc/sys/net/ipv4/ip_forward?
0
當你發現你可以對這些文件寫入的時候,你會覺得更加有意思。繼續舉例來說:
# echo 1 > /proc/sys/net/ipv4/ip_forward
將在運行的kernel中打開IP 轉發(IP forwarding)
除了使用cat和echo來檢查和更正/proc/sys下的設置以外,你也可以使用sysctl命令:
# sysctl net.ipv4.ip_forward?
net.ipv4.ip_forward = 0
這等同于:
# cat /proc/sys/net/ipv4/ip_forward?
0
也等同于:
# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
還等同于:
# echo 1 > /proc/sys/net/ipv4/ip_forward
????
需要注意的是,以這種方式你所做的設置改變只能影響當前運行的kernel的,當reboot的時候就不再有效。如果想讓設置永久有效,將它們放置在/etc/sysctl.conf文件中。在boot time時,sysctl將自動重新確定它在此文件下找到的任何設置。
/etc/sysctl.conf下的代碼行大概是這樣的:net.ipv4.ip_forward=1
?
現在我們隊Kernel是做什么的已經有了一些了解,讓我們再來簡單看下它的物理組成。早期版本的Linux Kernel是整體式的,也就是說所有的部件都靜態地連接成一個(很大的)執行文件。
相比較而言,現在的Linux Kernel是模塊化的:許多功能包含在模塊內,然后動態地載入kernel中。這使得kernel的內核很小,而且在運行kernel時可以不必reboot就能載入和替代模塊。
Kernel的內核在boot time時從位于/boot 目錄的一個文件加載進存儲中,通常這個/boot 目錄會被叫做KERNELVERSION,KERNELVERSION與kernel版本有關。(如果你想知道你的kernel版本是什么,運行命令行顯示系統信息-r。)kernel的模塊位于目錄/lib/modules/KERNELVERSION之下,所有的組件都會在kernel安裝時被拷貝。
管理模塊
大部分情況下,Linux管理它的模塊不需要你的幫忙,但是如果必要的時候有命令行可以來手動檢查和管理模塊。比如,為了查清楚當前到底哪個模塊在載入kernel。這里有一個輸出的例子:
# lsmod
pcspkr????????????? 4224? 0?
hci_usb??????????? 18204? 2?
psmouse??????????? 38920? 0?
bluetooth????????? 55908? 7 rfcomm,l2cap,hci_usb
yenta_socket?????? 27532? 5?
rsrc_nonstatic???? 14080? 1 yenta_socket
isofs????????????? 36284? 0?
輸出的內容包括:模塊的名字、大小、使用次數和依賴于它的模塊列表。使用次數對防止卸載當前活躍的模塊非常總要。Linux只允許使用次數為零的模塊被移除。
你可以使用modprobe來手動加載和卸載模塊,(還有兩個命令行叫做insmod和rmmod,但modprobe更易于使用因為它自動移除了模塊依賴)。比如lsmod的輸出在我們的電腦上顯示了一個名叫isofs的卸載模塊,它的使用次數是零而且沒有依賴模塊,(isofs是一個模塊,它支持CD上使用的ISO系統文件格式)這種情況下,kernel會允許我們卸載模塊:
# modprobe -r isofs
現在,isofs不再顯示在Ismod的輸出中,kernel由此節省了36,284字節的存儲。如果你放入CD并且讓它自動安裝,kernel將自動重新載入isofs模塊,而且isofs的使用次數增加到1次。如果這時候你還試圖移除模塊,就不會成功了因為它正在被使用:
# modprobe -r isofs?
FATAL: Module isofs is in use.
????
Lsmod只是列出了當前被載入的模塊,modprobe則將列出所有可用的模塊,它實際上輸出了/lib/modules/KERNELVERSION目錄下所有的模塊,名單會很長!
實際上,使用modprobe來手動加載一個模塊并不常見,但確實可以通過modprobe命令行來對模塊設置參數,例如:
# modprobe usbcore blinkenlights=1
我們并不是在創建blinkenlights,而是usbcore模塊的實參數。
那么如何知道一個模塊會接受什么參數呢?一個比較好的方法是使用modinfo命令,它列出了關于模塊的種種信息。這里有一個關于模塊snd-hda-intel的例子
# modinfo snd-hda-intel?
filename:?????? /lib/modules/2.6.20-16-generic/kernel/sound/pci/hda/snd-hda-intel.ko
description:??? Intel HDA driver
license:??????? GPL
srcversion:???? A3552B2DF3A932D88FFC00C
alias:????????? pci:v000010DEd0000055Dsv*sd*bc*sc*i*
alias:????????? pci:v000010DEd0000055Csv*sd*bc*sc*i*
depends:??????? snd-pcm,snd-page-alloc,snd-hda-codec,snd
vermagic:?????? 2.6.20-16-generic SMP mod_unload 586?
parm:?????????? index:Index value for Intel HD audio interface. (int)
parm:?????????? id:ID string for Intel HD audio interface. (charp)
parm:?????????? model:Use the given board model. (charp)
parm:?????????? position_fix:Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size). (int)
parm:?????????? probe_mask:Bitmask to probe codecs (default = -1). (int)
parm:?????????? single_cmd:Use single command to communicate with codecs (for debugging only). (bool)
parm:?????????? enable_msi:Enable Message Signaled Interrupt (MSI) (int)
parm:?????????? enable:bool
對我們來說比較有興趣的以"parm"開頭的那些部分:顯示了模塊所接受的參數。這些描述都比較簡明,如果想要更多的信息,那就安裝kernel的源代碼,在類似于/usr/src/KERNELVERSION/Documentation的目錄下你會找到。
里面會有一些有趣的東西,比如文件/usr/src/KERNELVERSION/Documentation/sound/alsa/ALSA-Configuration.txt描述的是被許多ALSA聲音模塊承認的參數;/usr/src/KERNELVERSION/Documentation/kernel-parameters.txt這個文件也很有用。
前幾天在Ubuntu論壇有一個例子,說的是如何將參數傳遞到一個模塊(詳見https://help.ubuntu.com/community/HdaIntelSoundHowto)。實際上問題的關鍵是snd-hda-intel參數在正確驅動聲音硬件時需要一點操作,而且在boot time加載時會中止。解決方法的一部分是將probe_mask=1選項賦給模塊,如果你是手動加載模塊,你需要輸入:
# modprobe snd-hda-intel probe_mask=1
更有可能,你在文件/etc/modprobe.conf中放置這樣類似的一行:options snd-hda-intel probe_mask=1
這"告訴"modprobe每次在加載snd-hda-intel模塊時包含probe_mask=1選項。現在的有些Linux版本將這一信息分離進/etc/modprobe.d下的不同文件中了,而不是放入modprobe.conf中。
/proc系統文件
Linux kernel同樣通過/proc系統文件來展示了許多細節。為了說明/proc,我們首先需要擴展我們對于文件的理解。除了認為文件就是存儲在硬盤或者CD或者存儲空間上的持久信息之外,我們還應當把它理解為任何可以通過傳統系統調用如:打開、讀、寫、關閉等訪問的信息,當然它也可以被常見的程序訪問。
/proc之下的"文件"完全是kernel虛擬的一個部分,給我們一個視角可以看到kernel內部的數據結構。實際上,許多Linux的報告工具均能夠很好地呈現在/proc下的文件中尋到的格式化版本的信息。比如,一列/proc/modules將展示一列當前加載的模塊。
同樣的,/proc/meminfo提供了關于虛擬存儲系統當前狀態的更多細節信息,而類如vmstat的工具則是以一種更加可理解的方式提供了相同的一些信息;/proc/net/arp顯示了系統ARP cache的當前內容,從命令行來說,arp -a顯示的也是相同的信息。
尤其有意思的是/proc/sys下的"文件"。/proc/sys/net/ipv4/ip_forward下的設置告訴我們kernel是否將轉發IP數據包,也就是說是否扮演網關的作用?,F在,kernel告訴我們這是關閉的:
# cat /proc/sys/net/ipv4/ip_forward?
0
當你發現你可以對這些文件寫入的時候,你會覺得更加有意思。繼續舉例來說:
# echo 1 > /proc/sys/net/ipv4/ip_forward
將在運行的kernel中打開IP 轉發(IP forwarding)
除了使用cat和echo來檢查和更正/proc/sys下的設置以外,你也可以使用sysctl命令:
# sysctl net.ipv4.ip_forward?
net.ipv4.ip_forward = 0
這等同于:
# cat /proc/sys/net/ipv4/ip_forward?
0
也等同于:
# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
還等同于:
# echo 1 > /proc/sys/net/ipv4/ip_forward
????
需要注意的是,以這種方式你所做的設置改變只能影響當前運行的kernel的,當reboot的時候就不再有效。如果想讓設置永久有效,將它們放置在/etc/sysctl.conf文件中。在boot time時,sysctl將自動重新確定它在此文件下找到的任何設置。
/etc/sysctl.conf下的代碼行大概是這樣的:net.ipv4.ip_forward=1
?
評論
查看更多