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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux设备驱动--块设备(二)之相关结构体

發(fā)布時(shí)間:2025/3/21 linux 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux设备驱动--块设备(二)之相关结构体 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上回最后面介紹了相關(guān)數(shù)據(jù)結(jié)構(gòu),下面再詳細(xì)介紹

塊設(shè)備對(duì)象結(jié)構(gòu) block_device

內(nèi)核用結(jié)構(gòu)block_device實(shí)例代表一個(gè)塊設(shè)備對(duì)象,如:整個(gè)硬盤(pán)或特定分區(qū)。如果該結(jié)構(gòu)代表一個(gè)分區(qū),則其成員bd_part指向設(shè)備的分區(qū)結(jié)構(gòu)。如果該結(jié)構(gòu)代表設(shè)備,則其成員bd_disk指向設(shè)備的通用硬盤(pán)結(jié)構(gòu)gendisk

當(dāng)用戶打開(kāi)塊設(shè)備文件時(shí),內(nèi)核創(chuàng)建結(jié)構(gòu)block_device實(shí)例,設(shè)備驅(qū)動(dòng)程序還將創(chuàng)建結(jié)構(gòu)gendisk實(shí)例,分配請(qǐng)求隊(duì)列并注冊(cè)結(jié)構(gòu)block_device實(shí)例。

塊設(shè)備對(duì)象結(jié)構(gòu)block_device列出如下(在include/Linux/fs.h中)

[cpp]?view plaincopy print?
  • struct?block_device?{??
  • dev_t?bd_dev;??/*?not?a?kdev_t?-?it's?a?search?key?*/??
  • struct?inode?*?bd_inode;?/*?分區(qū)節(jié)點(diǎn)?*/??
  • struct?super_block?*?bd_super;??
  • int?bd_openers;??
  • struct?mutex?bd_mutex;/*?open/close?mutex?打開(kāi)與關(guān)閉的互斥量*/??
  • struct?semaphore?bd_mount_sem;????/*掛載操作信號(hào)量*/???
  • struct?list_head?bd_inodes;??
  • void?*?bd_holder;??
  • int?bd_holders;??
  • #ifdef?CONFIG_SYSFS??
  • struct?list_head?bd_holder_list;??
  • #endif??
  • struct?block_device?*?bd_contains;??
  • unsigned?bd_block_size;?????/*分區(qū)塊大小*/??
  • struct?hd_struct?*?bd_part;??
  • unsigned?bd_part_count;???/*打開(kāi)次數(shù)*/??
  • int?bd_invalidated;??
  • struct?gendisk?*?bd_disk;?/*設(shè)備為硬盤(pán)時(shí),指向通用硬盤(pán)結(jié)構(gòu)*/??
  • struct?list_head?bd_list;??
  • struct?backing_dev_info?*bd_inode_backing_dev_info;??
  • unsigned?long?bd_private;??
  • /*?The?counter?of?freeze?processes?*/??
  • int?bd_fsfreeze_count;??
  • /*?Mutex?for?freeze?*/??
  • struct?mutex?bd_fsfreeze_mutex;??
  • };??

  • 通用硬盤(pán)結(jié)構(gòu) gendisk

    結(jié)構(gòu)體gendisk代表了一個(gè)通用硬盤(pán)(generic hard disk)對(duì)象,它存儲(chǔ)了一個(gè)硬盤(pán)的信息,包括請(qǐng)求隊(duì)列、分區(qū)鏈表和塊設(shè)備操作函數(shù)集等。塊設(shè)備驅(qū)動(dòng)程序分配結(jié)構(gòu)gendisk實(shí)例,裝載分區(qū)表,分配請(qǐng)求隊(duì)列并填充結(jié)構(gòu)的其他域。

    支持分區(qū)的塊驅(qū)動(dòng)程序必須包含 <linux/genhd.h> 頭文件,并聲明一個(gè)結(jié)構(gòu)gendisk,內(nèi)核還維護(hù)該結(jié)構(gòu)實(shí)例的一個(gè)全局鏈表gendisk_head,通過(guò)函數(shù)add_gendisk、del_gendisk和get_gendisk維護(hù)該鏈表。

    結(jié)構(gòu)gendisk列出如下(在include/linux/genhd.h中):

    [cpp]?view plaincopy print?
  • struct?gendisk?{??
  • ????int?major;????????????/*?驅(qū)動(dòng)程序的主設(shè)備號(hào)?*/??
  • ????int?first_minor;???????/*第一個(gè)次設(shè)備號(hào)*/??
  • ????int?minors;??????????/*次設(shè)備號(hào)的最大數(shù)量,沒(méi)有分區(qū)的設(shè)備,此值為1?*/??
  • ????char?disk_name[32];??/*?主設(shè)備號(hào)驅(qū)動(dòng)程序的名字*/??
  • ????struct?hd_struct?**part;???/*?分區(qū)列表,由次設(shè)備號(hào)排序?*/??
  • ????struct?block_device_operations?*fops;??/*塊設(shè)備操作函數(shù)集*/??
  • ????struct?request_queue?*queue;?????????/*請(qǐng)求隊(duì)列*/??
  • ????struct?blk_scsi_cmd_filter?cmd_filter;??
  • ????void?*private_data;?????????????????/*私有數(shù)據(jù)*/??
  • ????sector_t?capacity;?????/*?函數(shù)set_capacity設(shè)置的容量,以扇區(qū)為單位*/??
  • ????int?flags;?????????????????/*設(shè)置驅(qū)動(dòng)器狀態(tài)的標(biāo)志,如:可移動(dòng)介質(zhì)為?
  • GENHD_FL_REMOVABLE*/??
  • ????struct?device?dev;?????????????????/*從設(shè)備驅(qū)動(dòng)模型基類(lèi)結(jié)構(gòu)device繼承*/??
  • ????struct?kobject?*holder_dir;??
  • ????struct?kobject?*slave_dir;??
  • ?struct?timer_rand_state?*random;??
  • ????int?policy;???
  • ????atomic_t?sync_io;????????/*?RAID?*/??
  • ????unsigned?long?stamp;??
  • ????int?in_flight;??
  • #ifdef??CONFIG_SMP??
  • ????struct?disk_stats?*dkstats;????
  • #else??
  • /*硬盤(pán)統(tǒng)計(jì)信息,如:讀或?qū)懙纳葏^(qū)數(shù)、融合的扇區(qū)數(shù)、在請(qǐng)求隊(duì)列的時(shí)間等*/??
  • ????struct?disk_stats?dkstats;??
  • #endif??
  • ????struct?work_struct?async_notify;??
  • #ifdef??CONFIG_BLK_DEV_INTEGRITY??
  • ????struct?blk_integrity?*integrity;???/*用于數(shù)據(jù)完整性擴(kuò)展*/??
  • #endif??
  • };??

  • Linux內(nèi)核提供了一組函數(shù)來(lái)操作gendisk,主要包括:
    分配gendisk
    struct gendisk *alloc_disk(int minors);
    minors 參數(shù)是這個(gè)磁盤(pán)使用的次設(shè)備號(hào)的數(shù)量,一般也就是磁盤(pán)分區(qū)的數(shù)量,此后minors不能被修改。
    增加gendisk
    gendisk結(jié)構(gòu)體被分配之后,系統(tǒng)還不能使用這個(gè)磁盤(pán),需要調(diào)用如下函數(shù)來(lái)注冊(cè)這個(gè)磁盤(pán)設(shè)備:
    void add_disk(struct gendisk *gd);
    特別要注意的是對(duì)add_disk()的調(diào)用必須發(fā)生在驅(qū)動(dòng)程序的初始化工作完成并能響應(yīng)磁盤(pán)的請(qǐng)求之后。

    ?釋放gendisk
    當(dāng)不再需要一個(gè)磁盤(pán)時(shí),應(yīng)當(dāng)使用如下函數(shù)釋放gendisk:
    void del_gendisk(struct gendisk *gd);

    設(shè)置gendisk容量
    void set_capacity(struct gendisk *disk, sector_t size);
    塊設(shè)備中最小的可尋址單元是扇區(qū),扇區(qū)大小一般是2的整數(shù)倍,最常見(jiàn)的大小是512字節(jié)。扇區(qū)的大小是設(shè)備的物理屬性,扇區(qū)是所有塊設(shè)備的基本單元,塊設(shè)備 無(wú)法對(duì)比它還小的單元進(jìn)行尋址和操作,不過(guò)許多塊設(shè)備能夠一次就傳輸多個(gè)扇區(qū)。雖然大多數(shù)塊設(shè)備的扇區(qū)大小都是512字節(jié),不過(guò)其它大小的扇區(qū)也很常見(jiàn), 比如,很多CD-ROM盤(pán)的扇區(qū)都是2K大小。不管物理設(shè)備的真實(shí)扇區(qū)大小是多少,內(nèi)核與塊設(shè)備驅(qū)動(dòng)交互的扇區(qū)都以512字節(jié)為單位。因此,set_capacity()函數(shù)也以512字節(jié)為單位。

    分區(qū)結(jié)構(gòu)hd_struct代表了一個(gè)分區(qū)對(duì)象,它存儲(chǔ)了一個(gè)硬盤(pán)的一個(gè)分區(qū)的信息,驅(qū)動(dòng)程序初始化時(shí),從硬盤(pán)的分區(qū)表中提取分區(qū)信息,存放在分區(qū)結(jié)構(gòu)實(shí)例中。

    塊設(shè)備操作函數(shù)集結(jié)構(gòu) block_device_operations

    字符設(shè)備通過(guò) file_operations 操作結(jié)構(gòu)使它們的操作對(duì)系統(tǒng)可用. 一個(gè)類(lèi)似的結(jié)構(gòu)用在塊設(shè)備上是 struct block_device_operations,
    定義在 <linux/fs.h>.?
    int (*open)(struct inode *inode, struct file *filp);?
    int (*release)(struct inode *inode, struct file *filp);?
    就像它們的字符驅(qū)動(dòng)對(duì)等體一樣工作的函數(shù); 無(wú)論何時(shí)設(shè)備被打開(kāi)和關(guān)閉都調(diào)用它們. 一個(gè)字符驅(qū)動(dòng)可能通過(guò)啟動(dòng)設(shè)備或者鎖住門(mén)(為可移出的介質(zhì))來(lái)響應(yīng)一個(gè) open 調(diào)用. 如果你將介質(zhì)鎖入設(shè)備, 你當(dāng)然應(yīng)當(dāng)在 release 方法中解鎖.
    int (*ioctl)(struct inode *inode, struct file *filp,?
    ????????????????????????? unsigned int cmd, unsigned long arg);?
    實(shí)現(xiàn) ioctl 系統(tǒng)調(diào)用的方法. 但是, 塊層首先解釋大量的標(biāo)準(zhǔn)請(qǐng)求; 因此大部分的塊驅(qū)動(dòng) ioctl 方法相當(dāng)短.

    PS:在block_device_operations中沒(méi)有實(shí)際讀或?qū)憯?shù)據(jù)的函數(shù). 在塊 I/O 子系統(tǒng), 這些操作由請(qǐng)求函數(shù)處理

    請(qǐng)求結(jié)構(gòu)request

    結(jié)構(gòu)request代表了掛起的I/O請(qǐng)求每個(gè)請(qǐng)求用一個(gè)結(jié)構(gòu)request實(shí)例描述,存放在請(qǐng)求隊(duì)列鏈表中,由電梯算法進(jìn)行排序,每個(gè)請(qǐng)求包含1個(gè)或多個(gè)結(jié)構(gòu)bio實(shí)例

    [cpp]?view plaincopy print?
  • struct?request?{??
  • ????//用于掛在請(qǐng)求隊(duì)列鏈表的節(jié)點(diǎn),使用函數(shù)blkdev_dequeue_request訪問(wèn)它,而不能直接訪??
  • 問(wèn)??
  • ????struct?list_head?queuelist;???
  • ????struct?list_head?donelist;??/*用于掛在已完成請(qǐng)求鏈表的節(jié)點(diǎn)*/??
  • ????struct?request_queue?*q;???/*指向請(qǐng)求隊(duì)列*/??
  • ????unsigned?int?cmd_flags;????/*命令標(biāo)識(shí)*/??
  • ????enum?rq_cmd_type_bits?cmd_type;??/*命令類(lèi)型*/??
  • ????/*各種各樣的扇區(qū)計(jì)數(shù)*/??
  • ???/*為提交i/o維護(hù)bio橫斷面的狀態(tài)信息,hard_*成員是塊層內(nèi)部使用的,驅(qū)動(dòng)程序不應(yīng)該改變?
  • 它們*/??
  • ????sector_t?sector;?????/*將提交的下一個(gè)扇區(qū)*/??
  • ????sector_t?hard_sector;????????/*?將完成的下一個(gè)扇區(qū)*/??
  • ????unsigned?long?nr_sectors;??/*?整個(gè)請(qǐng)求還需要傳送的扇區(qū)數(shù)*/??
  • ????unsigned?long?hard_nr_sectors;?/*?將完成的扇區(qū)數(shù)*/??
  • ?/*在當(dāng)前bio中還需要傳送的扇區(qū)數(shù)?*/??
  • ????unsigned?int?current_nr_sectors;??
  • ????/*在當(dāng)前段中將完成的扇區(qū)數(shù)*/??
  • ????unsigned?int?hard_cur_sectors;??
  • ????struct?bio?*bio;?????/*請(qǐng)求中第一個(gè)未完成操作的bio*、?
  • ????struct?bio?*biotail;?/*請(qǐng)求鏈表中末尾的bio*、?
  • ????struct?hlist_node?hash;??/*融合?hash?*/??
  • ????/*?rb_node僅用在I/O調(diào)度器中,當(dāng)請(qǐng)求被移到分發(fā)隊(duì)列中時(shí),?
  • 請(qǐng)求將被刪除。因此,讓completion_data與rb_node分享空間*/??????
  • ????union?{??
  • ????????struct?rb_node?rb_node;???/*?排序/查找*/??
  • ????????void?*completion_data;??
  • ????};??
  • ?request結(jié)構(gòu)體的主要成員包括:
    ?sector_t hard_sector;?
    unsigned long hard_nr_sectors;?
    unsigned int hard_cur_sectors;?
    上述3個(gè)成員標(biāo)識(shí)還未完成的扇區(qū),hard_sector是第1個(gè)尚未傳輸?shù)纳葏^(qū),hard_nr_sectors是尚待完成的扇區(qū)數(shù),hard_cur_sectors是并且當(dāng)前I/O操作中待完成的扇區(qū)數(shù)。這些成員只用于內(nèi)核塊設(shè)備層,驅(qū)動(dòng)不應(yīng)當(dāng)使用它們。


    ?sector_t sector;?
    unsigned long nr_sectors;?
    unsigned int current_nr_sectors;?
    驅(qū)動(dòng)中會(huì)經(jīng)常與這3個(gè)成員打交道,這3個(gè)成員在內(nèi)核和驅(qū)動(dòng)交互中發(fā)揮著重大作用。它們以512字節(jié)大小為1個(gè)扇區(qū),如果硬件的扇區(qū)大小不是512字節(jié),則需要進(jìn)行相應(yīng)的調(diào)整。例如,如果硬件的扇區(qū)大小是2048字節(jié),則在進(jìn)行硬件操作之前,需要用4來(lái)除起始扇區(qū)號(hào)。


    ?hard_sector、hard_nr_sectors、hard_cur_sectors與sector、nr_sectors、current_nr_sectors之間可認(rèn)為是“副本”關(guān)系。


    struct bio *bio;?
    bio是這個(gè)請(qǐng)求中包含的bio結(jié)構(gòu)體的鏈表,驅(qū)動(dòng)中不宜直接存取這個(gè)成員,而應(yīng)該使用后文將介紹的rq_for_each_bio()。

    請(qǐng)求隊(duì)列結(jié)構(gòu)request_queue

    每個(gè)塊設(shè)備都有一個(gè)請(qǐng)求隊(duì)列,每個(gè)請(qǐng)求隊(duì)列單獨(dú)執(zhí)行I/O調(diào)度,請(qǐng)求隊(duì)列是由請(qǐng)求結(jié)構(gòu)實(shí)例鏈接成的雙向鏈表,鏈表以及整個(gè)隊(duì)列的信息用結(jié)構(gòu)request_queue描述,稱(chēng)為請(qǐng)求隊(duì)列對(duì)象結(jié)構(gòu)或請(qǐng)求隊(duì)列結(jié)構(gòu)。它存放了關(guān)于掛起請(qǐng)求的信息以及管理請(qǐng)求隊(duì)列(如:電梯算法)所需要的信息。結(jié)構(gòu)成員request_fn是來(lái)自設(shè)備驅(qū)動(dòng)程序的請(qǐng)求處理函數(shù)。

    請(qǐng)求隊(duì)列結(jié)構(gòu)request_queue列出如下(在/include/linux/blk_dev.h中)

    太長(zhǎng)了,此處略,其實(shí)也看不懂,- -#

    Bio結(jié)構(gòu)

    通常1個(gè)bio對(duì)應(yīng)1個(gè)I/O請(qǐng)求,IO調(diào)度算法可將連續(xù)的bio合并成1個(gè)請(qǐng)求。所以,1個(gè)請(qǐng)求可以包含多個(gè)bio。

    內(nèi)核中塊I/O操作的基本容器由bio結(jié)構(gòu)體表示,定義 在<linux/bio.h>中,該結(jié)構(gòu)體代表了正在現(xiàn)場(chǎng)的(活動(dòng)的)以片段(segment)鏈表形式組織的塊I/O操作。一個(gè)片段是一小 塊連續(xù)的內(nèi)存緩沖區(qū)。這樣的好處就是不需要保證單個(gè)緩沖區(qū)一定要連續(xù)。所以通過(guò)片段來(lái)描述緩沖區(qū),即使一個(gè)緩沖區(qū)分散在內(nèi)存的多個(gè)位置上,bio結(jié)構(gòu)體也 能對(duì)內(nèi)核保證I/O操作的執(zhí)行,這樣的就叫做聚散I/O.
    bio為通用層的主要數(shù)據(jù)結(jié)構(gòu),既描述了磁盤(pán)的位置,又描述了內(nèi)存的位置,是上層內(nèi)核vfs與下層驅(qū)動(dòng)的連接紐帶

    [cpp]?view plaincopy print?
  • struct?bio?{??
  • sector_t????????bi_sector;//該bio結(jié)構(gòu)所要傳輸?shù)牡谝粋€(gè)(512字節(jié))扇區(qū):磁盤(pán)的位置??
  • struct?bio????????*bi_next;????//請(qǐng)求鏈表??
  • struct?block_device????*bi_bdev;//相關(guān)的塊設(shè)備??
  • unsigned?long????????bi_flags//狀態(tài)和命令標(biāo)志??
  • unsigned?long????????bi_rw;?//讀寫(xiě)??
  • unsigned?short????????bi_vcnt;//bio_vesc偏移的個(gè)數(shù)??
  • unsigned?short????????bi_idx;????//bi_io_vec的當(dāng)前索引??
  • unsigned?short????????bi_phys_segments;//結(jié)合后的片段數(shù)目??
  • unsigned?short????????bi_hw_segments;//重映射后的片段數(shù)目??
  • unsigned?int????????bi_size;????//I/O計(jì)數(shù)??
  • unsigned?int????????bi_hw_front_size;//第一個(gè)可合并的段大小;??
  • unsigned?int????????bi_hw_back_size;//最后一個(gè)可合并的段大小??
  • unsigned?int????????bi_max_vecs;????//bio_vecs數(shù)目上限??
  • struct?bio_vec????????*bi_io_vec;????//bio_vec鏈表:內(nèi)存的位置??
  • bio_end_io_t????????*bi_end_io;//I/O完成方法??
  • atomic_t????????bi_cnt;?//使用計(jì)數(shù)??
  • void????????????*bi_private;?//擁有者的私有方法??
  • bio_destructor_t????*bi_destructor;????//銷(xiāo)毀方法??
  • };??

  • 內(nèi)存數(shù)據(jù)段結(jié)構(gòu)bio_vec

    ?????? 結(jié)構(gòu)bio_vec代表了內(nèi)存中的一個(gè)數(shù)據(jù)段,數(shù)據(jù)段用頁(yè)、偏移和長(zhǎng)度描
    述。I/O需要執(zhí)行的內(nèi)存位置用段表示,結(jié)構(gòu)bio指向了一個(gè)段的數(shù)組。
    結(jié)構(gòu)bio_vec列出如下(在include/linux/bio.h中):
    struct bio_vec {
    ?????? struct page???? *bv_page;?? /*數(shù)據(jù)段所在的頁(yè)*/
    ?????? unsigned short? bv_len;???? /*數(shù)據(jù)段的長(zhǎng)度*/
    ?????? unsigned short? bv_offset;? /*數(shù)據(jù)段頁(yè)內(nèi)偏移*/
    };

    塊設(shè)備各個(gè)結(jié)構(gòu)體間關(guān)系

    轉(zhuǎn)載于:https://www.cnblogs.com/Ph-one/p/6435916.html

    總結(jié)

    以上是生活随笔為你收集整理的Linux设备驱动--块设备(二)之相关结构体的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。