驱动学习--1--内核模块

驱动学习--1

内核模块

内核文件中实现多种功能的组件很多,要是都编译进内核,会出

现以两个问题

1,生成的内核会很大
2,如果要修改某个功能,将不得不重新编译内核

模块的机制
特点:

1,模块本身不被编译进内核,从控制内核的大小
2,模块一旦被加载,它就和内核中的其他部分完全一样

最简单的Linux内核模块示例

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
 printk(KERN_ALERT "Hello World enter/n");
 return 0;
}

static void hello_exit(void)
{
 printk(KERN_ALERT "Heloo World exit/n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_AUTHOR("Periscope");
MODULE_DESCRIPTION("A simply Hello Module");
MODULE_ALIAS("a simplest module");

保存为hello.c

模块的编译

Makefile内容如下
obj-m := hello.o

[root@Hunt-PC dri]# make -C /usr/src/kernels/2.6.27.5-

117.fc10.i686/ M=$(pwd) modules
make: Entering directory `/usr/src/kernels/2.6.27.5-

117.fc10.i686'
  CC [M]  /work/mypro/dri/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /work/mypro/dri/hello.mod.o
  LD [M]  /work/mypro/dri/hello.ko
make: Leaving directory `/usr/src/kernels/2.6.27.5-

117.fc10.i686'
[root@Hunt-PC dri]# ls
hello.c   hello.mod.c  hello.o   Module.markers 

Module.symvers
hello.ko  hello.mod.o  Makefile  modules.order
目前我不清楚上面的编译选项的意思

用如下命令时会出现找不到头文件的错误,而上面的编译命令好

像进入了Fedora的内核源码文件夹当中

加载模块
insmod ./hello.ko

未知原因,不打印那行输出????

查看
[root@Hunt-PC dri]# lsmod
Module                  Size  Used by
hello                   5376  0
fuse                   49436  2
sco                    12932  2
..........

卸载模块 rmmod hello

注意:
模块的几个组成部分
1,模块的加载函数(必须)
否则通过insmod或modprobe命令时无法加载,那模块还有什么用

,加载函数会自动被内核执行,完成模块的初始化工作

2,模块的卸载函数(必须)

3,模块许可证声明(必须)
如果不声明加载时会收到内核被污染的警告

4模块参数(可选)
被加载时传递给它自己,这本身是对应模块的内部全局变量

5,模块导出符号(可选)
symbol对应函数或变量,这样其他模块就可使用本模块中的变量

和函数。

6,模块作者信息(可选)

假设驱动写好后文件名为test.c
编译命令为:
gcc -O2 -DMODULE -D__KERNEL__ -c test.ko test.c

如果有多个文件,每个文件按上面命令编译后用下面的命令金链

ld - r file1.ko file1.lo -o modulename

当然可以写成Makefile的形式,推荐使用。

加载模块

insmod -f test.ko -f 表示强制加载,比较危险,这里举例

查看

cat /proc/devices

卸载

rmmod test 设备名即可

创建设备文件节点

mknod /dev/test c major minor

最简单的字符型设备驱动程序
Linux驱动的基本组成部分
1,包涵的头文件
2,驱动的加载和卸载函数
3,字符设备驱动的file_operations结构体中的成员函数实现

其主要的工作就是编写子函数,并填充file_opearations的各个


#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <asm/segment.h>

unsigned int test_major = 0;
static int read_test(struct inode *node, struct file

*file,char *buf, int count)
{
    int left;
    if (verify_aera(VERIFY_WRITE,buf,count)==-EFAULT)
         return -EFAULT;
    for(left = count;left>0;left--)
    {
        __put_user(1,buf,1);
        buf++;
    }
    return count;
       
}

static int write_test(struct inode *inode,struct file

*file,const charr *buf,int count)
{
    return count;
}

static int open_test(struct inode *inode,struct file

*file)
{
    MOD_INC_USE_COUNT;
    return 0;
}

static void release_test(struct inode *inode,struct file

*flie)
{
    MOD_DEC_USE_COUNT;
}

struct file_operations test_fops = {
    NULL,
    read_test,
    write_test,
    NULL,
    NULL,
    NULL,
    NULL,
    open_test,
    release_test,
    NULL,
    NULL,
};

int init_module(void)
{
    int result;
    result = register_chrdev(0, "test", &test_fops);
    if(result<0)
 
    {    printk(KERN_INFO "test:can't get major

number/n");
            return result;
    }

if(test_major==0)
    test_major=result;
return 0;
}
   
void cleanup_module(void)
{
    unregister_chrdev(test_major,"test");
}

一大堆错误,看不懂了。。。。

测试程序

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
int testdev;
int i;
char buf[10];
testdev = open("/dev/test",O_RDWR);
if ( testdev == -1 )
{
printf("Cann't open file /n");
exit(0);
}
read(testdev,buf,10);
for (i = 0; i < 10;i++)
printf("%d/n",buf[i]);
close(testdev);
}
编译运行,看看是不是打印出全1 ?
  以上只是一个简单的演示。真正实用的驱动程序要复杂的多

,要处理如中断,DMA,I/O port等问题。这些才是真正的难点

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值