第一个驱动程序

从今天开始就要进入内核驱动程序部分了,在这一节里就通过第一个驱动程序来介绍一下内核驱动模块的编写框架。

static int first_drv_open(struct inode *inode, struct file *file)
{
 printk("first_drv_open\n");
 return 0;
}

static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
 printk("first_drv_write\n");
 return 0;
}

static struct file_operations first_drv_fops = {
    .owner  =   THIS_MODULE,
    .open   =   first_drv_open,     
 .write = first_drv_write,
};

static void first_drv_init(void)
{
 register_chrdev(111, "first_drv", &first_drv_fops); 
}

static void first_drv_exit(void)
{
 unregister_chrdev(111, "first_drv");
}

mondlue_init(first_drv_init);
mondule_exit(first_drv_exit);
上面的程序框架就是我们要介绍的,虽然代码没有多少,但是这里面包含的只是要说起来也是不少
1、我们自己写的程序为什么能被内核识别,成为内核驱动模块呢?这里边主要是两个宏在起作用,module_init和module_exit,一个是注册入口,一个是卸载的出口,使用这两个宏修饰之后,我们的函数就可以被内核所识别,接下来就要从入口函数"first_drv_init"看起
2、注册入口:在之后会对这个接口进行更加深入的介绍,这里只做简单解释,使用register_chrdev注册字符设备驱动,这个函数有3个参数,第一个是字符设备驱动的主设备号,第二个是设备驱动的名字,第三个参数是设备操作函数集,对于这个函数我们可以这样理解,它在内核中维护着一个数组,在注册的时候找到主设备号为索引的空间,然后将file_operations结构体放在里面,这样,应用程序就可以直接使用应用接口进行操作了,可以看到这个操作函数集合中的接口和应用层接口名字是一样的,这样的话使用起来就如同应用程序一般
3、open函数:这里值得一提的是open函数的函数,第一个参数inode表示一个具体的文件,inode中对于编写驱动代码有用的主要成员是dev_t i_rdev,struct cdev  * i_cdev。对于代表设备文件的结点,dev_t i_rdev包含了实际的设备编号。内核中提供了两个宏可以提取inode中的主次编号。
unsigned int iminor(struct inode * inode);
unsigned int imajor(struct inode * inode);
当结点inode指的是一个字符设备文件时,成员struct cdev  * i_cdev指针指向的就是这个字符设备
第二个参数file表示一个已经打开的文件描述符,它不是专门给驱动程序使用的,系统中每一个打开的文件在内核中都有一个关联的struct file。它由内核在open时创建,并传递给在文件上操作的任何函数,直到最后关闭,file结构体中包含着重要的文件操作函数集和inode,所以在open的时候就会把inode和file进行关联,
//Makefile
KERN_DIR = /home/book/linux-2.6.22.6
all:
        make -C $(KERN_DIR) M=`pwd` modules 
clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf modules.order
obj-m   += first_drv.o                

编译成功之后生成.ko文件,将驱动模块使用insmod命令插入内核中,就可以看到我们编译的驱动程序,在/dev/device目录下,主设备号是111,和我们编写的一样
在这里插入图片描述
然后写一个简单的测试程序

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char **argv)
{
        int fd;
        int val = 1;
        fd = open("/dev/first_drv", O_RDWR);
        if (fd < 0)
        {
                printf("can't open!\n");
        }
        write(fd, &val, 4);
        close(fd);
        return 0;
 }

现在进行测试是不能成功的,因为之前只是插入了驱动模块,但是在/dev目录下并没有生成设备节点,所以测试程序使用open打开文件会失败,在这之前我手动创建一个设备节点

mknod /dev/first_drv c 111 0
//c表示字符设备  111 表示主设备号  0表示此设备号

完成之后就可以发现在/dev目录下生成了一个设备节点,然后执行测试程序
在这里插入图片描述
实验结果和预期的一样,好了,第一个驱动程序就简单记录到这里
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值