中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

blogger wordpressseo人員招聘

blogger wordpress,seo人員招聘,新鄉(xiāng)網(wǎng)站建設(shè)聯(lián)系方式,網(wǎng)站運(yùn)營(yíng)與管理的對(duì)策第六十八章 設(shè)備樹(shù)插件介紹 Linux 4.4之后引入了動(dòng)態(tài)設(shè)備樹(shù),其中的設(shè)備樹(shù)插件(Device Tree Overlay)是一種擴(kuò)展機(jī)制,允許在運(yùn)行時(shí)動(dòng)態(tài)添加、修改或刪除設(shè)備節(jié)點(diǎn)和屬性。 設(shè)備樹(shù)插件機(jī)制通過(guò)DTS(設(shè)備樹(shù)源文件&#xff0…

第六十八章 設(shè)備樹(shù)插件介紹

????????Linux 4.4之后引入了動(dòng)態(tài)設(shè)備樹(shù),其中的設(shè)備樹(shù)插件(Device Tree Overlay)是一種擴(kuò)展機(jī)制,允許在運(yùn)行時(shí)動(dòng)態(tài)添加、修改或刪除設(shè)備節(jié)點(diǎn)和屬性。

? ? ? ? 設(shè)備樹(shù)插件機(jī)制通過(guò)DTS(設(shè)備樹(shù)源文件)定義,提供了一種靈活配置硬件設(shè)備的方式,無(wú)需重新編譯整個(gè)設(shè)備樹(shù),也無(wú)需重啟系統(tǒng)即可進(jìn)行硬件配置更改。

????????在 linux 源碼中 linux_sdk/kernel/Documentation/filesystems/configfs 目錄下的 configfs.txt。是設(shè)備樹(shù)插件的幫助文檔。

第六十九章 設(shè)備樹(shù)插件語(yǔ)法和編譯實(shí)驗(yàn)

69.1 設(shè)備樹(shù)插件語(yǔ)法

????????設(shè)備樹(shù)插件的語(yǔ)法格式基于設(shè)備樹(shù)源文件的語(yǔ)法,但是有一些特定的語(yǔ)法和指令用于描述插件的行為。

????????我們新建 overlay.dts,

1 首先添加插件頭部聲明,它指定了插件的名稱(chēng)和版本等信息,并指定了要修改的設(shè)備樹(shù)的路徑,

/dts-v1/;  
/plugin/;  
// 插件頭部聲明(示例,實(shí)際內(nèi)容根據(jù)需求填寫(xiě))  
/plugin/name: "my_overlay";  
/plugin/version: "1.0";  
/plugin/target-path: "/"; // 目標(biāo)設(shè)備樹(shù)路徑

2 插件節(jié)點(diǎn)名稱(chēng)用于指定要操作的設(shè)備節(jié)點(diǎn)及其屬性。

? ? ? ? 假設(shè)需要編寫(xiě)插件的設(shè)備樹(shù)節(jié)點(diǎn)如下:

rk_485_ctl:rk-485-ctl{compatible = "topeet,rs485_ctl";gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;pinctrl-names = "default";pinctrl-0 = <&rk_485_gpio>;
}

? ? ? ? 設(shè)備樹(shù)插件有以下四種寫(xiě)法。?了解即可。

/dts-v1/;
/plugin/;&{/rk-485-ctl}{          或者   &rk_485_ctl{overlay_node{status = "okay";};
};/{fragment@0{target-path = "rk-485-cl";  或者 target= <rk-485-cl>;__overlay__{overlay_node{status = "okay";}}}
}

69.2 設(shè)備樹(shù)插件編譯

? ? ? ? 使用方法一,然后編譯設(shè)備樹(shù)插件 overlay.dts,輸入以下命令:

/home/topeet/Linux/linux_sdk/kernel/scripts/dtc/dtc-I dts          //輸入文件的格式-O dtb          //輸出文件的格式overlay.dts     //輸入的源文件-o overlay.dtbo //輸出文件的名稱(chēng)和路徑

????????反編譯設(shè)備樹(shù),輸入以下命令:

/home/topeet/Linux/linux_sdk/kernel/scripts/dtc/dtc -I dtb -O dts overlay.dtbo -o 1.dts

第七十章 設(shè)備樹(shù)插件使用

70.1 準(zhǔn)備實(shí)驗(yàn)環(huán)境

? ? ? ? 要求內(nèi)核鏡像支持設(shè)備樹(shù)插件,一般要求內(nèi)核版本4.4以上。

????????使用“insmod xxx.ko”命令加載設(shè)備樹(shù)插件驅(qū)動(dòng)。

? ? ? ? 使用 cat /proc/filesystems 查看當(dāng)前內(nèi)核支持的文件系統(tǒng)類(lèi)型的列表

cat /proc/filesystems 當(dāng)前內(nèi)核支持的文件系統(tǒng)類(lèi)型列表

????????在Linux系統(tǒng)中,/proc/filesystems文件是一個(gè)虛擬文件,它提供了當(dāng)前內(nèi)核支持的文件系統(tǒng)類(lèi)型的列表。這個(gè)文件是由內(nèi)核動(dòng)態(tài)生成的,并且只存在于內(nèi)存中,不占用磁盤(pán)空間。

????????輸出中的每一行都代表一個(gè)文件系統(tǒng)類(lèi)型,前面的 nodev表示該文件系統(tǒng)類(lèi)型不支持在磁盤(pán)上作為設(shè)備掛載(即它不是基于塊設(shè)備的文件系統(tǒng))。沒(méi)有nodev前綴的文件系統(tǒng)類(lèi)型則通??梢?huà)燧d在磁盤(pán)設(shè)備或其他類(lèi)型的文件系統(tǒng)之上。

70.2 設(shè)備樹(shù)插件的使用

????????在上一章節(jié)中,我們編寫(xiě)了 overlay.dts。

????????在 overlay.dts 中,rk-485-ctl 節(jié)點(diǎn)下添加新的節(jié)點(diǎn)overlay_node 節(jié)點(diǎn),如下所示:

/dts-v1/;
/plugin/;&{/rk-485-ctl}{          overlay_node{status = "okay";};
};

????????使用 dtc 編譯器編譯得到 dtbo 文件,并將 dtbo 拷貝到開(kāi)發(fā)板上。

/home/topeet/Linux/linux_sdk/kernel/scripts/dtc/dtc 
-I dts 
-O dtb 
overlay.dts 
-o overlay.dtbo

????????我們進(jìn)到系統(tǒng)?/sys/kernel/config/device-tree/overlays/(這個(gè)目錄需要加載設(shè)備樹(shù)插件才會(huì)生成)目錄下。

????????在這個(gè)目錄下使用以下命令創(chuàng)建一個(gè)內(nèi)核對(duì)象,

mkdir test

?????????使用命令 cd test 進(jìn)到 test 文件夾,在文件夾下創(chuàng)建 status和 dtbo兩個(gè)文件

cd test

? ? ? ? ?使用 cat /overlay.dtbo > dtbo插件.dtbo文件 寫(xiě)入 dtbo文件。

? ? ? ? ?在狀態(tài)文件status中寫(xiě)入 1,來(lái)使能插件。echo 1 > status。

????????此時(shí)查看 proc文件系統(tǒng)的devicetree可以看到加載的 插件節(jié)點(diǎn)。

ls /proc/device-tree/rk-485-ctl/overlay_node/
/proc/device-tree/節(jié)點(diǎn)/插件節(jié)點(diǎn)

要?jiǎng)h掉插件節(jié)點(diǎn),直接把?/sys/kernel/config/device-tree/overlays/ 下的 test文件刪掉就可。

????????要加載多個(gè)插件,多寫(xiě)幾個(gè)文件夾,把 dtc編譯后的插件內(nèi)容用 cat xxx > bbb 寫(xiě)到 dtbo 文件就行。?

第七十一章 虛擬文件系統(tǒng) ConfigFS

????????虛擬文件系統(tǒng) ConfigFS 是一個(gè)特殊的文件系統(tǒng),旨在提供一種動(dòng)態(tài)配置 Linux 內(nèi)核和設(shè)備的機(jī)制。

71.1 常用的虛擬文件系統(tǒng)

????????在Linux內(nèi)核中,虛擬文件系統(tǒng)為應(yīng)用程序提供了統(tǒng)一的文件訪(fǎng)問(wèn)接口,簡(jiǎn)化了開(kāi)發(fā)、維護(hù),提高了可移植性和靈活性。以下是幾個(gè)常用的虛擬文件系統(tǒng)及其功能簡(jiǎn)述:

Procfs:? ? 主要用于進(jìn)程、設(shè)備、驅(qū)動(dòng)等系統(tǒng)信息,表示運(yùn)行時(shí)狀態(tài)。

Sysfs:? ? ?主要用于設(shè)備、驅(qū)動(dòng)等內(nèi)核對(duì)象的屬性和狀態(tài)。

Configfs:主要用于動(dòng)態(tài)管理內(nèi)核對(duì)象。允許運(yùn)行時(shí)添加、修改和刪除內(nèi)核對(duì)象

Procfs

????????功能:訪(fǎng)問(wèn)內(nèi)核運(yùn)行時(shí)狀態(tài),包括進(jìn)程設(shè)備、驅(qū)動(dòng)程序等系統(tǒng)信息

????????路徑:通常在 /proc 目錄下。

# 訪(fǎng)問(wèn)CPU信息
/proc/cpuinfo 

Sysfs

????????功能:表示系統(tǒng)中的設(shè)備驅(qū)動(dòng)程序等內(nèi)核對(duì)象,為這些對(duì)象的屬性和狀態(tài)提供統(tǒng)一的訪(fǎng)問(wèn)接口。

路徑:通常在 /sys 目錄下。

# 查看設(shè)備信息
/sys/class/tty/ttyS0/device/idVendor  

Configfs

????????功能:動(dòng)態(tài)配置和管內(nèi)核對(duì)象,允許在運(yùn)行時(shí)添加、修改和刪除內(nèi)核對(duì)象。

????????路徑:通常在 /sys/kernel/config 目錄下。

# 動(dòng)態(tài)配置內(nèi)核對(duì)象
/sys/kernel/config  

????????設(shè)備樹(shù)插件選擇 ConfigFS 原因在于,

????????configfs允許用戶(hù)空間動(dòng)態(tài)配置內(nèi)核對(duì)象,無(wú)需改內(nèi)核代碼,適合設(shè)備樹(shù)插件技術(shù)。

第七十二章 ConfigFS 核心數(shù)據(jù)結(jié)構(gòu)

72.1 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)

ConfigFS核心數(shù)據(jù)結(jié)構(gòu):

configfs_subsystem頂層結(jié)構(gòu),代表整個(gè)ConfigFS系統(tǒng),含根配置項(xiàng)組和系統(tǒng)狀態(tài)。

config_group配置項(xiàng)組,可含多個(gè)相關(guān)配置項(xiàng),成層次結(jié)構(gòu),含父子配置項(xiàng)指針。

config_item基本配置項(xiàng),表示內(nèi)核對(duì)象,含類(lèi)型、名稱(chēng)、屬性和狀態(tài)、父子關(guān)系指針。

????????這些結(jié)構(gòu)形成樹(shù)形,subsystem為根,group為組,item為項(xiàng),通過(guò)指針連接成父子關(guān)系。

configfs核心數(shù)據(jù)結(jié)構(gòu)

72.2 子系統(tǒng)、配置組和?配置項(xiàng)

????????configfs_subsystem 結(jié)構(gòu)體:成員有config_group 結(jié)構(gòu)體: 和互斥鎖,

????????config_group 結(jié)構(gòu)體:成員有config_item結(jié)構(gòu)體,和多個(gè)鏈表頭,

? ? ? ? config_item結(jié)構(gòu)體,成員有 config_item_type結(jié)構(gòu)體引用計(jì)數(shù)等。

? ? ? ? config_item_type結(jié)構(gòu)體有

????????????????configfs_item_operations配置項(xiàng)操作集、

????????????????configfs_group_operations配置組操作集。

? ? ? ? ? ? ? ? configfs_attribute屬性文件操作集。

config_item_operations操作集release方法。

config_group_operations操作集make_item、drop_item、make_group等方法。

configfs_attribute屬性文件操作集有 myread_showmywrite_store方法,在 只讀屬性文件、只寫(xiě)屬性文件分別被 讀出、寫(xiě)入時(shí)執(zhí)行。?

????????configfs_subsystem 結(jié)構(gòu)體

/*configfs子系統(tǒng)結(jié)構(gòu)體*/
struct configfs_subsystem {struct config_group su_group;//配置項(xiàng)組結(jié)構(gòu)體struct mutex su_mutex;       //互斥鎖
};

? ? ? ? config_group 結(jié)構(gòu)體:?

/*config_group配置組*/
struct config_group {struct config_item cg_item;          //配置項(xiàng)struct list_head cg_children;        //雙向鏈表頭,鏈接配置組下所有子配置組和配置項(xiàng)struct configfs_subsystem *cg_subsys;//配置組所屬子系統(tǒng)struct list_head default_groups;     //雙向鏈表頭,鏈接配置組的默認(rèn)子組struct list_head group_entry;        //雙向鏈表頭,鏈接配置組所屬子系統(tǒng)的條目
};

?????????config_item 結(jié)構(gòu)體

/*config_item配置項(xiàng)*/
struct config_item {char *ci_name;                           //配置項(xiàng)名稱(chēng)指針char ci_namebuf[CONFIGFS_ITEM_NAME_LEN]; //配置項(xiàng)名稱(chēng)緩沖區(qū).一個(gè)配置項(xiàng)就是一個(gè)目錄struct kref ci_kref;                     //配置項(xiàng)引用計(jì)數(shù)          struct list_head ci_entry;               //配置項(xiàng)的鏈表?xiàng)l目struct config_item *ci_parent;           //父配置項(xiàng)struct config_group *ci_group;           //配置項(xiàng)組const struct config_item_type *ci_type; //目錄下屬性文件和屬性操作struct dentry *ci_dentry;               //指向與配置項(xiàng)關(guān)聯(lián)的目錄項(xiàng)(dentry)的指針。
};//每個(gè)配置項(xiàng)都對(duì)應(yīng)一個(gè)文件系統(tǒng)目錄項(xiàng),
//config_item_type用于描述配置項(xiàng)類(lèi)型和操作,包括用于讀寫(xiě)目錄項(xiàng)屬性的回調(diào)函數(shù)//在ConfigFS中,每個(gè)配置項(xiàng)都對(duì)應(yīng)一個(gè)文件系統(tǒng)目錄項(xiàng),
//該目錄項(xiàng)用于與用戶(hù)空間進(jìn)行交互
//(如通過(guò)mount命令掛載ConfigFS后,可以通過(guò)文件操作來(lái)訪(fǎng)問(wèn)這些配置項(xiàng))。

? ? ? ? 接下來(lái)我們分析一下設(shè)備樹(shù)插件驅(qū)動(dòng)代碼

????????設(shè)備樹(shù)插件驅(qū)動(dòng)代碼定義了ConfigFS子系統(tǒng)配置項(xiàng)組。

????????dtbocfg_root_subsys是子系統(tǒng)實(shí)例,其根配置項(xiàng)組由 config_group表示,命名為"device-tree",并指定了自定義類(lèi)型 dtbocfg_root_type。子系統(tǒng)使用互斥鎖保護(hù)操作。

????????首先,在這里,該結(jié)構(gòu)體的.cg_item 字段表示根配置項(xiàng)組的基本配置項(xiàng)。

/*創(chuàng)建configfs子系統(tǒng)實(shí)例的定義和初始化*/
static struct configfs_subsystem dtbocfg_root_subsys = {  //dtbocfg_root_subsys.su_group 是一個(gè) config_group 結(jié)構(gòu)體,它表示子系統(tǒng)的根配置項(xiàng)組。//.cg_item 字段表示根配置項(xiàng)組的基本配置項(xiàng).su_group.cg_item.ci_namebuf = "device-tree",   /*根配置項(xiàng)名稱(chēng)*///注冊(cè)子文件系統(tǒng)時(shí),會(huì)在sys/kernel/configs目錄下,用根配置項(xiàng)名稱(chēng)創(chuàng)建子文件系統(tǒng)//配置項(xiàng)的類(lèi)型=一個(gè)自定義config_item_type.su_group.cg_item.ci_type = &dtbocfg_root_type,//初始化互斥鎖.su_mutex = __MUTEX_INITIALIZER(dtbocfg_root_subsys.su_mutex),  
};  

? ? ? ? 注意,子文件系統(tǒng)有 配置項(xiàng)組成員,配置項(xiàng)組成員有根配置項(xiàng),注冊(cè)子文件系統(tǒng)時(shí),用的是根配置項(xiàng)的名字。?

? ? ? ? 注冊(cè) 配置項(xiàng)組的時(shí)候,用的是注冊(cè)函數(shù)給的名字參數(shù)?

????????通過(guò)這段代碼,創(chuàng)建了一個(gè)名為"device-tree"的子系統(tǒng),它的根配置項(xiàng)組為空。

????????可在該子系統(tǒng)下添加更多配置項(xiàng)和配置項(xiàng)組,用于動(dòng)態(tài)配置和管理設(shè)備樹(shù)相關(guān)的內(nèi)核對(duì)象。

?????????Linux 系統(tǒng)下創(chuàng)建了 device-tree 這個(gè)子系統(tǒng),

創(chuàng)建configfs_subsystem對(duì)象后sys/kernel/config目錄下新建了 與[子系統(tǒng)名]同名的目錄

?????????接下來(lái)是設(shè)備樹(shù)插件驅(qū)動(dòng)代碼中注冊(cè)配置項(xiàng)組的部分,

/*創(chuàng)建配置項(xiàng)組實(shí)例*/
static struct config_group dtbocfg_overlay_group = {  .cg_item.ci_type = &dtbocfg_overlays_type,  
};  /**/
static int dtbocfg_module_init(void) {  int retval;  /*初始化Configfs子系統(tǒng)的根配置項(xiàng)組*/config_group_init(&dtbocfg_root_subsys.su_group); /*初始化Confifs子系統(tǒng)的名為 overlays的配置項(xiàng)組*/ config_group_init_type_name(&dtbocfg_overlay_group,"overlays",     &dtbocfg_overlays_type);/*注冊(cè)子系統(tǒng)*/retval = configfs_register_subsystem(&dtbocfg_root_subsys);  if (retval) goto register_subsystem_failed; /*注冊(cè)配置項(xiàng)組*/retval = configfs_register_group(&dtbocfg_root_subsys.su_group, &dtbocfg_overlay_group);  if (retval) goto register_group_failed;  pr_info("OK\n");  return 0;  register_group_failed:  /*注銷(xiāo)子系統(tǒng)*/configfs_unregister_subsystem(&dtbocfg_root_subsys);  
register_subsystem_failed:  return retval;  
}

初始化函數(shù) dtbocfg_module_init()執(zhí)行以下步驟:

????????初始化子系統(tǒng)的根配置項(xiàng)組和名為"overlays"的配置項(xiàng)組,指定類(lèi)型dtbocfg_overlays_type。

????????configfs_register_subsystem()注冊(cè)子系統(tǒng)。

????????將"overlays"配置項(xiàng)組添加到子系統(tǒng)的根配置項(xiàng)組下。

????????configfs_register_group()在子系統(tǒng)中注冊(cè)配置項(xiàng)組。

????????如注冊(cè)失敗,注銷(xiāo)子系統(tǒng)并返回錯(cuò)誤碼;成功則打印"OK"。

????????結(jié)果是在/sys/kernel/config下創(chuàng)建了名為"device-tree"的子系統(tǒng),并在其下創(chuàng)建了名為"overlays"的容器。

overlays配置項(xiàng)組注冊(cè)成功,子系統(tǒng)目錄下出現(xiàn)對(duì)應(yīng)的配置項(xiàng)目錄

72.3 屬性和方法

????????我們要在容器下放目錄或?qū)傩晕募?#xff0c;所以我們看一下 config_item 結(jié)構(gòu)體

struct config_item {char *ci_name;char ci_namebuf[CONFIGFS_ITEM_NAME_LEN]; //目錄的名字struct kref ci_kref;struct list_head ci_entry;struct config_item *ci_parent;struct config_group *ci_group;const struct config_item_type *ci_type; //目錄下屬性文件和屬性操作struct dentry *ci_dentry;
};

????????config_item 結(jié)構(gòu)體中包含了 config_item_type 結(jié)構(gòu)體

/*配置項(xiàng)的屬性和操作*/
struct config_item_type {    struct module *ct_owner;                        //所屬模塊struct configfs_item_operations *ct_item_ops;   //item(目錄)的操作方法struct configfs_group_operations *ct_group_ops; //group(容器)的操作方法struct configfs_attribute **ct_attrs;           //屬性文件的操作方法struct configfs_bin_attribute **ct_bin_attrs;   //bin 屬性文件的操作方法
}; 

????????config_item_type 結(jié)構(gòu)體中包含了 struct configfs_item_operations 結(jié)構(gòu)體

/*配置項(xiàng)組下,配置項(xiàng)刪除和鏈接的創(chuàng)建、刪除的鉤子函數(shù)*/
struct configfs_item_operations {//刪除 item 方法,在 group 下面使用 rmdir 命令會(huì)調(diào)用這個(gè)方法void (*release)(struct config_item *);//參數(shù)是指向被刪除的配置項(xiàng)的指針/*在嘗試創(chuàng)建一個(gè)從 src 到 target 的鏈接之前,這個(gè)函數(shù)會(huì)被調(diào)用。在 ConfigFS 中,配置項(xiàng)可以通過(guò)創(chuàng)建鏈接(link)來(lái)組織成樹(shù)狀結(jié)構(gòu)或形成關(guān)聯(lián)。*/int (*allow_link)(struct config_item *src, struct config_item *target);/*當(dāng)從 src 到 target 的鏈接被刪除時(shí),這個(gè)函數(shù)會(huì)被調(diào)用。*/void (*drop_link)(struct config_item *src, struct config_item *target);
};

????????config_item_type 結(jié)構(gòu)體中包含了 struct configfs_group_operations 結(jié)構(gòu)體

/*配置項(xiàng)與配置項(xiàng)組關(guān)聯(lián)的相關(guān)鉤子函數(shù)*/
struct configfs_group_operations {//當(dāng)在配置組下使用 mkdir 命令創(chuàng)建一個(gè)新的子配置項(xiàng)時(shí),這個(gè)函數(shù)會(huì)被調(diào)用struct config_item *(*make_item)(struct config_group *group, const char *name);/*其實(shí)就是目錄下新建文件的時(shí)候,該函數(shù)調(diào)用*///當(dāng)在配置組下使用 mkdir 命令創(chuàng)建一個(gè)新的子配置組時(shí),這個(gè)函數(shù)會(huì)被調(diào)用。struct config_group *(*make_group)(struct config_group *group, const char *name);/*其實(shí)就是目錄下新建文件的時(shí)候,該函數(shù)調(diào)用.相較于make_item優(yōu)先級(jí)更高*///在配置項(xiàng)被完全設(shè)置或修改后,這個(gè)函數(shù)會(huì)被調(diào)用以確認(rèn)或提交這些更改。int (*commit_item)(struct config_item *item);//配置項(xiàng)與其父配置組之間的關(guān)聯(lián)被斷開(kāi)時(shí)(例如,當(dāng)配置項(xiàng)被刪除時(shí)),這個(gè)函數(shù)會(huì)被調(diào)用。void (*disconnect_notify)(struct config_group *group, struct config_item *item);//當(dāng)配置項(xiàng)從配置組中被刪除時(shí),這個(gè)函數(shù)會(huì)被調(diào)用。void (*drop_item)(struct config_group *group, struct config_item *item);
};

????????config_item_type 結(jié)構(gòu)體中包含了 struct configfs_attribute 結(jié)構(gòu)體,?

struct configfs_attribute {const char *ca_name;     //屬性文件的名字struct module *ca_owner; //屬性文件文件的所屬模塊umode_t ca_mode;         //屬性文件訪(fǎng)問(wèn)權(quán)限//讀寫(xiě)方法的函數(shù)指針,具體功能需要自行實(shí)現(xiàn)。ssize_t (*show)(struct config_item *, char *);ssize_t (*store)(struct config_item *, const char *, size_t); 
};
struct configfs_bin_attribute {  struct configfs_attribute cb_attr;  /* 標(biāo)準(zhǔn)的屬性結(jié)構(gòu)體 */  void *cb_private;                  /* 私有數(shù)據(jù)指針,可用于用戶(hù)空間 */  size_t cb_max_size;                /* 二進(jìn)制數(shù)據(jù)的最大大小 */  ssize_t (*read)(struct config_item *, void *, size_t);  /* 讀取回調(diào)函數(shù) */  ssize_t (*write)(struct config_item *, const void *, size_t); /* 寫(xiě)入回調(diào)函數(shù) */  
};

?

第七十三章 注冊(cè) configfs 子系統(tǒng)實(shí)驗(yàn)

????????我們編寫(xiě)驅(qū)動(dòng)代碼創(chuàng)建一個(gè)名為“myconfigfs”的 configfs 子系統(tǒng),并將其注冊(cè)到內(nèi)核中。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>//定義名為"myconfig_item_type"的配置項(xiàng)類(lèi)型結(jié)構(gòu)體
static const struct config_item_type myconfig_item_type ={.ct_owner = THIS_MODULE, .ct_item_ops = NULL, .ct_group_ops = NULL, .ct_attrs = NULL, };//定義一個(gè) configfs_subsystem 結(jié)構(gòu)體實(shí)例"myconfigfs_subsystem"
static struct configfs_subsystem myconfigfs_subsystem ={.su_group = {.cg_item = {.ci_namebuf = "myconfigfs",     //配置項(xiàng)的名稱(chēng).ci_type = &myconfig_item_type, //配置項(xiàng)的操作},}, 
};//模塊的初始化函數(shù)
static int myconfigfs_init(void)
{//初始化配置組config_group_init(&myconfigfs_subsystem.su_group);//注冊(cè)子系統(tǒng)configfs_register_subsystem(&myconfigfs_subsystem);return 0;
}// 模塊退出函數(shù)
static void myconfigfs_exit(void)
{/*注銷(xiāo)子系統(tǒng)*/configfs_unregister_subsystem(&myconfigfs_subsystem);
}
module_init(myconfigfs_init); // 指定模塊的初始化函數(shù)
module_exit(myconfigfs_exit); // 指定模塊的退出函數(shù)
MODULE_LICENSE("GPL"); // 模塊使用的許可證
MODULE_AUTHOR("topeet"); // 模塊的作者

????????驅(qū)動(dòng)加載之后,進(jìn)入/sys/kernel/config 目錄下,可以看到注冊(cè)生成的 myconfigfs 子系統(tǒng),

注冊(cè)生成的子系統(tǒng)目錄

第七十四章 注冊(cè) configs 配置項(xiàng)實(shí)驗(yàn)

? ? ? ? 由于 注冊(cè) config_group配置項(xiàng)組的過(guò)程和?注冊(cè) configfs子系統(tǒng)的過(guò)程相似,所以略過(guò),

????????而注冊(cè)配置項(xiàng)的過(guò)程包含了注冊(cè)配置項(xiàng)組的過(guò)程,且涉及config_item_type的配置過(guò)程,有著較多的鉤子函數(shù)需要配置。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>
// 定義一個(gè)名為"mygroup"的 config_group 結(jié)構(gòu)體
static struct config_group mygroup;
// 自定義的配置項(xiàng)結(jié)構(gòu)體
struct myitem
{struct config_item item;
};// 配置項(xiàng)釋放函數(shù)
void myitem_release(struct config_item *item)
{struct myitem *myitem = container_of(item, struct myitem, item);kfree(myitem);printk("%s\n", __func__);
}// 配置項(xiàng)操作結(jié)構(gòu)體
struct configfs_item_operations myitem_ops = {.release = myitem_release, 
};// 配置項(xiàng)類(lèi)型結(jié)構(gòu)體
static struct config_item_type mygroup_item_type = {.ct_owner = THIS_MODULE, .ct_item_ops = &myitem_ops, 
};// 新建配置項(xiàng)函數(shù)
struct config_item *mygroup_make_item(struct config_group *group, const char *name)
{struct myitem *myconfig_item;printk("%s\n", __func__);myconfig_item = kzalloc(sizeof(*myconfig_item), GFP_KERNEL);//創(chuàng)建一個(gè)配置項(xiàng),綁定 名稱(chēng) 和 屬性及操作config_item_init_type_name(&myconfig_item->item, name, &mygroup_item_type);return &myconfig_item->item;
}// 配置組操作結(jié)構(gòu)體
struct configfs_group_operations mygroup_ops = {/*綁定配置項(xiàng)的新建函數(shù)*/.make_item = mygroup_make_item, 
};//config_item_type 結(jié)構(gòu)體,用于描述配置項(xiàng)類(lèi)型(但其實(shí)是傳給配置項(xiàng)組的成員)。
static const struct config_item_type mygroup_config_item_type = {.ct_owner = THIS_MODULE, .ct_group_ops = &mygroup_ops,  
};// 定義名為"myconfig_item_type"的配置項(xiàng)類(lèi)型結(jié)構(gòu)體
static const struct config_item_type myconfig_item_type = {.ct_owner = THIS_MODULE, .ct_group_ops = NULL,     //省略了配置項(xiàng)與配置項(xiàng)關(guān)聯(lián)的相關(guān)鉤子函數(shù)
};// 定義一個(gè) configfs_subsystem 結(jié)構(gòu)體實(shí)例"myconfigfs_subsystem"
static struct configfs_subsystem myconfigfs_subsystem = {//填充配置項(xiàng)組成員.su_group = {//填充配置項(xiàng)成員.cg_item = {.ci_namebuf = "myconfigfs",     //填充配置項(xiàng)名稱(chēng).ci_type = &myconfig_item_type, //填充配置項(xiàng)操作}, },
};// 模塊的初始化函數(shù)
static int myconfig_group_init(void)
{// 初始化配置組config_group_init(&myconfigfs_subsystem.su_group);// 注冊(cè)子系統(tǒng)configfs_register_subsystem(&myconfigfs_subsystem);// 初始化配置組"mygroup" config_group_init_type_name(&mygroup, //配置項(xiàng)組實(shí)例"mygroup", //配置項(xiàng)組名字&mygroup_config_item_type); //配置項(xiàng)組操作// 在子系統(tǒng)中注冊(cè)配置組"mygroup" configfs_register_group(&myconfigfs_subsystem.su_group, &mygroup);return 0;
}// 模塊退出函數(shù)
static void myconfig_group_exit(void)
{// 注銷(xiāo)子系統(tǒng)configfs_unregister_subsystem(&myconfigfs_subsystem);
}
module_init(myconfig_group_init); // 指定模塊的初始化函數(shù)
module_exit(myconfig_group_exit); // 指定模塊的退出函數(shù)
MODULE_LICENSE("GPL"); // 模塊使用的許可

? ? ? ? ?加載模塊后,進(jìn)入 sys/kernel/config 目錄,發(fā)現(xiàn)注冊(cè)的文件系統(tǒng)目錄已經(jīng)生成,配置組目錄也已經(jīng)生成,

注冊(cè)配置項(xiàng)

????????然后輸入“mkdir test”命令創(chuàng)建 config_item,如下圖所示,創(chuàng)建成功之后,打印

????????“mygroup_make_item”,說(shuō)明驅(qū)動(dòng)程序中 mygroup_make_item 函數(shù)成功執(zhí)行。

配置項(xiàng)組下新建文件(配置項(xiàng))

第七十五章 drop 和 release 函數(shù)

????????.release 是在 struct config_item_type 結(jié)構(gòu)體中定義的回調(diào)函數(shù)指針,用于在配置項(xiàng)被刪除時(shí)執(zhí)行資源釋放操作。

?????????每個(gè)配置項(xiàng)實(shí)例都有一個(gè)與之關(guān)聯(lián)的引用計(jì)數(shù)。

????????這個(gè)引用計(jì)數(shù)用于跟蹤有多少實(shí)體(如內(nèi)核模塊、進(jìn)程或其他內(nèi)核組件)正在使用該配置項(xiàng)。當(dāng)你創(chuàng)建一個(gè)新的配置項(xiàng)實(shí)例時(shí),通常會(huì)初始化其引用計(jì)數(shù)為 1,表示該配置項(xiàng)已經(jīng)被創(chuàng)建者所引用。隨著配置項(xiàng)被不同的實(shí)體所使用,其引用計(jì)數(shù)會(huì)增加;相應(yīng)地,當(dāng)這些實(shí)體不再需要該配置項(xiàng)時(shí),它們會(huì)通過(guò)調(diào)用 config_item_put 來(lái)減少其引用計(jì)數(shù)。當(dāng)引用計(jì)數(shù)減少到 0就會(huì)調(diào)用.release函數(shù)執(zhí)行清理工作。

?????????.drop_item 是在 struct configfs_group_operations 結(jié)構(gòu)體中定義的回調(diào)函數(shù)指針,用于在配置組被刪除時(shí)執(zhí)行相關(guān)的清理操作。

// 定義一個(gè)名為"mygroup"的 config_group 結(jié)構(gòu)體
static struct config_group mygroup;// 自定義的配置項(xiàng)結(jié)構(gòu)體
struct myitem
{struct config_item item;
};// 配置項(xiàng)釋放函數(shù),配置項(xiàng)的引用計(jì)數(shù)為0時(shí)執(zhí)行
void myitem_release(struct config_item *item)
{struct myitem *myitem = container_of(item, struct myitem, item);kfree(myitem);printk("%s\n", __func__);
}/* 配置項(xiàng)操作結(jié)構(gòu)體,填充配置項(xiàng)操作的release函數(shù) */
struct configfs_item_operations myitem_ops = {.release = myitem_release, 
};// 配置項(xiàng)類(lèi)型結(jié)構(gòu)體
static struct config_item_type mygroup_item_type = {.ct_owner = THIS_MODULE, .ct_item_ops = &myitem_ops,  //填充配置項(xiàng)操作
};// 創(chuàng)建配置項(xiàng)函數(shù)
struct config_item *mygroup_make_item(struct config_group *group, const char *name)
{struct myitem *myconfig_item;printk("%s\n", __func__);myconfig_item = kzalloc(sizeof(*myconfig_item), GFP_KERNEL);config_item_init_type_name(&myconfig_item->item, name, &mygroup_item_type);return &myconfig_item->item;
}// 刪除配置項(xiàng)函數(shù)
void mygroup_delete_item(struct config_group *group, struct config_item *item)
{struct myitem *myitem = container_of(item, struct myitem, item);config_item_put(&myitem->item); //減少傳入 config_item 實(shí)例的引用計(jì)數(shù)printk("%s\n", __func__);
}// 配置組操作結(jié)構(gòu)體
struct configfs_group_operations mygroup_ops = {.make_item = mygroup_make_item,  //配置組創(chuàng)建配置項(xiàng)的鉤子函數(shù).drop_item = mygroup_delete_item,//配置組刪除配置項(xiàng)的鉤子函數(shù) 
};//  config_item_type 配置項(xiàng)類(lèi)型結(jié)構(gòu)體,用于描述配置項(xiàng)類(lèi)型。用于將配置組注冊(cè)進(jìn)子系統(tǒng)時(shí)初始化
static const struct config_item_type mygroup_config_item_type = {.ct_owner = THIS_MODULE, .ct_group_ops = &mygroup_ops, //填充配置組類(lèi)型的鉤子函數(shù)
};// 定義名為"myconfig_item_type"的配置項(xiàng)類(lèi)型結(jié)構(gòu)體,用于定義子系統(tǒng)時(shí)初始化
static const struct config_item_type myconfig_item_type = {.ct_owner = THIS_MODULE, .ct_group_ops = NULL, 
};// 定義一個(gè) configfs_subsystem 結(jié)構(gòu)體實(shí)例
static struct configfs_subsystem myconfigfs_subsystem = {.su_group = {.cg_item = {.ci_namebuf = "myconfigfs", .ci_type = &myconfig_item_type, }, }, 
};// 模塊的初始化函數(shù)
static int myconfig_group_init(void)
{// 初始化配置組config_group_init(&myconfigfs_subsystem.su_group);// 注冊(cè)子系統(tǒng)configfs_register_subsystem(&myconfigfs_subsystem);// 初始化配置組"mygroup" config_group_init_type_name(&mygroup, "mygroup",         &mygroup_config_item_type);// 在子系統(tǒng)中注冊(cè)配置組"mygroup" configfs_register_group(&myconfigfs_subsystem.su_group, &mygroup);return 0;
}//...省略模塊出口函數(shù)

? ? ? ? 在配置組目錄下,使用 mkdir創(chuàng)建配置項(xiàng),會(huì)執(zhí)行 make_item函數(shù),

? ? ? ? 使用 rmdir刪除配置項(xiàng),會(huì)先執(zhí)行 drop_item函數(shù),然后執(zhí)行release函數(shù)。

第七十六章 注冊(cè) attribute 實(shí)驗(yàn)

// 使用CONFIGFS_ATTR_RO和CONFIGFS_ATTR_WO宏定義只讀和只寫(xiě)屬性 ?
CONFIGFS_ATTR_RO(my, read); ?// 定義一個(gè)名為read的只讀屬性,關(guān)聯(lián)到myread_show函數(shù) ?
/*生成一個(gè) myattr_read只讀屬性*/    CONFIGFS_ATTR_WO(my, write); ?// 定義一個(gè)名為write的只寫(xiě)屬性,關(guān)聯(lián)到mywrite_store函數(shù) ?
/*生成一個(gè) myattr_write只寫(xiě)屬性*//*屬性文件和關(guān)聯(lián)的讀寫(xiě)方法是通過(guò)屬性名和函數(shù)名關(guān)聯(lián)的*/// 定義屬性數(shù)組,以NULL結(jié)尾,用于注冊(cè)到config_item_type中 ?
struct configfs_attribute *my_attrs[] = { ? ?&myattr_read, &myattr_write, NULL, ? ?
}; ?

?????????config_item_type 結(jié)構(gòu)體中包含了 struct configfs_attribute 結(jié)構(gòu)體,?

/*config_item_type結(jié)構(gòu)體下,包含了configfs_attribute結(jié)構(gòu)體*/
struct configfs_attribute {const char *ca_name; ? ? //屬性文件的名字struct module *ca_owner; //屬性文件文件的所屬模塊umode_t ca_mode; ? ? ? ? //屬性文件訪(fǎng)問(wèn)權(quán)限//讀寫(xiě)方法的函數(shù)指針,具體功能需要自行實(shí)現(xiàn)。ssize_t (*show)(struct config_item *, char *);ssize_t (*store)(struct config_item *, const char *, size_t);?
};
// 定義一個(gè)結(jié)構(gòu)體myitem,它包含一個(gè)config_item成員和其他自定義成員  
struct myitem {    struct config_item item;  // 內(nèi)嵌的config_item,用于與配置文件系統(tǒng)交互  int size;  // 用于存儲(chǔ)數(shù)據(jù)的大小  void *addr;  // 指向數(shù)據(jù)的指針  
};  // 釋放myitem資源的函數(shù),當(dāng)config_item被釋放時(shí)調(diào)用  
void myitem_release(struct config_item *item) {    struct myitem *myitem = container_of(item, struct myitem, item);  // 將config_item指針轉(zhuǎn)換回myitem指針  kfree(myitem);  // 釋放myitem占用的內(nèi)存  
}  // 讀取myitem數(shù)據(jù)的回調(diào)函數(shù),用于configfs的只讀屬性  
ssize_t myread_show(struct config_item *item, char *page) {    struct myitem *myitem = container_of(item, struct myitem, item);    memcpy(page, myitem->addr, myitem->size);  // 將數(shù)據(jù)復(fù)制到page中  return myitem->size;  // 返回復(fù)制的字節(jié)數(shù)  
}  // 寫(xiě)入數(shù)據(jù)到myitem的回調(diào)函數(shù),用于configfs的只寫(xiě)屬性  
ssize_t mywrite_store(struct config_item *item, const char *page, size_t size) {    struct myitem *myitem = container_of(item, struct myitem, item);    myitem->addr = kmemdup(page, size, GFP_KERNEL);  // 分配新內(nèi)存并復(fù)制數(shù)據(jù)  myitem->size = size;  // 更新數(shù)據(jù)大小  return size;  // 返回寫(xiě)入的字節(jié)數(shù)  
}  // 使用CONFIGFS_ATTR_RO和CONFIGFS_ATTR_WO宏定義只讀和只寫(xiě)屬性  
CONFIGFS_ATTR_RO(my, read);  // 定義一個(gè)名為myattr_read的只讀屬性,關(guān)聯(lián)到myread_show函數(shù)  
CONFIGFS_ATTR_WO(my, write); // 定義一個(gè)名為myattr_write的只寫(xiě)屬性,關(guān)聯(lián)到mywrite_store函數(shù)  // 定義屬性數(shù)組,以NULL結(jié)尾,用于注冊(cè)到config_item_type中  
struct configfs_attribute *my_attrs[] = {    &myattr_read, &myattr_write, NULL,    
};  // 定義myitem的操作集,包括釋放函數(shù)  
struct configfs_item_operations myitem_ops = {    .release = myitem_release,    
};  // 定義mygroup的config_item_type,包括所有者、操作集和屬性數(shù)組  
struct config_item_type mygroup_item_type = {    .ct_owner = THIS_MODULE,  // 模塊所有者  .ct_item_ops = &myitem_ops,  // 操作集  .ct_attrs = my_attrs,  // 屬性數(shù)組  
};  // 初始化函數(shù),用于注冊(cè)mygroup到配置文件系統(tǒng)  
static int myconfig_group_init(void) {    // 假設(shè)myconfigfs_subsystem已定義并初始化  configfs_register_subsystem(&myconfigfs_subsystem);  // 注冊(cè)子系統(tǒng)  config_group_init_type_name(&mygroup, "mygroup", &mygroup_item_type);  // 初始化組并設(shè)置名稱(chēng)和類(lèi)型  configfs_register_group(&myconfigfs_subsystem.su_group, &mygroup);  // 注冊(cè)組到子系統(tǒng)中  return 0;    
}  // 清理函數(shù),用于注銷(xiāo)mygroup和子系統(tǒng)  
static void myconfig_group_exit(void) {    configfs_unregister_subsystem(&myconfigfs_subsystem);  // 注銷(xiāo)子系統(tǒng)  
}

????????在使用CONFIGFS_ATTR_ROCONFIGFS_ATTR_WO宏時(shí),

????????它們會(huì)生成名為 myattr_read和 myattr_write的 configfs_attribute結(jié)構(gòu)體實(shí)例。

/*生成只讀屬性 名為[_name]attr_read的configfs_attribute實(shí)例*/
#define CONFIGFS_ATTR_RO(_name, _show)  struct configfs_attribute configfs_attr_##_name = { .ca_owner = THIS_MODULE,.ca_name = __stringify(_name), .ca_mode = S_IRUGO,.show = _show,}  /*生成只寫(xiě)屬性 名為[_name]attr_write的configfs_attribute實(shí)例*/
#define CONFIGFS_ATTR_WO(_name, _store) struct configfs_attribute configfs_attr_##_name = { .ca_owner = THIS_MODULE, .ca_name = __stringify(_name), .ca_mode = S_IWUSR,.store = _store,}

? ? ? ? 模塊編譯、加載后,在名為 myconfigfs的子系統(tǒng)目錄下,有 配置組 mygroup目錄,使用mkdir創(chuàng)建配置項(xiàng) test,可以看到配置項(xiàng)目錄 test下有生成的 屬性文件 read 和 write。

注冊(cè) attribute實(shí)驗(yàn),生成屬性文件

? ? ? ? 可以使用 以下命令對(duì)屬性文件進(jìn)行操作:?

cat read        //讀echo 1 > write  //寫(xiě)入

????????分別對(duì)屬性文件 read屬性文件 write 進(jìn)行讀寫(xiě)操作后,

????????會(huì)分別執(zhí)行 myread_showmywrite_store 函數(shù)。

第七十七章 實(shí)現(xiàn)多級(jí)目錄

? ? ? ? 完成了 configfs_group_operations 結(jié)構(gòu)體下的,.make_group函數(shù),

? ? ? ? .make_group函數(shù)優(yōu)先級(jí)比 .make_item優(yōu)先級(jí)高,因此編譯好驅(qū)動(dòng)裝載好,使用mkdir創(chuàng)建目錄的時(shí)候會(huì)調(diào)用 .make_group視為新建了 配置組。

// 創(chuàng)建配置組函數(shù)
struct config_group *mygroup_make_group(struct config_group *group, const char *name)
{struct mygroup *mygroup;printk("%s\n", __func__);mygroup = kzalloc(sizeof(*mygroup), GFP_KERNEL);config_group_init_type_name(&mygroup->group, name, &mygroup_type);return &mygroup->group;
};// 配置組操作結(jié)構(gòu)體
struct configfs_group_operations mygroup_ops = {.make_item = mygroup_make_item,   //新建配置項(xiàng)函數(shù).drop_item = mygroup_delete_item, //刪除配置項(xiàng)函數(shù).make_group = mygroup_make_group, //新建配置組函數(shù)
};

第七十八章 移植設(shè)備樹(shù)插件驅(qū)動(dòng)

????????移植設(shè)備樹(shù)插件到 iTOP-RK3568 開(kāi)發(fā)板上。移植設(shè)備樹(shù)插件主要包括以下幾個(gè)步驟

????????1 配置內(nèi)核支持掛載 configfs 虛擬文件系統(tǒng)。

????????2 配置內(nèi)核支持設(shè)備樹(shù)插件(kernel 4.4及以上)

????????3 移植設(shè)備樹(shù)插件驅(qū)動(dòng)

78.1 掛載 configfs 虛擬文件系統(tǒng)

? ? ? ? 內(nèi)核源碼的menuconfig頁(yè)面,選擇支持configfs文件系統(tǒng)。

內(nèi)核源碼menuconfig頁(yè)面,選擇支持 configfis文件系統(tǒng)

????????將編譯之后的內(nèi)核鏡像燒寫(xiě)到開(kāi)發(fā)板上,接著使用 mount 命令檢查 configfs 虛擬文件系是否掛載成功。

如果系統(tǒng)沒(méi)有自動(dòng)掛載 configfs 虛擬文件系統(tǒng),需要輸入以下命令掛載:

mount -t                 //掛載的類(lèi)型
configfs                 //configfs虛擬文件系統(tǒng)
none                     //不需要具體的設(shè)備與掛載點(diǎn)關(guān)聯(lián)
/sys/kernel/config       //掛載的文件目錄,掛載好后可通過(guò)該目錄與configfs交互,來(lái)動(dòng)態(tài)配置內(nèi)核對(duì)象

78.2 配置內(nèi)核支持設(shè)備樹(shù)插件

? ? ? ? 源碼,menuconfig頁(yè)面,勾選支持 device tree overlays。

驅(qū)動(dòng)支持設(shè)備樹(shù)插件
文件系統(tǒng)支持設(shè)備樹(shù)插件

? ? ? ? 內(nèi)核編譯成功后,就可以開(kāi)始移植設(shè)備樹(shù)。

78.3 移植驅(qū)動(dòng)

????????我們沒(méi)有必要重復(fù)造輪子,github 上有大神編寫(xiě)好的設(shè)備樹(shù)插件驅(qū)動(dòng)。

? ? ? ? 假設(shè) dtbocfg.c 是設(shè)備樹(shù)插件驅(qū)動(dòng)源碼,我們將此驅(qū)動(dòng)編譯成驅(qū)動(dòng)模塊或編譯進(jìn)內(nèi)核即可。

????????好了,設(shè)備樹(shù)插件驅(qū)動(dòng)移植完畢,設(shè)備樹(shù)插件的使用參考前面的章節(jié)即可。

第七十九章 設(shè)備樹(shù)插件驅(qū)動(dòng)分析

????????dtbocfg.c 為設(shè)備樹(shù)插件驅(qū)動(dòng)文件。

????????在 dtbocfg_overlays_type 中實(shí)現(xiàn)了 ct_group_ops 下的 make_itemdrop_item

// 初始化dtbocfg模塊的函數(shù)  
static int __init dtbocfg_module_init(void)  
{  int retval = 0;  // 打印初始化開(kāi)始信息,注意這里應(yīng)該使用__func__來(lái)獲取當(dāng)前函數(shù)名  pr_info("%s: Initialization started\n", __func__);  // 初始化configfs的group  config_group_init(&dtbocfg_root_subsys.su_group);  config_group_init_type_name(&dtbocfg_overlay_group, "overlays", &dtbocfg_overlays_type);  // 注冊(cè)子系統(tǒng)到configfs  retval = configfs_register_subsystem(&dtbocfg_root_subsys);  if (retval != 0) {  pr_err("%s: Couldn't register subsystem\n", __func__);  }  // 注冊(cè)group到已注冊(cè)的子系統(tǒng)  retval = configfs_register_group(&dtbocfg_root_subsys.su_group, &dtbocfg_overlay_group);  if (retval != 0) {  pr_err("%s: Couldn't register group\n", __func__);  }  // 打印初始化成功信息  pr_info("%s: Initialization OK\n", __func__);  return 0;  
}  
make_item和drop_item的實(shí)現(xiàn)

? ? ? ? 在配置組下,命令行輸入 mkdir時(shí),如果沒(méi)有實(shí)現(xiàn) make_group,則會(huì)去執(zhí)行 make_item。

? ? ? ? make_item負(fù)責(zé)開(kāi)辟空間,并調(diào)用初始化函數(shù)去初始化 config_item。

? ? ? ? config_item有 config_item_type成員,

? ? ? ? config_item_type成員 有

????????config_item_operations結(jié)構(gòu)體、config_group_operations結(jié)構(gòu)體。

????????attribute結(jié)構(gòu)體。bin_attribute結(jié)構(gòu)體。

部分成員未列出

? ? ? ? attribute結(jié)構(gòu)體有 read_show,和 write_store函數(shù)可以綁定。

? ? ? ? bin_attribute結(jié)構(gòu)體readwrite ?可以綁定。

// 定義一個(gè)二進(jìn)制屬性,用于dtbo(設(shè)備樹(shù)二進(jìn)制對(duì)象)的覆蓋  
CONFIGFS_BIN_ATTR(dtbocfg_overlay_item, dtbo, NULL, 1024*1024); // 1MiB足夠大  // 定義一個(gè)普通屬性,用于顯示或設(shè)置狀態(tài)  
CONFIGFS_ATTR(dtbocfg_overlay_item, status);
//定義一個(gè)status屬性,該屬性屬于 dtbocfg_overlay_item配置項(xiàng)/*    dtbocfg_overlay_item_attr_dtbo 和 dtbocfg_overlay_item_attr_status 是宏展開(kāi)后生成的變量名。*/// 定義一個(gè)屬性結(jié)構(gòu)體數(shù)組,包含所有與dtbocfg_overlay_item相關(guān)的普通屬性  
static struct configfs_attribute *dtbocfg_overlay_attrs[] = {  &dtbocfg_overlay_item_attr_status,  //將屬性,通過(guò)屬性數(shù)組,填充給 配置項(xiàng)NULL, // 數(shù)組結(jié)束標(biāo)志  
};  // 定義一個(gè)結(jié)構(gòu)體數(shù)組,包含所有與dtbocfg_overlay_item相關(guān)的二進(jìn)制屬性  
static struct configfs_bin_attribute *dtbocfg_overlay_bin_attrs[] = {  &dtbocfg_overlay_item_attr_dtbo,  //將屬性,通過(guò)屬性數(shù)組,填充給 配置項(xiàng)NULL, // 數(shù)組結(jié)束標(biāo)志  
};

????????CONFIGFS_BIN_ATTR 用于定義二進(jìn)制屬性。

/*定義一個(gè)二進(jìn)制屬性*/
#define CONFIGFS_BIN_ATTR(_name, _mode, _read,_write,_size) //二進(jìn)制屬性可存儲(chǔ)的最大字節(jié)數(shù)

????????CONFIGFS_ATTR 宏用于定義普通屬性。

/*定義一個(gè)普通屬性*/
#define CONFIGFS_ATTR(_name, //名稱(chēng)_mode, //權(quán)限_show, //讀操作函數(shù)_store) //寫(xiě)操作函數(shù)

????????當(dāng) status 寫(xiě)入 1 的時(shí),會(huì)執(zhí)行 dtbocfg_overlay_item_create 函數(shù)。在這個(gè)函數(shù)中又去執(zhí)行了 of_overlay_fdt_apply 函數(shù)。

????????完善dtbocfg_overlay_item_create 函數(shù),可以執(zhí)行我們需要的邏輯。

static ssize_t dtbocfg_overlay_item_status_store(struct config_item *item, const char *buf, size_t count)  
{  struct dtbocfg_overlay_item *overlay = container_of(item, struct dtbocfg_overlay_item, item);  ssize_t status;  unsigned long value;  // 嘗試將字符串緩沖區(qū)轉(zhuǎn)換為無(wú)符號(hào)長(zhǎng)整型值  if (0 != (status = kstrtoul(buf, 10, &value))) {  goto failed; // 轉(zhuǎn)換失敗,跳轉(zhuǎn)到錯(cuò)誤處理  }    // 根據(jù)值決定是釋放還是創(chuàng)建覆蓋項(xiàng)  if (value == 0) {  if (overlay->id >= 0) {  // 如果id有效,則釋放覆蓋項(xiàng)  dtbocfg_overlay_item_release(overlay);  } }  else {   if (overlay->id < 0) {  dtbocfg_overlay_item_create(overlay);  }  }   return count; // 假設(shè)成功寫(xiě)入全部數(shù)據(jù)  
failed:  return -EPERM; // 權(quán)限錯(cuò)誤或轉(zhuǎn)換失敗  
}

????????設(shè)備樹(shù)插件(dtbo)里面的節(jié)點(diǎn)也要被轉(zhuǎn)換成 device_node有的 device_node 也要被轉(zhuǎn)換成 platform_device。

????????不過(guò)在進(jìn)行轉(zhuǎn)換之前,of_overlay_fdt_apply 函數(shù)會(huì)先創(chuàng)建一個(gè)改變集。然后根據(jù)這個(gè)改變集去進(jìn)行修改。

????????改變集是為了方便修改和復(fù)原設(shè)備樹(shù)而設(shè)計(jì)的。

????????設(shè)備樹(shù)是靜態(tài)的,編譯加載后不易直接更改。改變集記錄了設(shè)備樹(shù)的修改操作,如增刪改節(jié)點(diǎn),允許運(yùn)行時(shí)動(dòng)態(tài)調(diào)整,無(wú)需改動(dòng)源文件。它提供了高層次抽象,簡(jiǎn)化描述變化,且可保存、傳遞、應(yīng)用于不同設(shè)備樹(shù)。同時(shí),改變集支持撤銷(xiāo)修改,恢復(fù)原始狀態(tài)。

http://www.risenshineclean.com/news/51295.html

相關(guān)文章:

  • 網(wǎng)站客戶(hù)續(xù)費(fèi)北京百度競(jìng)價(jià)托管
  • 沈陽(yáng)建設(shè)企業(yè)網(wǎng)站如何做好網(wǎng)絡(luò)營(yíng)銷(xiāo)
  • 零基礎(chǔ)網(wǎng)站建設(shè)教程seo的基本步驟是什么
  • wordpress 登錄seo外包公司專(zhuān)家
  • 網(wǎng)站策劃內(nèi)容有哪些靠譜的代運(yùn)營(yíng)公司
  • 企業(yè)網(wǎng)站建設(shè)怎么選擇空間百度關(guān)鍵詞優(yōu)化平臺(tái)
  • 網(wǎng)址ip域名解析寧波seo推廣如何收費(fèi)
  • 手機(jī)怎樣做網(wǎng)站圖解品牌推廣軟文200字
  • 跟我一起做網(wǎng)站 下載seo搜索優(yōu)化技術(shù)
  • 網(wǎng)站工作室最牛餐飲營(yíng)銷(xiāo)手段
  • 自己做網(wǎng)站開(kāi)店寧波網(wǎng)站建設(shè)推廣平臺(tái)
  • 安卓做視頻網(wǎng)站微信推廣軟件有哪些
  • 做投資網(wǎng)站深圳seo優(yōu)化公司哪家好
  • 哈爾濱網(wǎng)絡(luò)開(kāi)發(fā)放心網(wǎng)站推廣優(yōu)化咨詢(xún)
  • 高校門(mén)戶(hù)網(wǎng)站建設(shè)問(wèn)題seo網(wǎng)站關(guān)鍵詞優(yōu)化方式
  • 淘寶上有做網(wǎng)站的嗎某個(gè)網(wǎng)站seo分析實(shí)例
  • 外貿(mào)零售網(wǎng)站建設(shè)查關(guān)鍵詞排名網(wǎng)
  • 玉林市網(wǎng)站開(kāi)發(fā)公司swot分析
  • 網(wǎng)站建設(shè)圖書(shū)百度客服中心人工在線(xiàn)咨詢(xún)
  • 改wordpress評(píng)論郵箱willfast優(yōu)化工具下載
  • 做網(wǎng)站外包工作怎么樣360應(yīng)用商店
  • 手機(jī)h5網(wǎng)站模板利于seo的建站系統(tǒng)有哪些
  • 廣東省住房和城鄉(xiāng)建設(shè)局網(wǎng)站投廣告的平臺(tái)有哪些
  • 注冊(cè)公司流程和費(fèi)用需要哪些條件酒店seo是什么意思
  • 網(wǎng)站引導(dǎo)頁(yè)動(dòng)畫(huà)濟(jì)南優(yōu)化網(wǎng)站關(guān)鍵詞
  • 原單手表網(wǎng)站域名解析在線(xiàn)查詢(xún)
  • 做類(lèi)似美團(tuán)的網(wǎng)站得多少錢(qián)長(zhǎng)尾關(guān)鍵詞在線(xiàn)查詢(xún)
  • 網(wǎng)站語(yǔ)音轉(zhuǎn)寫(xiě)怎么做seo知識(shí)分享
  • 深圳注冊(cè)公司需要什么條件中國(guó)seo網(wǎng)站
  • html網(wǎng)頁(yè)制作背景圖片seo 優(yōu)化顧問(wèn)