【學習筆記】
驅動代碼
file_operations.c
#include <linux/init.h>
#include <linux/module.h>
//雜項設備驅動需要增加兩個頭檔案
#include <linux/miscdevice.h>
#include <linux/fs.h>
//傳輸函式頭檔案
#include <linux/uaccess.h>
int misc_open(struct inode *inode, struct file *file){//(*open)函式實作
printk("hello misc_open\n");
return 0;
}
int misc_release(struct inode *inode, struct file *file){//(*release)函式實作
printk("bye bye\n");
return 0;
}
ssize_t misc_read(struct file *file, char __user *ubuf, size_t size, loff_t *loff_t){
char kbuf[64] = "mydate";//定義字串,能夠在應用層讀取到
if(copy_to_user(ubuf, kbuf, strlen(kbuf)) != 0){//判斷是否成功向應用層傳輸資料
printk("copy_to_user error\n");
return -1;
}
return 0;
}
ssize_t misc_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loff_t){
char kbuf[64] = {0};
if(copy_from_user(kbuf, ubuf, size) != 0){//判斷是否成功向應用層傳輸資料
printk("copy_from_user error\n");
return -1;
}
printk("kbuf is %s\n",kbuf);
return 0;
}
//第2步:填充檔案操作集
struct file_operations misc_fops = {
.owner = THIS_MODULE, //這里簡單的填充一個owner
.open = misc_open, //根據我們自定義的函式名來填充
.release = misc_release,
.read = misc_read,
.write = misc_write
};
//第1步:填充雜項設備結構體
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR, //次設備號,動態分配
.name = "hello_misc", //設備節點的名字
.fops = &misc_fops //填充檔案操作集
};
//第3步;注冊到內核
static int misc_init(void){
int ret;
ret = misc_register(&misc_dev);//存盤注冊的地址
//判斷是否注冊成功
if(ret < 0){
printk("misc registe is error\n");
return -1;
}
printk("misc registe is successful\n"); //內核里不能使用c語言庫,所以不能用printf
return 0;
}
//卸載驅動
static void misc_exit(void){
misc_deregister(&misc_dev);
printk("misc bye bye\n");
}
//入口和出口
module_init(misc_init);
module_exit(misc_exit);
//宣告許可證
MODULE_LICENSE("GPL");
app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[]){//如果打開設備節點成功,這會呼叫驅動里邊的misc_open()函式
int fd;
char read_buf[64] = {0};
char write_buf[64] = "write date";
fd = open("/dev/hello_misc",O_RDWR);//open the device node
if(fd < 0){ //determine whether the opening is successful
perror("open error\n");//和printf用法相似
return fd;
}
read(fd,read_buf,sizeof(read_buf));//讀設備節點
printf("read_buf is %s\n",read_buf);//列印從內核層讀取的內容
write(fd,write_buf,sizeof(write_buf));//將資料寫入設備節點,將應用層資料傳入的內核層
close(fd);//關閉節點
return 0;
}
Makefile
obj-m +=file_operations.o
KDIR:=/home/pymeia/qemu/ARM/linux-4.9.268
PWD?=$(shell pwd)
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabi-
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
開發板初始資訊

編譯驅動和app
如果編譯出錯,則需要輸入如下命令
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-

拷貝file_operations.ko驅動和app到根目錄,更新磁盤鏡像

再次啟動開發板 sh runnolcd.sh

加載驅動,并顯示驅動資訊
insmod file_operations.ko
lsmod

卸載驅動
rmmod file_operations
rmmod file_operations.ko

運行app
./app
我這里虛擬開發板配置不完善,運行顯示錯誤
整理自嵌入式學習之Linux驅動篇
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/285838.html
標籤:其他
