摘要:通過對(duì)Solaris基本的驅(qū)動(dòng)規(guī)格的研究,介紹了Solaris下的設(shè)備驅(qū)動(dòng)器和設(shè)備配置,比較了Solaris 10和linux2.6環(huán)境下設(shè)備驅(qū)動(dòng)配置的異同。文章涉及的大部分內(nèi)容可以在早期的版本中使用。
關(guān)鍵詞:設(shè)備;設(shè)備驅(qū)動(dòng);Sun Solaris 10;Linux
中圖分類號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2008)36-2801-04
Introduction to Solaris10 Drivers
ZHANG Le
(College of software Engineering, Southeast University, Nanjing 210036, China)
Abstract: This article explains basic driver programming inside Solaris 10. It introduces device drivers and devices and compares Solaris 10 and Linux in general. Most of the article should hold for earlier releases of either system.
Key words: devices; device drivers; Sun Solaris 10; Linux
1 引言
Solaris 10是一款多任務(wù)處理的分布式企業(yè)網(wǎng)絡(luò)系統(tǒng),最初運(yùn)行在SUN公司的SPARC系列芯片之上。最多4萬臺(tái) Solaris 10網(wǎng)絡(luò)操作系統(tǒng)組合成的企業(yè)網(wǎng)絡(luò)計(jì)算環(huán)境可以集中用一臺(tái)工作站來進(jìn)行統(tǒng)一管理,Solaris操作系統(tǒng)一直以穩(wěn)定和強(qiáng)健的特性在Unix多路計(jì)算機(jī)處理 領(lǐng)域占有重要的地位。Solaris使用Motif圖形用戶接口以及NFS、NIS、ZFS等網(wǎng)絡(luò)文件系統(tǒng),目前版本的Solaris 10也可運(yùn)行在x64處理器架構(gòu)的計(jì)算機(jī)上。在Solaris和Linux系統(tǒng)中,設(shè)備驅(qū)動(dòng)的用途和目的相同,就是為系統(tǒng)提供一種控制和連接設(shè)備的一種手段,通常情況下,使用者連接設(shè)備是通過標(biāo)準(zhǔn)的I/O 命令進(jìn)行系統(tǒng)調(diào)用:比如 open,close,這些系統(tǒng)命令調(diào)用了設(shè)備驅(qū)動(dòng)程序。另外,操作系統(tǒng)也會(huì)自動(dòng)調(diào)用相關(guān)的程序去處理錯(cuò)誤和連接那些可能存在于系統(tǒng)中的不同的總線結(jié)構(gòu)。此外許多系統(tǒng)管理相關(guān)的命令也可能調(diào)用設(shè)備驅(qū)動(dòng)程序。因此掌握Solaris的設(shè)備和設(shè)備驅(qū)動(dòng)管理是在Solaris系統(tǒng)下編程必不可少的過程。
2 系統(tǒng)結(jié)構(gòu)和設(shè)備樹
Solaris使用設(shè)備樹來表示它的設(shè)備。每一個(gè)設(shè)備樹上的節(jié)點(diǎn)表示一個(gè)設(shè)備。設(shè)備樹顯示了設(shè)備在系統(tǒng)的物理位置。使用者和程序能夠通/devices和prtconf命令顯示設(shè)備驅(qū)動(dòng)。下面就是一些例子。
bash-2.05b# ls -R /devices
/devices: <---the \"root\" of the device tree
isa pci@0,0 pseudo:devctl xsvc
objmgrpci@0,0:devctlscsi_vhci xsvc:xsvc
options pseudoscsi_vhci:devctl
/devices/isa:<--- the system has an isa bus
asy@1,2f8 asy@1,2f8:b,cu i8042@1,60lp@1,3bc:ecpp0<--- devices on the isa bus
asy@1,2f8:b fdc@1,3f0 lp@1,3bc
/devices/isa/fdc@1,3f0:<--- a floppy disk controller on the isa bus
fd@0,0 fd@0,0:a,rawfd@0,0:b,raw fd@0,0:c,raw<--- floppy disk drives/slices
fd@0,0:a fd@0,0:bfd@0,0:c
/devices/isa/i8042@1,60:<--- an i8042 controller
keyboard@0 keyboard@0:kb8042mouse@1mouse@1:l
/devices/pci@0,0: <--- pci-host bus bridge
pci-ide@7,1pci8086,7112@7,2 pci8086,7112@7,2:hubd
pci1014,130@2pci8086,7112@7,2:1 pci8086,7191@1
pci1014,130@2,1pci8086,7112@7,2:2 pci8086,7191@1:devctl
/devices/pci@0,0/pci-ide@7,1: <--- pci-ide bridge
ide@0ide@0:controlide@1ide@1:control
/devices/pci@0,0/pci-ide@7,1/ide@0: <--- 1 of 2 ide controllers
cmdk@0,0cmdk@0,0:ecmdk@0,0:i,rawcmdk@0,0:ncmdk@0,0:r,raw<--- disks/slices
cmdk@0,0:acmdk@0,0:e,rawcmdk@0,0:jcmdk@0,0:n,rawcmdk@0,0:s
cmdk@0,0:a,rawcmdk@0,0:fcmdk@0,0:j,rawcmdk@0,0:ocmdk@0,0:s,raw
cmdk@0,0:bcmdk@0,0:f,rawcmdk@0,0:kcmdk@0,0:o,raw cmdk@0,0:t
cmdk@0,0:b,rawcmdk@0,0:gcmdk@0,0:k,rawcmdk@0,0:pcmdk@0,0:t,raw
cmdk@0,0:ccmdk@0,0:g,rawcmdk@0,0:lcmdk@0,0:p,rawcmdk@0,0:u
cmdk@0,0:c,rawcmdk@0,0:hcmdk@0,0:l,rawcmdk@0,0:qcmdk@0,0:u,raw
cmdk@0,0:dcmdk@0,0:h,rawcmdk@0,0:m cmdk@0,0:q,raw
cmdk@0,0:d,rawcmdk@0,0:icmdk@0,0:m,rawcmdk@0,0:r
/devices/pci@0,0/pci-ide@7,1/ide@1:<--- second ide controller
sd@0,0sd@0,0:esd@0,0:i,rawsd@0,0:nsd@0,0:r,raw
sd@0,0:asd@0,0:e,rawsd@0,0:jsd@0,0:n,rawsd@0,0:s
sd@0,0:a,rawsd@0,0:fsd@0,0:j,rawsd@0,0:osd@0,0:s,raw
sd@0,0:bsd@0,0:f,rawsd@0,0:ksd@0,0:o,rawsd@0,0:t
sd@0,0:b,rawsd@0,0:gsd@0,0:k,rawsd@0,0:psd@0,0:t,raw
sd@0,0:csd@0,0:g,rawsd@0,0:l sd@0,0:p,rawsd@0,0:u
sd@0,0:c,rawsd@0,0:hsd@0,0:l,rawsd@0,0:qsd@0,0:u,raw
sd@0,0:dsd@0,0:h,rawsd@0,0:msd@0,0:q,raw
sd@0,0:d,rawsd@0,0:i sd@0,0:m,rawsd@0,0:r
/devices/pseudo:<--- pseudo device nexus node
arp@0 pm@0ptsl@0:ttyp4 <--- pseudo devices
arp@0:arp pm@0:pm ptsl@0:ttyp5
bl@0 poll@0ptsl@0:ttyp6
bash-2.05b#
在上面的例子中列出的就是設(shè)備的名字,比如 /devices/pci@0,0/pci-ide@7,1表示了這是一個(gè)系統(tǒng)總線的(或者是主板的)PCI控制器,并且PCI總線是在一個(gè)PCI-IDE橋結(jié)構(gòu)中。設(shè)備在的設(shè)備樹上名字有2部分組成,@之前的部分表示設(shè)備的名字,@之后到‘:’的部分表示接口編號(hào)和設(shè)備在總線的位置。而設(shè)備驅(qū)動(dòng)的名稱在‘:’之后。Linux不管設(shè)備的位置和硬件都使用相同的名字表示。比如Linux不管硬盤是IDE還是SCSI接口都表示為/dev/hda,/dev/hdb,等等。Solaris以3種不同的方式表示物理和邏輯設(shè)備:物理設(shè)備名稱,物理設(shè)備文件和邏輯設(shè)備文件。物理設(shè)備名稱很容易識(shí)別,因?yàn)樗麄兪且唤M很長的字符串,提供了與設(shè)備的物理安裝相關(guān)的所有細(xì)節(jié)。而位于/dev目錄下的物理設(shè)備文件是用物理設(shè)備名字的縮寫得到的實(shí)例名,這個(gè)名字可以給內(nèi)核解釋。實(shí)例名到物理設(shè)備的映射關(guān)系不是固定的,在/etc/path_to_inst文件中總是會(huì)包含著他們之間的對(duì)應(yīng)細(xì)節(jié)。實(shí)際上的設(shè)備驅(qū)動(dòng)的文件存儲(chǔ)在/devices目錄之下。
值得注意的是:無論是LINUX還是Solaris 10 都使用了名為devfs的設(shè)備文件系統(tǒng)來管理設(shè)備。這意味著設(shè)備驅(qū)動(dòng)自身就可以創(chuàng)建和刪除節(jié)點(diǎn)。在Solaris中,驅(qū)動(dòng)通過調(diào)用在attach(9f) h和detach(9f)設(shè)備驅(qū)動(dòng)文件夾中的ddi_create-minor(9f)和ddi_remove_minor_node(9f)指令來完成創(chuàng)建和刪除。與之相對(duì)應(yīng)的在Linux初始命令中的devfs_mk_dir(),devfs_mk_cdev(),和devfs_mk_bdev()和清除命令中的devfs_remove()可以完成對(duì)節(jié)點(diǎn)的創(chuàng)建和刪除。雖然Linux沒有使用到devfs,但是它通過調(diào)用在驅(qū)動(dòng)中的或在register_chrdev()中mknod()方法,或者其他相關(guān)的程序,或者手動(dòng)創(chuàng)建了設(shè)備文件。在Solaris10之前的Solaris沒有devfs,所以它的驅(qū)動(dòng)通過使用ddi_create_minor_node(9f)來創(chuàng)建和刪除節(jié)點(diǎn),無論是硬盤驅(qū)動(dòng)還是網(wǎng)絡(luò)驅(qū)動(dòng)。
這是一個(gè)例子:
bash-2.05b# prtconf
System Configuration:Sun Microsystemsi86pc
Memory size: 512 Megabytes
System Peripherals (Software Nodes):
i86pc
scsi_vhci, instance #0
+boot (driver not attached)<--- \"driver not attached\" explained below
memory (driver not attached)
aliases (driver not attached)
chosen (driver not attached)
i86pc-memory (driver not attached)
i86pc-mmu (driver not attached)
openprom (driver not attached)
options, instance #0
packages (driver not attached)
delayed-writes (driver not attached)
itu-props (driver not attached)
isa, instance #0<--- an isa bus on the system board
motherboard (driver not attached)
i8042, instance #0
mouse, instance #0
keyboard, instance #0
fdc, instance #0
fd, instance #0
lp, instance #0
asy, instance #0
pci, instance #0<--- a pci bus on the system board
pci8086,7190 (driver not attached)
pci8086,7191, instance #0
display, instance #0
pci1014,130, instance #0
pci1014,130, instance #1
pci10b7,6356 (driver not attached)
pci10b7,6159 (driver not attached)
pci1014,153 (driver not attached)
pci8086,7110 (driver not attached)
pci-ide, instance #0<--- pci-ide bridge
ide, instance #0
cmdk, instance #0
ide, instance #1
sd, instance #0
pci8086,7112, instance #0
pci8086,7113 (driver not attached)
used-resources (driver not attached)
pseudo, instance #0
xsvc, instance #0
objmgr, instance #0
cpus (driver not attached)
cpu, instance #0 (driver not attached)
bash-2.05b#
“driver not attached” (“驅(qū)動(dòng)未聯(lián)接”表示)沒有驅(qū)動(dòng),即該設(shè)備未被使用并且并且驅(qū)動(dòng)沒有載入。或者硬件已經(jīng)給配置好了但是物理上不存在??墒褂胮rtconf -D 去為已存在的設(shè)備尋找合適的驅(qū)動(dòng)。
Solaris對(duì)設(shè)備和總線分別驅(qū)動(dòng),以擴(kuò)展傳統(tǒng)的設(shè)備驅(qū)動(dòng)程序管理的功能:一個(gè)設(shè)備驅(qū)動(dòng)控制一個(gè)設(shè)備的硬件,一個(gè)總線連接驅(qū)動(dòng)程序在兩類不同的總線中控制和轉(zhuǎn)換數(shù)據(jù)。那些設(shè)備可能附屬有其他的設(shè)備(通常通過一個(gè)總線)使用連接驅(qū)動(dòng)程序連接。舉例說包括總線控制器,象PCI-Host總線橋,PCI-PCI橋等等。葉節(jié)點(diǎn)驅(qū)動(dòng)主要是給沒有額外的附加設(shè)備的設(shè)備準(zhǔn)備的。包括虛擬設(shè)備,網(wǎng)絡(luò)設(shè)備,顯示卡和存儲(chǔ)設(shè)備等等。大部分的系統(tǒng)中的設(shè)備都是葉節(jié)點(diǎn)設(shè)備。
葉節(jié)點(diǎn)設(shè)備驅(qū)動(dòng)支持字符設(shè)備和塊設(shè)備。比如說塊設(shè)備是一些可尋址的可復(fù)用的數(shù)據(jù)硬盤。其他的一些設(shè)備能夠以字符設(shè)備的形式執(zhí)行。硬盤驅(qū)動(dòng)既是字符設(shè)備也是塊設(shè)備。一些關(guān)聯(lián)的設(shè)備有一個(gè)字符設(shè)備可以像關(guān)聯(lián)驅(qū)動(dòng)一樣執(zhí)行。
3 設(shè)備和驅(qū)動(dòng)類型
許多總線驅(qū)動(dòng)允許ioctl(2)使用基礎(chǔ)的葉節(jié)點(diǎn)驅(qū)動(dòng)結(jié)構(gòu)和整個(gè)程序。SCSI主機(jī)總線適配器(一個(gè)在系統(tǒng)中負(fù)責(zé)轉(zhuǎn)換許多總線的設(shè)備,比如PCI等等)和一個(gè)SCSI是一個(gè)關(guān)聯(lián)節(jié)點(diǎn)的格式,它們被開發(fā)用來處理SCSI HBA的問題,叫做SCSA(SUN 通用SCSI結(jié)構(gòu))下面來簡單的描述一下不同類型的設(shè)備和設(shè)備驅(qū)動(dòng)結(jié)構(gòu)是如何支持不同類型的設(shè)備。
3.1 總線適配器(SCSI,IDE等等)
網(wǎng)絡(luò)驅(qū)動(dòng)SCSA(SUN 通用SCSI結(jié)構(gòu))使得開發(fā)者不需要知道HBA控制器的是如何管理SCSI的就可以進(jìn)行驅(qū)動(dòng)的開發(fā)(比如硬盤,磁帶機(jī),掃描儀,等等)。同樣的HBA驅(qū)動(dòng)也不需要知道目標(biāo)設(shè)備在SCSI總線的情況。
下面是一個(gè)關(guān)于SCSA自適應(yīng)目標(biāo)和HBa驅(qū)動(dòng)共同工作的例子。所有的工作從SCSA的CSSI_部分開始執(zhí)行。注意:這里不是一個(gè)完整的過程。
User reads/writes a file;
foo_strategy(struct buf *bp)/* target driver strategy routine */
scsi_init_pkt(...);/* calls hba to alloc and init a SCSI packet */
/* see scsi_init_pkt(9F) and scsi_pkt(9s) */
makecom_g5(...);/* build the scsi command descriptor block, see makecom(9f) */
place completion callback routine pointer into scsi_pkt;
scsi_transport(...);/* hand over built scsi packet to HBA for transport on the bus */
bar_tran_start(...)/* hba routine to handle scsi pkts */
send command to target on SCSI bus via HBA;
bar_intr(...)/* interrupt handler following completion/timeout */
clean up;
call target callback function via scsi_pkt;
foo_completion(...)/* target callback function */
biodone(bp);/* wakeup waiting readers/writers */
scsi_free_pkt(...);
3.2 網(wǎng)絡(luò)驅(qū)動(dòng)
SOLARIS使用流消息在不同的網(wǎng)絡(luò)協(xié)議棧部分中轉(zhuǎn)遞數(shù)據(jù)包。值得注意的是SOLARIS10已重寫了TCP/IP以至于TCP和IP已不是分開的流模塊。這樣做的目的主要是因?yàn)樾阅艿脑颉⒖碏IReengine在SOLARIS的描述得到更多的細(xì)節(jié)。
在SOLARIS中,一個(gè)網(wǎng)絡(luò)驅(qū)動(dòng)必須能認(rèn)知流形式并且符合DLPI規(guī)格表。DLPI(數(shù)據(jù)連接提供者接口)是一個(gè)流數(shù)據(jù)連接的規(guī)格(網(wǎng)絡(luò)控制器)驅(qū)動(dòng)。因?yàn)榱骱虳LPI添加了許多復(fù)雜的功能用于寫一個(gè)網(wǎng)絡(luò)驅(qū)動(dòng)。SUN公司開發(fā)了通用局域網(wǎng)驅(qū)動(dòng)用來屏蔽DLPI和大部分來自于網(wǎng)絡(luò)驅(qū)動(dòng)的流。
3.3 USB驅(qū)動(dòng)
SOLARIS使用了一個(gè)類似于LINUX的方式來支持USB驅(qū)動(dòng)。
4 編譯和安裝
我們可以使用SUN公司的編譯器編譯。步驟如下:
# cc -xarch=v9 -D_KERNEL -O -c foo.c<-- -xarch=v9 needed for SPARC
# cc -xarch=v9 -D_KERNEL -O -c bar.c<-- compile each .c file for your driver
# ld -r -o foobar foo.o bar.o<-- create a relocatable object, foobar
<-- dependencies on other kernel modules
<-- can be specified with -Ndrv/module
<-- for example, ld -Nmisc/scsi ...
<-- for a scsa-compliant driver
在安裝驅(qū)動(dòng)的時(shí)候,拷貝可重定位的模塊到相關(guān)的目錄下面(通常是 /usr/kernel/drv, /kernel/drv, or /kernel/`uname -m`/kernel/drv。在SPARC中,驅(qū)動(dòng)在SPARCV9的子目錄中。如果你的驅(qū)動(dòng)有DRIVE.CONF文件,則驅(qū)動(dòng)文件在DRV目錄下面??截惤Y(jié)束以后,使用命令DEVFSADM(1M)或者ADD_DEV(1M)配置驅(qū)動(dòng))。
# cp foobar /usr/kernel/drv/sparcv9/foobar<-- no sparcv9 for x86
# cp foobar.conf /usr/kernel/drv/foobar.conf
#
# add_drv foobar
#<--any output here is probably an error!
#
安裝完驅(qū)動(dòng)之后,你可以在設(shè)備樹中找到設(shè)備文件。
5 調(diào)試
SOLARIS系統(tǒng)中有四種基本的調(diào)試工具:
MDB:模塊調(diào)試器。它為調(diào)試程序提供了一個(gè)完整的可定制的環(huán)境,其中包括一個(gè)動(dòng)態(tài)模塊工具程序員可以使用它來實(shí)現(xiàn)自己的調(diào)試命令,從而完成對(duì)特定的程序的分析。每個(gè)MDB程序可以在在運(yùn)行中或者故障后不同的上下文中檢查程序。這一套內(nèi)置的MDB模塊可以幫助程序員調(diào)試Solaris內(nèi)核和相關(guān)的設(shè)備驅(qū)動(dòng)和內(nèi)核模塊。
KMDB:運(yùn)行時(shí)的內(nèi)核調(diào)試器。它允許你在運(yùn)行的系統(tǒng)的內(nèi)核中設(shè)置中斷點(diǎn)斷點(diǎn)并設(shè)置單步運(yùn)行。它可以調(diào)試運(yùn)行中的內(nèi)核和內(nèi)核系統(tǒng)崩潰轉(zhuǎn)儲(chǔ)。它也可以控制和調(diào)試運(yùn)行中的用戶進(jìn)程和用戶的核心轉(zhuǎn)儲(chǔ)。kmdb擴(kuò)展了調(diào)試器的功能,增加了對(duì)內(nèi)核執(zhí)行指令的控制。而mdb只能觀看內(nèi)核的運(yùn)行。我們可以在控制臺(tái)的命令行上用mdb的-k選項(xiàng)啟動(dòng)kmdb。當(dāng)我們遇到solris啟動(dòng)時(shí)的掛起或者是系統(tǒng)崩潰時(shí) 就可以使用內(nèi)核調(diào)試器來收集問題的資料。我們可以在啟動(dòng)時(shí)使用-k選項(xiàng)來調(diào)用內(nèi)核調(diào)試器。但是它不是\"安全\"的,因?yàn)樵趉mdb工作的時(shí)候,它完全控制了系統(tǒng),當(dāng)它追蹤時(shí)系統(tǒng)完全暫停了。它做微觀分析,允許用戶觀察每條指令的執(zhí)行,允許用戶觀察和改變處理器的狀態(tài)。
DTRACE:動(dòng)態(tài)追蹤工具。它被設(shè)計(jì)在較高的層面上追蹤它在函數(shù)層面工作,從而對(duì)運(yùn)行中的系統(tǒng)的影響最小的。
CMN_ERR(9F):和Linux的printk()相似的輸出功能。
6 總結(jié)
通過本文我們了解了SOLARIS是如何管理驅(qū)動(dòng),并且對(duì)使用相應(yīng)的Solaris的服務(wù)器自帶的工具包去編譯和調(diào)試驅(qū)動(dòng)有了認(rèn)識(shí),同時(shí)也比較了linux和Soalris在設(shè)備和設(shè)備驅(qū)動(dòng)管理上的區(qū)別。這將在Solaris系統(tǒng)下編程有很大幫助。
參考文獻(xiàn):
[1] McDougall R,Mauro J.Solaris Internals[M].Beijing:China Machine Press,2007.
[2] McDougall R,Mauro J,Gregg B.Solaris性能與工具[M].北京:機(jī)械工業(yè)出版社,2007.
[3] Winsor J.Solaris參考手冊(cè)[M].北京:人民郵電出版社,2000.
[4] Corbet J,Rubini A,Kroah-Hartman G.Linux device drivers[M].南京:東南大學(xué)出版社,2005.