我是Linux内核模块开发的新手。我编写了一个模块,该模块创建了一个设备文件,可以向其中写入数据或从中读取数据。
我能够使用echo
成功地向其中写入数据,但是当我使用cat
从中打印数据时,什么也没发生。
但是,如果我使用read()
系统调用从用户空间应用程序中读取此设备文件,它的工作原理就像一个吊饰!
据我了解,cat
打开,读取和关闭文件,因此它的行为应与我的用户应用程序相同。
有人对这个问题有任何想法吗?谢谢。
这是我的模块代码的一部分:
static uint64_t my_data_value;
uint8_t *kernel_buffer;
/* Some variables & function prototypes ignored */
static struct file_operations fops =
{
.owner = THIS_MODULE,
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
};
static int device_open(struct inode *inode, struct file *file)
{
if((kernel_buffer = kmalloc(1024, GFP_KERNEL)) == 0)
{
return -1;
}
return 0;
}
static int device_release(struct inode *inode, struct file *file)
{
kfree(kernel_buffer);
return 0;
}
static ssize_t device_read(struct file *file, char __user *buf, size_t len, loff_t *off)
{
size_t ret;
snprintf(kernel_buffer, 1024, "%016llX", my_data_value);
ret = copy_to_user(buf, kernel_buffer, strlen(kernel_buffer);
return ret;
}
static ssize_t device_write(struct file *file, const char __user *buf, size_t len, loff_t *off)
{
size_t i;
my_data_value = 0;
copy_from_user(kernel_buffer, buf, len);
for(i=0;i<(len-1);i++)
{
if((kernel_buffer[i] < '0' || kernel_buffer[i] > '9') \
&& (kernel_buffer[i] < 'A' || kernel_buffer[i] > 'Z'))
{
return -1;
}
}
for(i=0; i<(len-1);i++)
{
my_data_value <<=4;
if(kernel_buffer[i] >= '0' && kernel_buffer[i] <='9')
{
my_data_value |= (uint64_t)(kernel_buffer[i] - '0');
}
else if(kernel_buffer[i] >= 'A' && kernel_buffer[i] <= 'Z')
{
my_data_value |= (uint64_t)(kernel_buffer[i] - 'A' + 10);
}
else
{
return -1;
}
}
return len;
示例命令
echo 1234567A > /dev/my_device # write successfully
cat /dev/my_device # nothing happens
和我的用户应用程序:
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int8_t read_buff[1024];
int main()
{
int fd;
fd = open("/dev/my_device", O_RDWR);
if(fd < 0)
{
printf("Cannot open device file\n");
return 0;
}
read(fd, read_buf, 1024);
printf("Data = %s\n", read_buf);
close(fd);
}