本講主要概述Linux設備驅動框架、驅動程序的配置文件及常用的加載驅動程序的方法;並且介紹Red Hat Linux安裝程序是如何加載驅動的,通過了解這個過程, 我們可以自己將驅動程序放到引導盤中;安裝完系統後,使用kudzu自動配置硬件程序。Linux設備驅動概述1. 內核和驅動模塊操作系統是通過各種驅動程序來駕馭硬件設備,它為用戶屏蔽了各種各樣的設備,驅動硬件是操作系統最基本的功能,並且提供統一的操作方式。正如我們查看屏幕上的文檔時,不用去管到底使用nVIDIA芯片,還是ATI芯片的顯示卡,只需知道輸入命令後,需要的文字就顯示在屏幕上。硬件驅動程序是操作系統最基本的組成部分,在Linux內核源程序中也占有較高的比例。Linux內核中采用可加載的模塊化設計(LKMs ,Loadable Kernel Modules),一般情況下編譯的Linux內核是支持可插入式模塊的,也就是將最基本的核心代碼編譯在內核中,其它的代碼可以選擇是在內核中,或者編譯為內核的模塊文件。如果需要某種功能,比如需要訪問一個NTFS分區,就加載相應的NTFS模塊。這種設計可以使內核文件不至於太大,但是又可以支持很多的功能,必要時動態地加載。這是一種跟微內核設計不太一樣,但卻是切實可行的內核設計方案。我們常見的驅動程序就是作為內核模塊動態加載的,比如聲卡驅動和網卡驅動等,而Linux最基礎的驅動,如CPU、PCI總線、TCP/IP協議、APM(高級電源管理)、VFS等驅動程序則編譯在內核文件中。有時也把內核模塊就叫做驅動程序,只不過驅動的內容不一定是硬件罷了,比如ext3文件系統的驅動。理解這一點很重要。因此,加載驅動時就是加載內核模塊。下面來看一下有關模塊的命令,在加載驅動程序要用到它們:lsmod、modprob、insmod、rmmod、modinfo。lsmod 列出當前系統中加載的模塊,例如:
#lsmod (與cat /proc/modules 得出的內容是一致的) ModuleSize Used by Not tainted radeon115364 1 agpgart56664 3 nls_iso8859-13516 1 (autoclean) loop12120 3 (autoclean) smbfs44528 2 (autoclean) parport_pc19076 1 (autoclean) lp9028 0 (autoclean) parport37088 1 (autoclean) [parport_pc lp] autofs13364 0 (autoclean) (unused) ds8704 2 yenta_socket13760 2 pcmcia_core57184 0 [ds yenta_socket] tg355112 1 sg36940 0 (autoclean) sr_mod18104 0 (autoclean) microcode 4724 0 (autoclean) ide-scsi 12208 0 scsi_mod 108968 3 [sg sr_mod ide-scsi] ide-cd 35680 0 cdrom33696 0 [sr_mod ide-cd] nls_cp936124988 1 (autoclean) nls_cp437 5148 1 (autoclean) vfat13004 1 (autoclean) fat 38872 0 (autoclean) [vfat] keybdev2976 0 (unused) mousedev5524 1 hid22212 0 (unused) input5888 0 [keybdev mousedev hid] ehci-hcd20104 0(unused) usb-uhci26412 0(unused) usbcore79392 1[hid ehci-hcd usb-uhci] ext391592 2 jbd52336 2[ext3]
上面顯示了當前系統中加載的模塊,左邊數第一列是模塊名,第二列是該模塊大小,第三列則是該模塊使用的數量。 如果後面為unused,則表示該模塊當前沒在使用。如果後面有autoclean,則該模塊可以被rmmod -a命令自動清洗。rmmod -a命令會將目前有autoclean的模塊卸載,如果這時候某個模塊未被使用,則將該模塊標記為autoclean。如果在行尾的[ ]括號內有模塊名稱,則括號內的模塊就依賴於該模塊。例如:
cdrom341440[sr_mod ide-cd]
其中ide-cd及sr_mod模塊就依賴於cdrom模塊。 系統的模塊文件保存在/lib/modules/2.4.XXX/kerne目錄中,根據分類分別在fs、net等子目錄中,他們的互相依存關系則保存在/lib/modules/2.4.XXX/modules.dep 文件中。 需要注意,該文件不僅寫入了模塊的依存關系,同時內核查找模塊也是在這個文件中,使用modprobe命令,可以智能插入模塊,它可以根據模塊間依存關系,以及/etc/modules.conf文件中的內容智能插入模塊。比如希望加載ide的光驅驅動,則可運行下面命令:
# modprobe ide-cd
此時會發現,cdrom模塊也會自動插入。 insmod也是插入模塊的命令,但是它不會自動解決依存關系,所以一般加載內核模塊時使用的命令為modprobe。 rmmod可以刪除模塊,但是它只可以刪除沒有使用的模塊。 Modinfo用來查看模塊信息,如modinfo -d cdrom,在Red Hat Linux系統中,模塊的相關命令在modutils的RPM包中。 2.設備文件 當我們加載了設備驅動模塊後,應該怎樣訪問這些設備呢?Linux是一種類Unix系統,Unix的一個基本特點是“一切皆為文件”,它抽象了設備的處理,將所有的硬件設備都像普通文件一樣看待,也就是說硬件可以跟普通文件一樣來打開、關閉和讀寫。 系統中的設備都用一個設備特殊文件代表,叫做設備文件,設備文件又分為Block(塊)型設備文件、Character(字符)型設備文件和Socket(網絡插件)型設備文件。Block設備文件常常指定哪些需要以塊(如512字節)的方式寫入的設備,比如IDE硬盤、SCSI硬盤、光驅等。 而Character型設備文件常指定直接讀寫,沒有緩沖區的設備,比如並口、虛擬控制台等。Socket(網絡插件)型設備文件指定的是網絡設備訪問的BSD socket 接口。
#ls -l /dev/hda /dev/video0 /dev/log brw-rw---- 1 root disk 3, 0 Sep 15 2003 /dev/hda srw-rw-rw- 1 root root 0 Jun 3 16:55 /dev/log crw------- 1 root root 81, 0 Sep 15 2003 /dev/video0
上面顯示的是三種設備文件,注意它們最前面的字符,Block型設備為b,Character型設備為c,Socket設備為s。 由此可以看出,設備文件都放在/dev目錄下,比如硬盤就是用/dev/hd*來表示,/dev/hda表示第一個IDE接口的主設備,/dev/hda1表示第一個硬盤上的第一個分區;而/dev/hdc 表示第二個IDE接口的主設備。可以使用下面命令:
#dd if=/dev/hda of=/root/a.img bs=446 count=1
把第一個硬盤上前446個字節的MBR信息導入到a.img文件中。 對於Block和Character型設備,使用主(Major)和輔(minor)設備編號來描述設備。主設備編號來表示某種驅動程序,同一個設備驅動程序模塊所控制的所有設備都有一個共同的主設備編號,而輔設備編號用於區分該控制器下不同的設備,比如,/dev/hda1(block 3/1)、/dev/hda2(block 3/2 )和/dev/hda3( block3/3 )都代表著同一塊硬盤的三個分區,他們的主設備號都是3,輔設備號分別為1、2、3。 這些設備特殊文件用mknod命令來創建:
# mknod harddisk b 3 0
我們就在當前位置創建出一個與 /dev/hda一樣的、可以訪問第一個IDE設備主硬盤的文件,文件名叫做harddisk。 使用下面命令可以查看設備編號:
#file /dev/hda /dev/hda: block special (3/0)
其中Block代表/dev/hda是系統的Block型(塊型)設備文件,它的主設備編號為3,輔設備編號為0。
#ls -l /dev/hda /dev/hdb brw-rw---- 1 root disk 3, 0 Sep 15 2003 /dev/hda brw-rw---- 1 root disk 3, 64 Sep 15 2003 /dev/hdb
使用ls -l也可以看到設備編號,/dev/hdb代表第一個IDE接口的從設備(Slave)也是Block設備,編號為(3/64),還有另外一種設備文件是/dev/tty*。使用如下命令:
#echo "hello tty1" > /dev/tty1
將字符串“hello tty1”輸出到/dev/tty1代表的第一個虛擬控制台上,此時按“Alt + F1”可以看到該字符出現在屏幕上,這個特殊的文件就代表著我們的第一虛擬控制台。
#file /dev/tty1 /dev/tty1: character special (4/1)
由上可以看到,它的類型為Character 型(字符型)設備文件,主設備號為4,輔設備號為1。同樣,/dev/tty2代表著第二個虛擬控制台,是Character設備,編號為 (4/2)。 當將/dev/cdrom加載到/mnt/cdrom中時,只要訪問/mnt/cdrom系統就會自動引入到/dev/cdrom對應的驅動程序中,訪問實際的數據。 有關設備文件的編號可以看內核文檔/usr/src/linux-2.*/Documentation/devices.txt 文件(在Kernel的源文件解包後的Documentation目錄中),其中詳細敘述了各種設備文件編號的意義。 3.使用/proc目錄中的文件監視驅動程序的狀態通過設備文件怎樣訪問到相應的驅動程序呢?它們中間有一個橋梁,那就是proc文件系統,它一般會被加載到/proc目錄。訪問設備文件時,操作系統通常會通過查找/proc目錄下的值,確定由哪些驅動模塊來完成任務。如果proc文件系統沒有加載,訪問設備文件時就會出現錯誤。Linux系統中proc文件系統是內核虛擬的文件系統,其中所有的文件都是內核中虛擬出來的,各種文件實際上是當前內核在內存中的參數。它就像是專門為訪問內核而打開的一扇門,比如訪問/proc/cpuinfo文件,實際上就是訪問目前的CPU的參數,每一次系統啟動時系統都會通過/etc/fstab中設置的信息自動將proc文件系統加載到/proc目錄下:
# grep proc /etc/fstab none/proc proc defaults 0 0 此外,也可以通過mount命令手動加載: # mount -t proc none /proc
通過/proc目錄下的文件可以訪問或更改內核參數,可以通過/proc目錄查詢驅動程序的信息。下面先讓我們看一下/proc目錄中的信息:
# ls /proc 1 4725 5032 5100 5248 5292 crypto kcore partitions 14 4794 5044 5110 5250 5293 devices kmsg pci 2 4810 5075 5122 5252 5295 dma ksyms self 3 4820 5079 5132 5254 5345 driver loadavg slabinfo 4 4831 5080 5151 5256 6 execdomains locks stat 4316 4910 5081 5160 5258 7 fb lvm swaps 4317 4912 5082 5170 5262 70 filesystems mdstat sys 4318 4924 5083 5180 5271 8 fs meminfo sysrq-trigger 4319 4950 5084 5189 5287 9 ide misc sysvipc 4620 4963 5085 5232 5288 apm interrupts modules tty 4676 5 5086 5242 5289 bus iomem mounts uptime 4680 5005 5087 5244 5290 cmdline ioports mtrr version 4706 5018 5088 5246 5291 cpuinfo irq net
需要知道的是,這些文件都是實時產生的虛擬文件,訪問它們就是訪問內存中真實的數據。這些數據是實時變化產生的,可以通過以下命令來查看文件的具體值:
# cat /proc/interrupts CPU0 0: 50662 XT-PIC timer 1: 3 XT-PIC keyboard 2: 0 XT-PIC cascade 5: 618 XT-PIC ehci-hcd, eth1 8: 1 XT-PIC rtc 9: 0 XT-PIC usb-uhci, usb-uhci 11: 50 XT-PIC usb-uhci, eth0 12: 16 XT-PIC PS/2 Mouse 14: 8009 XT-PIC ide0 15: 0 XT-PIC ide1 NMI: 0 ERR: 0
其它文件的含意見表1所示。 /proc/sys目錄下的文件一般可以直接更改,相當於直接更改內核的運行參數,例如:
# echo 1 > /proc/sys/net/ipv4/ip_forward
上面代碼可以將內核中的數據包轉發功能打開。 另外,Linux系統中提供一些命令來查詢系統的狀態,如free可以查看目前的內存使用情況,ide_info可以查看ide設備的信息,例如:
#ide_info /dev/had
類似的命令還有scsi_info,可以查看SCSI設備的信息。這些命令一般也是查詢/proc目錄下的文件,並返回結果。 系統初始化過程驅動程序的安裝在Linux安裝過程中,系統上的硬件會被檢測,基於檢測到的結果安裝程序會決定哪些模塊需要在引導時被載入。Red Hat的安裝程序為anaconda,它提供了自動檢測硬件,並且安裝的機制。但是,如果計算機內的某些硬件沒有默認的驅動程序,比如一塊SCSI卡,我們可以在啟動後的boot提示符下,輸入“linux dd”,在加載完內核後,系統會自動提示插入驅動盤,這時就有機會把該硬件的Linux驅動程序裝入。如果在安裝系統時,某種硬件總是因為中斷沖突(ISA總線的設備較常見,比如一塊ISA網卡)沒法正常驅動,或者是缺少驅動程序,那麼可以在boot提示符下輸入“linux noprobe”。在這種模式下,安裝程序不會自動配置找到的硬件,可以自己來選擇現有驅動,配置驅動程序的參數,或者選擇用光盤或軟盤加載驅動程序。定制引導盤系統啟動時是如何加載驅動的?下面讓我們來看一下Red Hat的安裝光盤是怎樣引導的。當Linux安裝光盤啟動時,加載位於光盤上isolinux中的內核文件vmlinuz,內核運行完畢後,又將initrd.img的虛擬文件系統加載到內存中。這個文件為ext2文件系統的鏡像,經過gzip壓縮,可以通過以下步驟查看該鏡像中的內容:
# mount /mnt/cdrom # mkdir /mnt/imgdir # gunzip < /mnt/cdrom/isolinux/initrd.img > /ext2img # mount -t ext2 -o loop /ext2img /mnt/imgdir # cd /mnt/imgdir # ls -F bin@ dev/ etc/ linuxrc@ lost+found/ modules/ proc/ sbin/ tmp/ var/ # cd modules # ls module-info modules.cgz modules.dep modules.pcimap pcitable
其中modules.dep為模塊的注冊文件,同時有各種模塊的依存關系。modules.cgz為cpio的打包文件,實際的各種驅動模塊就在該文件中。我們可以通過以下命令解包:
# cpio -idmv < modules.cgz
由此可以看到,解包出來的目錄2.4.21-4XXX。進入該目錄下的i386目錄,就可以看到當前啟動盤中支持的所以驅動程序:
# ls 3c59x.o 3w-xxxx.o 8139cp.o 8139too.o 8390.o aacraid.o acenic.o aic79xx.o ……
若希望在系統中加入需要的驅動程序,可以相應地修改這些文件,比如在modules.dep中加入該模塊的名字和依存關系,將編譯好的驅動模塊文件加入modules.cgz中,這樣就可以制定自己的安裝光盤。 硬盤上的系統啟動過程與上面類似,但是initrd的鏡像文件要更簡單些,一般在initrd-2.4.XXX.img的虛擬文件系統中,只會在/lib目錄下包含ext3.o jbd.o lvm-mod.o等少數文件,用來驅動硬盤上的ext3的文件系統。加載文件系統後,就可以使用/lib/modules/2.4.XXX/下的modules.dep文件及Kernel目錄中的各種驅動文件。自動配置安裝如果安裝完Linux系統後,又添加了新的硬件,那麼系統必須載入正確的驅動程序才可以使用它。在Red Hat Linux中,可以使用kudzu來配置硬件。這是PnP設備的檢測程序,當系統使用新硬件引導後,運行kudzu(默認會自動運行),如果新硬件被支持,那麼它就會被自動檢測到。該程序還會為它配置驅動模塊,把結果寫入到文件/etc/sysconfig/hwconf中,kudzu可以通過對比這個文件發現新安裝的硬件,並進行配置;也可以通過編輯模塊配置文件/etc/modules.conf來手工指定加載模塊。Kudzu服務默認每次啟動時都要運行,如果需要縮短啟動時間,使用下面命令可以停止系統啟動時的kudzu服務:
# chkconfig kudzu off
如果要安裝新的硬件,可以手動運行kudzu程序。
# kudzu
那麼kudzu程序如何認識硬件的呢?可以查看/usr/share/hwdata/目錄下的文件,根據這些文件中的PnP信息,kudzu可以識別各種硬件設備。 以上介紹了Linux下驅動程序的大體結構、主要的加載方式和相關配置文件,在安裝Linux時加載驅動程序,並且根據需要定制自己的引導盤,在安裝完成後安裝新的、即插即用硬件。下一講開始,我們將學習具體硬件驅動的安裝方法。
http://www.Stcore.com 收集整理