我正试着读和写给一个司机。当我使用C程序打开设备文件并进行读写时,它会产生SEG错误。当我在设备文件中使用cat时,它会进入无限循环。
1)我遗漏了什么,在file_operations中读写的正确实现是什么?
2)在原型读写中我知道:read(struct file *fp, char *ch, size_t count, loff_t *lofft)计数指的是读/写请求的字节数。但是,使用的最后一个参数偏移量是什么,需要对偏移量进行哪些检查?
3)对于像cat /dev/chardriver这样的多个读取调用,每次读取时是否会增加偏移量?就像count=100的第一次读取呼叫偏移量从1到100一样,在下一次读取呼叫中,偏移量会从101偏移吗?还是会从任何随机数中消失?
这是我的代码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
char kernelbuff[1024];
MODULE_LICENSE("GPL");
struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
int device_open(struct inode *inode, struct file *fp)
{
printk("device_open called");
return 0;
}
static int device_release(struct inode *inode, struct file *fp)
{
printk("device_release called");
return 0;
}
static ssize_t device_read(struct file *fp, char *ch, size_t sz, loff_t *lofft)
{
printk("device_read called");
copy_to_user(ch, kernelbuff, 1024);
return sz;
}
static ssize_t device_write(struct file *fp, const char *ch, size_t sz, loff_t *lofft)
{
printk("device_write called");
copy_from_user(kernelbuff, ch, 50);
return 1024;
}
static int hello_init(void)
{
printk("basicchardriver: module initialized");
register_chrdev(500, "chr_device", &fops);
return 0;
}
static void hello_exit(void)
{
printk("basicchardriver: module exited");
unregister_chrdev(500, "chr_device");
}
module_init(hello_init);
module_exit(hello_exit);
}测试:
sudo mknod -m 666 /dev/chardev c 500 0
echo "Hello World" >> /dev/chardev ===> Works fine
cat /dev/chardev ===> Goes to infinite loop如果我使用C程序调用驱动程序,就会产生SEG错误:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
int fd;
char buff[500];
fd = open("/dev/chardev", O_RDWR);
write(fd, "Hello World", 13);
read(fd, buff, 500);
printf("Reading data from kernel: \t");
puts(buff);
return 0;
}
raj@raj-VirtualBox:~/device-driver/chardriver/read-write$ ./a.out
Reading data from kernel: Hello World
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)发布于 2020-02-29 20:32:29
我想我的问题得到了正确的答案:(专家们可以随意添加您自己的答案,/modify)
下面是正确的阅读方式:
static ssize_t device_read(struct file *fp, char *ch, size_t sz, loff_t *lofft)
{
printk("device_read called");
if (*lofft > 1024 || sz > 1024)
{
return -EFBIF; // return 0 also works
}
if ((*lofft+sz) > 1024)
{
sz = 1024 - *lofft;
}
copy_to_user(ch, kernelbuff + *lofft, sz);
*lofft+=sz;
return sz;
}(编写操作代码如下)。
偏移量的答案可以从这里引用:Understanding loff_t *offp for file_operations
关于抵消的一些重要问题:
编辑:读取所需的有效检查可以在此链接中引用(由@Tsyvarev建议):Error checking in a '.read' function in kernel module
编辑:添加改进版本的写函数
static ssize_t device_write(struct file *fp, const char *ch, size_t sz, loff_t *lofft)
{
printk("device_write called");
if (((*lofft) > sizeof(kernelbuff)) || (sz > sizeof(kernelbuff)))
{
printk("Error: Allocating more than kernel buffer size"); // pr_err( ) can also be used as pointed by @KamilCuk
return -EFBIG;
}
if ((*lofft + sz) > sizeof(kernelbuff))
{
printk("Error: Allocating more than kernel buffer size");
return -EFBIG;
}
copy_from_user(kernelbuff + *lofft, ch, sz);
*lofft+=sz;
return sz;
}https://stackoverflow.com/questions/60469058
复制相似问题