1. 经典的Hello World 不管开发哪个语言下面的应用程序,我们的学习都是从一个叫Hello World的程序开始的。 模块的开发就像写一个应用程序,它有自己的入口点,出口点和自己的“生活空间“,也有生命期。 /* *hello.c Hello,World! As a Kernel Module */ #include #include #include
/* *hello_init the init function , called when the module is loaded. *Return zero if successfully loaded, nozero otherwisw. */ static int hello_init(void) { printk(KERN_ALERT" Hello,World!\n"); return 0; }
/* *hello_exit the exit function ,called when the module is removed. */ static void hello_exit(void) { printk(KERN_ALERT"Good,Bye!\n"); }
6、管理配置选项(Managing Configuration Options) 不同于2.4内核,在2.6内核中,由于有了新的“kbuild”系统,因此增添一项新的配置是相当容易的。 就是在Kconfig文件中增添一项新的配置内容。 Kconfig文件用于衔接整个Kernel源码树。 对于驱动程序而言,Kconfig文件在驱动程序源码的同级目录。若你的驱动在目录drivers/usb/gadget/online/下,那么你用的Kconfig是drivers/usb/gadget/online/Kconfig。 如果,你创建了一个新目录,那么要在其下创建新的Kconfig文件。 首先,我们要在一个已经存在的Kconfig文件中添加如下一行: source "drivers/usb/gadget/online/Kconfig" source命令的作用是,让后面带的文件或者目录下的文件生效。相当于,让文件执行一下,让修改生效。省去了重启电脑的麻烦。 由于我们的Kconfig是新建的,所以,它并没有生效。 所以,我们在一个已经存在的Kconfig文件中,调用source命令 , 让我们新建的Kconfig文件生效。 然后,修改我们新建的文件Kconfig。在新建的Kconfig中添加如下内容: config USB_GADGET_ONLINE tristate "Gadget Netmeeting support" default n help If you say Y here,netmeeting driver will be compiles into the kernel.You can also say M here and the driver will be built as a module named netmeeting.ko If unsure , say N. 第一行定义了配置选项。事先已经假设存在有CONFIG_前缀,因此用不着我们写。 第二行说明了这个配置选项是三态的,即有三种选择方式。第一种是选择Y,表示相对应的程序编译到Kernel之内;第二种选择是M,表示相对应的程序编译成模块;第三种选择是N,表示不编译相对应的程序。 如果没有编译成模块这个选项,可以用bool代替tristate。指令tristate后带引号的文本是配置选项名,用于各种配置实用程序的选项显示。 第三行为这个配置选项指定一个默认值,这里的默认值是选择n。即:不编译相对应的程序。 第四行help指令表示其后面是帮助文本。有助于用户和开发人员理解相应的程序和建立自己的内核。 还有一些其它的指令。 depends指令用于指定要使这个配置选项有效,则必须先要设置其它配置选项有效。如果,这种依赖关系不能被满足,那么配置选项就会失败。 例如:若添加了如下的指令: depends on PXA27X 要使CONFIG_GADGET_NETMEETING这个配置选项有效,必须首先要使CONFIG_PXA27X这个配置选项有效。 指令Select和depends类似,不同之处是:如果选择了当前配置选项,那么select后的配置选项也会选中。由于select命令会自动“打开”其它的配置选项,因此不如depends常用。 select用法如下: select PXA27X 如果打开了CONFIG_GADGET_NETMEETING配置选项,那么自动打开CONFIG_PXA27X配置选项。 对于select和depends指令,使用&&,||和!,可以组合多个配置选项,实现复杂的依赖关系。 如: depends on DUMB_DRIVERS && !ONE_DRIVER 意思即:当CONFIG_DUMB_DRIVERS配置选项打开,并且CONFIG_ONE_DRIVER配置选项关闭时,CONFIG_GADGET_NETMEETING配置选项才打开。 指令if可以跟在指令tristate和bool之后,这样为配置选项设置了一个条件选项。如果条件不符合,不仅关闭了配置选项甚至在配置实用工具内也不会出现这个配置选项。例如: bool "Deep Sea Mode" if OCEAN 表示只有配置选项CONFIG_OCEAN打开后,配置实用工具才会显示配置选项名Deep Sea Mode,而且也会打开CONFIG_GADGET_NETMEETING配置选项。 如果if跟在default之后,表示只有if的条件成立,才会赋默认值。 为了更容易的建立配置,配置系统提供了几个meta-options。当且仅当用户希望打开那些被设计用来禁止关键特性(关键特性:如在嵌入式系统上保留精确的内存)的选项时,那么打开配置选项CONFIG_EMBEDDED(This option allows certain base kernel options and settings to be disabled or tewaked.This is for specialized environments which can tolerate a "non-standard" kernel . Only use this if you really know what you are doing)。配置系统CONFIG_BROKEN_ON_SMP是用于指定一个驱动程序不是SMP-safe。通常这个选项是没有打开的,这样强制用户清晰地认识到一个驱动程序在SMP环境下具有“破坏性”。新开发的驱动程序是不要使用使用这个选项。(这一段有点迷糊,还得在琢磨琢磨) 最后,CONFIG——EXPERIMENTAL配置选项用于标志一个驱动程序是处于试验阶段或者beta版本阶段(beta版本:测试版本)。这个选项默认是关闭的,这使得用户在使用驱动程序之前清晰地认识到其中的风险性。
7、模块参数(Module Parameters) 对于如何向模块传递参数,LINUX Kernel提供了一个简单的框架。其允许驱动程序声明参数,并且用户在系统启动或模块装载时为参数指定相应值,在驱动程序中,参数的用法如同全局变量。这些模块参数也能够在sysfs中显示出来(sysfs暂不清楚是什么)。结果,有许多办法来创建和管理模块参数。 通过宏module_param()定义一个模块参数: module_param(name,type,perm); 参数解释: name:既是用户看到的参数名,也是模块内接受参数的变量。 type:表示参数的数据类型,是下列之一:byte,short,ushort,int,uint,long,ulong,charp,bool,invbool。 参数类型分别是:a byte, a short integer, an unsigned short integer, an integer, an unsigned integer, a long integer, an unsigned long integer, a pointer to a char, a Boolean, a Boolean whose value is inverted from what the user specifies. The byte type is stored in a single char and the Boolean types are stored in variables of type int. The rest are stored in the corresponding primitive C types. perm:指定了在sysfs中相应文件的访问权限。 访问权限用通常的八进制格式来表示或者通常的S_Ifoo定义。 八进制格式的使用和操作系统下是一致的。 0755:表示所有制是读写、执行的权限。所在组是读和执行的权限。其他用户是读和执行的权限。 S_Ifoo下:例如: S_IRUGO|S_IWUSR(表示其它用户具有读权限,用户具有写权限)。用0表示完全关闭在sysfs中相对应的项。
最后,用宏MODULE_PARM_DESC()对参数进行说明: static unsigned short size = 1; module_param(size,ushort,0644); MODULE_PARM_DESC(size,"The size in inches of the fishing pole"\ "connected to this computer"); 使用这些宏,需要包含头文件: