カスタム文字デバイスへの書き込み
猫 123 > /dev/chardev
与える
cat: 書き込みエラー: 無効な引数
権限を666に変更し、sudoでも試してみました。それでも結果は同じです。同様の方法でechoも試しました。
私はArch Linux 4.8を使用しています。
編集: ドライバーのコード
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
//Prototypes
static int __init init(void);
static void __exit cleanup(void);
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 *);
#define SUCCESS 0
#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices*/
#define BUF_LEN 80 /* Max length of the message from the device */
static int Major; //Major number of the devices
static int Device_Open = 0;
static char msg[BUF_LEN]; //Message given when asked
static char *msg_Ptr;
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
static int __init init(){
Major = register_chrdev(0,DEVICE_NAME,&fops);
if(Major < 0){
printk(KERN_ALERT "Failure in registering the device. %d\n", Major);
return Major;
}
printk(KERN_INFO "%s registered with major %d \n",DEVICE_NAME,Major);
printk(KERN_INFO "create a device with 'mknod /dev/%s c %d 0'\n",DEVICE_NAME,Major);
printk(KERN_INFO "Try to cat and echo the file and shit man.\n");
return SUCCESS;
}
static void __exit cleanup(){
unregister_chrdev(Major, DEVICE_NAME);
printk(KERN_ALERT "Unregistered the device %s i guess? \n"DEVICE_NAME);
}
static int device_open(struct inode *inode,struct file *file){
static int counter = 0;
if(Device_Open)
return -EBUSY;
Device_Open++;
sprintf(msg, "I already told you %d times Hello world!\n", counter++);
msg_Ptr = msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release(struct inode *inode,struct file *file){
Device_Open--;
module_put(THIS_MODULE);
return 0;
}
static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset){
int bytes_read = 0;
if(*msg_Ptr == 0)
return 0;
while(length && *msg_Ptr){
put_user(*(msg_Ptr++),buffer++);
length--;
bytes_read++;
}
return bytes_read;
}
static ssize_t device_write(struct file *filp,const char *buff, size_t len, loff_t *off){
printk(KERN_ALERT "You cannot write to this device.\n");
return -EINVAL;
}
module_init(init);
module_exit(cleanup);
ここでは、device_write 関数を使用して、それを fops 構造体で .write に割り当てていることがわかります。つまり、write コマンドを受け入れて、そのステートメントをログに出力することになっているのではないですか?
答え1
カーネルでは、各ドライバはファイルに対して実行できるさまざまな操作(開く、閉じる、読み取る、書き込む、シークする、ioctlなど)のための一連のメソッドを提供します。これらのメソッドは、struct file_operations
デバイスの場合、メソッドは、その特定のデバイス (つまり、ブロック/文字、メジャー番号、マイナー番号の特定の組み合わせ) を登録したドライバーによって提供されます。
ドライバーは一部のメソッドのみを実装できます。デフォルトが提供されます。デフォルトでは、通常何も実行されず、成功 (そのメソッドに対して何も実行しないことが適切な場合) または EINVAL (適切なデフォルトがなく、メソッドがないため機能がサポートされていないことを意味する場合) が返されます。
「書き込みエラー: 無効な引数」は、write
ドライバーのメソッドが EINVAL を返すことを意味します。最も可能性の高い説明は、このドライバーにメソッドがまったくないことですwrite
。ドライバーが特定のアクションをサポートしないのはごく普通のことです。たとえば、一部のドライバーは ioctl のみをサポートし、読み取り/書き込みはサポートしません。一部のドライバーは本質的に単方向 (入力デバイスなど) であり、読み取りのみをサポートし、書き込みはサポートしません (またはその逆)。
「無効な引数」は権限とは関係なく、デバイスが実行できることに関係します。書き込み権限がない場合、権限エラーが発生しますが、ドライバーと通信する権限はあります。ドライバーに実行するように要求している内容が、ドライバーには理解できないものであるというだけです。