C 错误:无法在FFFFFFFFFFFFFF处理内核分页请求
我的内核驱动程序中有一个ioctl处理程序,可以读取和写入ioctl。我还有一个用户空间应用程序,它使用这个IOCTL来写/读数据 当我在用户空间应用程序中使用此ioctl时,它会导致内核OOPS,出现C 错误:无法在FFFFFFFFFFFFFF处理内核分页请求,c,linux-kernel,kernel,ioctl,userspace,C,Linux Kernel,Kernel,Ioctl,Userspace,我的内核驱动程序中有一个ioctl处理程序,可以读取和写入ioctl。我还有一个用户空间应用程序,它使用这个IOCTL来写/读数据 当我在用户空间应用程序中使用此ioctl时,它会导致内核OOPS,出现“错误:无法在ffffffffffffffff处处理内核分页请求” 用户空间片段: typedef struct abc_T { uint8_t size; uint8_t addr; uint8_t data[64]; } abc_T; // Read int abc_
“错误:无法在ffffffffffffffff处处理内核分页请求”
用户空间片段:
typedef struct abc_T {
uint8_t size;
uint8_t addr;
uint8_t data[64];
} abc_T;
// Read
int abc_read(uint8_t addr, uint8_t size, uint8_t * data) {
abc_T abc = {};
int fd;
int retval = 0;
abc.size = size;
abc.addr = addr;
fd = open("/dev/"ABC_DEV, O_RDWR);
if (fd >=0) {
retval = ioctl(fd, READ_ABC, &abc);
if (retval == 0)
memcpy(data, abc.data, size);
}
close(fd);
return retval;
}
// Write
int abc_write(uint8_t addr, uint8_t size, uint8_t * data) {
abc_T abc = {};
int fd;
int retval = 0;
abc.size = size;
abc.addr = addr;
memcpy(abc.data, data, size);
fd = open("/dev/"ABC_DEV, O_RDWR);
if (fd >=0) {
retval = ioctl(fd, WRITE_ABC, &abc);
}
close(fd);
return retval;
}
内核:
static int ABC_ioctl(struct file * file, uint cmd, ulong arg)
{
ABC_T abc;
int retval;
if (copy_from_user(&abc, (void *)arg,
sizeof(ABC_T)) != 0) {
return -EFAULT;
}
switch(cmd) {
case READ_ABC:
retval = read_func(&abc);
if (retval == 0) {
if (copy_to_user((void *)arg, &abc,
sizeof(ABC_T)) != 0) {
retval = -EFAULT;
} else {
retval = 0;
}
}
break;
case WRITE_ABC:
ret_val = write_func(&abc);
break;
return retval;
}
错误:
错误:无法在FFFFFFFFFFFFFF处理内核分页请求
IP:[]0xFFFFFFFFFFFE
PGD 1e0f067 PUD 1e11067 PMD 0
Oops:0010[#1]抢占式SMP
...
呼叫跟踪:
[] ? vfs_写入+0x198/0x1b0
[] ? 系统ioctl+0x80/0x90
[] ? 系统写入+0x49/0xa0
[] ? 系统调用快速路径+0x16/0x1b
代码:错误的RIP值。
RIP[]0xFFFFFFFFFFFE
...
我不知道这是怎么回事。
有人能帮忙吗
更新:由于abc\T中的数组大小为32,我看不出有问题。但当我将数组大小更改为64时,我看到了问题。任何帮助都将不胜感激
更新2:abc\T中的数组大小为64,如果读/写
大小为我不能确定这是您的问题,但您的代码中存在一些问题
在
如果从未设置open FAILES retval,但您返回了它,则该行为在ABC_ioctl
中未指定,因为您使用了返回值
我们看不到abc_write的结尾,如果open失败,是否返回值
注意:我首先假设你做了memcpy,即使open失败,请注意缩进(我编辑了你的问题以更改它)
请看我不能确定这是您的问题,但您的代码中有一些问题
在
如果从未设置open FAILES retval,但您返回了它,则该行为在ABC_ioctl
中未指定,因为您使用了返回值
我们看不到abc_write的结尾,如果open失败,是否返回值
注意:我首先假设你做了memcpy,即使open失败,请注意缩进(我编辑了你的问题以更改它)
如果有以下更新,可以查看:
更新:由于abc\T中的数组大小为32,我看不出有问题。
但当我将数组大小更改为64时,我看到了问题。有什么帮助吗
将不胜感激
更新2:在abc\T中数组大小为64时,如果读/写大小给定这些更新:
更新:由于abc\T中的数组大小为32,我看不出有问题。
但当我将数组大小更改为64时,我看到了问题。有什么帮助吗
将不胜感激
更新2:在abc\T中,数组大小为64,如果读/写大小正常,则这是一个错误。最初我将retval初始化为0。将编辑该部分。@oak1208您的意思是您的真实代码将其初始化为0,所以您给我们的代码不是真实代码?它是真实代码。我只是在输入问题时漏掉了它:)@oak1208好的,所以init不见了。我编辑了我的问题,如果open失败,您是否在abc\u write
中返回值?我认为这不是问题所在,因为当我打印fd
的值时,它总是>0。好的,这是一个错误。最初我将retval初始化为0。将编辑该部分。@oak1208您的意思是您的真实代码将其初始化为0,所以您给我们的代码不是真实代码?它是真实代码。我只是在输入问题时漏掉了它:)@oak1208好的,所以init不见了。我编辑了我的问题,如果open失败,您是否在abc\u write
中返回值?我不认为这是问题所在,因为当我打印fd
的值时,它总是>0。您能展示一下如何注册chardev吗?(尤其包括结构物)。写函数指针似乎没有正确初始化。static struct file_operations abc_fops={.owner=THIS_MODULE、.unlocked_ioctl=abc_ioctl、.open=abc_open、.release=abc_release、}代码>``if(alloc_chrdev_region(&abc_dev,0,1,abc_dev)<0){return-1;}if(device_create(dev_class,NULL,abc_dev,NULL,abc_dev)==NULL){注销chrdev region(abc_dev,1);return-1;}cdev init(&abc_cdev,abc_fops);如果(cdev_add(&abc_cdev,abc_dev,1)=-1){device_destroy(dev_class,abc_dev);注销chrdev_region(abc_dev,1);返回-1;}``您可以确定用户空间客户端中的哪个调用触发了故障吗?不要假设,确保在调试之后,我发现如果我将abc\u t
中的data
数组大小设置为32,它不会崩溃,而将其更改为64会导致崩溃。但是我需要它大于32:(你能展示一下你是如何注册chardev的吗?(特别是包括结构)。写函数指针似乎没有正确初始化。static struct file\u operations abc\u fops={.owner=THIS_MODULE、.unlocked_ioctl=ABC_ioctl、.open=ABC_open、.release=ABC_release、};
`if(alloc_chrdev_region(&ABC_dev,0,1,ABC_dev)<0){return-1;}if(设备创建(开发类,NULL,ABC_dev,NULL,ABC_dev)==NULL){注销chrdev_区域(abc_-dev,1);返回-1;}cdev_-init(&abc_-cdev,&abc_-fops);如果(cdev_-add(&abc_-cdev,abc_-dev,1)=-1){设备销毁(开发类,abc_-dev);注销chrdev区域(abc_-dev,1);返回-1}“``您能确定是哪个用户空间客户端调用触发了故障吗?不要假设,请确保在调试之后,我发现如果我在abc\u t
中的data
数组大小为32,它不会崩溃,而将其更改为64则会崩溃。但我需要它大于32:(
Error:
BUG: unable to handle kernel paging request at ffffffffffffffff
IP: [<ffffffffffffffff>] 0xfffffffffffffffe
PGD 1e0f067 PUD 1e11067 PMD 0
Oops: 0010 [#1] PREEMPT SMP
...
Call Trace:
[<ffffffff8117a8b8>] ? vfs_write+0x198/0x1b0
[<ffffffff8118ccc0>] ? SyS_ioctl+0x80/0x90
[<ffffffff8117b139>] ? SyS_write+0x49/0xa0
[<ffffffff819af419>] ? system_call_fastpath+0x16/0x1b
Code: Bad RIP value.
RIP [<ffffffffffffffff>] 0xfffffffffffffffe
...
int abc_read(uint8_t addr, uint8_t size, uint8_t * data) {
abc_T abc = {};
int fd, retval;
abc.size = size;
abc.addr = addr;
fd = open("/dev/"ABC_DEV, O_RDWR);
if (fd >=0) {
retval = ioctl(fd, READ_ABC, &abc);
if (retval == 0)
memcpy(data, abc.data, size);
}
return retval;
}
abc_T abc = {};
abc_T *abc = kmalloc( sizeof( *abc ), GFP_KERNEL );
kfree( abc );