在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux新字符設備驅動開發方式

CHANBAEK ? 來源:嵌入式攻城獅 ? 作者:安迪西 ? 2023-04-14 12:02 ? 次閱讀

Linux字符設備驅動開發模板中介紹了舊版本的驅動開發模板,其需要手動分配設備號后,再進行注冊,驅動加載成功后還需要手動創建設備節點,比較麻煩。 目前Linux內核推薦的新字符設備驅動API函數,可以自動分配設備號、創建設備節點,使得驅動的使用更加方便

1. 新字符設備驅動原理

1.1 分配和釋放設備號

舊字符設備驅動開發中使用register_chrdev函數注冊字符設備時,需要事先確定好主設備號,并且注冊成功后,會將該設備號下的所有次設備號都使用掉

而新字符設備驅動API函數很好的解決了這個問題,使用設備號時再向內核申請,需要幾個就申請幾個,由內核分配設備可以使用的設備號

設備號申請函數:沒有指定設備號

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) 
//dev:保存申請到的設備號
//baseminor:次設備號起始地址,一般為0
//count:要申請的設備號數量
//name:設備名字

設備號申請函數:指定了主次設備號

int register_chrdev_region(dev_t from, unsigned count, const char *name) 
//from:要申請的起始設備號
//count:要申請的設備號數量
//name:設備名字

設備號釋放函數:統一使用下面函數釋放

void unregister_chrdev_region(dev_t from, unsigned count) 
//from:要釋放的設備號
//count:表示從from開始,要釋放的設備號數量

因此新字符設備驅動中,設備號分配代碼通常按如下示例編寫:

int major;     /* 主設備號 */
int minor;     /* 次設備號 */
dev_t devid;   /* 設備號 */

if (major) {   /* 定義了主設備號 */
    devid = MKDEV(major, 0);    /*大部分驅動次設備號都選擇0*/
    register_chrdev_region(devid, 1, "test");
} else {      /* 沒有定義設備號 */
    alloc_chrdev_region(&devid, 0, 1, "test"); /*申請設備號*/
    major = MAJOR(devid);       /* 獲取分配號的主設備號 */
    minor = MINOR(devid);       /* 獲取分配號的次設備號 */
}

1.2 注冊字符設備

Linux中使用cdev表示字符設備,在include/linux/cdev.h中定義:

struct cdev {
    struct kobject kobj;
    struct module *owner;
    const struct file_operations *ops; //文件操作函數集合
    struct list_head list;
    dev_t dev;  //設備號
    unsigned int count;
};
//編寫字符設備驅動之前需要定義一個cdev結構體變量

cdev_init函數:定義好cdev變量后,用該函數進行初始化

cdev_add函數:向系統添加字符設備(cdev結構體變量)

struct cdev testcdev;
/* 設備操作函數 */
static struct file_operations test_fops = {
    .owner = THIS_MODULE,
    /* 其他具體的初始項 */
};

testcdev.owner = THIS_MODULE;
cdev_init(&testcdev, &test_fops);  /* 初始化cdev結構體變量 */
cdev_add(&testcdev, devid, 1);     /* 添加字符設備 */

cdev_del函數:卸載驅動時從內核中刪除相應的字符設備

void cdev_del(struct cdev *p)
//p:要刪除的字符設備

1.3 自動創建設備節點

舊字符設備驅動開發中,驅動程序加載成功后還需要使用mknod命令手動創建設備節點,十分麻煩。

而新字符設備驅動開發中,Linux通過udev用戶程序來實現設備文件的自動創建與刪除。 udev會檢測系統中硬件設備狀態,并根據硬件設備狀態來創建或者刪除設備文件。

使用busybox構建根文件系統時,busybox會創建一個udev的簡化版本mdev。 因此,在嵌入式開發中使用mdev來實現設備節點文件的自動創建與刪除。 Linux系統中的熱插拔事件也由mdev管理,在/etc/init.d/rcS文件中有如下語句:

echo /sbin/mdev > /proc/sys/kernel/hotplug

創建類:自動創建設備節點的工作是在驅動程序入口函數中完成的,一般在cdev_add之后添加相關代碼

struct class *class_create (struct module *owner, const char *name)
//owner 一般為 THIS_MODULE
//name 是類名字
//返回值是個指向結構體class的指針,也就是創建的類

刪除類:卸載驅動程序時需要刪除類

void class_destroy(struct class *cls)
//cls 就是要刪除的類

創建設備:類創建好后還不能實現自動創建設備節點,還需要在該類下創建一個設備

struct device *device_create(struct class *class, 
                             struct device *parent, 
                             dev_t devt,   
                             void *drvdata,   
                             const char *fmt, ...) 
//class 設備創建在哪個類下
//parent 父設備,一般為NULL
//devt 設備號
//drvdata 設備可能會使用的數據,一般NULL
//fmt 設備名字
//返回值是創建好的設備

刪除設備:卸載驅動時需要刪除創建的設備

void device_destroy(struct class *class, dev_t devt)
//class 是要刪除的設備所處的類
//devt 是要刪除的設備號

1.4 設置文件私有數據

每個硬件設備都有一些屬性,比如主設備號、類、設備、開關狀態等等,在編寫驅動時可將這些屬性封裝成一個結構體。 并在編寫驅動open函數時將設備結構體作為私有數據添加到設備文件中:

/*設備結構體*/ 
struct test_dev{ 
    dev_t         devid;     /*設備號*/ 
    struct cdev   cdev;      /*cdev*/ 
    struct class  *class;    /*類*/ 
    struct device *device;   /*設備*/ 
    int           major;     /*主設備號*/ 
    int           minor;     /*次設備號*/ 
}; 

struct test_dev testdev; 
/*open函數*/ 
static int test_open(struct inode *inode, struct file *filp) 
{ 
    filp->private_data = &testdev; /*設置私有數據*/ 
    return 0; 
}

綜上所述,新字符設備驅動開發流程如下圖所示:

圖片

2. 新字符設備驅動開發實驗

新字符設備驅動開發實驗是在Linux字符設備驅動開發模板一文的基礎上進行修改,只更改了驅動的編寫方式,與應用程序無關,因此只修改驅動程序即可

2.1 驅動程序編寫

添加定義:宏及字符設備定義

#define CHRDEVBASE_CNT   1            //設備號個數
#define CHRDEVBASE_NAME  "chrdevbase" //名字
/*newchr設備結構體 */
struct newchr_dev{
    dev_t devid;             //設備號
    struct cdev cdev;        //cdev 
    struct class *class;     //類   
    struct device *device;   //設備 
    int major;               //主設備號
    int minor;               //次設備號
};

struct newchr_dev chrdevbase; //自定義字符設備

修改open函數:設置私有數據

static int chrdevbase_open(struct inode *inode, struct file *filp)
{
    printk("chrdevbase open!\\r\\n");
    filp->private_data = &chrdevbase; //設置私有數據
    return 0;
}

修改init函數

static int __init chrdevbase_init(void)
{
    /* 注冊字符設備驅動 */
    //1、創建設備號
    if (chrdevbase.major) /* 定義了設備號 */
    {
        chrdevbase.devid = MKDEV(chrdevbase.major, 0);
        register_chrdev_region(chrdevbase.devid, CHRDEVBASE_CNT, CHRDEVBASE_NAME);
    } 
    else /* 沒有定義設備號 */
    {
        alloc_chrdev_region(&chrdevbase.devid, 0, CHRDEVBASE_CNT, CHRDEVBASE_NAME); /* 申請設備號 */
        chrdevbase.major = MAJOR(chrdevbase.devid); /* 獲取分配號的主設備號 */
        chrdevbase.minor = MINOR(chrdevbase.devid); /* 獲取分配號的次設備號 */
    }
    printk("chrdevbase major=%d,minor=%d\\r\\n",chrdevbase.major, chrdevbase.minor);  
    //2、初始化cdev
    chrdevbase.cdev.owner = THIS_MODULE;
    cdev_init(&chrdevbase.cdev, &chrdevbase_fops); 
    //3、添加一個cdev
    cdev_add(&chrdevbase.cdev, chrdevbase.devid, CHRDEVBASE_CNT);
    //4、創建類
    chrdevbase.class = class_create(THIS_MODULE, CHRDEVBASE_NAME);
    if (IS_ERR(chrdevbase.class)) 
    {
     return PTR_ERR(chrdevbase.class);
     }
    //5、創建設備
    chrdevbase.device = device_create(chrdevbase.class, NULL, chrdevbase.devid, NULL, CHRDEVBASE_NAME);
    if (IS_ERR(chrdevbase.device)) 
    {
        return PTR_ERR(chrdevbase.device);
    }
    
    printk("chrdevbase init done!\\r\\n");
    return 0;
}

修改exit函數

static void __exit chrdevbase_exit(void)
{
    /* 注銷字符設備驅動 */
    cdev_del(&chrdevbase.cdev);/*  刪除cdev */
    unregister_chrdev_region(chrdevbase.devid, CHRDEVBASE_CNT); /* 注銷設備號 */

    device_destroy(chrdevbase.class, chrdevbase.devid);
    class_destroy(chrdevbase.class);
    
    printk("chrdevbase exit done!\\r\\n");
}

2.2 程序編譯

程序編譯包括驅動程序和應用程序編譯兩個部分:

驅動程序編譯:創建Makefile文件,使用make命令,編譯驅動程序

KERNELDIR := /home/andyxi/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_andyxi
CURRENT_PATH := $(shell pwd)
obj-m := newchrdev.o

build: kernel_modules

kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

應用程序編譯:無需內核參與,直接編譯即可

arm-linux-gnueabihf-gcc newchrdevApp.c -o newchrdevApp

2.3 運行測試

為了方便,選擇通過TFTP從網絡啟動,并使用NFS掛載網絡根文件系統。 確保開發板能正常啟動,在Ubuntu中將驅動和測試文件復制到modules/4.1.15目錄中

在開發板中輸入如下指令加載驅動模塊

depmod                    //第一次加載驅動的時候需要運行此命令
modprobe newchrdev.ko     //加載驅動

驅動加載成功后,可以看到自動申請到的主設備號和次設備號

圖片

使用ls /dev/chrdevbase -l命令驗證該設備節點文件是否存在,而舊驅動方式需要額外使用mknod指令來手動創建該設備節點文件

圖片

驅動加載成功后,測試APP程序,如下

圖片

測試完使用rmmod指令卸載驅動

圖片

以上可見Linux新字符設備驅動開發方式可以自動分配設備號、創建設備節點,使得驅動的使用更加方便、便捷。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11465

    瀏覽量

    212817
  • API
    API
    +關注

    關注

    2

    文章

    1563

    瀏覽量

    63548
  • 字符
    +關注

    關注

    0

    文章

    234

    瀏覽量

    25484
  • 函數
    +關注

    關注

    3

    文章

    4371

    瀏覽量

    64219
  • 驅動開發
    +關注

    關注

    0

    文章

    133

    瀏覽量

    12255
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    i.MX6ULL驅動開發1—字符設備開發模板

    本篇介紹了嵌入式Linux驅動開發中的基礎驅動——字符驅動
    的頭像 發表于 03-17 09:13 ?3650次閱讀
    i.MX6ULL<b class='flag-5'>驅動</b><b class='flag-5'>開發</b>1—<b class='flag-5'>字符</b><b class='flag-5'>設備</b><b class='flag-5'>開發</b>模板

    i.MX6ULL驅動開發2—新字符設備開發模板

    上篇文章介紹了字符設備開發模板,但那是一種舊版本的驅動開發模式,設備
    的頭像 發表于 03-17 09:11 ?3489次閱讀
    i.MX6ULL<b class='flag-5'>驅動</b><b class='flag-5'>開發</b>2—<b class='flag-5'>新字符</b><b class='flag-5'>設備</b><b class='flag-5'>開發</b>模板

    Linux驅動開發:字符設備驅動開發理論

    大部分學習者的最終目的就是學習 Linux驅動開發Linux中的外設驅動可以分為:字符
    發表于 10-26 09:53 ?1374次閱讀

    Linux字符設備驅動開發框架介紹

    字符設備Linux驅動中最基本的一類設備驅動字符
    發表于 04-15 11:52 ?1688次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>字符</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>框架介紹

    ArmSoM系列板卡 嵌入式Linux驅動開發實戰指南 之 字符設備驅動

    字符設備驅動 本章,我們將學習字符設備使用、字符設備
    的頭像 發表于 04-10 09:53 ?1337次閱讀
    ArmSoM系列板卡 嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>實戰指南 之 <b class='flag-5'>字符</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b>

    「正點原子Linux連載」第四十二章新字符設備驅動實驗

    1)實驗平臺:正點原子Linux開發板2)摘自《正點原子I.MX6U嵌入式Linux驅動開發指南》關注官方微信號公眾號,獲取更多資料:正點原
    發表于 03-18 15:12

    字符設備驅動開發流程

    做嵌入式linux驅動開發,首先要搞明白大致框架。linux驅動通常分為字符
    發表于 12-24 08:30

    嵌入式Linux字符設備驅動的設計與應用

    描述了基于嵌入式Linux字符設備驅動程序的設計方法和實現過程。以電機、數碼管、串口和mini鍵盤的驅動設計為例,詳細闡述了嵌入式
    發表于 02-23 15:45 ?24次下載

    嵌入式Linux字符設備驅動的設計與應用

    描述了基于嵌入式Linux字符設備驅動程序的設計方法和實現過程。以電機、數碼管、串口和mini鍵盤的驅動設計為例,詳細闡述了嵌入式
    發表于 07-14 17:31 ?31次下載

    基于linux系統的字符設備驅動研究與設計_王森

    基于linux系統的字符設備驅動研究與設計_王森
    發表于 03-18 09:23 ?1次下載

    Linux設備驅動開發字符設備驅動編程分析

    1.字符設備驅動編寫流程 設備驅動程序可以使用模塊的方式動態加載到內核中去。加載模塊的
    發表于 10-18 17:33 ?1次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>之<b class='flag-5'>字符</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b>編程分析

    Linux設備驅動開發詳解》第6章、字符設備驅動

    Linux設備驅動開發詳解》第6章、字符設備驅動
    發表于 10-27 11:46 ?23次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>詳解》第6章、<b class='flag-5'>字符</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b>

    基于PXA255開發板外圍字符設備的嵌入式Linux字符設備驅動設計與應用

    驅動程序和應用程序的需求在成倍增長。本文通過實現對 PXA255開發板外圍字符設備(電機、數碼管、串口和 mini鍵盤)的操作和控制,詳細討論了嵌入式
    發表于 08-21 10:19 ?1306次閱讀
    基于PXA255<b class='flag-5'>開發</b>板外圍<b class='flag-5'>字符</b><b class='flag-5'>設備</b>的嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>字符</b><b class='flag-5'>設備</b><b class='flag-5'>驅動</b>設計與應用

    Linux字符設備架構是如何實現的

    一、Linux設備分類Linux系統為了管理方便,將設備分成三種基本類型:字符設備
    的頭像 發表于 12-24 18:12 ?870次閱讀

    i.MX6ULL驅動開發3—GPIO寄存器配置原理

    介紹了字符設備驅動的兩種新舊開發方式,并使用一個虛擬的字符驅動來學習
    的頭像 發表于 03-18 08:17 ?3047次閱讀
    i.MX6ULL<b class='flag-5'>驅動</b><b class='flag-5'>開發</b>3—GPIO寄存器配置原理
    主站蜘蛛池模板: 日本一本高清视频 | 女人张开腿 让男人桶个爽 免费观看 | 全部免费a级毛片 | 国产重口老太和小伙乱视频 | 手机看片福利视频 | 成人精品一区二区不卡视频 | 亚洲一区视频在线 | 亚洲成人网页 | 日韩精品一区二区三区免费视频 | 狠狠色噜噜狠狠狠狠2018 | 另类五月 | 婷婷九月色 | 一级片免费在线观看视频 | 狠狠色婷婷丁香六月 | 亚洲一级毛片在线观播放 | 综合7799亚洲伊人爱爱网 | 免费国产成高清人在线视频 | 7777奇米| 三级毛片在线免费观看 | www欧美在线观看 | 性欧美大战久久久久久久野外 | 欧美一级片免费观看 | 一级特黄特色的免费大片视频 | 国产成人在线播放视频 | 成人网在线观看 | 久青草免费视频 | 欧美色频| 狠狠操狠狠搞 | 天天干天天夜 | 蜜月mv国产精品 | 四虎影视色费永久在线观看 | 中国特黄一级片 | free性欧美高清另类 | 午夜国产福利 | 亚洲影院手机版777点击进入影院 | 欧美性极品xxxxx | 午夜视频免费在线 | 亚洲不卡在线播放 | 爱爱的免费视频 | 无遮挡很爽很污很黄在线网站 | 亚洲综合啪啪 |