一、.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>  注:“module_name”是lsmod显示的模块名称,而不是对应的ko文件名
    //

注:“module_name”是lsmod显示的模块名称,而不是对应的ko文件名
//

五、编写生成.ko 文件

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

[cpp] view plain copy

#include <linux/init.h>  
    #include <linux/module.h>  
      
    MODULE_LICENSE("GPL");  
    static int hello_init(void)  
    {  
      printk(KERN_ALERT "Hello, world\n");  
      return 0;  
    }  
    static void hello_exit(void)  
    {  
      printk(KERN_ALERT "Goodbye, cruel world\n");  
    }  
      
    module_init(hello_init);  
    module_exit(hello_exit);

4. 编写hello模块的Makefile文件,Makefile内容如下:

Makefile

[plain] view plain copy

#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

[plain] view plain copy

# 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. 查询安装内核头文件

[plain] view plain copy

aptitude search linux-headers-2.6.32*  
    aptitude install linux-headers-2.6.32-5-686

注意:2.6.32-5-686来自命令uname -r的结果

上面这个命令比较麻烦,还可以选择下面的命令实现同样的目的

[plain] view plain copy

apt-get install linux-headers-`uname -r`

注意这个命令里使用的不是单引号,而是反单引号,位于键盘的左上角, 一般和数字1是邻居。

4. 写个Hello模块测试

5. FAQ

<Q1> 内核代码下载后, 要简单的运行俩命令配置一下,我这里的命令如下[当然, 您也可以不尝试这一步, 当你make时, 系统会提示你该怎么做]

<A1>

[plain] view plain copy

cd /home/kernel/linux-2.6.32.10  
    make oldconfig && make prepare

<Q2>WARNING: Symbol version dump /home/kernel/linux-2.6.32.10/Module.symvers

is missing; modules will have no dependencies and modversions.

<A2>

[plain] view plain copy

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

参考:http://bbs.chinaunix.net/thread-3570849-1-1.html

6. hello驱动涉及到linux驱动模型的方方面面

hello.h代码文件

[cpp] view plain copy

#ifndef _HELLO_ANDROID_H  
    #define _HELLO_ANDROID_H  
      
    #include <linux/cdev.h>  
    #include <linux/semaphore.h>  
      
    #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)  
      
    #endif

hello.c代码文件

[cpp] view plain copy

#include <linux/init.h>  
    #include <linux/module.h>  
    #include <linux/types.h>  
    #include <linux/fs.h>  
    #include <linux/proc_fs.h>  
    #include <linux/device.h>  
      
    #include <asm/uaccess.h>  
      
    #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");  
        dev = container_of(inode->i_cdev, struct hello_android_dev, dev);  
        printk(KERN_ALERT"hello_open 3\n");  
        filp->private_data = dev;  
        printk(KERN_ALERT"hello_open 4\n");  
      
        return 0;  
    }  
      
    static int hello_release(struct inode *inode, struct file *filp)  
    {  
        return 0;  
    }  
      
    static ssize_t hello_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)  
    {  
        ssize_t err = 0;  
        struct hello_android_dev *dev = filp->private_data;  
      
        if (down_interruptible(&(dev->sem))) {  
            return -ERESTARTSYS;  
        }  
      
        if (count < sizeof(dev->val)) {  
            goto out;  
        }  
      
        printk(KERN_ALERT"hello_read\n");  
        if (copy_to_user(buf, &(dev->val), sizeof(dev->val))) {  
            err = -EFAULT;  
            goto out;  
        }  
      
        err = sizeof(dev->val);  
      
    out:  
        up(&(dev->sem));  
        return err;  
    }  
      
    static ssize_t hello_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)  
    {  
        struct hello_android_dev *dev = filp->private_data;  
        ssize_t err = 0;  
      
        if (down_interruptible(&(dev->sem))) {  
            return -ERESTARTSYS;  
        }  
      
        if (count != sizeof(dev->val)) {  
            goto out;  
        }  
      
        if (copy_from_user(&(dev->val), buf, count)) {  
            err = -EFAULT;  
            goto out;  
        }  
      
        err = sizeof(dev->val);  
      
    out:  
        up(&(dev->sem));  
        return err;  
    }  
      
    /*
     * dev fs operations  
     */  
    static ssize_t __hello_get_val(struct hello_android_dev *dev, char *buf)  
    {  
        int val = 0;  
      
        if (down_interruptible(&(dev->sem))) {  
            return -ERESTARTSYS;  
        }  
      
        val = dev->val;  
        up(&(dev->sem));  
      
        return snprintf(buf, PAGE_SIZE, "%d\n", val);  
    }  
      
    static ssize_t __hello_set_val(struct hello_android_dev *dev, const char *buf, size_t count)  
    {  
        int val = 0;  
      
        val = simple_strtol(buf, NULL, 10);  
      
        if (down_interruptible(&(dev->sem))) {  
            return -ERESTARTSYS;  
        }  
      
        dev->val = val;  
        up(&(dev->sem));  
      
        return count;  
    }  
      
    static ssize_t hello_val_show(struct device *dev, struct device_attribute *attr, char *buf)  
    {  
        struct hello_android_dev *hdev = (struct hello_android_dev *)dev_get_drvdata(dev);  
      
        return __hello_get_val(hdev, buf);  
    }  
      
    static ssize_t hello_val_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)   
    {  
        struct hello_android_dev *hdev = (struct hello_android_dev *)dev_get_drvdata(dev);  
      
        return __hello_set_val(hdev, buf, count);  
    }  
      
    /*
     * proc fs operations
     */  
    static ssize_t hello_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)  
    {  
        if (off > 0) {  
            *eof = 1;  
            return 0;  
        }  
      
        return __hello_get_val(hello_dev, page);  
    }  
      
    static ssize_t hello_proc_write(struct file *filp, const char __user *buf, unsigned long len, void *data)  
    {  
        int err = 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;  
            goto out;  
        }  
      
        err = __hello_set_val(hello_dev, page, len);  
      
    out:  
        free_page((unsigned long)page);  
        return err;  
    }  
      
    /*
     * /proc/hello  
     */  
    static void hello_create_proc(void)  
    {  
        struct proc_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;  
        }  
    }  
      
    static void hello_remove_proc(void)  
    {  
        remove_proc_entry(HELLO_DEVICE_PROC_NAME, NULL);  
    }  
      
    static int __hello_setup_dev(struct hello_android_dev *dev)  
    {  
        int err;  
        dev_t devno = MKDEV(hello_major, hello_major);  
      
        memset(dev, 0, sizeof(struct hello_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) {  
            return err;  
        }  
      
        init_MUTEX(&(dev->sem));  
        dev->val = 0;  
      
        return 0;  
    }  
      
    static int __init hello_init(void)  
    {  
        int err = -1;  
        dev_t dev = 0;  
        struct device *temp = NULL;  
      
        printk(KERN_ALERT"Initializing hello device.\n");  
      
        err = alloc_chrdev_region(&dev, 0, 1, HELLO_DEVICE_NODE_NAME);  
        if (err < 0) {  
            printk(KERN_ALERT"Failed to alloc char dev region.\n");  
            goto fail;  
        }  
      
        hello_major = MAJOR(dev);  
        hello_minor = MINOR(dev);  
      
        hello_dev = kmalloc(sizeof(struct hello_android_dev), GFP_KERNEL);  
        if (!hello_dev) {  
            err = -ENOMEM;  
            printk(KERN_ALERT"Failed to alloc hello_dev.\n");  
            goto unregister;  
        }  
      
        err = __hello_setup_dev(hello_dev);  
        if (err) {  
            printk(KERN_ALERT"Failed to setup dev: %d.\n", err);  
            goto cleanup;  
        }  
      
        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");  
            goto destroy_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");  
            goto destroy_class;  
        }  
      
        /*  
         * create /sys/class/hello/hello/val  
         */  
        err = device_create_file(temp, &dev_attr_val);  
        if (err < 0) {  
            printk(KERN_ALERT"Failed to create attribute val.\n");  
            goto destroy_device;  
        }  
      
        dev_set_drvdata(temp, hello_dev);  
      
        /*
         * create /proc/hello
         */  
        hello_create_proc();  
      
        printk(KERN_ALERT"Succedded to initialize hello device.\n");  
        return 0;  
      
    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:  
        return err;  
    }  
      
    static void __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);

[问题] Can't find default configuration "arch/x86/configs/

[解答] 默认编译 x86 配置的config

diff --git a/Makefile b/Makefile

index 39af85f..f7bcdad 100644

--- a/Makefile

+++ b/Makefile

@@ -192,7 +192,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \

# "make" in the configured kernel build directory always uses that.

# Default value for CROSS_COMPILE is not to prefix executables

# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile

-ARCH ?= i$(SUBARCH)

+ARCH ?= mips

CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)

---------------------
作者:然心向往之
来源:CSDN
原文:https://blog.csdn.net/qq_38880380/article/details/79227760
版权声明:本文为博主原创文章,转载请附上博文链接!

【Linux 驱动】下编写和加载 .ko 文件(驱动模块文件)相关推荐

  1. Linux下编写和加载 .ko 文件(驱动模块文件)

    版权声明:本文为博主原创文章,如要转载,请注明地址,谢谢^...^ https://blog.csdn.net/qq_38880380/article/details/79227760 一..ko 文 ...

  2. linux系统下编写I2C驱动

    I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线. ...

  3. linux的启动流程和加载程序

    linux的启动流程和加载程序 先来了解一下整个过程,大致知道linux是怎么启动的. 启动时要加载内核,让内核来驱动硬件,这样才算是一个真正的操作系统 但内核启动前是要做一些其它工作的.启动过过程如 ...

  4. LINUX环境下资源下载中文目录及中文文件名称问题

    为什么80%的码农都做不了架构师?>>>    http://www.yeeach.com/2009/04/09/linux%E7%8E%AF%E5%A2%83%E4%B8%8B%E ...

  5. Linux系统下如何加载U盘或移动硬盘

    Linux系统下如何加载U盘或移动硬盘 2007-05-15 00:00作者:赵彪出处:论坛整理责任编辑:原野 - 1.在插入U盘或硬盘之前,在命令行窗口运行:fdisk -l 命令,系统将显示目前所 ...

  6. linux 虚拟仪器,linux平台下编写虚拟仪器系统设计

    描述 计算机及其接口技术的发展和传统测试测量仪器系统暴露出来的不足,使得基于计算机的虚拟仪器设备越来越成为测试测量仪器的主导.虚拟仪器系统以其平台通用性.可扩充.易升级和高度的智能性获得了广泛的工业应 ...

  7. linux系统下shell命令使用通配符批量创建文件或目录

    linux系统下shell命令使用通配符批量创建文件或目录 批量创建log文件 批量创建文件夹 批量删除目录 批量创建log文件 touch {1..5}.log 批量创建文件夹 mkdir dir_ ...

  8. 【树莓派开发】使用树莓派在Linux环境下编写C语言代码

    文章目录 前言 1.创建test.c文件 2.编译运行该文件 3.编译并链接两个源文件 结语 前言 如何使用树莓派编译C语言代码呢? 21年暑假的时候,学习编程的劲头高涨,然后冲动消费买了个树莓派4B ...

  9. Windows驱动_文件系统微小过滤驱动之二驱动的安装和加载

    机会总是留给有准备的人,人生只不过有6到7次机会,极少数的人抓住了,大部分的人,让机会从自己的身边溜走.在机会还没有到来的时候,千万不要气馁,也千万不要放弃.首先,认清自己,很多人,其实都没有将自己认 ...

最新文章

  1. Anaconda 2019.03 发布,Python 跨平台科学计算软件
  2. ID vs Class 老生常谈的选择器问题
  3. leetcode 46 全排列
  4. C++指针数组、数组指针、数组名及二维数组技巧汇总
  5. 关于GPS的1PPS时间同步功能探索与测试
  6. c语言中tgx是什么函数,《高等数学》课后练习题
  7. Python基础之:Python中的异常和错误
  8. 除留余数法构造哈希表_哈希表算法原理
  9. 安装提示卸载office_office2010 卸载工具
  10. 对注册表操作的REG函数
  11. IntelliJ IDEA 快捷键 Windows
  12. 【转】.NET Interop入门-P/Invoke和Reverse P/Invoke
  13. python实现黑客帝国动画效果
  14. aardio利用鼠标钩子响应文件拖动过程(一)
  15. 智能客服问题相似度算法设计——第三届魔镜杯大赛第12名解决方案
  16. Linux 系统调用
  17. mysql存储特殊表情符号,解决mysql存储特殊文字(表情符号)utf8mb4
  18. 数学四大思想八大方法_四大数学思想
  19. PC 客户端产品使用场景小解
  20. 让AI像人类一样思考

热门文章

  1. 毕业设计 单片机森林远程智能火灾监控系统
  2. 解锁 2022 Google 游戏开发者峰会 | 打造高质量的游戏体验
  3. 地址有关码和地址无关码
  4. 红米 12C earth 秒解锁 跳过168小时 红米note12 note12pro note12pro+系列机型解锁bl root教程步骤Fastboot
  5. Linux(xUbuntu18.04)安装VMware workstation15.1 解决报错:Before you can runVMware
  6. 鱼眼镜头行业调研报告 - 市场现状分析与发展前景预测
  7. linux调试MCX314AL过程
  8. Android_基于g-sensor的坐下动作的的识别
  9. yan-master项目启动报错No bean named 'springSessionRepositoryFilter' is defined
  10. OSG智能指针:osg::ref_ptr