模拟有名管道驱动
2015-09-09 22:04
204 查看
``` #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/ioctl.h> #include <asm/uaccess.h> #include <linux/slab.h> // kmalloc kfree #define PIPE_UDEV //#define PIPE_KMALLOC //#define PIPE_DEBUG_MSG #define PIPE_IOC_BUFFER_CLEAR _IO ('P', 1) #define PIPE_IOC_BUFFER_LENGTH _IOR ('P', 2, unsigned int) #define PIPE_IOC_BUFFER_AVAIL _IOR ('P', 3, unsigned int) #define MAX_STRING_LENGTH 1024 char msg[MAX_STRING_LENGTH + 1]; #if !defined ( PIPE_KMALLOC ) // 没有定义PIPE_KMALLOC,使用数组模拟管道 #define PIPE_BUFFER_SIZE 4096 #define PIPE_BUFFER_MASK 0x0FFF //#define PIPE_BUFFER_VALUE(x) ( (x) & PIPE_BUFFER_MASK ) #define PIPE_BUFFER_EMPTY(pipe) ( (pipe)->head == (((pipe)->tail + 1) & PIPE_BUFFER_MASK) ) #define PIPE_BUFFER_FULL(pipe) ( (pipe)->head == (((pipe)->tail + 2) & PIPE_BUFFER_MASK) ) // 避免与队空情况相同,队满间隔为2 #define DATA_TYPE char //#define COPY_DATA_TYPE(pDest,pSrc) ( *(pDset) = *(pSrc) ) struct my_pipe { int head, tail; DATA_TYPE buffer[PIPE_BUFFER_SIZE]; }pipe; void init_pipe (struct my_pipe * pipe) { pipe->head = 0; // head指向队首元素 pipe->tail = -1; // tail指向队尾元素 } void clear_pipe (struct my_pipe * pipe) { pipe->head = 0; // head指向队首元素 pipe->tail = -1; // tail指向队尾元素 } int push_pipe (struct my_pipe * pipe, DATA_TYPE * data) // 入队 { if (PIPE_BUFFER_FULL(pipe)) return -1; // 满队列 pipe->tail = ((pipe->tail + 1) & PIPE_BUFFER_MASK); // 新元素位置 pipe->buffer[pipe->tail] = *data; return 0; } int pop_pipe (struct my_pipe * pipe) // 出队 { if (PIPE_BUFFER_EMPTY(pipe)) return -1; // 空队列 pipe->head = ((pipe->head + 1) & PIPE_BUFFER_MASK); return 0; } int top_pipe (struct my_pipe * pipe, DATA_TYPE * dest) // 获取队首元素 { if (PIPE_BUFFER_EMPTY(pipe)) return -1; // 空队列 *dest = pipe->buffer[pipe->head]; return 0; } int length_pipe (struct my_pipe * pipe) { if (PIPE_BUFFER_EMPTY(pipe)) return 0; if (pipe->head <= pipe->tail) return (pipe->tail - pipe->head + 1); else return (pipe->tail - pipe->head + 1 + PIPE_BUFFER_SIZE); } int avail_pipe (struct my_pipe * pipe) { if (PIPE_BUFFER_EMPTY(pipe)) return PIPE_BUFFER_SIZE; if (pipe->head <= pipe->tail) return PIPE_BUFFER_SIZE - (pipe->tail - pipe->head + 1); else return PIPE_BUFFER_SIZE - (pipe->tail - pipe->head + 1 + PIPE_BUFFER_SIZE); } #endif // !PIPE_KMALLOC #ifdef PIPE_UDEV static struct class * zone_pipe_class = NULL; static struct device * zone_pipe_device = NULL; #endif // PIPE_UDEV static struct cdev * zone_pipe = NULL; // 字符设备指针(管道) static dev_t zone_pipe_devno; // 设备号 static ulong zone_pipe_major = 0; // 主设备号 static ulong zone_pipe_minor = 0; // 次设备号 //module_param (zone_pipe_devno, ulong, 0660); module_param (zone_pipe_major, ulong, 0660); static int zone_pipe_open (struct inode * inode, struct file * filp) { #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "zone_pipe_open ...\n"); #endif // PIPE_DEBUG_MSG #if !defined ( PIPE_KMALLOC ) init_pipe (&pipe); #endif // !PIPE_KMALLOC return 0; } static int zone_pipe_release (struct inode * inode, struct file * filp) { #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "zone_pipe_release ...\n"); #endif // PIPE_DEBUG_MSG return 0; } static ssize_t zone_pipe_write (struct file * filp, const char __user * buf, size_t count, loff_t * f_pos) { #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "zone_pipe_write ...\n"); #endif // PIPE_DEBUG_MSG int ret, len, cnt, i, num; #if !defined ( PIPE_KMALLOC ) for (cnt=0, num=count; num; num-=cnt) { // 写完 cnt = (num <= MAX_STRING_LENGTH) ? num : MAX_STRING_LENGTH; len = cnt - copy_from_user (msg, buf, cnt); for (i=0; i<len; ++i) if ( (ret = push_pipe (&pipe, &msg[i]))) { // 满队列 #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "\t pipe full ...\n"); #endif // PIPE_DEBUG_MSG return (count - num + i); } if (len != cnt) { // 地址出错 return (count - num + len); } } #endif // !PIPE_KMALLOC return count; } static ssize_t zone_pipe_read (struct file * filp, const char __user * buf, size_t count, loff_t * f_pos) { #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "zone_pipe_read ...\n"); #endif // PIPE_DEBUG_MSG int ret, len, cnt, i, num; #if !defined ( PIPE_KMALLOC ) char ch; for (cnt=0, num=count; num; num-=cnt) { // 写完 cnt = (num <= MAX_STRING_LENGTH) ? num : MAX_STRING_LENGTH; for (i=0; i<cnt; ++i) { if ( (ret = top_pipe (&pipe, &ch)) < 0) { // 空队列 #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "\t pipe empty ...\n"); #endif // PIPE_DEBUG_MSG cnt = i; break; } msg[i] = ch; pop_pipe (&pipe); } len = cnt - copy_to_user (buf, msg, cnt); if (ret < 0) { return (count - num + len); } if (len != cnt) { // 地址出错 return (count - num + len); } } #endif // !PIPE_KMALLOC return count; } static long zone_pipe_ioctl (struct file * filp, unsigned int cmd, unsigned long arg) { int ret = 1, length; #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "zone_pipe_ioctl ...\n"); #endif // PIPE_DEBUG_MSG if (_IOC_DIR (cmd) & _IOC_READ) { ret = access_ok (VERIFY_WRITE, (void __user *)arg, _IOC_SIZE (cmd)); } else { ret = access_ok (VERIFY_READ, (void __user *)arg, _IOC_SIZE (cmd)); } if (!ret) { #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "_IOC_DIR error ...\n"); #endif // PIPE_DEBUG_MSG return -EFAULT; } switch (cmd) { case PIPE_IOC_BUFFER_LENGTH: #if !defined ( PIPE_KMALLOC ) length = length_pipe (&pipe); ret = put_user (length, (int *)arg); #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "\t pipe length = %d ...\n", length); #endif // PIPE_DEBUG_MSG #endif // !PIPE_KMALLOC break; case PIPE_IOC_BUFFER_AVAIL: #if !defined ( PIPE_KMALLOC ) length = avail_pipe (&pipe); ret = put_user (length, (int *)arg); #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "\t pipe avail = %d ...\n", length); #endif // PIPE_DEBUG_MSG #endif // !PIPE_KMALLOC break; case PIPE_IOC_BUFFER_CLEAR: #if !defined ( PIPE_KMALLOC ) clear_pipe (&pipe); #endif // !PIPE_KMALLOC break; default: break; } return 0; } static struct file_operations zone_pipe_fops = { .owner = THIS_MODULE, .open = zone_pipe_open, .release = zone_pipe_release, .write = zone_pipe_write, .read = zone_pipe_read, .unlocked_ioctl = zone_pipe_ioctl }; static int __init zone_pipe_init (void) { int ret; #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "zone_pipe_init ...\n"); #endif // PIPE_DEBUG_MSG if (zone_pipe_major) { // 设置了主设备号模块参数 ret = register_chrdev_region (&zone_pipe_devno, 1, "zone_pipe_devno"); } else { zone_pipe_devno = MKDEV (zone_pipe_major, zone_pipe_minor); ret = alloc_chrdev_region (&zone_pipe_devno, 0, 1, "zone_pipe_devno"); } if (ret < 0) { // 申请设备号出错 printk (KERN_INFO "zone_pipe_init : Register devno error ...\n"); return -EFAULT; } zone_pipe_major = MAJOR (zone_pipe_devno); // 主设备号 zone_pipe_minor = MINOR (zone_pipe_devno); // 次设备号 #ifdef PIPE_DEBUG_MSG // 打印主设备号,次设备号 printk (KERN_INFO "zone_pipe_devno %lu %lu\n", zone_pipe_major, zone_pipe_minor); #endif // PIPE_DEBUG_MSG zone_pipe = cdev_alloc (); // 分配空间 //cdev_init (zone_pipe, &zone_pipe_fops); // 结构体需要初始化 zone_pipe->ops = &zone_pipe_fops; // 指针需要设置ops指针 zone_pipe->owner = THIS_MODULE; if (cdev_add (zone_pipe, zone_pipe_devno, 1) < 0) { // 加入字符设备内核链表 printk (KERN_INFO "zone_pipe_init : Add cdev kernel_list error ...\n"); return -EFAULT; } #ifdef PIPE_UDEV zone_pipe_class = class_create (THIS_MODULE, "zone_pipe_class"); if (IS_ERR (zone_pipe_class)) { printk (KERN_INFO "zone_pipe_init : class_create error ...\n"); cdev_del (zone_pipe); unregister_chrdev_region (zone_pipe_devno, 1); return -EFAULT; } zone_pipe_device = device_create (zone_pipe_class, NULL, zone_pipe_devno, NULL, "zone_pipe_device"); #endif // PIPE_UDEV return 0; } static void __exit zone_pipe_exit (void) { cdev_del (zone_pipe); unregister_chrdev_region (zone_pipe_devno, 1); zone_pipe_devno = 0; #ifdef PIPE_UDEV device_destroy (zone_pipe_class, zone_pipe_devno); class_destroy (zone_pipe_class); #endif // PIPE_UDEV #ifdef PIPE_DEBUG_MSG printk (KERN_INFO "zone_pipe_exit ...\n"); #endif // PIPE_DEBUG_MSG } MODULE_LICENSE ("GPL"); MODULE_AUTHOR ("wilson1068@163.com"); module_init (zone_pipe_init); module_exit (zone_pipe_exit);
“`
相关文章推荐
- git 删除右键菜单
- AUC---Binary classifier metric
- springmvc上传临时文件目录配置
- 网络流例题及构图选讲
- 文章标题
- 40种网站常用Javascript技巧
- IO流详解之代码详解
- 学习MySQL之数据类型(四)
- Markdown学习(二)
- MLNG_线性回归_梯度下降_正规方程组
- 【Direct3D】使用深度检测画两个平面
- 2015第37周三
- 勇者斗恶龙 UVA 11292
- maxPathSum
- 纽曼纽扣偷袭奇酷青春,YunOS与360OS会不会发生点什么
- 学习使用Mark Man、Axure
- think in java 学习笔记(一)方法重载
- UI设计编程:基础视图、程序启动流程
- Java.的包装类
- BZOJ 1114 Number theory(莫比乌斯反演+预处理)