使用寫入自訂字元設備
貓 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 。那麼它不是應該接受寫入命令並在日誌中列印該語句嗎?
答案1
在核心中,每個驅動程式都提供了一系列可以對檔案執行的各種操作的方法:open、close、read、write、seek、ioctl 等。struct file_operations
。對於設備,這些方法由註冊該特定設備(即區塊/字元、主設備號碼和次設備號碼的特定組合)的驅動程式提供。
驅動程式可能只實作其中的一些方法;提供了預設值。預設值通常不執行任何操作,並傳回 success(如果對該方法不執行任何操作是明智的)或 EINVAL(如果沒有合理的預設值並且缺少方法意味著不支援該功能)。
“Write error: Invalid argument”表示write
驅動程式的方法回傳EINVAL。最可能的解釋是該驅動程式write
根本沒有方法。驅動程式不支援某些操作是相當常見的,例如,某些驅動程式僅支援ioctl 且不支援讀取/寫入,某些驅動程式本質上是單向的(例如輸入設備)且僅支援讀取而不支持寫,反之亦然。
「無效參數」與權限無關,而是設備能夠執行的操作。如果您沒有寫入權限,但您有與驅動程式對話的權限,則會收到權限錯誤。只是你要求司機做的事情是它沒有概念的。