内核中制作ko文件的步骤_Linux下hello.ko内核模块制作的全过程

转载地址: http://blog.csdn.net/jiankangshiye/article/details/6665179

Linux下hello.ko内核模块制作的全过程

1. linux系统用的是Redflag 6.0 SP1 下载地址:ftp://ftp.redflag-linux.com/pub/redflag/dt6sp1/SP1/redflag-6-sp1.iso, 系统安装很容易,安提示做就好。

所用的内核源码目录树下载地址:ftp://ftp.redflag-linux.com/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");

staticinthello_init(void)

{

printk(KERN_ALERT "Hello, world\n");

return0;

}

staticvoidhello_exit(void)

{

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/2.6.23.1-4-i686/

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模块测试

5. FAQ

内核代码下载后, 要简单的运行俩命令配置一下,我这里的命令如下[当然, 您也可以不尝试这一步, 当你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传输命令

debian中安装sshd的命令:  apt-get install openssh-server

启动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"

structhello_android_dev {

intval;

structsemaphore sem;

structcdev dev;

};

#define init_MUTEX(sem) sema_init(sem, 1)

#endif

hello.c代码文件

#include

#include

#include

#include

#include

#include

#include

#include "hello.h"

staticinthello_major = 0;

staticinthello_minor = 0;

staticstructclass*hello_class = NULL;

staticstructhello_android_dev *hello_dev = NULL;

staticinthello_open(structinode *inode,structfile *filp);

staticinthello_release(structinode *inode,structfile *filp);

staticssize_t hello_read(structfile *filp,char__user *buf,size_tcount, loff_t *f_pos);

staticssize_t hello_write(structfile *filp,constchar__user *buf,size_tcount, loff_t *f_pos);

staticstructfile_operations hello_fops = {

.owner = THIS_MODULE,

.open  = hello_open,

.release = hello_release,

.read  = hello_read,

.write = hello_write,

};

staticssize_t hello_val_show(structdevice *dev,structdevice_attribute *attr,char*buf);

staticssize_t hello_val_store(structdevice *dev,structdevice_attribute *attr,constchar*buf,size_tcount);

staticDEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store);

staticinthello_open(structinode *inode,structfile *filp)

{

structhello_android_dev *dev;

printk(KERN_ALERT"hello_open 1\n");

dev = container_of(inode->i_cdev, structhello_android_dev, dev);

printk(KERN_ALERT"hello_open 2\n");

dev = container_of(inode->i_cdev, structhello_android_dev, dev);

printk(KERN_ALERT"hello_open 3\n");

filp->private_data = dev;

printk(KERN_ALERT"hello_open 4\n");

return0;

}

staticinthello_release(structinode *inode,structfile *filp)

{

return0;

}

staticssize_t hello_read(structfile *filp,char__user *buf,size_tcount, loff_t *f_pos)

{

ssize_t err = 0;

structhello_android_dev *dev = filp->private_data;

if(down_interruptible(&(dev->sem))) {

return-ERESTARTSYS;

}

if(count sizeof(dev->val)) {

gotoout;

}

printk(KERN_ALERT"hello_read\n");

if(copy_to_user(buf, &(dev->val),sizeof(dev->val))) {

err = -EFAULT;

gotoout;

}

err = sizeof(dev->val);

out:

up(&(dev->sem));

returnerr;

}

staticssize_t hello_write(structfile *filp,constchar__user *buf,size_tcount, loff_t *f_pos)

{

structhello_android_dev *dev = filp->private_data;

ssize_t err = 0;

if(down_interruptible(&(dev->sem))) {

return-ERESTARTSYS;

}

if(count !=sizeof(dev->val)) {

gotoout;

}

if(copy_from_user(&(dev->val), buf, count)) {

err = -EFAULT;

gotoout;

}

err = sizeof(dev->val);

out:

up(&(dev->sem));

returnerr;

}

/*

* dev fs operations

*/

staticssize_t __hello_get_val(structhello_android_dev *dev,char*buf)

{

intval = 0;

if(down_interruptible(&(dev->sem))) {

return-ERESTARTSYS;

}

val = dev->val;

up(&(dev->sem));

returnsnprintf(buf, PAGE_SIZE,"%d\n", val);

}

staticssize_t __hello_set_val(structhello_android_dev *dev,constchar*buf,size_tcount)

{

intval = 0;

val = simple_strtol(buf, NULL, 10);

if(down_interruptible(&(dev->sem))) {

return-ERESTARTSYS;

}

dev->val = val;

up(&(dev->sem));

returncount;

}

staticssize_t hello_val_show(structdevice *dev,structdevice_attribute *attr,char*buf)

{

structhello_android_dev *hdev = (structhello_android_dev *)dev_get_drvdata(dev);

return__hello_get_val(hdev, buf);

}

staticssize_t hello_val_store(structdevice *dev,structdevice_attribute *attr,constchar*buf,size_tcount)

{

structhello_android_dev *hdev = (structhello_android_dev *)dev_get_drvdata(dev);

return__hello_set_val(hdev, buf, count);

}

/*

* proc fs operations

*/

staticssize_t hello_proc_read(char*page,char**start, off_t off,intcount,int*eof,void*data)

{

if(off > 0) {

*eof = 1;

return0;

}

return__hello_get_val(hello_dev, page);

}

staticssize_t hello_proc_write(structfile *filp,constchar__user *buf, unsignedlonglen,void*data)

{

interr = 0;

char*page = NULL;

if(len > PAGE_SIZE) {

printk(KERN_ALERT"The buff is too large: %lu.\n", len);

return-EFAULT;

}

page = (char*)__get_free_page(GFP_KERNEL);

if(!page) {

printk(KERN_ALERT"Failed to alloc page.\n");

return-ENOMEM;

}

if(copy_from_user(page, buf, len)) {

printk(KERN_ALERT"Failed to copy buff from user.\n");

err = -EFAULT;

gotoout;

}

err = __hello_set_val(hello_dev, page, len);

out:

free_page((unsigned long)page);

returnerr;

}

/*

* /proc/hello

*/

staticvoidhello_create_proc(void)

{

structproc_dir_entry *entry;

entry = create_proc_entry(HELLO_DEVICE_PROC_NAME, 0, NULL);

if(entry) {

/* entry->owner = THIS_MODULE;*/

entry->read_proc  = hello_proc_read;

entry->write_proc = hello_proc_write;

}

}

staticvoidhello_remove_proc(void)

{

remove_proc_entry(HELLO_DEVICE_PROC_NAME, NULL);

}

staticint__hello_setup_dev(structhello_android_dev *dev)

{

interr;

dev_t devno = MKDEV(hello_major, hello_major);

memset(dev, 0, sizeof(structhello_android_dev));

cdev_init(&(dev->dev), &hello_fops);

dev->dev.owner = THIS_MODULE;

dev->dev.ops   = &hello_fops;

err = cdev_add(&(dev->dev), devno, 1);

if(err) {

returnerr;

}

init_MUTEX(&(dev->sem));

dev->val = 0;

return0;

}

staticint__init hello_init(void)

{

interr = -1;

dev_t dev = 0;

structdevice *temp = NULL;

printk(KERN_ALERT"Initializing hello device.\n");

err = alloc_chrdev_region(&dev, 0, 1, HELLO_DEVICE_NODE_NAME);

if(err

printk(KERN_ALERT"Failed to alloc char dev region.\n");

gotofail;

}

hello_major = MAJOR(dev);

hello_minor = MINOR(dev);

hello_dev = kmalloc(sizeof(structhello_android_dev), GFP_KERNEL);

if(!hello_dev) {

err = -ENOMEM;

printk(KERN_ALERT"Failed to alloc hello_dev.\n");

gotounregister;

}

err = __hello_setup_dev(hello_dev);

if(err) {

printk(KERN_ALERT"Failed to setup dev: %d.\n", err);

gotocleanup;

}

hello_class = class_create(THIS_MODULE, HELLO_DEVICE_CLASS_NAME);

if(IS_ERR(hello_class)) {

err = PTR_ERR(hello_class);

printk(KERN_ALERT"Failed to create hello class.\n");

gotodestroy_cdev;

}

/*

* create /dev/hello

* create /sys/class/hello/hello

*/

temp = device_create(hello_class, NULL, dev, "%s", HELLO_DEVICE_FILE_NAME);

if(IS_ERR(hello_class)) {

err = PTR_ERR(hello_class);

printk(KERN_ALERT"Failed to create hello device.\n");

gotodestroy_class;

}

/*

* create /sys/class/hello/hello/val

*/

err = device_create_file(temp, &dev_attr_val);

if(err

printk(KERN_ALERT"Failed to create attribute val.\n");

gotodestroy_device;

}

dev_set_drvdata(temp, hello_dev);

/*

* create /proc/hello

*/

hello_create_proc();

printk(KERN_ALERT"Succedded to initialize hello device.\n");

return0;

destroy_device:

device_destroy(hello_class, dev);

destroy_class:

class_destroy(hello_class);

destroy_cdev:

cdev_del(&(hello_dev->dev));

cleanup:

kfree(hello_dev);

unregister:

unregister_chrdev_region(MKDEV(hello_major, hello_minor), 1);

fail:

returnerr;

}

staticvoid__exit hello_exit(void)

{

dev_t devno = MKDEV(hello_major, hello_minor);

printk(KERN_ALERT"Remove hello device.\n");

/*

* remove /proc/hello

*/

hello_remove_proc();

/*

* destroy device and class

*/

if(hello_class) {

device_destroy(hello_class, MKDEV(hello_major, hello_minor));

class_destroy(hello_class);

}

/*

* delete cdev and free malloced mem

*/

if(hello_dev) {

cdev_del(&(hello_dev->dev));

kfree(hello_dev);

}

/*

* free device ID

*/

unregister_chrdev_region(devno, 1);

}

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("First Android Driver /dev/hello");

module_init(hello_init);

module_exit(hello_exit);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值