日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux字符驱动之概念介绍

發布時間:2023/11/30 linux 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux字符驱动之概念介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、字符驅動框架

問:應用程序open、read、write如何找到驅動程序的open、read、write函數?

答:應用程序的open、read、write是在C庫里面實現的,它里面通過swi val指令去觸發一個異常,這個異常就會進入到內核空間,在內核的異常處理函數里面有根據我們傳入的val來決定調用system_open還是system_read、system_write函數,這些函數根據我們打開不同的文件、不同的文件就有不同的屬性(例如設備類型(字符設備還是塊設備還是網絡設備)、主設備號),根據這些屬性找到更底層的驅動程序。

?

問:什么是主設備號,什么是次設備號

答:Linux主設備號用來區分不同硬件設備類型,如LED和串口之間的區別;
Linux次設備號用來區分不同硬件設備,如串口1和串口2之間的區別;

?

問:通過什么樣的方法來找到驅動程序的open函數

答:通過一個注冊函數+設備節點

注冊函數如下(舊的注冊函數,新的以后再說):

register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)

參數1:主設備號(重要)

參數2:名字(不重要)

參數3:file_operations結構體(重要)

設備節點:

可以手工創建也可以自動創建,這里暫且只說手工創建

mknod ?/dev/xxx ?c ?252 ?0

創建一個名為/dev/xxx的設備節點,c表示字符設備節點,252是主設備號,0是次設備號。

?

問:應用程序一般是由main函數開始執行,那么驅動程序一般是先執行什么?

答:通過一個宏,指定驅動程序的入口函數,當裝載驅動時就會執行入口函數。

例如:module_init(first_drv_init); ?//用于修飾入口函數

自然地,驅動程序的出口函數,則是在卸載驅動時就會執行出口函數。

例如:module_exit(first_drv_exit); ?//用于修飾出口函數
?

?

驅動源程序如下:

#include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <linux/module.h>int major; static int first_drv_open(struct inode * inode, struct file * filp) {printk("first_drv_open\n");return 0; } static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos) {printk("first_drv_write\n");return 0; }/* File operations struct for character device */ static const struct file_operations first_drv_fops = {.owner = THIS_MODULE,.open = first_drv_open,.write = first_drv_write, };/* 驅動入口函數 */ static int first_drv_init(void) {/* 主設備號設置為0表示由系統自動分配主設備號 */major = register_chrdev(0, "first_drv", &first_drv_fops);return 0; }/* 驅動出口函數 */ static void first_drv_exit(void) {unregister_chrdev(major, "first_drv"); }module_init(first_drv_init); //用于修飾入口函數 module_exit(first_drv_exit); //用于修飾出口函數 MODULE_AUTHOR("LWJ"); MODULE_DESCRIPTION("Just for Demon"); MODULE_LICENSE("GPL"); //遵循GPL協議

Makefile源碼如下:

ifneq ($(KERNELRELEASE),)obj-m := first_drv.oelseKDIR := /home/opt/EmbedSky/linux-2.6.30.4all:make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux- clean:rm -f *.ko *.o *.mod.o *.mod.c *.symversendif

測試程序如下:

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h>int main(void){int fd;int val = 1;fd = open("/dev/xxx",O_RDWR); //打開名為 /dev/xxx 的設備節點if(fd < 0){printf("open error\n");}write(fd,&val,4);return 0; }

開發板上的測試步驟如下:

[WJ2440]# insmod first_drv.ko [WJ2440]# ./first_test open error //沒有創建設備節點 [WJ2440]# cat proc/devices Character devices:1 mem4 /dev/vc/04 tty5 /dev/tty5 /dev/console5 /dev/ptmx7 vcs10 misc13 input14 sound29 fb81 video4linux89 i2c90 mtd 116 alsa 128 ptm 136 pts 180 usb 188 ttyUSB 189 usb_device 204 tq2440_serial 252 first_drv //我們創建的字符設備,主設備號252 253 usb_endpoint 254 rtcBlock devices: 259 blkext7 loop8 sd31 mtdblock65 sd66 sd67 sd68 sd69 sd70 sd71 sd 128 sd 129 sd 130 sd 131 sd 132 sd 133 sd 134 sd 135 sd 179 mmc [WJ2440]# mknod /dev/xxx c 252 0 //手動創建一個字符設備節點 [WJ2440]# ls -l /dev/xxx crw-r--r-- 1 root root 252, 0 Jan 1 20:49 /dev/xxx [WJ2440]# ./first_test //有設備節點后成功我們的應用程序運行了 first_drv_open first_drv_write [WJ2440]#

本文參考:

https://blog.csdn.net/lwj103862095/article/details/17468587

總結

以上是生活随笔為你收集整理的linux字符驱动之概念介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。