Steward
分享是一種喜悅、更是一種幸福
驅動程式 - Linux Device Driver (LDD) - 使用範例 - C/C++ (PocketBeagle) - Char Device - File Read/Write
參考資訊:
https://www.aps-web.jp/en/ca-en/21578/#anchor2
User Application可以透過read()、write()傳送資料給驅動程式,但是需要注意的地方是,在Linux Kernel中,如果要存取User Application傳送過來的資料時,必須使用copy_to_user()、copy_from_user(),而不是一般的memcpy()或者直接指標操作,否則會導致驅動程式崩潰,這是因為Linux Kernel和User Application是位於不同保護空間,因此,在存取User Application資料時,必須確保該資料已經被Map且位於記憶體
使用方式:
1. copy_to_user() 2. copy_from_user()
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #include <linux/cdev.h> #include <linux/init.h> #include <linux/device.h> #include <linux/module.h> #include <linux/uaccess.h> MODULE_LICENSE ( "GPL" ); MODULE_AUTHOR ( "Steward Fu" ); MODULE_DESCRIPTION ( "Linux Driver" ); static int base = 0; static struct cdev mycdev; static char mybuf[255] = {0}; static struct class *myclass = NULL ; static int myopen ( struct inode * inode , struct file * file ) { printk ( "%s\n" , __func__ ); return 0; } static int myclose ( struct inode * inode , struct file * file ) { printk ( "%s\n" , __func__ ); return 0; } static ssize_t myread ( struct file *flip, char __user *buf, size_t len, loff_t *off) { int r = 0; r = copy_to_user (buf, mybuf, strlen (mybuf)); printk ( "%s, %s\n" , __func__ , mybuf); return r; } static ssize_t mywrite ( struct file *flip, const char __user *buf, size_t len, loff_t *off) { int r = 0; r = copy_from_user (mybuf, buf, len); printk ( "%s, %s\n" , __func__ , mybuf); return r; } static const struct file_operations myfops = { . owner = THIS_MODULE , . open = myopen , . read = myread , . write = mywrite , . release = myclose , }; int ldd_init ( void ) { alloc_chrdev_region (&base, 0, 1, "myfile" ); myclass = class_create ( THIS_MODULE , "myfile" ); device_create (myclass, NULL , base, NULL , "myfile" ); cdev_init (&mycdev, &myfops); cdev_add (&mycdev, base, 1); return 0; } void ldd_exit ( void ) { device_destroy (myclass, base); cdev_del (&mycdev); class_destroy (myclass); unregister_chrdev_region (base, 1); } module_init ( ldd_init ); module_exit ( ldd_exit ); |
ldd_init: 建立字元驅動程式
myopen: 僅列印字串
mywrite: 儲存並且列印User Application傳送的字串
myread: 複製儲存的字串給User Application並且列印出來
myclose: 僅列印字串
ldd_exit: 刪除字元驅動程式
寫入字串
# echo "test" > /dev/myfile mywrite, test
P.S. 按下Ctrl+C停止
讀取字串
# cat /dev/myfile myopen myread, test myclose