執行shell命令的函數——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()