Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Ring buffer character device - example for Operating System course
- *
- * Copyright (C) 2016, 2017, 2018 Krzysztof Mazur <krzysiek@podlesie.net>
- *
- * Add your copyright here and change MODULE_AUTHOR.
- *
- * Copyright(C) 2019 Jakub Glowacki, Karolina Szotek, Jakub Berwid <jakuglo773@student.polsl.pl> <jakuber444@student.polsl.pl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
- #define pr_fmt(fmt) "ringdev: " fmt
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/miscdevice.h>
- #include <linux/sched.h>
- #include <linux/uaccess.h>
- #include <linux/slab.h>
- /*
- * mutex used for access synchronization to buffer (ringdev_buf and ringdev_len)
- */
- static struct mutex ringdev_lock;
- #define BUFFOR 64
- static char ringdev_buf[BUFFOR];
- static DECLARE_WAIT_QUEUE_HEAD(queue);
- static size_t ringdev_len;
- static size_t HEAD;
- //static size_t TAIL;
- static int ringdev_open(struct inode *inode, struct file *filp)
- {
- size_t *tail_p=kmalloc(sizeof(size_t),GFP_KERNEL);
- *tail_p = HEAD;
- filp->private_data=tail_p;
- return 0;
- }
- static ssize_t ringdev_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
- {
- ssize_t ret=0;
- size_t TAIL=0;
- size_t* read_p;
- read_p = filp->private_data;
- TAIL=*read_p;
- turn_back:
- if ((filp->f_flags & O_NONBLOCK) && HEAD==TAIL)
- {
- return -EAGAIN;
- }
- else if(!(filp->f_flags & O_NONBLOCK) && HEAD!=TAIL)
- {
- wait_event_interruptible(queue, HEAD != TAIL);
- }
- if (HEAD==*read_p) goto turn_back;
- mutex_lock(&ringdev_lock);
- count=(count>HEAD-TAIL) ? (HEAD-TAIL):(BUFFOR-TAIL);
- //if (count>HEAD-TAIL)
- //{
- // count=HEAD-TAIL;
- //}
- ret=copy_to_user(buf,ringdev_buf+TAIL,count);
- TAIL+=count-ret;
- if (TAIL>=BUFFOR)
- {
- TAIL=0;
- }
- *read_p=TAIL;
- mutex_unlock(&ringdev_lock);
- return count -ret;
- /*
- * access to ringdev_buf i ringdev_len is protected by ringdev_lock,
- * take that lock
- mutex_lock(&ringdev_lock);
- if (*off > ringdev_len)
- count = 0;
- else if (count >= ringdev_len - *off)
- count = ringdev_len - *off;
- * for access to user memory special functions must be used,
- * to copy to user memory copy_to_user must be used.
- ret = -EFAULT;
- if (copy_to_user(buf, ringdev_buf + *off, count))
- goto out_unlock;
- ret = count;
- *off += ret;
- out_unlock:
- mutex_unlock(&ringdev_lock);
- return ret;
- */
- }
- static ssize_t ringdev_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *off)
- {
- ssize_t ret = 0;
- mutex_lock(&ringdev_lock);
- if(count>=BUFFOR-HEAD)
- {
- count =BUFFOR-HEAD;
- }
- ret=copy_from_user(ringdev_buf+HEAD, buf, count);
- HEAD+=count-ret;
- if(HEAD>=BUFFOR)
- {
- HEAD=0;
- }
- mutex_unlock(&ringdev_lock);
- wake_up_interruptible(&queue);
- return count -ret;
- /*
- ret = -EFAULT;
- if(copy_from_user(ringdev_buf, buf, count ))
- {
- goto out_unlock;
- }
- ret = count;
- ringdev_len = count;
- out_unlock:
- mutex_unlock(&ringdev_lock);
- return ret;
- // return -EINVAL;
- */
- }
- static int ringdev_release(struct inode *inode, struct file *filp)
- {
- return 0;
- }
- static const struct file_operations ringdev_fops = {
- .owner = THIS_MODULE,
- .open = ringdev_open,
- .read = ringdev_read,
- .write = ringdev_write,
- .release = ringdev_release,
- };
- static struct miscdevice ringdev_miscdevice = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "ringdev",
- .fops = &ringdev_fops
- };
- static int __init ringdev_init(void)
- {
- int ret;
- init_waitqueue_head(&queue);
- mutex_init(&ringdev_lock);
- ringdev_len = snprintf(ringdev_buf, sizeof(ringdev_buf),
- "PAN TADEUSZ\n");
- ret = misc_register(&ringdev_miscdevice);
- if (ret < 0)
- {
- pr_err("can't register miscdevice.\n");
- return ret;
- }
- pr_info("minor %d\n", ringdev_miscdevice.minor);
- return 0;
- }
- static void __exit ringdev_exit(void)
- {
- misc_deregister(&ringdev_miscdevice);
- mutex_destroy(&ringdev_lock);
- }
- module_init(ringdev_init);
- module_exit(ringdev_exit);
- MODULE_DESCRIPTION("Ring buffer device");
- MODULE_AUTHOR("Jakub Glowacki Karolina Szotek Jakub Berwid");
- MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement