#include<linux/init.h> #include<linux/module.h> #include<linux/kernel.h> #include <linux/poll.h> /* COPY_TO_USER */ #include<linux/errno.h> #include <linux/cdev.h> #include <linux/slab.h> #define DEV_NAME "rwtest" #define DEV_NUM 2 #define DEV_MEM_SIZE 4096 static int major=0; //static int MAX_BUF_LEN=1024; static char drv_buffer[2][1024]; //static char drv_buf0[1024]; //static char drv_buf1[1024]; //static int WRI_LENGTH=0; struct cdev cdev; struct mem_dev * mem_devp; /*璁惧缁撴瀯浣撴寚閽?/ /*mem璁惧鎻忚堪缁撴瀯浣?/ struct mem_dev { char *data; unsigned long size; }; /***********鍐欏叆*************************/ static ssize_t dx_write(struct file *filp, const char __user *buffer, size_t size, loff_t * ppos) { unsigned long p=*ppos; unsigned int count =size; int ret=0; char * data=filp->private_data ; //struct mem_dev *dev = filp->private_data; /*鑾峰緱璁惧缁撴瀯浣撴寚閽?/ //struct mem_dev *dev=&mem_devp[0];/*鑾峰緱璁惧缁撴瀯浣撴寚閽? [0]*/ printk("data:::%s\n",data); if(p>=DEV_MEM_SIZE)return 0; if(count>DEV_MEM_SIZE-p) { count=DEV_MEM_SIZE-p; } printk("write p::%ld\n",p); /*浠庤繃鎴风┖闂村啓鍏ユ暟鎹?/ if(copy_from_user(data + p,buffer,count)) { ret=-EFAULT; } else { *ppos +=count; ret=count; printk(KERN_INFO "written %d bytes from %ld\n",count,p); } printk("write:%s\n",(char *)(filp->private_data+p)); printk("write buffer:%s\n",buffer); return count; } /**************************************璇诲彇***********************************************/ static ssize_t dx_read(struct file *filp, char __user *buffer, size_t size, loff_t *ppos) { //鏂囦欢璇诲彇浣嶇疆 unsigned long p=*ppos; unsigned int count =size;//瑕佽鍙栫殑,澶у皬 int ret=0; char * data=filp->private_data ; //struct mem_dev *dev = filp->private_data; /*鑾峰緱璁惧缁撴瀯浣撴寚閽?/ //struct mem_dev *dev=&mem_devp[0];/*鑾峰緱璁惧缁撴瀯浣撴寚閽? [0]*/ if(p>=DEV_MEM_SIZE) return 0; if(count>DEV_MEM_SIZE-p) { count=DEV_MEM_SIZE-p; } printk("read p::%ld\n",p); /*浠庢暟鎹鍒扮敤鎴风┖闂?*/ if(copy_to_user(buffer,data + p,count)) { ret=-EFAULT; } else { *ppos +=count; ret=count; printk(KERN_INFO "written %d bytes from %ld\n",count,p); } printk("read:%s\n",(char *)(filp->private_data)); printk("read buffer:%s\n",buffer); return count; } //===========================鎵撳紑========================================= static int dx_open(struct inode *inode, struct file *filp) { //printk("device open sucess!\n"); //struct mem_dev *dev; /*鑾峰彇娆¤澶囧彿*/ int num = MINOR(inode->i_rdev); if (num >= DEV_NUM) return -ENODEV; //dev = &mem_devp[num]; //dev = drv_buffer[num]; printk("num:%d\n",num); /*灏嗚澶囨弿杩扮粨鏋勬寚閽堣祴鍊肩粰鏂囦欢绉佹湁鏁版嵁鎸囬拡*/ filp->private_data = drv_buffer[num]; filp->f_pos +=strlen(drv_buffer[num]); printk("open:%s\n",(char *)filp->private_data); return 0; } /**********************************release***************************************************/ static int dx_release(struct inode *inode, struct file *filp) { printk("device release\n"); return 0; } static loff_t dx_llseek(struct file *filp, loff_t offset, int whence) { loff_t newpos; switch(whence) { case 0: /* SEEK_SET */ newpos = offset;//鏂囦欢寮€濮嬩綅缃姞鍋忕Щ閲? break; case 1: /* SEEK_CUR */ newpos = filp->f_pos + offset;//褰撳墠鎸囬拡浣嶇疆鍔犲亸绉婚噺 break; case 2: /* SEEK_END */ newpos = DEV_MEM_SIZE -1 + offset;//鏂囦欢鏈熬鍔犲亸绉婚噺(鏈€鍚庝竴浣嶄负'\0') break; default: /* can't happen */ return -EINVAL; } if ((newpos<0) || (newpos>DEV_MEM_SIZE)) return -EINVAL; filp->f_pos = newpos; return newpos; } //===============缁撴瀯浣?椹卞姩鍚勫睘鎬?========= static struct file_operations file_opt = { .owner= THIS_MODULE, .llseek= dx_llseek, .write= dx_write, .read= dx_read, .open= dx_open, .release=dx_release, }; //---------------------------------------------------------------------- static int __init qudong_init(void) { int ret; ret = register_chrdev(0, DEV_NAME, &file_opt); if(ret<0) { printk(DEV_NAME " can't get major number\n"); return 0; } major=ret; printk("dx module major number is %d\n", ret); return 0; } //----------------------------------------------------------------------- static void __exit qudong_exit(void) { /*娉ㄩ攢璁惧*/ cdev_del(&cdev); //kfree(mem_devp); /*閲婃斁璁惧缁撴瀯浣撳唴瀛?/ unregister_chrdev_region(MKDEV(major,0),1);/*閲婃斁璁惧鍙?/ printk("exit\n"); } module_init(qudong_init); module_exit(qudong_exit); MODULE_LICENSE("GPL");/*浣跨敤鏉冮檺*/ MODULE_AUTHOR("Made in China <[email protected]>");/*浣滆€?/ MODULE_DESCRIPTION("s3c6410 Hypervisor Filesystem");/*鐗堟湰*/
测试代码如下:
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include<string.h> int main() { int fd0=0; int fd1=0; int ret=0; char bufw[100]={'\0'}; char bufr[100]={'\0'}; char bufw1[100]={'\0'}; char bufr1[100]={'\0'}; fd0=open("/dev/rw0",O_RDWR); if(fd0<0) { perror("open error\n"); return 0; } fd1=open("/dev/rw1",O_RDWR); if(fd1<0) { perror("open error\n"); return 0; } printf("Please input string:\n"); scanf("%s",bufw); ret=write(fd0,bufw,strlen(bufw)); if(ret<0) { perror("write bufw error\n"); return 0; } printf("burw====%s\n",bufw); printf("Please input string:\n"); scanf("%s",bufw1); ret=write(fd1,bufw1,strlen(bufw1)); if(ret<0) { perror("write bufw1 error\n"); return 0; } printf("burw1====%s\n",bufw1); int num0=strlen(bufw); printf("num0:%d\n",num0); lseek(fd0,-(num0),SEEK_CUR); //lseek(fd0,0,SEEK_CUR); ret=read(fd0,bufr,99); if(ret<0) { perror("read bufr error\n"); return 0; } printf("bufr====%s\n",bufr); int num1=strlen(bufw1); printf("num1:%d\n",num1); lseek(fd1,-(num1),SEEK_CUR); //lseek(fd1,0,SEEK_SET); ret=read(fd1,bufr1,99); if(ret<0) { perror("read bufr1 error\n"); return 0; } printf("bufr1====%s\n",bufr1); close(fd0); close(fd1); return 0; }
Makefile文件:
## Makefile template. obj-m := qudong.o UNAME := $(shell uname -r) PWD := $(shell pwd) ADVMOD := qudong defualt: @make -C /lib/modules/$(UNAME)/build SUBDIRS=$(PWD) modules clean: @rm -f *.o @rm -f *.ko @rm -f *.mod.c @rm -f .*.cmd @rm -rf .tmp_versions #endif