初識Linux/C語言編程,管道和重定向暨fork與execlp函數的理解
Linux中C語言的編程有兩個Windows環境下根本無須考慮的問題,關於管道和重定向的概念。
fork函數是讓程序創建一個跟自己一模一樣的副本,就跟當下流行的很多網絡遊戲中副本的概念差不多,昨晚在練習的時候忽然感到,這玩意兒又有點像WEB 編程中的表單自提交。在同一個程序裏面寫兩套方案,運行時讓其中的一套(安排在fork>=1的分支結構中)調用來自自身代碼文件中的另一套方案 (安排在fork==0分支結構)乍一看這跟管道根本就挨不着邊,我一開始也是覺得這樣,就像一個進程又去調用了一個進程一樣,不過另外調用的進程又是本 身,大腦裏一團漿糊一樣。那麼請看代碼吧:
- /**//*
- ============================================================================
- Name : fork_example.c
- Author : newflypig
- Version :
- Copyright : Your copyright notice
- Description : Hello World in C, Ansi-style
- ============================================================================
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- int main(void) ...{
- int i=1;
- printf("in the begining,the value=%d ",i);
- switch(fork())...{
- case -1:
- fprintf(stderr,"%s ","fork error");
- break;
- case 0:
- printf("child process start,at this time value=%d ",i);
- i++;
- printf("child process end,at this time value=%d ",i);
- break;
- default:
- printf("parent process: value=%d ",i);
- }
- return 0;
- }
複製代碼
運行結果是這樣的:
in the begining,the value=1 child process start,at this time value=1 child process end,at this time value=2 parent process: value=1
可 以看到父進程首先設置i=1然後調用子進程,子進程一開始就有了父進程的i值,然後子進程在自己的基礎上將i++了,子進程結束時輸出了i=2。當程序返 回父進程時,子進程的改變並沒有影響父進程中i的值,i依然爲1。這個fork()的功能僅僅如此,有誰會想到讓這個函數在Linux最具特色的管道機制 中大顯伸手呢。
花開兩朵,各表一枝。
下面看看重定向的概念:
先做一個演示程序:
- /**//*
- ============================================================================
- Name : execlp_example.c
- Author : newflypig
- Version :
- Copyright : Your copyright notice
- Description : Hello World in C, Ansi-style
- ============================================================================
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- int main(void) ...{
- int filedes;
- if((filedes=open("dd.txt",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))<0)
- fprintf(stderr,"%s ","open file error");
- close(1);
- dup(filedes);
- close(filedes);
- execlp("ls","-l",(char * )0);
- return 0;
- }
複製代碼
這是一段輸出重定向的程序,爲了解釋方便,首先了解一下Linux中標準輸入輸出文件,Linux中基本上所有的元素都可以理解爲文件,包括文件夾,設備等。程序中,首先使用close(1)關閉標準輸出端子,{/*當然如果你想輸入重定向的話可以關閉標準輸入端子,它的序列是0;序列爲3的端子是異常拋出端子,一般可以讓此端子與輸出設備保持一致。*/}, 然後使用dup函數將main函數的第一步所創建的名爲dd.txt的文件設置爲此程序的輸出設備。接着要關閉該文件的連接,釋放資源鎖以便讓程序來對此 文件進行讀寫。最後一步調用execlp函數進行命令的執行,這裏執行了一個ls的命令,讓當前目錄下的所有文件名輸出,execlp函數是可變參數函 數,第一個參數需要設置系統環境變量中所能獲取的命令文件,或者自己設置絕對路徑的命令文件,最後一個參數必須設置爲空,以便標記這個函數的參數已經設置 完成,中間的所有參數設置爲第一個命令的參數,如此段程序其實是執行ls -l這個命令。這樣就將輸出信息不直接打印到終端而輸出到dd.txt文本文件中,完成輸出重定向。
回到管道的問題上來。
如果將 剛剛講得重定向技術配合fork()進程產生函數,便可以實現管道的作用了。這裏說一下思路,就不給具體代碼了,也就是設置兩個全局的文件變量,將子進程 的輸出重定向到其中一個文件變量,因爲是全局變量,這個文件變量就被子進程徹底修改了,然後將父進程的輸入重定向到剛剛子進程的輸出,以此來完成 Linux中的管道機制。
不知各位看觀對本人關於Linux中的管道以及重定向問題的看法是否認同,昨晚就看這兩個函數的API和源代碼了。
綜上所述,一個毋庸置疑的結論:Linux編程比Windows編程艱鉅而有趣多了。以前從來不高興碰C語言,認爲C++和java此類OO語言纔是最人性化,最舒服的編程語言,這次初探C,感受到是另一種源於代碼和算法的舒服感。 |