内核是个复杂庞大的系统,对它进行配置、裁剪、编译原本非常的复杂和困难,但现在我们却只需要简单的2个命令make menuconfig和make uImage就搞定了,原因是在其背后有一个设计精巧的内核构造系统帮我们精确完成了各项任务。内核构造系统最关键的组成元素就是各个目录下的Kconfig文件和Makefile文件,本文将对这2类文件进行介绍,以使大家了解内核构造系统的基本情况,从而能够修改他们,以完成向内核中添加功能组件的目的。
一、Kconfig文件
Kconfig文件的作用是:控制make menucofig时,出现的配置选项;并根据用户在配置界面中的选择,将配置结果保存在.config配置文件(该文件将供Makefile使用,以决定要编译的内核组件以及如何编译)。
主(初始)Kconfig文件是arch/arm/Kconfig(打开来看看吧!并试着改一改,看看当你make menuconfig的时候会出现什么样的变化)。
Kconfig文件的语法和语义,详情可查阅内核源码中的Documentation/kbuild/kconfig-language.txt文件。
1、Kconfig文件的基本要素:config条目(entry)
config REISERFS_FS_POSIX_ACL
bool
prompt "ReiserFS POSIX Access Control List”
default y
depends on REISERFS_FS_XATTR
select FS_POSIX_ACL
help
Posix Access Control Lists (ACLs) support
If you don’t know what Access Control Lists are, say N
上面的config条目,各个部分的含义是:
- REISERFS_FS_POSIX_ACL为变量名,将在.config中以CONFIG_REISERFS_FS_POSIX_ACL=y或n的形式出现;
- bool为变量取值的类型,可为y或n
- prompt为出现在配置菜单中的文字,没有它,将使得用户不能在配置界面中显示并配置它
- default为变量缺省值,可被用户设置值覆盖
- depends on表示该变量必须在REISERFS_FS_XATTR被设置的情况下才能进行设置,否则取值为n,即使default为y
- select表示它将影响到变量FS_POSIX_ACL,使得FS_POSIX_ACL至少应该配置为y或m(如果它最终取值为y或m)
- help中的文字将作为配置界面中的帮助信息
附加说明:
- 无depends on ,default 为y :默认为y。 一般用于必须要设置的选项,此时不要设置prompt
- 有depends on ,default 为y :所依赖的条目已设置,则默认为y;所依赖的条目未设置,则为n
- 有depends on ,default 为n :所依赖的条目已设置,则默认为n;所依赖的条目未设置,则为n
- 无depends on ,default 为n :默认为n。在未设置prompt的情况下,此选项想要被设置,需要由其它选项来select它
2、Kconfig中变量的取值类型总共有5种。其中最常见的是tristate和bool,分别对应于配置界面中[ ]和< >选项
- tristate:可取y、n、m
- bool (其为tristate的变体) :可取y、n
- string:取值为字符串,如:CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
- hex (其为string的变体) :取值为十六进制数据,如:CONFIG_VECTORS_BASE=0xffff0000
- int (其为string的变体) :取值为十进制数据,如:CONFIG_SPLIT_PTLOCK_CPUS=4096
3、Kconfig文件的要素:menu
在menu和endmenu中间可配置若干config条目;
体现在配置菜单上为 System type —>,按下该条目后,将出现各个config条目
4、Kconfig文件的要素:choice
在choice和endchoice之间可定义若干config条目;
体现在配置菜单上为 ARM system type —>,按下该条目后,将出现各个config条目;
choice中的config条目变量只能有2种类型:bool或tristate,且不能同时有这2种类型的变量。对于bool型变量只能在多个选择中选择1个为y;对于tristate型变量要么将多个(当然也可以是1个)设为m,要么仅将1个设为y,其余为n。这好比一个硬件有多个驱动,要么选择1个编入内核,要么把多个全编为模块
5、Kconfig文件的要素:comment
用于定义帮助信息,将出现在配置界面的第一行;并且还会出现在配置文件.config中(作为注释)
6、Kconfig文件的要素:source
由于内核源代码中大多数目录下都有各自的Kconfig文件,因此需要一种手段将所有的Kconfig文件组织为一个整体。这就是source的功能,它用于引入另一个Kconfig文件,有点类似于C语言中的#include
二、.config文件
make menuconfig配置完成退出时,选择保存,则用户所作的选择将保存在内核源代码顶层目录的.config文件中。下面.config文件的片断显示内核配置者作了如下选择:将BLK_DEV_LOOP、CONFIG_BLK_DEV_RAM功能编译进zImage;不编译BLK_DEV_COW_COMMON、BLK_DEV_CRYPTOLOOP、BLK_DEV_UB功能;将BLK_DEV_NBD功能编译为模块。
484 #
485 # Block devices
486 #
487 # CONFIG_BLK_DEV_COW_COMMON is not set
488 CONFIG_BLK_DEV_LOOP=y
489 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
490 CONFIG_BLK_DEV_NBD=m
491 # CONFIG_BLK_DEV_UB is not set
492 CONFIG_BLK_DEV_RAM=y
三、Makefile文件
下面是drivers/net/Makefile文件的片断。
12 obj-$(CONFIG_ATL1) += atl1/
13 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
14
15 gianfar_driver-objs := gianfar.o \
16 gianfar_ethtool.o \
17 gianfar_mii.o \
18 gianfar_sysfs.o
26 obj-$(CONFIG_PLIP) += plip.o
它的含义是:
1、26行,如果.config文件中变量CONFIG_PLIP=y,那么将编译本目录下的plip.c文件并将其功能集成进zImage;如果.config文件中变量CONFIG_PLIP=m,那么将编译本目录下的plip.c文件生成模块plip.ko;否则,将不编译plip.c
2、第13-18行,如果.config文件中变量CONFIG_GIANFAR=y,那么将编译本目录下的gianfar.c、gianfar_ethtool.c、gianfar_mii.c、gianfar_sysfs.c文件并将其功能集成进zImage;如果.config文件中变量CONFIG_GIANFAR=m,那么将编译本目录下的gianfar.c、gianfar_ethtool.c、gianfar_mii.c、gianfar_sysfs.c文件生成模块gianfar_driver.ko;否则,将不编译gianfar.c、gianfar_ethtool.c、gianfar_mii.c、gianfar_sysfs.c
3、12行,如果.config文件中变量CONFIG_ATL1=y,将递归进入本目录的子目录atl1,并根据该子目录下的Makefile文件的内容决定该子目录如何进行编译;否则,将不进入本目录的子目录atl1进行编译
四、修改Kconfig和Makefile,完成向内核中添加新的功能组件——网卡驱动与声卡驱动
目前我们的内核还不支持网卡cs8900的驱动,这让我们很不爽,下面就来解决这个问题。
1、首先,先将cs8900的驱动源代码文件cs8900.c(单击下载)和cs8900.h(单击下载)放到drivers/net目录(其实放到任何目录都可以,只是根据惯例,网络设备驱动都放置于drivers/net)。
2、在drivers/net/Kconfig增加config条目,以使cs8900驱动的配置选项能够出现在make menuconfig的配置界面中
878 config CS8900
879 tristate "CS8900 support"
880 default y
881 depends on (ARCH_S3C2410 && NET_ETHERNET)
882 help
883 Support for CS8900 chipset on qq2440v3. Add by Dennis Yang.
3、在drivers/net/Makefile(第198行)增加条目,以使cs8900驱动能被编译进zImage中
198 obj-$(CONFIG_CS8900) += cs8900.o
4、测试新内核
1)、支持cs8900网卡驱动
# ifconfig eth0 192.168.2.17
# ping 192.168.2.11
PING 192.168.2.11 (192.168.2.11): 56 data bytes
64 bytes from 192.168.2.11: seq=0 ttl=64 time=4.275 ms
64 bytes from 192.168.2.11: seq=1 ttl=64 time=3.154 ms
64 bytes from 192.168.2.11: seq=2 ttl=64 time=3.938 ms
— 192.168.2.11 ping statistics —
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 3.154/3.789/4.275 ms
顺带测试“移植、裁剪及配置Linux内核到s3c2440开发板”一文中还未测试的内核功能。
2)、TCP/IP协议栈
3)、开发板充当NFS客户端
# mount -t nfs -o nolock 192.168.2.11:/work/nfs_root /mnt
# ls /mnt
fs_mini fs_mini.jffs2 fs_mini3.jffs2
ls时能显示Linux机器上/work/nfs_root目录下的内容。说明内核已经支持了上述2项功能
4)、将NFS服务器上的共享目录挂载为根文件系统
将根文件系统压缩包fs_mini3.tar.bz2放在Linux机器的/work/nfs_root目录。在Linux机器上解压缩:
dennis@dennis-desktop:/$ cd /work/nfs_root
dennis@dennis-desktop:/work/nfs_root$ sudo tar xjvf fs_mini3.tar.bz2
在开发板上指定根文件系统位于nfs服务器(192.168.2.11)的共享目录/work/nfs_root/fs_mini3中:
Dennis Yang > setenv bootargs noinitrd root=/dev/nfs nfsroot=192.168.2.11:/work/nfs_root/fs_mini3 ip=192.168.2.17:192.168.2.11:192.168.2.11:255.255.255.0:www.ifl.com:eth0:off console=ttySAC0
Dennis Yang > saveenv
Dennis Yang > boot
IP-Config: Complete:
device=eth0, addr=192.168.2.17, mask=255.255.255.0, gw=192.168.2.11,
host=www, domain=, nis-domain=ifl.com,
bootserver=192.168.2.11, rootserver=192.168.2.11, rootpath=
Looking up port of RPC 100003/2 on 192.168.2.11
Looking up port of RPC 100005/1 on 192.168.2.11
VFS: Mounted root (nfs filesystem).
5)、动态加载和卸载模块
6)、开发板充当PC机的U盘
在Linux机器上编译内核模块,并将g_file_storage.ko拷贝到根文件系统中
dennis@dennis-desktop:/work/nfs_root$ cd /work/system/linux-2.6.22.6
dennis@dennis-desktop:/work/system/linux-2.6.22.6$ make modules
dennis@dennis-desktop:/$ mkdir /work/nfs_root/fs_mini3/lib/modules
dennis@dennis-desktop:/$ cp /work/system/linux-2.6.22.6/drivers/usb/gadget/g_file_storage.ko /work/nfs_root/fs_mini3/lib/modules/
重启开发板,然后动态加载模块
# cd /lib/modules
# insmod g_file_storage.ko file=/dev/mtdblock2 stall=0 removable=1
g_file_storage gadget: File-backed Storage Gadget, version: 28 November 2005
g_file_storage gadget: Number of LUNs=1
g_file_storage gadget-lun0: ro=0, file: /dev/mtdblock2
# usb 2-1: new high speed USB device using dummy_hcd and address 2
usb 2-1: configuration #1 chosen from 1 choice
g_file_storage gadget: high speed config #1
scsi0 : SCSI emulation for USB Mass Storage devices
将开发板与运行windows的PC通过usb线相连(PC机为主设备,开发板为从设备),将看到PC机上产生1个可移动硬盘。
# rmmod g_file_storage
可卸载该模块。这说明内核已经支持了上述2项功能。
7)、支持USB网卡DM9601
未插入usb网卡时
# ifconfig
eth0 Link encap:Ethernet HWaddr 08:00:3E:26:0A:5B
inet addr:192.168.2.17 Bcast:192.168.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2288 errors:28 dropped:28 overruns:0 frame:0
TX packets:1139 errors:0 dropped:0 overruns:0 carrier:0
collisions:801 txqueuelen:1000
RX bytes:2518046 (2.4 MiB) TX bytes:169064 (165.1 KiB)
Interrupt:53 Base address:0×2300
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
将usb网卡DM9601插入开发板的usb接口
# usb 1-1: new full speed USB device using s3c2410-ohci and address 7
usb 1-1: configuration #1 chosen from 1 choice
eth1: register ‘dm9601′ at usb-s3c24xx-1, Davicom DM9601 USB Ethernet, 00:80:14:00:02:00
配置ip地址后,再查看
# ifconfig eth1 192.168.3.11
eth1: link down
# ifconfig
eth0 Link encap:Ethernet HWaddr 08:00:3E:26:0A:5B
inet addr:192.168.2.17 Bcast:192.168.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2343 errors:28 dropped:28 overruns:0 frame:0
TX packets:1192 errors:0 dropped:0 overruns:0 carrier:0
collisions:801 txqueuelen:1000
RX bytes:2525700 (2.4 MiB) TX bytes:176186 (172.0 KiB)
Interrupt:53 Base address:0×2300
eth1 Link encap:Ethernet HWaddr 00:80:14:00:02:00
inet addr:192.168.3.11 Bcast:192.168.3.255 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
这说明内核已经支持了该功能。
目前我们的内核还不支持声卡驱动,这让我们也很不爽,下面就来解决这个问题。
1、首先,先将声卡uda1341的驱动源代码文件s3c_uda1341.c(单击下载)放到sound/oss目录。
2、在sound/oss/Kconfig的最后增加config条目,以使uda1341驱动的配置选项能够出现在make menuconfig的配置界面中
742 config SOUND_S3C2410_UDA1341
743 tristate "S3C2410 UDA1341 support"
744 default y
745 depends on SOUND_PRIME && ARCH_S3C2410
746 help
747 oss sound driver for qq2440v3, add by Dennis Yang
配置界面中,单击Device Drivers — Sound
选择Sound card support后,单击Open Sound System,选择Open Sound System (DEPRECATED)和S3C2410 UDA1341 support (NEW)
3、在sound/oss/Makefile最后(第141行)增加条目,以使uda1341驱动能被编译进zImage中
141 obj-$(CONFIG_SOUND_S3C2410_UDA1341) += s3c_uda1341.o
4、由于linux-2.6.22.6这个版本对s3c24XX芯片的DMA驱动有一个小bug,会导致播放歌曲时不能出声音,现在就来修复这个小bug
将arch/arm/plat-s3c24xx/dma.c的第528行 s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
修改为 s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL, S3C2410_DMAOP_START);
5、测试声卡驱动
重启开发板后,运行播放器软件播放歌曲
# madplay /pianpianxihuanni.mp3
MPEG Audio Decoder 0.15.2 (beta) – Copyright (C) 2000-2004 Robert Leslie et al.
Title: Track 1
Artist: 陳百強
Orchestra: 陳百強
Album: Best Memory
Track: 15
Genre: Other