嵌入式內核及驅動開發之學習筆記(二) 實現應用控制驅動
Linux系統根據驅動程序實現的模型框架將設備驅動分成字符設備驅動、塊設備驅動、網絡設備驅動三大類。這里簡單理解一下概念
字符設備:設備按字節流處理數據,通常用的串口設備、鍵盤設備都是這種。
塊設備:設備按塊單位對數據處理,通常是存儲設備。
網絡設備:顧名思義,建立在socket接口上的設備。
字符設備驅動框架
作為字符設備驅動要素:
1,必須有一個設備號,用在眾多到設備驅動中進行區分
2,用戶必須知道設備驅動對應到設備節點(設備文件)
3,對設備操作其實就是對文件操作,應用空間操作open,read,write的時候,實際在驅動代碼有對應到open, read,write
linux把所有到設備都看成文件,用戶對字符設備進行操作實際上就是對驅動進行操作,實際上就是操作對應的設備文件!
而設備號是內核層區別設備的一個標識,我們通過驅動代碼程序實現下面 應用程序到設備驅動的控制過程。
應用層程序 -->? 設備結點? -->? 設備號? -->? 設備驅動? -->? 硬件
實現一簡易的框架。首先是驅動程序的實現
當用戶裝載完驅動模塊,程序會執行 chr_drv_init 這個回調函數,向系統申請一個主設備號(表示程序為哪一類設備服務),創建設備結點(產生/dev/chr2,linux系統能識別這個設備文件);當用戶卸載驅動模塊后,程序執行 chr_drv_exit 這個回調函數,將之前申請的設備結點和設備號回收。
結構體類型 file_operations 定義了很多對應用層的接口,這些成員變量都是函數指針。我們將這些指針指向自己定義的函數入口。再去實現我們的函數功能。
//chr_drv.c
#include
#include
#include
#include
static unsigned int dev_major = 250;
static struct class *devcls;
static struct device *dev;
ssize_t chr_drv_read(struct file *filp, char __user *buf, size_t count, loff_t *fpos);
ssize_t chr_drv_write(struct file *filp, const char __user *buf, size_t count, loff_t *fpos);
int chr_drv_open(struct inode *inode, struct file *filp);
int chr_drv_close(struct inode *inode, struct file *filp);
const struct file_operations my_fops = {
.open = chr_drv_open,
.read = chr_drv_read,
.write = chr_drv_write,
.release = chr_drv_close,
};
static int __init chr_drv_init(void)
{
printk("-------%s-------------\n", __FUNCTION__);
//向系統申請設備號
int ret;
ret = register_chrdev(dev_major, "chr_dev_test", &my_fops);
if(ret == 0){
printk("register ok\n");
}else{
printk("register failed\n");
return -EINVAL;
}
//創建設備結點
devcls = class_create(THIS_MODULE, "chr_cls");
dev = device_create(devcls, NULL, MKDEV(dev_major, 0), NULL, "chr2");
return 0;
}
static void __exit chr_drv_exit(void)
{
printk("-------%s-------------\n", __FUNCTION__);
//銷毀這個設備結點
device_destroy(devcls, MKDEV(dev_major, 0));
class_destroy(devcls);
//釋放這個設備號
unregister_chrdev(dev_major, "chr_dev_test");
}
module_init(chr_drv_init);
module_exit(chr_drv_exit);
MODULE_LICENSE("GPL");
// read(fd, buf, size);
ssize_t chr_drv_read(struct file *filp, char __user *buf, size_t count, loff_t *fpos)
{
printk("-------%s-------\n", __FUNCTION__);
return 0;
}
ssize_t chr_drv_write(struct file *filp, const char __user *buf, size_t count, loff_t *fpos)
{
printk("-------%s-------\n", __FUNCTION__);
return 0;
}
int chr_drv_open(struct inode *inode, struct file *filp)
{
printk("-------%s-------\n", __FUNCTION__);
return 0;
}
int chr_drv_close(struct inode *inode, struct file *filp)
{
printk("-------%s-------\n", __FUNCTION__);
return 0;
}
應用程序用來測試驅動程序的這些接口函數,實現對驅動的控制。
這里open函數定位到驅動程序的chr_drv_open函數,read函數定位到驅動程序的chr_drv_read函數(參考驅動程序中my_fops結構體的初始化)。就像文件IO函數那樣使用,只不過我們驅動程序里對應的函數沒有具體的實現,能看到一些打印信息。
//chr_test.c
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int fd;
int value = 0;
//打開設備結點
fd = open("/dev/chr2", O_RDWR);
if(fd < 0)
{
perror("open");
exit(1);
}
//讀操作
read(fd, &value, 4);
while(1)
{
//寫操作
value = 0;
write(fd, &value, 4);
sleep(1);
//寫操作
value = 1;
write(fd, &value, 4);
sleep(1);
}
close(fd);
return 0;
}
Makefile文件負責整個工程的編譯與管理
相比于之前,要多編譯了chr_test.c這個文件,APP_NAME 指定目標文件名,CROSS_COMPILE 指定交叉編譯工具鏈。下面還要修改添加一下編譯規則
ROOTFS_DIR = /nfs/rootfs
APP_NAME = chr_test
CROSS_COMPILE = /home/linux/soft/gcc-4.6.4/bin/arm-none-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc
ifeq ($(KERNELRELEASE), )
KERNEL_DIR = /mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412
CUR_DIR = $(shell pwd)
all :
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
$(CC) $(APP_NAME).c -o $(APP_NAME)
clean :
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
install:
cp -raf *.ko $(APP_NAME) $(ROOTFS_DIR)/drv_module
else
obj-m += chr_drv.o
endif
查看實驗結果
編譯并移動文件到nfs根目錄
root@linux:/mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412/drivers/mydrivers/chr_drv# make
root@linux:/mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412/drivers/mydrivers/chr_drv# make install
開發板加載模塊,執行應用程序
[root@farsight drv_module]# ls
chr_drv.ko ? chr_test ? ? chr_test.ko ?hello.ko ? ? math.ko
[root@farsight drv_module]# insmod chr_drv.ko
[ 3036.170000] -------chr_drv_init-------------
[ 3036.175000] register ok
[root@farsight drv_module]# ./chr_test
[ 3041.255000] -------chr_drv_open-------
[ 3041.255000] -------chr_drv_read-------
[ 3041.260000] -------chr_drv_write-------
[ 3042.265000] -------chr_drv_write-------
[ 3043.265000] -------chr_drv_write-------
嵌入式
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。