您的位置:首页 > 运维架构 > Linux

Linux添加设备驱动步骤和实例

2012-06-09 16:25 661 查看
在系统内部,I/O设备等等存取通过一组固定的入口点来进行,这组入口点由每个

设备的设备驱动程序提供。在Linux系统里,设备驱动程序提供的入口点由一个结构来向系统进行说明,此结构体定义为:

Structfile_operations{

int (*lseek)(struct innode *innode, structfile *file,off_t off, int pos);

/*移动文件指针的位置*/

int (*read)(struct innode *innode, structfile *file, char *buf, int count);

/*读操作,buf为存放读取结果的缓冲区,count为要读取的数据长度*/

int (*write)(struct innode *innode, structfile *file, char *buf, int count);

/*写操作,与read类似*/

int (*readdir)(struct innode *innode, structfile *file, struct dirent *dirent, int count);

/*取得下一个目录入口点*/

int (*select)(struct innode *innode, structfile *file, int sel_type, select_table *wait);

/*检查设备,看数据是否可读或设备是否可用于写数据*/

int (*ioctl)(struct innode *innode, structfile *file, unsigned int cmd, unsigned int arg);

/*进行读写以外的其他特殊操作,参数cmd为自定义的命令*/

int (*mmap)(void)

/*把设备的内容映射到地址空间*/

int (*open)(struct innode *innode, structfile *file);

/*打开设备进行I/O操作*/

int (*release)(struct innode *innode, structfile *file);

/*关闭设备*/

}

操作步骤

①编写设备驱动程序zhangjiajie.c;

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

unsigned int zjj_major = 0;

/*buf涓哄瓨鏀捐鍙栫粨鏋滅殑缂撳啿鍖猴紝length涓鸿璇诲彇鏁版嵁鐨勯暱搴?/
static ssize_t zjj_read(struct file *file, char *buf, size_t length, loff_t *offset)
{
int n = 0;
n = min( strlen("zhangjiajie's driver!"), length );
if( copy_to_user(buf,"zhangjiajie's driver!", n) )
{
return -EFAULT;
}
return n;
}

static ssize_t zjj_write( struct file *file, const char *buf, size_t length,loff_t *offset)
{
return length;
}
static int zjj_open(struct inode *inode, struct file *file)
{
printk("open file succeed\n");
return 0;
}

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

static const struct file_operations zjj_fops = {
.open = zjj_open,
.read = zjj_read,
.write = zjj_write,
.release = zjj_release,
};

static int  __init zjj_init(void)
{
zjj_major = register_chrdev(0,"ZJJ_DRIVER",&zjj_fops);
if( zjj_major < 0 )
{
printk("register dirver error\n");
return -1;
}
else{
printk("register driver %d succeed\n",zjj_major);
}
return 0;
}

static void __exit zjj_exit(void)
{
unregister_chrdev(zjj_major,"ZJJ_DRIVER");
printk("unistall driver succeed\n");
}

module_init(zjj_init);
module_exit(zjj_exit);


②在zhangjiajie.c同一目录下编写Makefile文件;

obj-m:=zhangjiajie.o
KERNELBUILD:=/lib/modules/3.2.13/build
default:


③ $make:编译Makefile文件,生成zhangjiajie.ko文件;

④ $insmod./zhangjiajie.ko:挂载驱动;

⑤ $cat/proc/devices:查看添加的设备的主驱动号,我的驱动号为250,如下图3所示;



⑥ $mknod/dev/zhangjiajie c 250 0:挂载设备驱动。

⑦编译测试程序,测试驱动。

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

int main(void)
{
int fd, n;
char string[32];

for(n = 0; n < 32; n++){
string
= ' ';
}

printf("Input string: ");
scanf("%s",string);

fd = open("/dev/ZJJ_DRIVER",O_RDWR);
write(fd,string,32);
read(fd,string,32);
printf("from ZJJ_DRIVER: %s\n",string);

return 1;
}




用到的函数说明

(一)intregister_chrdev(unsigned int major, const char *name, struct

file_operations*fops);

major为设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态分配一个主设备号。Name是设备名。Fops为对各个调用的入口点的说明。

返回0便是返回成功,返回-EINVAL表示申请的主设备号非法,返回-EBUSY表示说申请的主设备号正被其他设备驱动程序使用。如果动态分配主设备号成功,会返回说分配的主设备号。

如果register_chrdev成功,设备名就会出现在/proc/devices文件里。

(二) obj-m:=zhangjiajie.o

Makefile中的该语句表示最终生成模块文件,生成的模块文件名为zhangjiajie.o。

(三) Make –Cxxx M=$(shell pwd) modules

表示首先改变目录到-C指定的位置,M=选项是makefile在构造modukes目标前,返

回到模块源码目录。然后modules目标指向obj-m变量中设定的模块。

操作过程中要注意到的

① .c驱动程序文件和 .o文件名要一致;

② Makefile文件名的M要大写;

③ make时需要切换到root权限。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: