1. 程式人生 > >執行shell命令的函數——system()、popen()

執行shell命令的函數——system()、popen()

system、popen

1、FILE* popen(const char* cmd,const char* type);

int pclose(FILE* stream);

popen()函數fork()一個子進程,創建管道用於父子進程間通信,父進程要麽從管道讀,要麽往管道寫,執行一個shell以運行命令來開啟一個進程

相比於system()的又是在於使用簡單,popen()只返回兩個值,成功返回子進程的status,失敗返回-1



2、int system(const char* cmd);

處理了fork()、execl()、waitpid()這些細節,還有一些信號


1、這個庫函數使用fork()創建一個子進程來;

2、子進程調用/bin/sh-c cmd執行指定的參數命令(/bin/sh一般是一個軟連接,指向某個具體的shell,比如bash,-c選項告訴shell從字符串cmd中讀取命令),執行完之後返回調用原進程;

3、父進程調用waitpid等待子進程結束。

執行命令時SIGCHLD將被阻塞,在調用system()的進程中SIGINT和SIGQUIT將被忽略。


返回值:

如果cmd是NULL,返回非0,一般為1;

如果fork()失敗,即子進程無法被創建,返回-1;

如果shell在子進程中不能被替換,即execl()失敗,返回127;

如果所有系統調用成功了,子進程執行cmd命令,但cmd命令不一定執行成功,返回cmd通過exit或return返回的值;


system()源碼:

int system(const char * cmdstring) 
{ 
pid_t pid; 
int status; 
if(cmdstring == NULL) 
{ 
return (1); //如果cmdstring為空,返回非零值,一般為1 
} 
if((pid = fork())<0) 
{ 
 status = -1; //fork失敗,返回-1 
} 
else if(pid == 0) 
{ 
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 
_exit(127); // exec執行失敗返回127,註意exec只在失敗時才返回現在的進程,成功的話現在的進程就不存在啦~~ 
} 
else //父進程 
{ 
while(waitpid(pid, &status, 0) < 0) 
{ 
if(errno != EINTR) 
{ 
status = -1; //如果waitpid被信號中斷,則返回-1 
break; 
} 
} 
} 
return status; //如果waitpid成功,則返回子進程的返回狀態 
}

system()會繼承環境變量,編寫具有SUID/SGID權限的程序時不要用這個函數

建議system()只用來執行shell命令

建議監控一下system()函數執行完畢之後的errno值

建議使用popen()代替system()



http://blog.sina.com.cn/s/blog_8043547601017qk0.html


《完》

本文出自 “零蛋蛋” 博客,謝絕轉載!

執行shell命令的函數——system()、popen()