linux字符驱动设备.docx_第1页
linux字符驱动设备.docx_第2页
linux字符驱动设备.docx_第3页
linux字符驱动设备.docx_第4页
linux字符驱动设备.docx_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux字符驱动设备的模板框架(2.4内核)/* leddrv.c - Create an input/output character device */#include #include #include #include /* for -EBUSY */#include /* for verify_area */#include /* for module_init */#include /* for get_user and put_user */#include #include drv.h#define BUF_LEN 4#define DEVICE_NAME char_dev/*驱动实现的功能函数*/static int device_open(struct inode *inode, struct file *file)static int device_release(struct inode *inode, struct file *file)static ssize_t device_read(struct file *file,char *buffer,size_t length, loff_t *offset) static ssize_t device_write(struct file *file,const char *buffer,size_t length,loff_t *offset)int device_ioctl(struct inode *inode,struct file *file,unsigned int ioctl_num, unsigned long ioctl_param) /*驱动实现的功能函数*/ /*模块加载、卸载、声明*/struct file_operations Fops = .read = device_read, .write = device_write,.open = device_open,.release = device_release,.ioctl= device_ioctl;/*这个文件结构体非常重要,联系内核和用户空间的桥梁*/* Initialize the module - Register the character device */static int _init led_module_init( void ) ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);/* Cleanup - unregister the appropriate file from /proc */static void _exit led_module_cleanup(void) ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME); ;module_init(led_module_init);module_exit(led_module_cleanup);MODULE_LICENSE(GPL);MODULE_AUTHOR(Cvtech Co., Ltd );MODULE_DESCRIPTION(LED char driver);/*模块加载、卸载、声明*/重要函数的说明:1、 模块注册删除函数:模块注册register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);功能:向内核注册一个字符驱动MAJOR_NUM 驱动主设备号。如果内核中已经相同的设备号,注册会失败。DEVICE_NAME设备名称模块删除unregister_chrdev( MAJOR_NUM, DEVICE_NAME ); 2、file_operationsstruct file_operations Fops = .read = device_read,/左边表示系统调用名称,右边表示编写的函数名.write = device_write,.open = device_open,.release = device_release,.ioctl= device_ioctl;file_operations结构体中的成员函数是字符驱动设备程序设计中的主体内容,这些函数实际会在应用程序进行Linux的open(),write(),close()等系统调用时最终被调用。file_operations的功能:file_operation就是把系统调用和驱动程序关联起来的关键数据结构。这个结构的每一个成员都对应着一个系统调用。读取file_operation中相应的函数指针,接着把控制权转交给函数,从而完成了Linux设备驱动程序的工作。 在系统内部,I/O设备的存取操作通过特定的入口点来进行,而这组特定的入口点恰恰是由设备驱动程序提供的。通常这组设备驱动程序接口是由结构file_operations结构体向系统说明的,它定义在include/linux/fs.h中。传统上, 一个 file_operation 结构或者其一个指针称为 fops( 或者它的一些变体). 结构中的每个成员必须指向驱动中的函数, 这些函数实现一个特别的操作, 或者对于不支持的操作留置为 NULL. 当指定为 NULL 指针时内核的确切的行为是每个函数不同的。file_operations的理解:内核内部通过file结构识别设备,通过file_operations数据结构提供文件系统的入口点函数,也就是访问设备驱动的函数。这个结构的每一个成员的名字都对应着一个系统调用。在用户进程利用系统调用对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数,这是Linux设备驱动程序工作的基本原理。从某种意义上说,写驱动程序的任务之一就是完成file_operations中的函数指针。File_operations相关的函数说明:static int device_open(struct inode *inode, struct file *file)struct file代表一个打开的文件,在执行file_operation中的open操作时被创建,这里需要注意的是与用户空间inode指针的区别,一个在内核,而file指针在用户空间,由c库来定义。 struct inode被内核用来代表一个文件,注意和struct file的区别,struct inode一个是代表文件,struct file一个是代表打开的文件static ssize_t device_read(struct file *file,char *buffer,size_t length, loff_t *offset)struct file*file 为文件结构体指针char*buffer是读取文件的缓冲区size_t length为读取信息的长度loff_t*offset 是读取文件当前的偏移位置,这个值通常是用来判断文件是否越界注意:1、由于驱动工作在内核态,所以打印语句需要使用printk()而不是printf()2、 在驱动编写的device_open和device_write以及device_ioctl这几个个函数中会访问用户空间的内存,但是我们不能直接引用传递过来指针,这些传递过来的指针都是指向用户内存空间的,在驱动中需要使用get_usr()函数和put_usr()函数来实现内核内存空间和用户内存空间之间的数据复制。get_usr(int a,int *buffer)从用户空间写入字符到内核空间设备文件:从缓冲区写入到变量aput_usr(int a, int*buffer)从内核空间设备文件读入字符到用户空间实例:用户空间输入字符static ssize_t device_write(struct file *file, const char *buffer, size_t length, loff_t *offset) int value; int bytes_writes = 4; int* data = (int*)buffer;内核空间从用户空间复制字符 char str256; get_user(value, data); flags = value; sprintf(str, device_write %dn, flags); printk(str); /* Again, return the number of input characters used */ return bytes_writes;驱动实例/* leddrv.c - Create an input/output character device */#include #include #include #include /* for -EBUSY */#include /* for verify_area */#include /* for module_init */#include /* for get_user and put_user */#include #include drv.h#define BUF_LEN 4#define DEVICE_NAME char_devint device_ioctl(struct inode *,struct file *,unsigned int ,unsigned long ); /* This function is called whenever a process attempts * to open the device file */static int device_open(struct inode *inode, struct file *file) printk(Device Openn); /* We dont want to talk to two processes at the * same time */ if (Device_Open) return -EBUSY; Device_Open+; /标记打开的设备数 MOD_INC_USE_COUNT; /* Initialize the message */ Message_Ptr = Message; /消息队列 return 0;/* This function is called when a process closes the * device file. It doesnt have a return value because * it cannot fail. Regardless of what else happens, you * should always be able to close a device (in 2.0, a 2.2 * device file could be impossible to close). */static int device_release(struct inode *inode, struct file *file) printk(device_releasen); /* Were now ready for our next caller */ Device_Open -; /标记当前设备数 MOD_DEC_USE_COUNT; return 0;static int flags = 0xff;/* This function is called whenever a process which * has already opened the device file attempts to * read from it. */static ssize_t device_read( struct file *file, char *buffer, /* The buffer to fill with the data */ size_t length, /* The length of the buffer */ loff_t *offset) /* offset to the file */ /* Number of bytes actually written to the buffer */ int bytes_read = 4; int * data=(int *)buffer; char str256; sprintf(str, device_read %dn, flags); /flags读入str printk(str); put_user(flags, data); /* Read functions are supposed to return the number * of bytes actually inserted into the buffer */ return bytes_read;/* This function is called when somebody tries to * write into our device file. */ static ssize_t device_write(struct file *file, const char *buffer, size_t length, loff_t *offset) int value; int bytes_writes = 4; int* data = (int*)buffer; char str256; get_user(value, data); flags = value; sprintf(str, device_write %dn, flags); printk(str); /* Again, return the number of input characters used */ return bytes_writes;/* This function is called whenever a process tries to * do an ioctl on our device file. We get two extra * parameters (additional to the inode and file * structures, which all device functions get): the number * of the ioctl called and the parameter given to the * ioctl function. * * If the ioctl is write or read/write (meaning output * is returned to the calling process), the ioctl call * returns the output of this function. */int device_ioctl( struct inode *inode, struct file *file, unsigned int ioctl_num,/* The number of the ioctl */ unsigned long ioctl_param) /* The parameter to it */ inttemp; int* data; int ioctl; char str256; printk(Device_ioctln); /* Switch according to the ioctl called */ switch (ioctl_num) case IOCTL_SET_MSG: /* Receive a pointer to a message (in user space) * and set that to be the devices message. */ /* Get the parameter given to ioctl by the process */ data = (int*) ioctl_param; get_user(temp, data); sprintf(str, Device_ioctl SET_MSG %dn, temp); printk(str); break; case IOCTL_GET_MSG: printk(Device_ioctl PUT_MSGn); break; return 0;/* Module Declarations * */* This structure will hold the functions to be called * when a process does something to the device we * created. Since a pointer to this structure is kept in * the devices table, it cant be local to * init_module. NULL is for unimplemented functions. */struct file_operations Fops = .read = device_read, .write = device_write,.open = device_open,.release = device_release,.ioctl= device_ioctl;/* Initialize the module - Register the character device */static int _init led_module_init( void ) int ret_val; /* Register the character device (atleast try) */ ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops); /* Negative values signify an error */ if (ret_val 0) printk (%s failed with %dn, Sorry, registering the character device , ret_val); return ret_val; printk (%s The major device number is %d.n, Registeration is a success, MAJOR_NUM); printk (If you want to talk to the device driver,n); printk (youll have to create a device file. n); printk (We suggest you use:n); printk (mknod %s c %d 0n, DEVICE_FILE_NAME,MAJOR_NUM); printk (The device file name is important, becausen); printk (the ioctl program assumes thats then); printk (file youll use.n); return 0;/* Cleanup - unregister the appropriate file from /proc */static void _exit led_module_cleanup(void) int ret; / release_region(LED_BASE, 12); /* Unregister the device */ ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME); /* If theres an error, report it */ if (ret 0) printk(Error in module_unregister_chrdev: %dn, ret);module_init(led_module_init);module_exit(led_module_cleanup);MODULE_LICENSE(GPL);MODULE_AUTHOR(Cvtech C

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论