docker原理與架構,linux component組件架構分析

 2023-12-06 阅读 26 评论 0

摘要:Linux component 組件系統架構分析 原創文章,轉載請標明出處。 背景介紹 任何架構的提出都是有其現實應用背景的,都是為了解決一些現實問題。而component系統架構的提出就是出于這樣一種現實需求:構建功能系統! docker原理與架構。系統就是各種功

Linux component 組件系統架構分析

原創文章,轉載請標明出處。

背景介紹

任何架構的提出都是有其現實應用背景的,都是為了解決一些現實問題。而component系統架構的提出就是出于這樣一種現實需求:構建功能系統!

docker原理與架構。系統就是各種功能單元(組件)的有序結合。一個系統,只有集齊了它的所有組件才能正常工作。
可以打個比方:一輛車就是一個系統,它由各種組件–發動機,變速箱,中控臺,車輪等構成。

一輛車,只裝上發動機,或變速箱。是不能工作的,必須安裝了所有的組件,才能開始發動。

而發動的過程,也是有順序要求的,如先采離合,再掛當(變速箱初始化),再踩油門(發動機初始化),車輪再開始轉動。(有序)

docker的核心組件有哪些,所以component架構構建功能系統就包括兩方面的作用:

  1. 保證系統安裝了所有的組件
  2. 規定了系統各組件初始化的順序

component架構在linux內核中現在主要的應用是用來構建display-subsystem,一個顯示子系統,由LCD控制器(vop),接口控制器(mipi,lvds,hdmi),液晶背光,電源等多個獨立的功能單元構成。而把這些功能單元構成一個系統,就需要這些功能單元間有一定的協同配合。

如在掃描設備樹時,每一個設備節點依次被注冊到系統中(一般用platform_device_register)。而只有當所有顯示子系統相關的設備節點都注冊到系統中時,整個顯示系統才能正常工作。

yarn組件架構。如果沒有component架構的參與,在用platform_device_register函數注冊每個設備節點時,在其驅動的probe函數中。就已經執行了一系列的初始化工作,而此時系統相關的其他設備節點可能還沒有注冊到內核中,這樣可能就會導致一些問題出現。

在component架構的參下,可以保證在顯示子系統的所有功能單元都注冊后,才按照一定順序執行初始化操作。

架構分析

component架構的實現位于drivers/base/componet.c
對系統組件架構有了概念上的理解后,分析架構就比較簡單了。

數據結構

android組件化架構 PDF,component系統組件架構涉及到如下幾個數據結構:
struct component用來表示系統組件。
struct master表示需要構建的系統。
struct component_match用來匹配系統需要的組件。并規定了組件的初始化順序。
component 架構上述結構可以用拼樂高積木的過程來理解:
一個一個形態各異的積木就用struct component來表示,而struct master就是
要拼接成的東西(系統)(例如想拼成一輛車,一只恐龍,或一個房子)。而struct component_match就是你手里的圖紙。根據圖紙,你就可以在一個個積木(component)中,找出需要的積木,然后拼成一個想要的作品(master)。
根據上面的理解我們在詳細的看一下這些結構體中的內容就比較好理解了.

  1. component
struct component {struct list_head node;        struct list_head master_node;struct master *master;bool bound;const struct component_ops *ops;struct device *dev;
};

node:用于加入到component_list鏈表,該鏈表保存了注冊到組件系統架構中的所有component
master_node:該組件如果最終被某個master選中,則通過此成員用于加入到該master的components鏈表中,便于后續該master來遍歷其組件。
master: 組件所屬的master
bound: 表示組件是否已經執行了bind操作
ops: 組件可執行的初始化操作。

  1. master
struct master {struct list_head node;struct list_head components;bool bound;const struct component_master_ops *ops;struct device *dev;struct component_match *match;
};

node:同compnent中node作用一樣,用于向組件系統架構中注冊master。
components:用于保存該系統(master)下的組件。
ops:master可執行的初始化和退出操作。
match:該master用到的compnent_match,master 應用該match在組件系統架構component_list鏈表中找到適配于自己的component組件。

虛擬化基礎架構有哪幾個組件。3.component_match

我們之前說過組件系統的兩方面作用,即保證系統安裝了所有組件和保證組件的初始化順序。compnent_match是實現這兩個作用的核心數據結構! component_match中用compare結構體數組表示一個系統(master)中需要的所有組件。每個數組條目代表了一個需要安裝的組件。而一個系統中所需的組件數量是不定的,所以采用了零長數組的方式,用于動態擴展組件數量。 而master又是如何通過compnent_match匹配到component的呢?答案就是通過每個compare[]數組元素中的fn函數,int (*fn)(struct device *, void *)函數指針指定了匹配的規則(方法)*data 中保存了fn用到的匹配數據。

struct component_match {size_t alloc;size_t num;struct {void *data;int (*fn)(struct device *, void *);} compare[0];
};

alloc:用于記錄分配的compare數組大小。
num:用于記錄系統實際需要的組件(compnents)數量。當num等于alloc時,會引發compare數組的空間擴展分配。

我們再回到最初的問題:

如何保證系統安裝了所有組件?

答案即是通過component_match的compare數組。master只有在匹配到了compare數組中指定的所有組件后才會執行初始化函數component_master_ops->bind

而又是如何指定各個組件的執行順序呢?

同樣也是通過compare數組,compare數組元素的順序即指定了加入master 的component鏈表的順序,進而決定了component組件初始化的順序。

4.component_master_ops master執行的操作。

struct component_master_ops {int (*add_components)(struct device *, struct master *);int (*bind)(struct device *);void (*unbind)(struct device *);
};

5.component_ops 組件可以執行的操作。

struct component_ops {int (*bind)(struct device *, struct device *, void *);void (*unbind)(struct device *, struct device *, void *);
};

組件系統工作流程

組件系統大致包括如下操作:

  1. 向組件系統注冊component
    注冊的component被保存到static LIST_HEAD(component_list);靜態鏈表中。此操作通過int component_add(struct device *dev, const struct component_ops *ops)函數實現。每次向系統注冊一個組件時,都會遍歷系統的master鏈表,嘗試把該組件綁定到合適的master中去。這個過程是通過master掃描其component_mach,并遍歷系統component_list,找出符合mach匹配函數的組件進行綁定。
    當一個master找到了其所有的組件后會執行其初始化函數。
    ret = master->ops->bind(master->dev);

  2. 構建component_match
    component_match作為master查找component的地圖,需要在master注冊到系統前來構建。系統通過component_match_add函數逐一添加compare條目,用于匹配每一個comonent,這個過程也確定了后續每個component的初始化過程。

  3. 向組件系統注冊master。
    注冊的master被保存到組件系統架構的static LIST_HEAD(masters)靜態鏈表中。一般通過component_master_add_with_match函數實現。此函數同時會遍歷系統component_list鏈表,找出符合match的組件進行綁定。
    當一個master找到了其所有的組件后會執行其初始化函數。
    ret = master->ops->bind(master->dev);

  4. bind執行
    系統和系統組件初始化函數執行的時機是什么呢?
    無論是通過component_add函數向組件系統中注冊component,還是通過component_master_add_with_match函數向系統中注冊master時,當mastr安裝了其所有的componet后都會執行master->ops->bind(master->dev);操作,在此操作中一般會執行component_bind_all函數,開始執行各組件的初始化:component->ops->bind

代碼分析

/** Add a component to be matched.** The match array is first created or extended if necessary.*/
void component_match_add(struct device *dev, struct component_match **matchptr,int (*compare)(struct device *, void *), void *compare_data)
{struct component_match *match = *matchptr;if (IS_ERR(match))return;/*當第一次分配match或mactch中compare數組已經滿了時,進行match的空間分配*/if (!match || match->num == match->alloc) {size_t new_size = match ? match->alloc + 16 : 15;//如果是第一次分配compare數組size 為15,如果不是第一次分配,會用原來大小alloc+16match = component_match_realloc(dev, match, new_size);//new_size表示的是分配的compare數組的大小。*matchptr = match;if (IS_ERR(match))return;}/*下面初始化了一個compare數組元素,表示增加了一個組件的匹配項*/match->compare[match->num].fn = compare;match->compare[match->num].data = compare_data;match->num++;//可以看到num記錄了match中增加的組件數。最終作為master需要的組件數。
}static struct component_match *component_match_realloc(struct device *dev,struct component_match *match, size_t num)
{struct component_match *new;if (match && match->alloc == num)return match;/*分配component_match空間,num指定了compare結構體數組的大小*/new = devm_kmalloc(dev, component_match_size(num), GFP_KERNEL);if (!new)return ERR_PTR(-ENOMEM);if (match) {memcpy(new, match, component_match_size(min(match->num, num)));devm_kfree(dev, match);//擴展match時執行的是重新分配。釋放了原來的空間。} else {new->num = 0;}new->alloc = num;//記錄了分配的compare數組sizereturn new;
}/*向comonent架構系統中注冊一個組件*/
int component_add(struct device *dev, const struct component_ops *ops)
{struct component *component;int ret;component = kzalloc(sizeof(*component), GFP_KERNEL);//分配componentif (!component)return -ENOMEM;component->ops = ops;//對compnent進行初始化,指定了組件的操作函數component->dev = dev;dev_dbg(dev, "adding component (ops %ps)\n", ops);mutex_lock(&component_mutex);list_add_tail(&component->node, &component_list);//把組件加入鏈表component_listret = try_to_bring_up_masters(component);//遍歷注冊的每個master,并嘗試把compnent綁定之。if (ret < 0) {list_del(&component->node);kfree(component);}mutex_unlock(&component_mutex);return ret < 0 ? ret : 0;
}int component_master_add_with_match(struct device *dev,const struct component_master_ops *ops,struct component_match *match)
{struct master *master;int ret;if (ops->add_components && match)return -EINVAL;if (match) {//根據compare數組的大小重新分配match空間/* Reallocate the match array for its true size */match = component_match_realloc(dev, match, match->num);if (IS_ERR(match))return PTR_ERR(match);}/*master初始化并注冊*/master = kzalloc(sizeof(*master), GFP_KERNEL);if (!master)return -ENOMEM;master->dev = dev;master->ops = ops;master->match = match;INIT_LIST_HEAD(&master->components);/* Add to the list of available masters. */mutex_lock(&component_mutex);list_add(&master->node, &masters);//加入鏈表ret = try_to_bring_up_master(master, NULL);//開始查找組件,進而啟動系統。if (ret < 0) {/* Delete off the list if we weren't successful */list_del(&master->node);kfree(master);}mutex_unlock(&component_mutex);return ret < 0 ? ret : 0;
}static int try_to_bring_up_masters(struct component *component)
{struct master *m;int ret = 0;list_for_each_entry(m, &masters, node) {ret = try_to_bring_up_master(m, component);if (ret != 0)break;}return ret;
}/** Try to bring up a master.  If component is NULL, we're interested in* this master, otherwise it's a component which must be present to try* and bring up the master.** Returns 1 for successful bringup, 0 if not ready, or -ve errno.*/
static int try_to_bring_up_master(struct master *master,struct component *component)
{int ret;if (master->bound)return 0;/** Search the list of components, looking for components that* belong to this master, and attach them to the master.*/if (find_components(master)) {/* Failed to find all components */ret = 0;goto out;}if (component && component->master != master) {//如果component !=NULL,component必須屬于master。才會執行后面的系統初始化。ret = 0;goto out;}if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {//設備模型中的設備資源管理相關操作,用于管理設備的資源組。這里不具體介紹。ret = -ENOMEM;goto out;}/* Found all components */ret = master->ops->bind(master->dev);//如果綁定了所有的組件,開始執行系統初始化。一般在此函數中會繼續調用component_bind_all函數執行組件的初始化。if (ret < 0) {devres_release_group(master->dev, NULL);dev_info(master->dev, "master bind failed: %d\n", ret);goto out;}master->bound = true;//表示系統已經綁定了所有組件,并執行了初始化。return 1;out:master_remove_components(master);return ret;
}static int find_components(struct master *master)
{struct component_match *match = master->match;size_t i;int ret = 0;if (!match) {/** Search the list of components, looking for components that* belong to this master, and attach them to the master.*/return master->ops->add_components(master->dev, master);}/** Scan the array of match functions and attach* any components which are found to this master.*/for (i = 0; i < match->num; i++) {//遍歷了component_match中的compare數組。對比每一個數組項,綁定component到masterret = component_master_add_child(master,match->compare[i].fn,match->compare[i].data);if (ret)break;}return ret;
}

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/192917.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息