驱动程序学习(二)一个简单的字符型设备驱动函数

通过第一个hello world驱动程序,我们学会了驱动程序的框架。

知道了,如何编译,如何加载,如何卸载一个驱动程序。接下来我们来做一个完整的驱动程序

Demo_Driver.c

#include<linux/kernel.h>

#include<linux/init.h>
#include<linux/fs.h>
#include<linux/module.h>
#define Demo_MAJOR 98   //定义主设备号
#define Demo_DEBUG
#define VERSION   "Demo_Driver"


void showversin(void)
{
printk(KERN_EMERG"***********************************************\n");
printk(KERN_EMERG"\tVERSION\t\n");
printk(KERN_EMERG"***********************************************\n");
}


//static int Demo_temp_count=0;


size_t Demo_read(struct file *file,char *buf,size_t count,loff_t *f_ops)
{
#ifdef Demo_DEBUG
printk(KERN_EMERG"Demo_read[-kernel--]\n");
#endif
return count;
}


size_t Demo_write(struct file *file,const char *buf,size_t count,loff_t * f_ops)
{
#ifdef Demo_DEBUG
printk(KERN_EMERG"Demo_write[-kernel-]\n");
#endif
return count;
}
int Demo_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long data)
{
#ifdef Demo_DEBUG
printk(KERN_EMERG"Demo_ioctl[-kernel-]\n");
#endif
return 0;
}


int Demo_open(struct inode * inode,struct file * file)
{
#ifdef Demo_DEBUG
printk(KERN_EMERG"Demo_open[-kernel-]\n");
#endif
//MOD_INC_USE_COUNT;
return 0;
}


int Demo_release(struct inode *inode,struct file *file)
{
#ifdef Demo_DEBUG
printk(KERN_EMERG"Demo_release[-kernel-]\n");
#endif
//MOD_DEC_USE_COUNT;
return 0;
}


struct file_operations Test_ctl_ops={
open: Demo_open,
read: Demo_read,
write: Demo_write,
ioctl: Demo_ioctl,
release: Demo_release,
};//a


static int HW_Test_CTL_init(void)
{
int ret = -ENODEV;
ret = register_chrdev(Demo_MAJOR,"demo_drv",&Test_ctl_ops);
if(ret<0)
{
printk(KERN_EMERG"Demo_module failed with %d\n[-kernel-]",ret);
return ret;
}
else
{
printk(KERN_EMERG"Demo_driver register success!!![-kernel-]\n");
}
printk("\n...\nret=%x\n...\n",ret);
showversin();
return ret;
}


static int Demo_Test_CTL_init(void)
{
int ret = -ENODEV;
#ifdef Demo_DEBUG
printk(KERN_EMERG"Demo_Test_CTL_init[-kernel-]\n");
#endif
ret = HW_Test_CTL_init();
if(ret)
return ret;
return 0;
}


static void cleanup_Test_ctl(void)
{
#ifdef Demo_DEBUG
printk(KERN_EMERG"cleanup_INT_CTL[-kernel-]\n");
#endif
unregister_chrdev(Demo_MAJOR,"demo_drv");
}


MODULE_DESCRIPTION("simple int drive module");
MODULE_LICENSE("GPL");
module_init(Demo_Test_CTL_init);

module_exit(cleanup_Test_ctl);

相比于hello world驱动程序,上面这个程序更加完整。

首先要介绍一个重要的结构体

struct     file_operations fops={

read: device_read;

write: device_write;

open: device_open;

release: device_release;

}

它的原型在<include/linux/fs.h>中

struct    file_operations{

struct  module * owner;

loff_t (*llseek)();

ssize_t     (*read)();

ssize_t     (*aio_read)();

ssize_te   (*write)();

.........

}

在结构体file_operations{}中,每一个成员的名字都对应一个系统调用,对应着设备驱动程序提供的入口位置

使用方法如第一个file_operations

read:device_read;........

这样我们在应用程序中调用read()对设备文件进行操作时,

驱动程序就会直接调用device_read()来进行读操作了。

现在我们知道了,应用程序中的函数是怎么与驱动程序中的操作函数对应起来了。那么驱动程序中的操作函数是

如何连接到设备文件上的呢?

靠register_chrdev()注册我们的设备

如上面代码:

ret   = register_chrdev(Demo_MAJOR,"demo_drv",&Test_ctl_ops);

第一个参数是我们的主设备号,第二个是我们要注册的设备的设备名,第三个是我们建立的结构体file_operations。

这三个参数都是有重要作用的。

第一个主设备号是内核识别我们设备的标志,内核通过主设备号识别我们的设备文件。

第二个是我们要注册的设备名,这个参数要与我们在/dev 目录下建立的设备文件名一致,这样我们才可以打开设备文件。

第三个是我们的结构体,它建立设备文件到设备操作函数的对应关系。

另外一个函数是:

unregister_chrdev()

unregister_chrdev(Demo_MAJOR,"demo_drv");

用来卸载我们的设备。

Makefile代码如下:

KERNELDIR ?= /lib/modules/2.6.25-14.fc9.i686/build/


PWD := $(shell pwd)
#CC=$(CROSS_COMPILE)gcc
obj-m :=Demo_Driver.o
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules


modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

然后执行命令:make

得到我们要加载的模块Demo_Driver.ko

这时候需要我们建立一个设备节点,也就是/dev/目录下的设备文件

mknod    /dev/demo_drv     c   98      0

第二个命令参数是我们注册的设备名

第三个命令参数是c代表char 字符型设备  b代表block块设备  u 是unbuff    p是fifo文件

第四个参数是主设备号,第五个参数是次设备号

接着我们编写一个应用程序进行一下测试

test_drive.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>


#define DEVICE_NAME "/dev/demo_drv"


int main()
{
int fd;
int ret;
char *i;
printf("\nstart Demo_driver test\n\n");
fd=open(DEVICE_NAME,O_RDWR);
printf("fd=%d\n",fd);
if(fd==-1)
{
printf("open device %s error\n",DEVICE_NAME);
}
else
{
read(fd,NULL,0);
write(fd,NULL,0);
ioctl(fd);
ret=close(fd);
printf("ret=%d\n",ret);
printf("close Demo_driver test\n");
}
return 0;
}

gcc  test_drive.c    -o  test_drive

然后执行程序

./test_drive

会有如下打印信息

鉴于本人比较懒,运行结果大家自己分析吧。

这个例子主要是告诉大家完整的驱动程序框架。

主要熟记三个东西

file_operation

register_chrdev

unregister_chrdev

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值