您的位置首页>企业动态>

需要学习的linux驱动模块编写

导读大家好,我是极客范的本期栏目编辑小友,现在为大家讲解需要学习的linux驱动模块编写问题。Linux内核是一个整体结构。因此,很难在内核中添

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解需要学习的linux驱动模块编写问题。

Linux内核是一个整体结构。因此,很难在内核中添加任何东西或删除一些函数。为了解决这个问题,引入了内核机制,使得模块可以从内核中动态添加或删除。模块不在内核中编译,从而控制内核的大小。然而,一旦模块被插入内核,它们就像内核的其他部分一样。这样,就会有一部分系统开销。同时,如果模块有问题,也许。

1.1模块:的实现机制

启动时,模块由函数void inti_modules()初始化,因为启动时没有模块。该函数通常将内核本身视为一个虚拟模块。

如果系统需要,从sys开始调用一系列函数来操作模块。例如, sys _ cream _ modules(),sys _ inti _ modules(),

Sys_deldte_modules()等等。

这里将使用一些模块的数据结构。in/usr/SCR/Linux/include/Linux/module . h,感兴趣的朋友可以一探究竟看看。添加块有两种方法:一种是手动添加3360,比如:insmod modulename。另一种是根据需要添加块。动态加载模块。如果您执行命令: $ mount-t MSDOS/dev/HDD/mnt/d,系统将自动加载FAT模块以支持MSDOS的文件系统。

1.2模块编程

写一个模块,必须有一定的多进程编程基础。因为你意识到程序不是作为一个独立的程序运行的。另外,由于模块需要在内核模式下运行,会遇到内部空间和用户空间数据交换的问题。一般的数据复制功能无法完成这个过程。因此,系统引入了一些特殊的功能来完成内核空间和用户空间之间的数据交换。这些功能包括3360 void put _ user(

Memcpy_tofs()等等。感兴趣的朋友可以仔细看看所有的功能及其用法。需要注意的是,模块编程的版本与river内核有很大的关系。如果版本被阻止,内核模块可能无法编译,或者。运行此模块时,会出现不可预知的结果,如:系统崩溃等。理解了这一点之后,就可以尝试编写内核模块了。对于每个内核模块,它必须包含两个函数,int init_module(),在插入内核时启动,在内核中注册某些功能函数,或者用他的代码替换内核和内核中某些函数的内容(估计这些函数是空的)。因此,可以安全地卸载内核和内核。

Int cleanup_module()当内核模块被卸载时,调用它从内核中清除该模块。像其他编程教程一样,我们举一个hello world的例子。

#包括“linux/kernerl.h”

#包含' llinux/module.h '

#if CONFIG_MODVERSIONS==1

#定义MODVERSIONS

#包括“linux/modversions.h”

#如果结束

int init_module()

{

printk(' hello world!\ n ');

printd('我在内核中运行@!\ n ');

返回1;

}

int清理_module()

{

printk('我会在kernerl mod /n中关闭自己');

retutn 0;

}

这样的例子就讲完了。我们还写了一个makefile的例子,它适合我们在大型程序中的应用。下面是makefile的内容。

#模块的生成文件

CC=gcc

modcflag s 3360=-Wall _ dmmodule-D _ KERNEL _ Dlinux

hello . o hello . c/usr/include?linux/version.h

CC $(MODCFLAGS) 0c hello.c

回声模块是完全复杂的

然后运行make命令来获取hello.o模块。奔跑

$insmod hello.o

你好世界!

我会在kernerl mod中关闭自己

$lsmod

你好(未使用)

….

$remmod

我会在kernerl mod中关闭自己

这样,您的模块可以随意插入和删除。

linux中的大多数驱动程序都是以模块的形式编写的。这些

驱动程序源码可以修改到内核中,也可以把他们编译成模块形势,在需要的时候动态加载. 一个典型的驱动程序,大体上可以分为这么几个部分: 1,注册设备 在系统初启,或者模块加载时候,必须将设备登记到相应的设备数组,并返回设备的主驱动号,例如:对快设备来说调用 refister_blkdec()将设备添加到数组blkdev中.并且获得该设备号.并利用这些设备号对此数组进行索引.对于字符驱动设备来说,要使用module_register_chrdev()来获得祝设备的驱动号.然后对这个设备的所有调用都用这个设备号来实现 2,定义功能函数 对于每一个驱动函数来说.都有一些和此设备密切相关的功能函数.那最常用的块设备或者字符设备来说.都存在着诸如 open() read() write() ioctrol()这一类的操作.当系统社用这些调用时.将自动的使用驱动函数中特定的模块.来实现具体的操作.而对于特定的设备.上面的系统调用对应的函数是一定的. 如:在块驱动设备中.当系统试图读取这个设备(即调用read()时),就会运行驱动程序中的block_read() 这个函数.打开新设备时会调用这个设备驱动程序的device_open() 这个函数. 3,谢载模块 在不用这个设备时,可以将他卸载.主要是从/proc 中取消这个设备的特殊文件.可用特定的函数实现. 下面我们列举一个字符设备驱动程序的框架.来说明这个过程.    #include"param.h" #include"user.h" #include"tty.h" #include"dir.h" #include”fs.h"   #include"linux/kernel.h" #include"linux/module.h" #if CONFIG_MODBERSIONS==1 degine MODBERSIONS #include"linux.modversions.h" #endif #difine devicename mydevice  int init_module() { int tag=module_register_chrdev(0,mydevice,&Fops); if (tag<0) { printk("the device init is erro!\n"); return 1; } return 0; }   int device_open () { ……. } int device_read () { ……. } int device_write () { ……. } int device_ioctl () { ……. } ……  int cleanup_module() { int re=module_unregister_chrdev(tag,mydevice); if( re<0) { printk("erro unregister the module !!\n"); return 1; } return 0; } 

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。