📄 chardev.c
字号:
#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/malloc.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/proc_fs.h>#include <linux/fcntl.h>#include <asm/system.h>#include "chardev.h"long chardev_buflen=CHARDEV_BUFLEN;int chardev_major=CHARDEV_MAJOR;CHAR_DEV *char_dev;MODULE_PARM(chardev_major,"i");MODULE_AUTHOR("Lipeng,BUAA");#ifdef CHARDEV_DEBUG /* use proc only if debugging *//* * The proc filesystem: function to read and entry */int chardev_read_procmem(char *buf, char **start, off_t offset, int count, int *eof, void *data){ }#endifstruct file_operations chardev_fops = { open: chardev_open, release:chardev_release, read: chardev_read, write: chardev_write,};int chardev_trim(CHAR_DEV* dev){ if (dev->data) { kfree(dev->data); dev->data=NULL; } return 0;}int chardev_open(struct inode *inode, struct file *filp){ CHAR_DEV *dev; dev=(CHAR_DEV*)filp->private_data; if (!dev) { dev=char_dev; filp->private_data=dev; } MOD_INC_USE_COUNT; if ((filp->f_flags & O_ACCMODE)==O_WRONLY) { if (down_interruptible(&dev->sem)) { MOD_DEC_USE_COUNT; return -ERESTARTSYS; } chardev_trim(dev); up(&dev->sem); } return 0;}int chardev_release(struct inode *inode, struct file *filp){ MOD_DEC_USE_COUNT; return 0;}ssize_t chardev_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){ CHAR_DEV *dev=filp->private_data; ssize_t ret=0; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (*f_pos>=chardev_buflen) goto out; if (*f_pos+count>chardev_buflen) count=chardev_buflen-(long)*f_pos; if (copy_to_user(buf,dev->data+*f_pos,count)) { ret=-EFAULT; goto out; } *f_pos+=count; ret=count; out: up(&dev->sem); return ret;}ssize_t chardev_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos){ CHAR_DEV *dev=filp->private_data; ssize_t ret=0; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (*f_pos>=chardev_buflen) goto out; if (count>chardev_buflen-(long)*f_pos) count=chardev_buflen-(long)*f_pos; if (!dev->data) { dev->data=kmalloc(chardev_buflen,GFP_KERNEL); if (!dev->data) goto out; memset(dev->data,0,chardev_buflen); } if (copy_from_user(dev->data+(long)*f_pos,buf,count)) { ret=-EFAULT; goto out; } *f_pos+=count; ret=count; out: up(&dev->sem); return ret;}/*lofft chardev_llseek(struct file *filp, loff_t f_pos, int count){ if ( }*/int chardev_init_module(void){ int ret=0; SET_MODULE_OWNER(&chardev_fops); ret=register_chrdev(chardev_major,"chardev",&chardev_fops); if (ret<0) { printk(KERN_WARNING "chardev:can't get major:%d\n",chardev_major); return ret; } if (chardev_major==0) chardev_major=ret; char_dev=kmalloc(sizeof(CHAR_DEV),GFP_KERNEL); if (char_dev==NULL) { printk(KERN_WARNING "error to allocate DEVICE char_dev\n"); ret=-ENOMEM; goto fail; } memset(char_dev,0,sizeof(CHAR_DEV)); sema_init(&(char_dev->sem),1); printk("init module succeed\n"); EXPORT_NO_SYMBOLS; return 0; fail: chardev_cleanup_module(); return ret;}void chardev_cleanup_module(void){ unregister_chrdev(chardev_major,"chardev"); kfree(char_dev->data); kfree(char_dev);}module_init(chardev_init_module);module_exit(chardev_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -