發表文章

目前顯示的是 2018的文章

IPC: (3) socket

圖片
Socket 為 Linux IPC (Inter-process communication) 的方式之一. process 可藉由 socket 傳遞資料至另一個 process. 以下以 AF_INET 作為範例來介紹 TCP 與 UDP. TCP 與 UDP 皆以講解流程圖與 API 的用法為主. 完整範例 code 請點選 github 連結. TCP 以下為 TCP server 與 client 端的建立通訊流程. 當中的 write 與 read 可以與 send 與 recv 替換 . 範例 code 請參閱 github TCP 流程圖 [1] Server 與 client 透過 socket 來通訊的流程如下. Server 端: 建立 socket 後, 藉由 bind() 綁上 ip 與 port. 執行 listen() 等待 client 的連線要求. 透過 accept() 接受要求後, 便可開始與 client 進行傳輸的動作. Client 端: 建立 socket 後, 在 connect() 綁上 server 的 ip 與 port 進行連線. 當連線要求被接受後, 便可以進行傳輸. TCP APIs socket [2] #include <sys/socket.h> sockfd = socket( int socket_family, int socket_type, int protocol); socket_family: 為所用的 socket domain, 這邊採用網際網路的關係, 故選用 AF_INET. socket_type: 由於選用 TCP, 所以使用 SOCK_STREAM. protocol: 預設數值為 0 bind [3] #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int bind ( int sockfd, const struct sockaddr

IPC : (2) signal

Signal Signal 為 Linux IPC(Inter-process communication)的方式之一. process 藉由 system call 傳遞特定 signal number 至另一個 process. 當 signal number 被傳遞至目標 process, process 會執行下列其中一項應對[2]: 此 signal number 的配置(disposition) 被設為 SIG_IGN(signal is ignored)[3]. 忽略此 signal number 此 signal number 的配置(disposition) 被設為 SIG_DFL(default signal handling)[3]. default action 會處理此 signal number 此 signal number 的配置(disposition) 對應到一個 function. 呼叫對應的 handler function[3] 並把 signal number 帶入此 function. 注意: SIGKILL 與 SIGSTOP 無法被 略過 以及 攔截 . API 範例 以下針對 signal 與 kill 的 API 說明. 完整的範例程式可於 github 看到 API 說明 signal[2] #include <signal.h> typedef void ( * sighandler_t )( int ); sighandler_t signal ( int signum, sighandler_t handler); 在 signal 函數設置 signum 所要對應的 handler. 其 handler 可以為 SIG_IGN, SIG_DFL 或者自訂的 handler. 其 handler 格式為 void (*sighandler_t)(int);. kill[4] #include <sys/types.h> #include <signal.h> int kill ( pid_t pid, int sig)

IPC : (1) pipe & fifo

PIPE & FIFO 簡介 Pipe 與 fifo 為 Linux IPC(Inter-process communication)的方式之一. 共同的部分為 (1) 建立一個單向的 data channel. (2) 同樣使用 fd(file descriptor) 作為讀寫的媒介. (3) 預設讀取端(read)沒資料讀取會被鎖住(block), 直到寫入端(write)寫入資料. 相反過來 pipe buffer 滿了, write 會被鎖住(block). 若想改為非鎖住(non-block)則可透過 fcntl 或於 API 設置相關 flag 參數(如果 API 提供) 存取限制的部分 (1) pipe 僅舉限於關聯的 processes. (2) fifo 則是透過 permission mask 來作為限制. 相關的特性如下表所示[1]. 類型 識別名稱 於系統的表示 存取特性 persistence pipe no name fd Only by related processes process FIFO path name fd permission mask process (?) API 範例 以下針對兩個 API 個別進行說明. 其個別完整的範例程式可於 github 看到 Pipe[2] API 說明 #include <unistd.h> int pipe ( int pipefd[ 2 ]); #define _GNU_SOURCE /* See feature_test_macros(7) */ #include <fcntl.h> /* Obtain O_* constant definitions */ #include <unistd.h> int pipe2 ( int pipefd[ 2 ],

yocto recipe : (4) recipe's task 撰寫

Recipe's Task recipe 包含許多 tasks, 以下紀錄關於 recipe 的 task 撰寫 1. 列出 recipe 的 tasks yijyun@wd-disk: build $ bitbake libunistring -c listtasks 2. function types of tasks 根據[1] 的 3.6.1 Promoting a Function to a Task. 能成為 task 的 function 只有兩種類型. 此外需要以 "do_" 為開頭 shell function do_shell_msg () { bbwarn 'hello' } BitBake-style Python functions python do_py_msg () { import time bb . warn( "hello %s " % ( time . strftime( '%Y%m %d ' , time . gmtime()))) } 3. 新增/刪除/插入 task 新增 以 addtask 加入 new task, 可以搭配 before 與 after 決定順序 # syntax addtask task [before task] [after task] # e.g. addtask do_msg before do_configure after do_fetch 插入 以現有 task function 名稱. 尾部使用 append or prepend 即可 do_msg_prepend () { bbwarn 'before' } do_msg_append () { bbwarn 'before' } do_msg () { bbwarn 'kkk' } addtask do_msg 刪除 deltask 特定 task 即可. 切記使用此方式會把此任務相依的 task 一併刪除. 如果要忽略某個 ta

yocto recipe : (3) 使用 External Source 來編譯軟體

Yocto 有提供許多 fetch code 的方式[3], 大都是以抓取外網的方式. 雖然很齊全, 但是開發時候多少需要以本機上的 source code 作為來源進行編譯. 這邊就紀錄如何讓 yocto 直接抓取本機上的 source code 使用本機上的 source code 這邊介紹兩種方式. 使用硬碟上的 source code, 而不是透過 yocto fetch 去網路上抓取 (1) git fetcher: 基於 git fetcher, 僅修改 src_uri 參數, 就可以用本機上的 source code (2) external source: 基於 externalsrc class. 有兩種方式達成: (1) 於 recipe 直接新增 external source 變數 (2)於 local.conf 新增特定 recipe 的 external source 參數. 事前準備 於 build 目錄底下建立 3rd-pkgs. 把下載的 giflib 程式碼放置於此 [ yijyun@localhost build ] $ pwd /media/disk1-1/Github/poky/build [ yijyun@localhost build ] $ ls 3rd-pkgs/ giflib-5.1.4.tar.bz2 新增 meta-test 於 yocto. 並在此 meta-layer 底下新增 giflib 目錄. 存放之後的 bb files [ yijyun@localhost build ] $ bitbake-layers create-layer meta-test [ yijyun@localhost build ] $ bitbake-layers add-layer meta-test [ yijyun@localhost build ] $ mkdir meta-test/recipes-example/giflib git fetcher 使用 git fetcher 有兩個重點: src_uri 的 protocol 參數需要改為 file. S 的路徑要改為 S="

yocto recipe : (2) 撰寫 bbappend

前言 xxx.bb 檔案是用來描述一個 recipe. 然而 xxx.bb 會因為 patch codes、新增 tasks、等等的因素修改. 這邊介紹如何使用 xxx.bbappend[1] 檔案. 以不修改 xxx.bb 的情況下擴充需求. 文章將以 patch codes 為例子, 並個別以 devtool 工具和手動的方式示範. bbapend 簡介 .bbappend 是擴充 .bb 的方式. 藉由 .bbappend 來新增 tasks、patch code、新增/修改變數等等諸此之類的事. 其名稱必須跟所要修改的相同, 而版本號則依據需求寫. 舉例: bb file 名稱: giflib_5.1.4.bb bbappend 名稱: giflib_5.1.4.bbappend 或 giflib_%.bbappend. %: 表示萬用字元 使用 .bbappend 的情況, 我個人認為有以下情況再使用 (1) 當 recipe 已存在 yocto 最基本的 layer, 不應隨便修改. 舉例: u-boot_2017.09.bb 存在於 yocto 的 meta layer (2) 某些 layers 會共用此 recipe 的情況下. 舉例: meta-raspberrypi 與 meta-ti 分別各自使用自己的 xserver-xf86-config_0.1.bbappend 來對 yocto meta layer 的 xserver-xf86-config_0.1.bb 做擴充修改. bbappend 範例 事前準備 用 giflib [4] 作為測試程式. 先下載 giflib-5.1.4.tar.bz2. 接著使用 bitbake-layer 建立 meta-custom layer, 再透過 recipetool 把產生的 giflib_5.1.4.bb 存放於此 layer. # 執行 oe-init-build-env 進行 yocto 編譯環境設定 [ yijyun@localhost poky ] $ . oe-init-build-env # 建立 3rd-pkgs, 並把 giflib 放至此 [ yijyun@localhost build ] $

Linux 的 binfmt_misc (binfmt) module 介紹

linux 透過 qemu 的動態轉譯(dynamic translation)模式, 能直接執行別架構的程式. 舉例: x86_64 中執行 arm64 架構的程式. 然而每次都必須透過 qemu-aarch64 [program] [args...] 的方式執行, 似乎有點瑣碎. 以下就介紹 linux 是如何使用 binfmt_misc kernel module 來化繁為簡... qemu 與 binfmt 搭配 測試環境為 x86_64 架構, 使用 aarch64 toolchain 編譯下方 hello.c 為 static 的程式. 免去執行時候 link 尋找 libraries 的問題. 這邊透過 1) 直接執行. 2)藉由 qemu 執行. 3) qemu 搭配 binfmt_misc 來示範結果. #include <stdio.h> int main () { printf( "hello !! \n " ); return 0 ; } 首先安裝 aarch64 的 toolchain 來編譯程式. 並確認編譯出來的格式為 aarch64 # 安裝 arm 版本的 toolchain yijyun@yijyun-VirtualBox:~ $ sudo apt-get install gcc-aarch64-linux-gnu # 使用 arm-gcc 編譯 yijyun@yijyun-VirtualBox:~ $ aarch64-linux-gnu-gcc -static hello.c # 查看編譯出來的格式 yijyun@yijyun-VirtualBox:~ $ aarch64-linux-gnu-objdump -f a.out a.out: file format elf64-littleaarch64 architecture: aarch64, flags 0x00000112: EXEC_P, HAS_SYMS, D_PAGED start address 0x0000000000400cd8 # 顯示本機的架構 yijyun@yijyun-VirtualBox:~ $ uname -i x86_

邏輯區塊位址 (Logical block addressing, LBA)

圖片
現今都使用LBA(Logical block addressing)的方式來描述資料對應到硬碟的儲存區塊. 而下就以硬碟的基本架構為頭, 再接著說明LBA的計算方式. CHS (cylinders-heads-sectors, 磁柱-磁頭-磁區) 硬碟主要可以看成磁盤和磁頭兩個部分, 如圖1. 磁盤負責存放資料, 資料的讀寫則透過磁頭. 通常一個磁盤上下兩面皆可讀寫, 所以會有對應到兩個磁頭. 而磁頭的起始編號為 0, 1, 2, n. 圖1. 硬碟架構 磁盤又可以在分為磁軌(track)和磁區(sector), 如圖2. 磁盤會被分成數個軌道, 這可以想像成操場的跑道. 每個軌道即是磁軌. 編號由外而內編號, 0, 1, 2,...,n. 而磁軌又會被被劃分成數個區段稱為磁區, 起始為 1, 2, 3, ...n. 每個磁區的大小依照規範而定. 傳統常用為 512 bytes, 現今主流則偏向 4096 bytes(Advance Format). 圖2. 磁盤 而多個磁盤相同磁軌所呈現的關係則稱為磁柱. 基本上磁柱的數量等同於磁軌. 計算硬碟容量的公式如下: 容量 = 磁柱 x 磁頭 x 磁軌擁有的磁區數量 x 磁區大小. LBA (Logical block addressing) 由於要經由CHS來算出要存資料的位置頗麻煩的. 所以就有了 LBA 的方式, 來對應硬碟的每一個存取區塊. 公式如下[1]: LBA = (C × HPC + H) × SPT + (S - 1) LBA: the logical block address C, H, S: cylinder number, the head number, and the sector number HPC: maximum number of heads per cylinder SPT: the maximum number of sectors per track 而 LBA 反推回 CHS 的公式如下[1]: C = LBA ÷ (HPC × SPT) H = (LBA ÷ SPT) mod HPC S = (LBA mod SPT) + 1 e.g

yocto recipe : (1) 撰寫 recipe

此篇文章介紹如何透過 yocto 的 utilities 來產生 recipe. 而完成的 recipe 又如何加入到 image. yocto 相關工具介紹 有三個適用於 layer 與 recipe 相關的 utilities. bitbake-layers: 負責 (1) 建立 layer. (2) 修改 bblayers.conf. (3) 查看 layer 底下的 recipes recipetool: 用於建立一個 recipe 和新增/修改 recipe. 這邊 recipe 在 yocto 即是 xx.bb 或 xx.bbappend 檔案 devtool: 定位在開發測試上. devtool 會建立一個獨立的 workspace layer. 讓開發者於此建立/修改 recipe 與 patch source code. 在不修改原有設定下與現有 layers 進行整合測試. 完畢之後可以再透過 devtool 新增或更新到 layer 裡 利用 utilities 撰寫 recipe 的時候. 要確保所屬的 layer 是存在於 bblayer.conf. 不然執行 bitbake [recipe basename] 會找不到相關的 recipe. yocto 事前準備 以 core-image-miniaml recipe 為例子. core-image-miniaml 會產生系統所需的 image 相關檔案. 接著利用 bitbake-layers 建立自己的 layer 於 build 目錄底下. 再透過 bitbake-layers 把 layer 加入到 bblayers.conf 設定檔. [ yijyun@localhost poky ] $ . oe-init-build-env [ yijyun@localhost build ] $ bitbake core-image-minimal [ yijyun@localhost build ] $ bitbake-layers create-layer meta-layer [ yijyun@localhost build ] $ bitbake-layers add-

yocto 概念

圖片
這篇文章紀錄我對於 yocto 的概念. 以下用的版本為 2.4 (rocko). 一開始介紹幾個用詞. 接著述說架構的運作流程. 最後再介紹 bitbake 指令用法. 名詞定義 [2]摘錄比較常看到的名詞定義 BitBake: The task executor and scheduler used by the OpenEmbedded build system to build images. For more information on BitBake, see the BitBake User Manual. Task: A unit of execution for BitBake (e.g. do_compile, do_fetch, do_patch, and so forth). Recipe: A set of instructions for building packages. A recipe describes where you get source code, which patches to apply, how to configure the source, how to compile it and so on. Recipes also describe dependencies for libraries or for other recipes. Recipes represent the logical unit of execution , the software to build, the images to build, and use the .bb file extension. P.S recipe 在 yocto 用 .bb 檔案表示. 而 .bbappend 用於修改 .bb 的設定 Metadata: The files that BitBake parses when building an image. In general, Metadata includes recipes, classes, and configuration files. In the context of t