一、Makefile编程分析
(1)编译路径设置
(2)Makefile编程文件
(3)Linux内核编程流程分析
(4)简单测试(实验)
1.拿到源码后要设置编译路径
root@ubuntu:/home/topeet/android4.0/iTop4412_Kernel_3.0#
vim Makefile
编译器路径
export KBUILD_BUILDHOST := $(SUBARCH)
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
#CROSS_COMPILE ?= /usr/local/arm/4.5.1/bin/arm-none-linux-gnueabi-
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
SRCARCH := $(ARCH)
强制编译:
源码开发者强制要求编译进内核的文件
打开drivers/Makefile文件
类似下面的写法,只要编译内核就必须编译这个文件
root@ubuntu:/home/topeet/android4.0/iTop4412_Kernel_3.0/drivers#
vim Makefile
obj-y += gpio/
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_RAPIDIO) += rapidio/
obj-y += video/
obj-y += idle/
obj-$(CONFIG_ACPI) += acpi/
obj-$(CONFIG_SFI) += sfi/
配置编译:
驱动开发人员可以通过配置选择编译
打开/drivers/Makefile文件
强制编译char目录下的文件
obj-$(CONFIG_MAX485_CTL) += max485_ctl.o
obj-$(CONFIG_LEDS_CTL) += itop4412_leds.o
obj-$(CONFIG_BUZZER_CTL) += itop4412_buzzer.o
obj-$(CONFIG_ADC_CTL) += itop4412_adc.o
obj-$(CONFIG_RELAY_CTL) += itop4412_relay.o
依赖编译:
一个驱动的编译需要另外驱动的支持
这一部分不需要另外写编译脚本,只需要在Kconfig中配置即可
例如显卡驱动VIDEO_JPEG_V2X中需要MEDIA_SUPPORT等驱动,那么编译显卡驱动的同时也需要将依赖的驱动选上
二、Linux内核最小模块代码分析
Linux内核驱动处理的两种方式:
第一种方式:把所有需要的功能全部编译进内核中
第二种方式:动态的添加模块,也就是实验要介绍的"模块的方式添加驱动"
第一部分:必须包含头文件
linux/init.h和linux/module.h想要编译成模块就必须使用这两个头文件
第二部分:驱动的申明区
MODULE_LICENSE(“Dual BSD/GPL”);
/声明是开源的,没有内核版本限制/
这一句代码申明遵循GPL协议,否则模块在加载的时候,内核会提示被污染的“警报”
MODULE_AUTHOR(“iTOPEET_dz”)
/申明作者/
第三部分:功能代码
在功能区加载驱动和卸载驱动时候调用的函数,这两个函数都只是调用了printk函数
第四部分:模块的入口
加载模块。采用动态的方式添加驱动到内核中,添加驱动的入口就是这个函数。无main函数
Linux操作系统相当于“一个球”,要做的事情就是在这个球上添加驱动来实现具体的功能。
也可以说初始化函数当做main函数是模块的入口
第五部分:模块的出口
卸载的时候调用了功能区的函数static void hello_exit(void)
编译模块的时候会生成一个ko文件,可以使用insmod和rmmod加载和卸载它。加载的时候会打印"Hello World enter"卸载的时候会打印“Hello world exit”
第六部分:原驱动代码
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("TOPEET");
static int hello_init(void)
{
printk(KERN_EMERG "HELLO WORLD enter!\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_EMERG "HELLO WORLD exit!\n");
}
module_init(hello_init);
module_exit(hello_exit);