📄 chardev.c
字号:
/**************************************************************/
/***** chardev.c *****/
/**************************************************************/
#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#define WE_REALLY_WANT_TO_USE_A_BROKEN_INTERFACE#define __NO_VERSION__#include <linux/version.h>#include <linux/module.h>char kernel_version[]=UTS_RELEASE;#include <linux/kernel.h>#include <linux/mm.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/ioport.h>#include <linux/malloc.h>#include <linux/string.h>#include <asm/io.h>#include <asm/segment.h>#include <asm/uaccess.h>
#include "chardev.h"
#define DEVICE_NAME "dynchar"static int usage,new_msg; // control flags
static char *data;// open the device
static int dynchar_open(struct inode *inode,struct file *filp) { MOD_INC_USE_COUNT; printk("This chrdev is in open!\n"); return 0; }
// close the device
static int dynchar_release(struct inode *inode,struct file *filp) {
MOD_DEC_USE_COUNT;
printk("This chrdev is in release!\n");
return 0;
}
// write to device -transfer from user space to kernel space static ssize_t dynchar_write(struct file *filp,const char *buf,
size_t count,loff_t *offset) { if(count<0) return -EINVAL; if(usage || new_msg) return -EBUSY; usage=1; kfree(data); data=kmalloc(sizeof(char)*(count+1),GFP_KERNEL); if(!data) { return -ENOMEM; } copy_from_user(data,buf,count+1); // start transfering usage=0; new_msg=1; return count; } // read from device -transfer from kernel space to user space static ssize_t dynchar_read(struct file *filp,char *buf,size_t count,
loff_t *offset) { int length; if(count<0) return -EINVAL; if(usage) return -EBUSY; usage=1; if(data==NULL) return 0; length=strlen(data); if(length<count) count=length; copy_to_user(buf,data,count+1); // start transfering new_msg=0; usage=0; return count; }// ioctl for device -control or set the device static int dynchar_ioctl(struct inode *inode,struct file *filp,
unsigned long int cmd,unsigned long arg) { int ret=0; switch(cmd) {
case DYNCHAR_RESET;
kfree(data);
data=NULL;
usage=0;
new_msg=0;
break;
case DYNCHAR_QUERY_NEW_MSG:
if(new_msg)
return IOC_NEW_MSG;
break;
case DYNCHAR_QUERY_MSG_LENGTH:
if(data==NULL) {
return 0;
}
else {
return strlen(data);
}
break;
default: return -ENOTTY; } return ret; }
struct file_operations dynchar_fops={ NULL, // seek dynchar_read, // read dynchar_write, // write NULL, // readdir NULL, // poll dynchar_ioctl, // ioctl NULL, // mmap dynchar_open, // open
NULL, // flush dynchar_release, // release NULL, // fsync NULL, // fasync NULL, // check media change NULL, // revalidate
NULL // lock };// Initialize the module -Register the character device int init_module(){ if(register_chrdev(DYNCHAR_MAJOR,DEVICE_NAME,&dynchar_fops)) {
printk("registering character device major: %d failed!\n",DYNCHAR_MAJOR);
return -EIO;
} // initialize the data ptr
data=NULL;
usage=0;
new_msg=0; return 0; }// Clean up -Unregister the character device void cleanup_module() {
// free data memory if any
if(data)
kfree(data); unregister_chrdev(DYNCHAR_MAJOR,DEVICE_NAME); printk("Sorry! The dynchar is unloading now!\n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -