第一、什麼是udev?
這篇文章UDEV Primer給我們娓娓道來,花點時間預習一下是值得的。當然,不知道udev是什麼也沒關係,
把它當個助記符好了,有了下面的上路指南,可以節省很多時間。我們只需要樹立一個信念:udev很簡單!
嵌入式的udev應用尤其簡單。
第二、爲什麼udev要取代devfs?
這是生產關係適應生產力的需要,udev好,devfs壞,用好的不用壞的。
udev是硬件平臺無關的,屬於user space的進程,它脫離驅動層的關聯而建立在操作系統之上,基於這種設
計實現,我們可以隨時修改及刪除/dev下的設備文件名稱和指向,隨心所欲地按照我們的願望安排和管理設
備文件系統,而完成如此靈活的功能只需要簡單地修改udev的配置文件即可,無需重新啓動操作系統。udev
已經使得我們對設備的管理如探囊取物般輕鬆自如。
第三、如何得到udev?
udev的主頁在這裏:http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
我們按照下面的步驟來生成udev的工具程序,以arm-linux爲例:
1、 下載最新的udev
wget http://www.us.kernel.org/pub/linux/utils/kernel/hotplug/udev-113.tar.bz2
或其他的方法下載udev-113.tar.bz2 。
2、解壓udev-113.tar.bz2
tar jxvf udev-113.tar.bz2
3、修改Makefile
cd udev-113
編輯Makefile,查找CROSS_COMPILE,修改CROSS_COMPILE ?= arm-linux-
4、編譯(交叉編譯器要用2.95.3以上的,不然可能編譯過不去。我用的是3.4.1)
export PATH=/usr/local/arm/3.4.1/bin:$PATH
make
沒有什麼意外的話當前目錄下生成udev,udevcontrol,udevd,udevinfo,udevmonitor,udevsettle,udevstart,
udevtest,udevtrigger九個工具程序,在嵌入式系統裏,我們只需要udevd和udevstart就能使udev工作得很好,
其他工具則幫助我們完成udev的信息察看、事件捕捉或者更高級的操作。
5、看看用到了哪共享些庫
arm-linux-readelf -a udevstart | grep "Shared library"
----------------------------------------------------------------------------------
eg:
[root@localhost udev-113]# arm-linux-readelf -a udevstart | grep "Shared library"
0x00000001 (NEEDED) Shared library: [libc.so.6]
----------------------------------------------------------------------------------
說明用到了libc.so的庫,所以要把 libc.so 和 libc.so.6 庫拷貝到文件系統的/lib目錄.
其它共享庫,用同樣方法只是把arm-linux-readelf -a udevstart | grep "Shared library"中的
udevstart 改成 別的文件名。
6、拷貝相應的共享庫到/lib目錄(共享庫指交叉編譯器的庫在本文用到的庫在 /usr/local/arm/3.4.1).
(/lib是你建的文件系統的目錄,不是你的電腦的/lib。提醒下就怕新手盲目亂做。)
ld-2.3.2.so ld-linux.so.2 libc.so.6 libc.so libc-2.3.2.so
第四、如何配置udev?
首先,udev需要內核sysfs和tmpfs的支持,sysfs爲udev提供設備入口和uevent通道,tmpfs爲udev設備文件提
供存放空間,也就是說,在上電之前系統上是沒有足夠的設備文件可用的,我們需要一些技巧讓kernel先引導
起來。
於在kernel啓動未完成以前我們的設備文件不可用,如果使用mtd設備作爲rootfs的掛載點,這個時候/dev/mtdblock
這個設備目錄是不存在的,我們無法讓kernel通過/dev/mtdblock/X這樣的設備找到rootfs,kernel只好停在那裏驚慌。
這個問題我們可以通過給kernel傳遞設備號的方式來解決,在linux系統中,mtdblock的主設備號是31,part號
從0開始,那麼以前的/dev/mtdblock/3就等同於31:03,以次類推,所以我們只需要修改bootloader傳給kernel
的cmd line參數,使root=31:03,就可以讓kernel在udevd未起來之前成功的找到rootfs。
另外一種方法就是給kernel傳遞未經歸類的設備文件名,在udev未創建之前,所有的設備實際上已經通過sysfs
建立,mtdblockX的位置相對於/sys/block/mtdblockX/dev,這個文件裏存放着mtdblockX的設備號,形式與上
一種方式相同。這時由於沒有相應的udev規則,所有的設備都被隱含地映射到/dev目錄下,mtdblockX對應於
/dev/mtdbockX,這樣我們給kernel傳遞root=/dev/mtdblock3,kernel發現/dev沒有被建立,就自動從映射表裏
查找對應關係,最後取出/sys/block/mtdblockX/dev裏的設備號,完成rootfs的掛載。
O.K.下一個問題。
其次,需要做的工作就是重新生成rootfs。
1.把udevd和udevstart,test-udev,udevcontrol,udevtrigger,
udevinfo,udevmonitor,udevsettle,udevtest複製到/sbin目錄。
2. 然後我們需要在/etc/下爲udev 建立設備規則
建立設備規則是udev最爲複雜的一步。這篇文章提供了最完整的指導:Writing udev rules
文中描述的複雜規則我們可以暫時不用去理會,上路指南將帶領我們輕鬆穿過這片迷霧。
這裏提供一個由簡入繁的方法,對於嵌入式系統,這樣做可以一勞永逸。
1、在前面用到的udev-113目錄裏,有一個etc目錄,裏面放着的udev目錄包含了udev設備規則的詳細樣例文
本。爲了簡單而又簡潔,我們只需要用到etc/udev/udev.conf這個文件,在我們的rootfs/etc下建立一個udev目
錄,把它複製過去,這個文件很簡單,除了註釋只有一行,是用來配置日誌信息的,嵌入式系統也許用不上
日誌,但是udevd需要檢查這個文件。
2、在rootfs/etc/udev下建立一個rules.d目錄.
mkdir -p rootfs/etc/udev/rules.d
生成一個空的配置文件
touch etc/udev/rules.d/udev.rules。
3. 然後在rootfs/etc/udev/目錄下新建udev.conf文件。
touch etc/udev/udev.conf
然後 我們來編輯這個文件並向它寫入以下配置項:
###############################################
udev_root="/dev/"
udev_rules="/etc/udev/rules.d/"
udev_log="err"
# vc devices
KERNEL=="tty[0-9]*", NAME="vc/%n"
# block devices
KERNEL=="loop[0-9]*", NAME="loop/%n"
# mtd devices
KERNEL=="mtd[0-9]*", NAME="mtd/%n"
KERNEL=="mtdblock*", NAME="mtdblock/%n"
# input devices
KERNEL=="mice" NAME="input/%k"
KERNEL=="mouse[0-9]*", NAME="input/%k"
KERNEL=="ts[0-9]*", NAME="input/%k"
KERNEL=="event[0-9]*", NAME="input/%k"
# misc devices
KERNEL=="apm_bios", NAME="misc/%k"
KERNEL=="rtc", NAME="misc/%k"
################################################
保存它爲 udev.conf,注意: udev.conf的位置是rootfs/etc/udev/udev.conf
我們的設備文件系統基本上就可以了,udevd和udevstart會自動分析這個文件。
4、 爲了使udevd在kernel起來後能夠自動運行,我們在rootfs/etc/init.d/rcS中增加以下幾行:
##################################
/bin/mount -t tmpfs tmpfs /dev
/bin/mount -t sysfs sysfs /sys
#掛載/proc爲proc文件系統
echo "mount /proc as proc"
/bin/mount -n -t proc none /proc
echo "Starting udevd..."
/sbin/udevd --daemon
/sbin/udevstart
##################################
5、 還有一點就是別忘要在/dev下手工建console和null等設備。
cd /dev
mknod -m 660 console c 5 1
mknod -m 660 null c 1 3
6、 重新生成rootfs,燒寫到flash指定的rootfs part中。
7、 如果需要動態改變設備規則,可以把etc/udev 放到jffs或yaffs part,以備修改,根據需求而定,可以隨時擴
充udev.conf中的配置項。
8、生成文件系統。(不同的板子,和文件系統,或目錄不同,下面的方法不是通用的根據個人情況改下。)
./mkfs.jffs2 -p -l -e 0x20000 -n -v -r /data/rootfs2.6/ -o filesys.jffs2
支持熱拔插。
echo /sbin/mdev > /proc/sys/kernel/hotplug
==================================================================================
我的rcS文件
==================================================================================
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
#
# Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
HOSTNAME=OMAP5912OSK
hostname $HOSTNAME
echo ""
echo "******************************************"
echo "Starting System Init for $HOSTNAME"
echo "******************************************"
# goto the init.d directory
cd /etc/init.d
# Mount the default file systems
mount -a # Mount the default file systems
/bin/mount -t tmpfs tmpfs /dev
/bin/mount -t sysfs sysfs /sys
echo "Starting udevd..."
/sbin/udevd --daemon
/sbin/udevstart
/etc/rc.d/init.d/netd start
/etc/rc.d/init.d/httpd start
/sbin/ifconfig lo 127.0.0.1
/sbin/ifconfig eth0 192.168.0.2 up