初識Linux/C語言編程,管道和重定向暨fork與execlp函數的理解

火星人 @ 2014-03-26 , reply:0



Linux中C語言的編程有兩個Windows環境下根本無須考慮的問題,關於管道和重定向的概念。

昨晚研究了一個通宵,關於fork()和execlp()函數,基本上用fork函數實現管道,用execlp來實現重定向。不過它們兩個實現功能的方法都非常奇怪。

fork函數是讓程序創建一個跟自己一模一樣的副本,就跟當下流行的很多網路遊戲中副本的概念差不多,昨晚在練習的時候忽然感到,這玩意兒又有點像WEB 編程中的表單自提交。在同一個程序裡面寫兩套方案,運行時讓其中的一套(安排在fork>=1的分支結構中)調用來自自身代碼文件中的另一套方案 (安排在fork==0分支結構)乍一看這跟管道根本就挨不著邊,我一開始也是覺得這樣,就像一個進程又去調用了一個進程一樣,不過另外調用的進程又是本 身,大腦里一團漿糊一樣。那麼請看代碼吧:
CODE:
/**//*
============================================================================
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最具特色的管道機制 中大顯伸手呢。

花開兩朵,各表一枝。

下面看看重定向的概念:

先做一個演示程序:
CODE:
/**//*
============================================================================
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,感受到是另一種源於代碼和演算法的舒服感。



[火星人 via ] 初識Linux/C語言編程,管道和重定向暨fork與execlp函數的理解已經有112次圍觀

http://www.coctec.com/docs/linux/show-post-186626.html