發表文章

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_