内核中制作ko⽂件的步骤_转:Linux下编写和加载.ko⽂件
(驱动模块⽂件)
⼀、.ko ⽂件介绍
.ko⽂件是kernel object⽂件(内核模块),该⽂件的意义就是把内核的⼀些功能移动到内核外边, 需要的时候插⼊内核,不需要时卸载。
⼆、优点
(1)这样可以缩⼩内核体积;
(2)使⽤⽅便。
三、.ko⽂件⼀般的⽤处
(1)作为⼀个功能模块,需要使⽤时,直接插⼊运⾏就⾏。如在imx6上连接模拟摄像头,先运⾏模拟摄像头对应的驱动模块 camera.ko⽂件,然后对应的⼯程执⾏⽂件运⾏就⾏。
四、使⽤.ko ⽂件
1、加载驱动模块test.ko
(1)⽅法⼀
进⼊test.ko驱动模块⽂件所在的⽬录,然后直接  insmod  test.ko
(2)⽅法⼆
将test.ko⽂件拷贝到/lib/module/#uname-r#/⽬录下,这⾥,#uname -r#意思是,在终端中输⼊
uname -r后显⽰的内核版本及名称,例如mini2440中#uname-r#就是2.6.32.2-FriendlyARM。
然后 depmod(会在/lib/modules/#uname -r#/⽬录下⽣成modules.dep和modules.dep.bb⽂件,表明模块的依赖关系)
最后 modprobe test(注意这⾥⽆需输⼊.ko后缀) 即可
注:两种⽅法的区别
modprobe和insmod类似,都是⽤来动态加载驱动模块的,区别在于modprobe可以解决load module时的依赖关系,它是通
过/lib/modules/#uname -r/modules.dep(.bb)⽂件来查依赖关系的;⽽insmod不能解决依赖问题。也就是说,如果你确定你要加载的驱动模块不依赖其他驱动模块的话,既可以insmod也可以modprobe,当然insmod可以在任何⽬录下执⾏,更⽅便⼀些。⽽如果你要加载的驱动模块还依赖其他ko驱动模块的话,就只能将模块拷贝到上述的特定⽬录,depmod后再modprobe。
2、查看已加载的驱动模块列表
在任何⽬录下输⼊命令
lsmod
3、卸载驱动模块
在任何⽬录下, 输⼊命令
rmmod 注:“module_name”是lsmod显⽰的模块名称,⽽不是对应的ko⽂件名
五、编写⽣成.ko ⽂件
Linux下hello.ko内核模块制作的全过程
1. linux系统⽤的是Redflag 6.0 SP1 下载地址:ftp://dflag-linux/pub/redflag/dt6sp1/SP1/redflag-6-sp1.iso, 系统安装很容易,安提⽰做就好。
所⽤的内核源码⽬录树下载地址:ftp://dflag-linux/pub/redflag/dt6sp1/SP1/redflag-6-tool-sp1-src1.iso,将此iso⽂件挂载到/mnt下,安装其中的内核rpm包。
挂载⽅法:mount -t iso9660 redflag-6-tool-sp1-src1.iso /mnt/ -o loop
内核⽬录树安装⽅法:cd /mnt/RedFlag/SRMPS/
rpm -i kernel-2.6.23.1-4.src.rpm
3. 编写hello模块代码,源码如下:
hello.c
#include
#include
MODULE_LICENSE("GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
linux内核文件放在哪{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
4. 编写hello模块的Makefile⽂件,Makefile内容如下:
Makefile
#Makefile 2.6
obj-m :=hello.o
KERNEL :=/usr/src/kernels/$(uname -r)/
PWD :=$(shell pwd)
modules :
$(MAKE) -C $(KERNEL) M=$(PWD) modules
.PHONEY:clean
clean :
rm -f *.o *.ko
5. 编译模块
在命令⾏进⼊hello.c所在的⽂件夹下执⾏make命令即可完成hello模块的编译。⽤ls命令可以查看到hello.ko⽂件,此⽂件就是我们⾃定义的内核模块。
6. 安装hello模块
命令⾏下执⾏命令:insmod hello.ko 。通过命令:cat /var/log/messages
可以看到下⾯这样的信息:“Aug  6 13:37:59 localhost kernel: Hello, world”,说明模块加载成功了。
7. 另外⼀种模块Makefile的编写⽅法
Makefile
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
7. 卸载hello模块
命令⾏下执⾏命令:rmmod hello.ko即可。通过命令:cat /var/log/messages.
可以看到下⾯这样的信息:“Aug  6 13:40:36 localhost kernel: Goodbye, cruel world”,说明模块卸载成功。
8. 查看模块信息
命令⾏下执⾏命令:modinfo hello
⼆ Debian 6下制作hello内核模块的过程
1. 软件
Debian 6.02
linux-2.6.32.10.tar.bz2
2. 解压内核源码到⼀个⽬录下, 我解压到/home/kernel/下来
3. 查询安装内核头⽂件
aptitude search linux-headers-2.6.32*
aptitude install linux-headers-2.6.32-5-686
注意:2.6.32-5-686来⾃命令uname -r的结果
上⾯这个命令⽐较⿇烦,还可以选择下⾯的命令实现同样的⽬的
apt-get install linux-headers-`uname -r`
注意这个命令⾥使⽤的不是单引号,⽽是反单引号,位于键盘的左上⾓, ⼀般和数字1是邻居。
4. 写个Hello模块测试
内核代码下载后, 要简单的运⾏俩命令配置⼀下,我这⾥的命令如下[当然, 您也可以不尝试这⼀步, 当你make时, 系统会提⽰你该怎么做
cd /home/kernel/linux-2.6.32.10
make oldconfig && make prepare
WARNING: Symbol version dump /home/kernel/linux-2.6.32.10/Module.symvers
is missing; modules will have no dependencies and modversions.
cd /home/kernel/linux-2.6.32.10
make modules
[参考内容]
The Module.symvers is (re)generated when you (re)compile modules. Run make modules, and you should get a
Module.symvers file at the root of the kernel tree.
Note that if you only ran make and not make modules, you haven't built any modules yet. The symbols from the kernel itself (vmlinux or one of the architecture-dependent image formats) are in System.map.
经测试问题得到很好的解决, make modules要花费好长编译时间段。
[问题] type defaults to "int' in declaration of module_init
[解答] module_init(hello_init);这句中某个字符弄成汉字编码导致的
[问题]  XP与虚拟机⾥的debian通信我⽤俩办法⼀个samba传输数据,⼀个是ssh传输命令
[解答] 启动sshd服务的命令: /etc/init.d/ssh start
6. hello驱动涉及到linux驱动模型的⽅⽅⾯⾯
hello.h代码⽂件
#ifndef _HELLO_ANDROID_H
#define _HELLO_ANDROID_H
#include
#include
#define HELLO_DEVICE_NODE_NAME  "hello"
#define HELLO_DEVICE_FILE_NAME  "hello"
#define HELLO_DEVICE_PROC_NAME  "hello"
#define HELLO_DEVICE_CLASS_NAME "hello"
struct hello_android_dev {
int val;
struct semaphore sem;
struct cdev dev;
};
#define init_MUTEX(sem) sema_init(sem, 1)
hello.c代码⽂件
#include
#include
#include
#include
#include
#include
#include
#include "hello.h"
static int hello_major = 0;
static int hello_minor = 0;
static struct class *hello_class = NULL;
static struct hello_android_dev *hello_dev = NULL;
static int hello_open(struct inode *inode, struct file *filp);
static int hello_release(struct inode *inode, struct file *filp);
static ssize_t hello_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
static ssize_t hello_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
static struct file_operations hello_fops = {
.owner = THIS_MODULE,
.open  = hello_open,
.release = hello_release,
.read  = hello_read,
.write = hello_write,
};
static ssize_t hello_val_show(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t hello_val_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store);
static int hello_open(struct inode *inode, struct file *filp)
{
struct hello_android_dev *dev;
printk(KERN_ALERT"hello_open 1\n");
dev = container_of(inode->i_cdev, struct hello_android_dev, dev);
printk(KERN_ALERT"hello_open 2\n");

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。