#include<linux/init.h>
#include<linux/module.h>
#include<linux/types.h>
#include<linux/kdev_t.h>
#include<linux/fs.h>
#include<linux/slab.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#include <linux/wait.h>
#include<linux/sched.h>
MODULE_LICENSE("Dual BSD/GPL");
int open1(struct inode *inode, struct file *filp);
int close1(struct inode *inode, struct file *filp);
ssize_t read1(struct file *filp,char __user *buf,size_t count,loff_t *f_pos);
size_t mini (size_t count,size_t siz);
static ssize_t write1(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos);
int major=0;
int minor=0;
int i;
struct file_operations scull_fops =
{
.owner = THIS_MODULE,
.open = open1,
.read = read1,
.write = write1,
.release=close1,
};
struct scull_pipe
{
wait_queue_head_t inq;
wait_queue_head_t outq;
char *buffer, *end;
int buffersize;
int maxsize;
char *rp, *wp;
struct cdev cdev;
};
struct scull_pipe dev[4];
static void scull_setup_cdev(struct scull_pipe *dev,int i)
{
int err, devno = MKDEV(major, minor+i);
dev->maxsize=5;
cdev_init(&dev->cdev, &scull_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &scull_fops;
err = cdev_add (&dev->cdev, devno, 1);
init_waitqueue_head(&(dev->inq));
init_waitqueue_head(&(dev->outq));
dev->buffer=kmalloc(dev->maxsize,GFP_KERNEL);
if(dev->buffer==NULL)
{
printk(KERN_ALERT "error");
}
memset(dev->buffer,0,dev->maxsize);
dev->rp=dev->buffer;
dev->wp=dev->buffer;
dev->end=dev->buffer+dev->maxsize-1;
if (err)
printk(KERN_NOTICE "Error %d adding scull", err);
}
static int hello(void)
{
int result,devno;
if(major)
{
devno=MKDEV(major,minor);
result=register_chrdev_region(major,1,"pipe");
}
else
{
result=alloc_chrdev_region(&devno,minor,1,"pipe");
major=MAJOR(devno);
}
if(result<0)
return -1;
for(i=0;i<4;i++)
scull_setup_cdev(&dev[i],i);
return 0;
}
int open1(struct inode *inode, struct file *filp)
{
struct scull_pipe *ptr;
ptr=container_of(inode->i_cdev,struct scull_pipe, cdev);
filp->private_data=ptr;
return 0;
}
int close1(struct inode *inode, struct file *filp)
{
return 0;
}
ssize_t read1(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
int flag=0;
struct scull_pipe *dev = filp->private_data;
while (dev->rp==dev->wp)
{
if (wait_event_interruptible(dev->inq,(dev->rp!=dev->wp)))
return -1;
}
if (dev->wp > dev->rp)
count = mini(count,(size_t)(dev->wp-dev->rp));
else
count = mini(count,(size_t)(dev->end-dev->rp));
if(dev->rp+count==dev->end)
flag=1;
if (copy_to_user(buf, dev->rp,(count+flag)))
{
return -1;
}
dev->rp += count;
if (dev->rp==dev->end)
{
dev->rp = dev->buffer;
if(dev->wp==dev->end)
dev->wp=dev->buffer;
}
wake_up_interruptible(&dev->outq);
return (count+flag);
}
static int spacefree(struct scull_pipe *dev)
{
if (dev->rp == dev->wp)
return dev->maxsize - 1;
return ((dev->rp + dev->maxsize - dev->wp) % dev->maxsize) - 1;
}
static ssize_t write1(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
int flag=0;
struct scull_pipe *dev = filp->private_data;
while (spacefree(dev) == 0)
{
if (wait_event_interruptible(dev->outq, (spacefree(dev)!= 0)))
return -1;
}
count = mini(count, (size_t)spacefree(dev));
if (dev->wp >= dev->rp)
count = mini(count, (size_t)(dev->end - dev->wp));
else
count = mini(count, (size_t)(dev->rp - dev->wp - 1));
if(dev->wp+count==dev->end)
flag=1;
if (copy_from_user(dev->wp, buf,(count+flag)))
{
return -1;
}
dev->wp += count;
wake_up_interruptible(&dev->inq);
if (dev->wp == dev->end)
if(dev->rp!=dev->buffer)
dev->wp = dev->buffer;
return (count+flag);
}
size_t mini (size_t count,size_t siz)
{
if(count>siz)
return siz;
else
return count;
}
static void exit1(void)
{
for(i=0;i<4;i++)
cdev_del(&dev[i].cdev);
unregister_chrdev(major,"pipe");
}
module_init(hello);
module_exit(exit1);
#include<linux/module.h>
#include<linux/types.h>
#include<linux/kdev_t.h>
#include<linux/fs.h>
#include<linux/slab.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#include <linux/wait.h>
#include<linux/sched.h>
MODULE_LICENSE("Dual BSD/GPL");
int open1(struct inode *inode, struct file *filp);
int close1(struct inode *inode, struct file *filp);
ssize_t read1(struct file *filp,char __user *buf,size_t count,loff_t *f_pos);
size_t mini (size_t count,size_t siz);
static ssize_t write1(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos);
int major=0;
int minor=0;
int i;
struct file_operations scull_fops =
{
.owner = THIS_MODULE,
.open = open1,
.read = read1,
.write = write1,
.release=close1,
};
struct scull_pipe
{
wait_queue_head_t inq;
wait_queue_head_t outq;
char *buffer, *end;
int buffersize;
int maxsize;
char *rp, *wp;
struct cdev cdev;
};
struct scull_pipe dev[4];
static void scull_setup_cdev(struct scull_pipe *dev,int i)
{
int err, devno = MKDEV(major, minor+i);
dev->maxsize=5;
cdev_init(&dev->cdev, &scull_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &scull_fops;
err = cdev_add (&dev->cdev, devno, 1);
init_waitqueue_head(&(dev->inq));
init_waitqueue_head(&(dev->outq));
dev->buffer=kmalloc(dev->maxsize,GFP_KERNEL);
if(dev->buffer==NULL)
{
printk(KERN_ALERT "error");
}
memset(dev->buffer,0,dev->maxsize);
dev->rp=dev->buffer;
dev->wp=dev->buffer;
dev->end=dev->buffer+dev->maxsize-1;
if (err)
printk(KERN_NOTICE "Error %d adding scull", err);
}
static int hello(void)
{
int result,devno;
if(major)
{
devno=MKDEV(major,minor);
result=register_chrdev_region(major,1,"pipe");
}
else
{
result=alloc_chrdev_region(&devno,minor,1,"pipe");
major=MAJOR(devno);
}
if(result<0)
return -1;
for(i=0;i<4;i++)
scull_setup_cdev(&dev[i],i);
return 0;
}
int open1(struct inode *inode, struct file *filp)
{
struct scull_pipe *ptr;
ptr=container_of(inode->i_cdev,struct scull_pipe, cdev);
filp->private_data=ptr;
return 0;
}
int close1(struct inode *inode, struct file *filp)
{
return 0;
}
ssize_t read1(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
int flag=0;
struct scull_pipe *dev = filp->private_data;
while (dev->rp==dev->wp)
{
if (wait_event_interruptible(dev->inq,(dev->rp!=dev->wp)))
return -1;
}
if (dev->wp > dev->rp)
count = mini(count,(size_t)(dev->wp-dev->rp));
else
count = mini(count,(size_t)(dev->end-dev->rp));
if(dev->rp+count==dev->end)
flag=1;
if (copy_to_user(buf, dev->rp,(count+flag)))
{
return -1;
}
dev->rp += count;
if (dev->rp==dev->end)
{
dev->rp = dev->buffer;
if(dev->wp==dev->end)
dev->wp=dev->buffer;
}
wake_up_interruptible(&dev->outq);
return (count+flag);
}
static int spacefree(struct scull_pipe *dev)
{
if (dev->rp == dev->wp)
return dev->maxsize - 1;
return ((dev->rp + dev->maxsize - dev->wp) % dev->maxsize) - 1;
}
static ssize_t write1(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
int flag=0;
struct scull_pipe *dev = filp->private_data;
while (spacefree(dev) == 0)
{
if (wait_event_interruptible(dev->outq, (spacefree(dev)!= 0)))
return -1;
}
count = mini(count, (size_t)spacefree(dev));
if (dev->wp >= dev->rp)
count = mini(count, (size_t)(dev->end - dev->wp));
else
count = mini(count, (size_t)(dev->rp - dev->wp - 1));
if(dev->wp+count==dev->end)
flag=1;
if (copy_from_user(dev->wp, buf,(count+flag)))
{
return -1;
}
dev->wp += count;
wake_up_interruptible(&dev->inq);
if (dev->wp == dev->end)
if(dev->rp!=dev->buffer)
dev->wp = dev->buffer;
return (count+flag);
}
size_t mini (size_t count,size_t siz)
{
if(count>siz)
return siz;
else
return count;
}
static void exit1(void)
{
for(i=0;i<4;i++)
cdev_del(&dev[i].cdev);
unregister_chrdev(major,"pipe");
}
module_init(hello);
module_exit(exit1);
0 nhận xét:
Đăng nhận xét