폴더 아래에 장치 파일을 성공적으로 생성했지만 /dev
장치 파일에 쓰면 커널에서 다음 오류 메시지가 표시됩니다.
Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10090.943733] Internal error: : 1b [#3] PREEMPT SMP ARM
Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.049020] Process echo (pid: 3728, stack limit = 0xdc40a218)
Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.054880] Stack: (0xdc40be60 to 0xdc40c000)
Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.059267] be60: c15491c6 00000022 dc5cb14c bf30430c dc40bedc dc40be88 c075312c c074fe5c
Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.067488] be80: c0753018 ffffff04 ffff0a00 c140414c c0d407c8 bf30430c c140414c 40cfbcf3
Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.075709] bea0: 00852878 ffffff04 ffff0a00 00040952 c01a7404 c140414c 00852878 00852878
Segmentation fault
나는 매우 기본적인 Linux 장치 드라이버를 알고 있습니다.
누구든지 이 문제를 해결하도록 도와줄 수 있나요?
캐릭터 파일 작성을 위한 코드 조각을 첨부합니다
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/uaccess.h>
#include<linux/device.h>
MODULE_AUTHOR("RUCHA");
MODULE_DESCRIPTION("Character Driver First test");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.0.1");
static int MajorNum;
static struct class* RetValOfClassRegistration = NULL;
static struct device* RetVal = NULL;
static char message[1024];
static int openDev(struct inode * , struct file *);
static int closeDev(struct inode * , struct file *);
static ssize_t readDev(struct file *, char *, size_t, loff_t *);
static ssize_t writeDev(struct file *, const char *, size_t, loff_t *);
static struct file_operations FileOps = {
.owner = THIS_MODULE,
.open = openDev,
.read = readDev,
.write = writeDev,
.release = closeDev,
};
static int registerCharDev(void){
return register_chrdev(0,"MyDev",&FileOps);
}
static int __init Loaded(void){
// registering device
MajorNum = registerCharDev();
if(MajorNum < 0){
printk("Can not register device\n");
return -1;
}
printk("Driver Loaded with %d \n",MajorNum);
// registering device class
RetValOfClassRegistration = class_create(THIS_MODULE,"MyCharacterDriver");
if(RetValOfClassRegistration < 0){
printk("can not register class for driver number : %d\n",MajorNum);
return 0;
}
// register the driver
RetVal = device_create(RetValOfClassRegistration,NULL,MKDEV(MajorNum,0),NULL,"MyDev");
return 0;
}
static void __exit Removed(void){
device_destroy(RetValOfClassRegistration,MKDEV(MajorNum,0));
class_unregister(RetValOfClassRegistration);
class_destroy(RetValOfClassRegistration);
unregister_chrdev(MajorNum,"MyDev");
printk("Driver Removed\n");
}
module_init(Loaded);
module_exit(Removed);
static int openDev(struct inode *inodep , struct file *filep){
printk("Device is now open to read write operations\n");
return 0;
}
static int closeDev(struct inode *inodep , struct file *filep){
printk("Device Closed\n");
return 0;
}
static ssize_t readDev(struct file *filep, char *c, size_t v, loff_t *lp){
printk("Read From the device\n");
return 0;
}
static ssize_t writeDev(struct file *file, const char __user *buf, size_t len, loff_t *offset)
{
sprintf(message, "%s(%zu letters)", buf, len);
return 0;
}
내가 제공하는 사용자 입력은 echo 명령을 통해 이루어집니다.
에코 "1" > /dev/MyDev
이 문제를 해결하도록 도와주세요!
답변1
내가 말했듯이...문제는 캐릭터 드라이버의 기능에 있습니다 write
. 보다 구체적으로 말하면 사용자 공간에서 직접 버퍼에 액세스합니다. 이렇게 하면 안 됩니다. 커널에는 이를 수행하는 특정 API가 있습니다. 예를 들어 이것을 참조하십시오StackOverflow 게시물이 주제에 대해.
특정한 경우에는 사용자 공간 버퍼의 데이터를 삭제 sprintf
하고 copy_from_user
드라이버 버퍼로 복사하는 데 사용해야 합니다. 이와 같은 방법으로 내 비글본 칠판의 문제가 해결되었습니다.
static ssize_t writeDev(struct file *file, const char __user *buf, size_t len, loff_t *offset)
{
printk("Write to device buf: 0x%p: len = %d, offset = %lld\n", buf, len, *offset);
if (copy_from_user(message, buf, len)) {
printk("Unable to read buffer from user\n");
return -EFAULT;
}
return len;
}