在Linux的應用程式裡面調用我的shell(這玩意功能實在太強大)的辦法有很多種一般來說有fork()、exec*()、pipe、system()其中又以system()
調用很少方便,現在加以說明。
#include<stdlio.h>
#include<stdlib.h>
int main()
{
system(“ifconfig eth0 10.17.28.1”);
//system(“./ifconfig.sh”);使用你的指令碼shell路徑要注意
return 0;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
exec*
方法二: exec( )函數族(轉)
下面我們來看看一個進程如何來啟動另一個程式的執行。在Linux中要使用exec函數族。系統調用execve()對當前進程進行替換,替換者為一個指定的程式,其參數包括檔案名稱(filename)、參數列表(argv)以及環境變數(envp)。exec函數族當然不止一個,但它們大致相同,在 Linux中,它們分別是:execl,execlp,execle,execv,execve和execvp,下面我只以execlp為例,其它函數究竟與execlp有何區別,請通過manexec命令來瞭解它們的具體情況。
一個進程一旦調用exec類函數,它本身就"死亡"了,系統把程式碼片段替換成新的程式的代碼,廢棄原有的資料區段和堆棧段,並為新程式分配新的資料區段與堆棧段,唯一留下的,就是進程號,也就是說,對系統而言,還是同一個進程,不過已經是另一個程式了。(不過exec類函數中有的還允許繼承環境變數之類的資訊。)
那麼如果我的程式想啟動另一程式的執行但自己仍想繼續啟動並執行話,怎麼辦呢?那就是結合fork與exec的使用。 下面一段代碼顯示如何啟動運行其它程式:
char command[256];
void main()
{
int rtn; /*子進程的返回數值*/
while(1)
{
/* 從終端讀取要執行的命令 */
printf( ">" );
fgets( command, 256, stdin );
command[strlen(command)-1] = 0;
if ( fork() == 0 )
{
/* 子進程執行此命令 */
execlp( command, command );
/* 如果exec函數返回,表明沒有正常執行命令,列印錯誤資訊*/
perror( command ); exit( errorno ); }
else
{
/* 父進程, 等待子進程結束,並列印子進程的傳回值 */
wait ( &rtn );
printf( " child process return %d\n",. rtn );
}
}
}
此程式從終端讀入命令並執行之,執行完成後,父進程繼續等待從終端讀入命令。熟悉DOS和WINDOWS系統調用的朋友一定知道
DOS/WINDOWS 也有exec類函數,其使用方法是類似的,但DOS/WINDOWS還有spawn類函數,因為DOS是單任務的系統,它只能將"父進程"駐留在機器內再執行"子進程",這就是spawn類的函數。WIN32已經是多任務的系統了,但還保留了spawn類函數,WIN32中實現spawn函數的方法同前述 UNIX中的方法差不多,開設子進程後父進程等待子進程結束後才繼續運行。UNIX在其一開始就是多任務的系統,所以從核心角度上講不需要spawn類函數。
/------------------------------------------------------------------------------------------------------------------------------------------------------
system 是在單獨的進程中執行命令,完了還會回到你的程式中。
而exec函數是直接在你的進程中執行新的程式,新的程式會把你的程式覆蓋,除非調用出錯,否則你再也回不到exec後面的代碼,就是說你的程式就變成了exec調用的那個程式了.
/------------------------------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
char *envp[] = { "PATH=/tmp", "USER=lei", "STATUS=testing", NULL };
char *argv_execv[] = { "echo", "excuted by execv", NULL };
char *argv_execvp[] = { "echo", "executed by execvp", NULL };
char *argv_execve[] = { "env", NULL };
if (fork() == 0) {
if (execl("/bin/echo", "echo", "executed by execl", NULL) < 0)
perror("Err on execl");
}
if (fork() == 0) {
if (execlp("echo", "echo", "executed by execlp", NULL) < 0)
perror("Err on execlp");
}
if (fork() == 0) {
if (execle("/usr/bin/env", "env", NULL, envp) < 0)
perror("Err on execle");
}
if (fork() == 0) {
if (execv("/bin/echo", argv_execv) < 0)
perror("Err on execv");
}
if (fork() == 0) {
if (execvp("echo", argv_execvp) < 0)
perror("Err on execvp");
}
if (fork() == 0) {
if (execve("/usr/bin/env", argv_execve, envp) < 0)
perror("Err on execve");
}
return 0;
}
/------------------------------------------------------------------------------------------------------------------------------------------------------
程式裡調用了2 個Linux 常用的系統命令,echo和env。echo會把後面跟的命令列參數原封不動的列印出來,env用來列出所有環境變數。
由於各個子進程執行的順序無法控制,所以有可能出現一個比較混亂的輸出–各子進程列印的結果交雜在一起,而不是嚴格按照程式中列出的次序。
最常見的錯誤:
大家在平時的編程中,如果用到了exec 函數族,一定記得要加錯誤判斷語句。因為與其他系統調用比起來,exec很容易受傷,被執行檔案的位置,許可權等很多因素都能導致該調用的失敗。
最常見的錯誤是:
1)找不到檔案或路徑,此時errno 被設定為ENOENT;
2)數組argv和envp忘記用NULL結束,此時errno被設定為EFAULT;
3)沒有對要執行檔案的運行許可權,此時errno被設定為EACCES。