(圖片擷取自 Legato 官網:https://docs.legato.io/latest/conceptsEnvironment.html)
Legato 框架有幾個重要的概念,分別是 Component、Executable、App、以及 System。
從上圖可以看到,使用 Legato Application Framework 的話,我們的系統裡面會有一個一個的 App,而每個 App 裡面可以由一個或多個 Executable 組成,而每個 Executable 可以由一個或多個 Component 組成。
COMPONENT_INIT
。COMPONENT_INIT
內的東西,在程式剛執行時的 start-up 階段就會馬上被該程式的 main thread 執行,主要是用來初始化該 Component 用的,所以一個 Component 只會有一個 COMPONENT_INIT
。COMPONENT_INIT
不可 return 東西。Component.cdef
檔案(cdef
:Component DEFinition),用來告訴 build tools 該怎麼 build 這個 component。Component.cdef
檔案也可用來描述說這個 Component 提供了怎樣的 API 或者是需要什麼 API。.adef
檔案做設定(後面會介紹)。Legato Application Framework 的一個 App 跟平常說的一個應用程式(application)是不太一樣的。
.adef
檔案(Application DEFinition),定義這個 App 該怎麼執行。.adef
的名稱就會是這個 App 的名稱,例如 helloPrintApp.adef
,則使用 app status
所看到的該 App 名稱就會是 helloPrintApp
chroot
來限制一個 App 只能看到其 directory 下的檔案和目錄。檔案使用 bind mounts 機制來跟 chroot
產生的隔離環境做連結。Processes 只能存取其 root directory 下的檔案和目錄。.adef
檔案的 sandboxed
section 設定該 App 是否要執行在 sandbox。appxxxx
,其中的 xxxx
是 App 的名稱。由於目前我在使用上都沒用到 System 層級的東西,所以對他較不熟,有需要可以參考官網的說明(後續摸熟的話會再補充 >_<):
前面簡單的介紹完了 Component、Executable、以及 App,來看一下在 target machine 上的 Legato App 會怎麼呈現~
我們可以在前面安裝的 TelAF simulation docker container 內執行 app status
,就可以看到目前系統內有安裝的 App 有哪些,以及他們的狀態,如下圖中一項一項的都是一個 App:
其中 taf
開頭的 App 都是 TelAF 提供的 service,例如 tafDataCallSvc
就會提供跟 Data call 有關的 service,若我們的 App 想要使用 Data call 的 API,就必須要去存取這個 App,並且確保它是 running
的狀態。
接下來,來看一個簡單的 Legato App 的架構會是長怎樣~
假設目前有一個 Legato App 的資料夾,叫做 helloServer
,其架構如下圖:
首先,一個 Legato App 一定會有:
.adef
檔案:其檔名就會是該 App 的名稱,也就是執行 app status
所看到的名稱,所以這個 App 的名稱是 helloServerApp
ServerComp
。Component.cdef
檔案
Component.cdef
的名稱是固定的,不可擅自修改。Component.cdef
和 source code file(如 server.c
)等等。此外,一個 Legato App 若有提供 service 給其他人使用,那就還會有 .api
檔案:
.api
檔案使用 Legato 的 interface definition language(IDL)撰寫 API 介面。.api
檔案內定義每個 API 的名稱、參數、return type、以及其他資訊等等。serverComp
有提供 API 給其他 App 使用,所以才會有 .api
檔案。上圖右側則是一個簡單的示意圖:
helloServerApp
,其內含有一個 Executable,名稱是 serverExec
(Executable 的名稱由 helloServerApp.adef
內定義)serverComp
。serverComp
這個 Component 有提供一個 API 介面,它會被 expose 出來讓其他 App 可以使用(這部分是由 helloServerApp.adef
內的 extern
section 所定義),該 API interface 名稱是 server_interface
,想使用這個 API 的 App 只要連接到 helloServerApp
的 server_interface
即可(怎麼連接到別人的 API,後面會再介紹~)。接下來,從前面這個 helloServerApp
例子來簡單介紹一下 .adef
和 Component.cdef
裡面會長怎樣~
(這裡只是做基本的簡單介紹,讓第一次接觸的人有些概念,詳細內容還是要參閱官網喔~)
Application definition files 和 component definition files 都是由一個一個的 section 所組成,上圖僅列出部分 section,各 section 詳細的說明可參閱官網說明。
(各 section 的擺放順序,我目前測試起來好像沒有一定要特定的順序,官網也沒特別提到)
.adef
)Application definition file 由許多 section 構成,一個最簡單的 App 至少一定要有 executables
和 processes
這兩個 sections。
executables
section:
COMPONENT_INIT
會在 process 的 start-up 階段被執行。bin
directory 內。processes
section:
processes
section 內的 process 設定環境變數(藉由 envVar
這個 subsection),但若要給不同 process 設定不同的環境變數,則要寫在不同的 processes
section。extern
section:
extern
section 將其 API interface 露出來給其他 App 使用。.adef
的 bindings
section 做設定(後面會再提到)。其他重要的 section 還有 bindings
、bundles
等等,更多 Application Definition 的細節請參閱 Legato 官網的說明:
在 processes
section 底下有 faultAction
這個 subsection,千萬不要在 TelAF simulation 內測試:
也就是如果有錯誤發生,process crash 了,那要採取什麼行動,reboot
則是重新開機。
我這樣測試後,我的 TelAF simulation 就壞掉惹QQ,刪掉重新安裝 TelAF simulation 也沒用 😭 最後只能靠著之前 VirtualBox 的 snapshot 才救回來 @_@
.cdef
)sources
section 來指定這個 Component 的 source files 有誰。接下來來看 helloServerApp
的 server_api.api
以及 server.c
。
PS. .api
檔的命名並沒有特別規範,這裡只是為了幫助識別,才命名成 server_api
。
這個 server_api.api
檔案有定義兩個 API,第一個是 server_func1
,第二個是 server_func2
:
server_func1
void
。
FUNCTION
跟 API name 之間,也就是 FUNCTION
跟 server_func1
之間。string
型態的參數,且是 IN
參數。server.c
裡面,API 的 function name 的組成規則是 <interface_name>_<API_name>
interface_name
是在 Component.cdef
的 provides
section 的 server_interface = server_api.api
所定義的 interface name。interface_name
就會是 server_interface
。server.c
裡面,此 API 的 function name 就是 server_interface_server_func1
,該 function 的參數是 const char *message
server_func2
int32
n1
、n2
、和 res
,其中 n1
和 n2
是 IN
參數,而 res
是 OUT
參數若要確認 API 在 C 語言確切的 function prototype,可以用以下方式確認:
假如在 ~/test/
內有 <yourApp>.adef
、.api
檔案以及 Component 的資料夾。
接下來在 ~/test/
內執行:mkapp -t simulation <yourApp>.adef
。
則會在執行 mkapp
的資料夾內產生 _build_<yourApp>
資料夾,查看 _build_<yourApp>/simulation/api/<一串數字>/server/<interface_name>_server.h
這份檔案的內容即可確認在 C source code 裡面該使用怎樣的 function prototype。
我們的 source file 要依據這份檔案內的 function prototype 去實作 API 的內容。
Legato 官網有 API 檔更多的說明:
Legato 的 communication 的機制可以探討以下三種情況:
由於是位在同一個 Executable 內的 Components,也就是都在同一個 process 內,所以可以存取彼此的東西。
如下例,有兩個 Component,serverComp
和 clientComp
,server 提供 server_showMsg
這個 function,並將 function prototype 放在 server.h
。
Client 若要使用的話,就要在 source code 內 include 該 header file,並且在 client 的 Component.cdef
的 cflags
section 內將 serverComp
的路徑加入 search path,讓 build tool 能找到 server.h
即可。
helloIPC1App.adef
server.h
Server 端把欲提供出去的東西寫在一個 header file,server.h
。以此例而言,server 分享了一個 int
型態的變數 num
,以及一個 function server_ShorMsg
。
欲分享出去的東西前面都要加上 LE_SHARED
這個 macro,此 macro 可將 symbol 分享出去
server.c
serverComp/Component.cdef
client.c
clientComp/Component.cdef
此情況需要透過 IPC 的機制來溝通,且需要定義 API。
如下例,有兩個 Component,clientComp
和 serverComp
。在 helloIPC2App.adef
內,將這兩個 Component 各自放到一個 Executable 內執行,由於這樣就是執行在不同的 process 內,無法直接存取彼此的東西,因此需要定義 API 檔案,並透過 IPC 的機制來溝通。
helloIPC2App.adef
server_api.api
serverComp/Component.cdef
server.c
clientComp/Component.cdef
client.c
此情況僅可透過 IPC 溝通,且需要 API。這是最安全的溝通方式,也是 Legato 官方比較推薦的作法。
以下例子,server 和 client 都有各自的 App:
.adef
的 extern
section 將其想給其他 App 使用的 IPC API interface 露出來,其他 App 若想使用該 interface 則需藉由其 .adef
的 bindings
section 來連接到該 interface。.adef
的 bindings
section 使其 interface 和 server 的 interface 做連結。helloIPC3ServerApp.adef
server_api.api
serverComp/Component.cdef
server.c
helloIPC3ClientApp.adef
clientComp/Component.cdef
client.c
此例子在 make app 時,記得要 include server_api.api
所在的 path:
由於一開始在接觸 Legato 時搞不太懂 interface name 的規則,所以自己做了以下小整理~
我們在使用 TelAF 時,若要使用 TelAF 的某個 service,就是用第三種方式 bind 到該 service 的 API interface。
譬如說若要用 Data Call 相關的 API,官網( https://docs.qualcomm.com/bundle/publicresource/topics/80-41102-2/page_c_tafDataCallSvc.html?product=1601111740010418 )就會告知說我們自己開發的 App 的 .adef
的 bindings
section 要做怎樣的設定才能連結到他們 Data Call 的 service。