c - 跨用户的字符设备 I/O
问题描述
我正在学习 Linux,但我有我无法处理的任务。我必须创建字符设备并使跨用户读写成为可能。例如,我打开第一个终端并使用echo 'test' > /tmp/ringdev
(ringdev
我的字符设备在哪里)。我还打开第二个终端并使用cat /tmp/ringdev
,我希望输出为test
. 我已经阅读了一些示例片段,但所有这些都只是我已经拥有的基础知识。
问题是如何跨用户读取/写入字符设备?
#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/wait.h>
#include <linux/sched.h>
DECLARE_WAIT_QUEUE_HEAD(head);
/*
* mutex used for access synchronization to buffer (ringdev_buf and ringdev_len)
*/
static struct mutex ringdev_lock;
/*
* buffer and number of written bytes in the buffer
*/
static char ringdev_buf[4096];
static size_t ringdev_len;
static int ringdev_open(struct inode *inode, struct file *filp)
{
printk("device_open called \n");
return 0;
}
static ssize_t ringdev_read(struct file *filp, char __user *buf, size_t count,
loff_t *off)
{
ssize_t ret = 0;
printk("device_read called \n");
/*
* access to ringdev_buf i ringdev_len is protected by ringdev_lock,
* take that lock
*/
//wait_event_interruptible(head,ringdev_len!=0);
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);
ringdev_len=0;
return ret;
}
static ssize_t ringdev_write(struct file *filp, const char __user *buf,
size_t count, loff_t *off)
{
ssize_t ret=0;
ringdev_len=0;
printk("device_write called \n");
mutex_lock(&ringdev_lock);
ret=-EFAULT;
if(copy_from_user(ringdev_buf+ringdev_len ,buf, count)==0){
ringdev_len= ringdev_len + count;
ret=count;
wake_up_interruptible(&head);
goto out_unlock;
}
else{
ret=-ENOSPC;
}
/*
* not supported yet. Do not forget about copy_from_user().
*/
out_unlock:
mutex_unlock(&ringdev_lock);
return ret;
}
static int ringdev_release(struct inode *inode, struct file *filp)
{
mutex_unlock(&ringdev_lock);
printk("device_release called \n");
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;
mutex_init(&ringdev_lock);
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("Device");
MODULE_AUTHOR("xxx");
MODULE_LICENSE("GPL");
解决方案
推荐阅读
- syntax-highlighting - 自 Atom 1.32.0 以来,语法高亮(在模板文字中)发生了什么变化?
- angular - 使用 Angular 的 GET 请求中出现错误 [object Object]
- javascript - 导入要在 HTML 表单提交时调用的 JS 模块
- python - 如何查看 Python 的假设库的输出
- html - 使用 onmouseover 函数显示“热点”区域以及静态文本
- c# - 必须声明标量变量“@soNum”。一种方法有效,另一种无效
- mysql - MySQL - 在第二个表中选择具有某些值的行
- ios - 在 iOS 中处理 AWSAppSyncClient 超时
- r - 在 R 中打开 .bin 文件
- ios - 如何避免厄运金字塔 - iOS?