Version 10 (modified by wade, 16 years ago) (diff) |
---|
基礎 Linux Programming
安裝 GNU/Linux 開發手冊
- 安裝 manpages-dev 跟 glibc-doc-reference,其中 manpages-dev 提供常用 POSIX 的 C 函式庫 manpage,而 glibc-doc-reference 則提供 C 函式庫的 info 檔(內含更多範例程式)
# sudo apt-get install manpages-dev glibc-doc-reference
- 更新 manpage
mandb
- 當用語法
- 查詢這所有 manpage 內「指令」的用法:
man -a 指令
- 查詢這所有 manpage 內「指令」的用法:
例如要查調 printf 對應到那些 manpages:
man -a printf
- 查詢特定 manpages 內「指令」用法:
man [section] 指令
例如要查詢 (1) Executable programs or shell commands 類的 printf 的用法。
man 1 printf
File Descriptors
可以想成他只是一個 index ,負責檔案的開啟與關閉,是一個 C type int。
- 特殊的 FD:
FD | Name | 功能描述 |
0 | Standard Input (stdin) | 標準輸入,如 keyboard |
1 | Standard Output (stdout) | 標準輸出,如 monitor |
2 | Standard Error (stderr) | 標準錯誤,特殊輸出 |
Pipe
- 範例:pipe.c
// parent process 借由 fork() 產生一個跟自己一樣的 child process // 兩個 processes 間藉由 pipe 來傳遞資料 // child → pipe → parent ,由 child 寫入資料至 pipe , parent 再由 pipe 接收資料並寫入 stdout #include <unistd.h> #include <stdio.h> int main(void) { int n, fd[2]; pid_t pid; char line[255]; // 建立 pipe // fd[1] → pipe → fd[0] // pipe 的形勢與 FIFO 類似 if (pipe(fd) < 0) { printf("Can't create pipe!\n"); } // fork 創造一個 child process ,他與 parent 相同 if ( (pid = fork()) < 0) { printf("fork error\n"); } else if (pid == 0) { // child process = 0 close(fd[0]); // 將字串寫入 pipe 內 2 次 write(fd[1], "hello world\n",12); write(fd[1], "second time\n",12); } else { // parent process close(fd[1]); n = read(fd[0], line, 255); // 將結果寫出到 FD=1 (stdout) write(1,line,n); write(1,line,n); } }
- FD[0] 負責 read pipe。FD[1] 負責 write pipe,換句話說,寫入 FD[1] 的資料可以由 FD[0] 讀取。
- 寫入 FD[1] → [PIPE] → 讀取 FD[0] 。
- 由於 FD 是 file descriptor, 非 file stream。所以為法使用 fread 和 fwrite。要使用 read 和 write 函式。
- read() 會被 block 住,所以不用擔心 parent 會比 child 先結束,而導致 child 也跟著結束 (因為 child process 是依附著 parent process 而存在,依存關係可透過 pstree 查詢)。
- 先使用 pipe(FD[2]),再使用 fork() 時,FD[2] 也會同時複製兩份,child 跟 parent 有各自的 FD[0]、FD[1],所以要記得關掉不必要的 FD ,兩個 processes 各自與 pipe 相接。
- 範例:pipe2.c
// parent process 借由 fork() 產生一個跟自己一樣的 child process // 兩個 processes 間藉由 pipe 來傳遞資料 // child → stdout → fd[1] → pipe → fd[0] → stdin → parent ,由 child 寫入資料至 pipe , parent 再由 pipe 接收資料並寫入 stdout #include <unistd.h> #include <stdio.h> int main(void) { int n, fd[2]; pid_t pid; // 建立 pipe if (pipe(fd) == 0) { // fork 創造一個 child process ,他與 parent 相同 pid = fork(); // 錯誤偵測,將結果寫入 stderr 中。 if( pid == -1) { fprintf(stderr, "fore failure"); exit(EXIT_FAILURE); } // child process PID = 0 if (pid == 0) { // 關閉標準輸入 close(0); // 將讀取 pipe 的 fd[0] 與 標準輸入連起來,則從 pipe 來的資料會成為一個標準輸入 dup(fd[0]); close(fd[0]); close(fd[1]); // 此時 more 會開起來等待標準輸入的資料,他會從標準輸入(pipe)讀取資料。 execlp("more", "more", NULL); } // parent process PID ≠ 0 else { // 關閉標準輸出 close(1); // 將寫入 pipe 的 fd[1] 與 標準輸出結合,則所有的標準輸出會自動寫入 pipe 中 dup(fd[1]); close(fd[0]); close(fd[1]); // 執行 ls ,並將結果寫入標準輸出,而標準輸出已經與 pipe 結合,所以結果會寫入 pipe 中 execlp("ls", "ls", "-l", NULL); } } }
- process 將自己的 stdout 寫入 write pipe ,將讀取 read pipe 轉換為本身的 stdin
Reference
- Jazz 教學檔案。
- http://en.wikipedia.org/wiki/File_descriptor。
- Linux 程式設計教學手機(第三版), Richard Stones。
- LINUX 系統程式設計, Robert love。