Linux 嵌入式開發 – 並行開發— Unix進程間的通訊方式 Process間通訊介紹 早期:
pipe fifo signal System V IPC
share memory message queue semphore set —————————本地通信↑
—————————本地/網路通信↓ Linux
socket 無名管道 只能用於有親緣關係的進程之間的通信 單工的通信模式,具有固定的讀端和寫端 創建時返回兩個文件描述符,分別用於讀寫管道 創建 - pipe 1 2 #include<unistd.h>int pipe(int pfd[2]); 成功時返回0,失敗時返回EOF pfd 包含兩個元素的int 陣列,用來保存文件描述符 pfd[0]用於read管道,pfd[1]用於write管道 範例 子進程1和2分別往管道寫入字串,父進程讀管道內容並打印
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include<stdio.
Linux 嵌入式開發 – 並行開發—進程與線程 Process概念 program 存放在disk上的指令和數據的有序集合(文件) 靜態的 process 執行一個program所分配的資源總稱 是program一次執行的總稱 動態的,包括創建,調度,執行,死亡 有獨立的地址空間 linux為每個進程創建task_struct Process 內容 1 2 3 process ----------| 正文段 |-------- --------- | 用戶數據段 |----program --------- | 系統數據段 | Process control block PID process user process status / priority file description table Process 類型 交互進程:在shell下啟動,可在前臺/後台運行 批處理進程:和在終端無關,被提交到一個作業隊列中以便順序執行 守護進程:和終端無關,一直在後台運行 Process status running / ready waiting interrupt not interrupt terminated : 收到signal後可以繼續運行 zombie : pcb沒有被釋放 殭屍與孤兒 殭屍:一個process 使用fork()建立child,如果child退出(terminated),而父進程沒有呼叫wait/waitpid並回收時,OS進程表中仍然存在子進程的進程控制塊(PCB),長時間保持殭屍狀態會導致resource leak
檔案I/O緩衝區 The Linux programming interface chapter 13
核心緩衝區概述 system call read() & write()在操作磁碟檔案時不會直接對磁碟存取,而是單純在使用者空間緩衝區與核心緩衝區快取(kernel buffer cache)之間複製資料。 例如: write(fd, "abc",3) 在後續的某個時間點,核心會將其緩衝區的資料寫入磁碟
如果在此期間,另外一個process試圖讀取檔案的這幾個bytes,則核心將自動從緩衝區提供資料,而不是從檔案讀取。同理於read()期間有write() process的情況
緩衝區大小對效能的影響 system cpu time:主要是測量使用者空間與核心空間之間資料傳輸所消耗的時間 包含CPU的處理, 等待I/O I/O的處理,作業系統處理提供一些服務額外的時間,以及系統閒置的時間 Elapsed time : 完整的程式在這個系統裡面執行的時間 當緩衝區大小為1byte,需要呼叫大約一億次的system call,而緩衝區大小為4096bytes時,system call次數約為24000,當超過此設定值,效能的改善就開始不明顯,是因為在使用者空間和核心空間之間複製資料以及執行實際I/O所需的時間相較之下,read()和write()的system call 成本就顯得微不足道。
* 結論: 若我們正對檔案進行大量的資料讀寫,則以大區塊緩衝資料來減少system call 即可提升系統效能
stdio函式庫的緩衝 操作磁碟檔案時,對大型區塊資料使用緩衝可以降低system call。
設定一個stdio stream的緩衝模式 1 2 #include<stdio.h>int setvbuf(FILE *stream, char *buf, int mode, size_t size); 在開啟串流之後,必須在對串流進行任何其他的stdio函式之前先呼叫setbuf() 因為setbuf()將影響後續的stdio操作對串流的行為
參數 stream:可以識別要修改的檔案stream緩衝區 buf & size 指定使用的緩衝區 若buf不為NULL則以其指向的size大小區塊作為stream的緩衝區,因為stdio接著會使用buf指向的緩衝區,所以應該以靜態配置或使用malloc()於heap做動態配置,不應該配置為stack裡面的區域變數,否則當函式返回時會釋放stack frame,導致混亂 若buf為NULL,stdio會自動配置一個緩衝區提供stream使用(除非我們選擇無緩衝的I/O)。在SUSv3允許但不要求實作時使用size來決定緩衝區的大小 mode指定緩衝區的類型 範例 1 2 3 4 #defind BUF_SIZE 1024 static char buf[BUF_SIZE]; if(setvbuf(stdout, buf, _IOFBF) !
檔案I/O 概述 全部執行I/O的系統呼叫都是透過檔案描述符來控制開啟的檔案,各類型的檔案在開啟之後,都能以檔案描述符進行操控。
標準檔案符 shell平時會將以下三個檔案描述符保持一直開啟,可以使用I/O redirection進行適當的修改
file descriptor 用途 POSIX 名稱 stdio stream 0 標準輸入 STDIN_FILENO stdin 1 標準輸出 STDOUT_FILENO stdout 2 標準錯誤 STDERR_FILENO stderr 開啟檔案 open()
1 2 3 4 5 #include<sys/stat.h>#include<fcntl.h>int open(const char *pathname, int flags, ... /*mode_t mode*/); Return file descriptor on success, -1 on error flags -> 為位元mask 指定檔案的存取模式 mode -> 指定了檔案的存取權限(如果open()沒有指定O_CREATflags可以省略)