有时候还是需要把自己写的驱动模块添加到内核中去编译成一个整体,这样很容易YY,我靠,我也能在内核目录里加代码了
首先选一个典型的例子,一个外部驱动模块,需要传入两个参数,然后通过cat /proc/result 查看他们的和
/*
test_inline_driver.c
这是一个例子,把模块参数val1+ val2的和通过 cat /proc/result 显示出来
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>
struct proc_dir_entry *sumproc_result_fp=NULL;
int val1=0,val2=0;
module_param(val1,int,S_IRUGO);
module_param(val2,int,S_IRUGO);
MODULE_DESCRIPTION("My kernel module");
MODULE_AUTHOR("deep_pro");
MODULE_LICENSE("GPL");
int read_result(char *page,char **start,off_t off,int count,int *eof,void *data_unused)
{
char *buf;
buf=page;
buf+=sprintf(buf,"result %d+%d = %d /n",val1,val2,val1+val2);
*eof=1;
return buf-page;
}
static int test_inline_driver_init_module(void)
{
printk( KERN_DEBUG "Module test_inline_driver init/n" );
sumproc_result_fp=create_proc_entry("result",S_IFREG|S_IRUSR,NULL);
if(sumproc_result_fp!=NULL)
{
sumproc_result_fp->read_proc=read_result;
}
return 0;
}
static void test_inline_driver_exit_module(void)
{
printk( KERN_DEBUG "Module test_inline_driver exit/n" );
remove_proc_entry("result",0);
}
#ifndef MODULE
static int __init get_val(char *str)
{
int ints[10];
str=get_options(str,ARRAY_SIZE(ints),ints);
if(ints[0]==2)
{
val1=ints[1];
val2=ints[2];
}
return 1;
}
__setup("getval=",get_val);
__initcall(test_inline_driver_init_module);
#else
module_init(test_inline_driver_init_module);
#endif
module_exit(test_inline_driver_exit_module);
可以看到,在代码上有两个要求
首先,编译进内核的模块就不能靠module_init来启动了,需要__initcall
其次,编译进内核的模块不能靠insmod命令这样的方式传入参数,只能通过__setup读取linux启动参数
所以需要靠#ifndef MODULE 来判断当前模块是编译成外部模块还是直接编译进内核
然后就需要修改对应驱动目录下的Kconfig和Makefile文件,这个例子放在/linux-2.6.29/drivers/char 目录下
对于Kconfig,打开后在靠前的位置进行如下修改后的前20行
#
# Character device configuration
#
menu "Character devices"
config test_inline_driver
tristate "test_inline_driver is my test"
---help---
this is a sample driver,to test building a driver into kernel
config VT
bool "Virtual terminal" if EMBEDDED
depends on !S390
select INPUT
default y
---help---
If you say Y here, you will get support for terminal devices with
display and keyboard devices. These are called "virtual" because you
can run several virtual terminals (also called virtual consoles) on
其中加粗的是自己添加的内容,config选项定义了符号值
tristate命令可以选择是Y还是M
这样的修改,make menuconfig可以看到
接下来修改Makefile,修改后前20行
#
# Makefile for the kernel character device drivers.
#
#
# This file contains the font map for the default (hardware) font
#
FONTMAPFILE = cp437.uni
obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o
obj-$(CONFIG_test_inline_driver) += test_inline_driver.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
obj-y += misc.o
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o
obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
obj-$(CONFIG_AUDIT) += tty_audit.o
其中的加粗的一行是自己加的
很容易理解,obj-y是无条件一定会编译进内核的,obj-$(CONFIG_xxxx)是编译成xxxx.o但会不会链接进内核得看make menuconfig的选择的,obj-m就一定会编译成外部模块
好了,准备工作完成,make之后修改启动linux参数,在最后加上 getval=1,2
如mini2440是noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0 getval=1,2
测试结果
通过命令行给自己写的编译进内核的模块传参
最新推荐文章于 2024-01-30 14:51:47 发布