popen和system問題


popen和system問題

1. 問題描述

C的代碼里面去調用命令啟動一個shell腳本,分別使用了下面兩個途徑。
其中一個是: func1(cmd) { popen(cmd,type); pclose(); }
另一個是: func2() { system(cmd); } 其中cmd類似於“./xxx.sh &”。
問題就是,func1這種調法,會導致xxx.sh運行阻塞,腳本最開始添加打印信息都沒有顯示,但是top后顯示進程存在;而func2調用后腳本運行正常。

2. 問題分析

通過分析popen,pclose,system的源碼,兩者的流程分別如下:
首先看popen,pclose的流程:
父進程調用popen,
popen(cmd, type)
{ 返回一對fd(分別用來重定向子進程的讀和寫,但不是同時,根據type父進程和子進程最后分別只能用一個)
fork
1. 子進程重定向fd,將標准輸出或者標准輸入定向到一個fd,然后執行execl cmd,
返回;
2. 父進程收到子進程返回的fd
}
父進程調用pclose
pclose { 1.等待popen出來的子進程結束; 2.關閉fd }
 
然后是system的流程:
system { fork; 1. 子進程execv cmd; 2. 父進程wait子進程退出; 返回; }
 
 
上面的流程簡單點,總結出來就是摘自stackoverflow上的一個解釋:
popen gives you a pair of file handles you can use to read and write input and output to and from stdin/stdout of the running process in an interactive manner. The system call is merely executing that and redirecting stdin of the current process to that of the invoked child process, and stdout of that process to stdout of the current (host) process. It depends what you are trying to achieve, in general. If your goal is simply to run a command, system works fine. If you're interested in reading its output in a programmatic manner and processing it (and possibly generating more input), then popen is going to work better.

子進程的標准輸入和標准輸出,和跟着開啟他的父進程的配置來的,當執行一個命令會后台運行的時候,比如./test.sh &, 其實又是fork出來一個子進程,然而內部封裝的接口my_system接口中是連續調用的popen和pclose,這就導致了最終后台運行起來的那個test.sh子進程,它里面被popen中重定向的fd已經被關閉了,所以后面所有的echo打印都會報錯“broken pipe”。表現出來就是在串口中看不到任何腳本里面的打印信息。

 

3. 問題總結

封裝一個popen和pclose連續調用的接口,對於執行不依賴任何標准輸入輸出的命令是可以使用的,但是實際上這樣做還不如直接調用system; 代碼中頻繁調用system和popen這種系統調用都會有一個問題,就是進程的切換都會帶來性能上的一些開銷,這個是c和shell混合編程的一個隱患,所以項目后期還是需要盡量將shell腳本中的業務集成進來,減少這種性能開銷,也減少這種類似的調用上的一些異常。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM