1. 程式人生 > >C++中SYSTEM的用法

C++中SYSTEM的用法

曾經的曾經,被system()函式折磨過,之所以這樣,是因為對system()函數了解不夠深入。只是簡單的知道用這個函式執行一個系統命令,這遠遠不夠,它的返回值、它所執行命令的返回值以及命令執行失敗原因如何定位,這才是重點。當初因為這個函式風險較多,故拋棄不用,改用其他的方法。這裡先不說我用了什麼方法,這裡必須要搞懂system()函式,因為還是有很多人用了system()函式,有時你不得不面對它。 先來看一下system()函式的簡單介紹:
1 #include <stdlib.h>
2 int system(const char *command);

system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.

  system()函式呼叫/bin/sh來執行引數指定的命令,/bin/sh 一般是一個軟連線,指向某個具體的shell,比如bash,-c選項是告訴shell從字串command中讀取命令;   在該command執行期間,SIGCHLD是被阻塞的,好比在說:hi,核心,這會不要給我送SIGCHLD訊號,等我忙完再說;   在該command執行期間,SIGINT和SIGQUIT是被忽略的,意思是程序收到這兩個訊號後沒有任何動作。 再來看一下system()函式返回值: The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command otherwise. This latter return status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case /bin/sh could not be executed, the exit status will be that of a command that does exit(127).
If the value of command is NULL, system() returns nonzero if the shell is available, and zero if not. 為了更好的理解system()函式返回值,需要了解其執行過程,實際上system()函式執行了三步操作:  1.fork一個子程序; 2.在子程序中呼叫exec函式去執行command; 3.在父程序中呼叫wait去等待子程序結束。   對於fork失敗,system()函式返回-1。   如果exec執行成功,也即command順利執行完畢,則返回command通過exit或return返回的值。   (注意,command順利執行不代表執行成功,比如command:"rm debuglog.txt",不管檔案存不存在該command都順利執行了)   如果exec執行失敗,也即command沒有順利執行,比如被訊號中斷,或者command命令根本不存在,system()函式返回127. 如果command為NULL,則system()函式返回非0值,一般為1. 看一下system()函式的原始碼
  看完這些,我想肯定有人對system()函式返回值還是不清楚,看原始碼最清楚,下面給出一個system()函式的實現:
01 int system(const char * cmdstring)
02 {
03 pid_t pid;
04 int status;
05
06 if(cmdstring == NULL)
07 {
08 return (1); //如果cmdstring為空,返回非零值,一般為1
09 }
10
11 if((pid = fork())<0)
12 {
13 status = -1; //fork失敗,返回-1
14 }
15 else if(pid == 0)
16 {
17 execl("/bin/sh""sh""-c", cmdstring, (char *)0);
18 _exit(127); // exec執行失敗返回127,注意exec只在失敗時才返回現在的程序,成功的話現在的程序就不存在啦~~
19 }
20 else //父程序
21 {
22 while(waitpid(pid, &status, 0) < 0)
23 {
24 if(errno != EINTR)
25 {
26 status = -1; //如果waitpid被訊號中斷,則返回-1
27 break;
28 }
29 }
30 }
31
32 return status; //如果waitpid成功,則返回子程序的返回狀態
33 }
仔細看完這個system()函式的簡單實現,那麼該函式的返回值就清晰了吧,那麼什麼時候system()函式返回0呢?只在command命令返回0時。 看一下該怎麼監控system()函式執行狀態   這裡給我出的做法:
01 int status;
02 if(NULL == cmdstring) //如果cmdstring為空趁早閃退吧,儘管system()函式也能處理空指標
03 {
04 return XXX;
05 }
06 status = system(cmdstring);
07 if(status < 0)
08 {
09 printf("cmd: %s\t error: %s", cmdstring, strerror(errno)); // 這裡務必要把errno資訊輸出或記入Log
10 return XXX;
11 }
12
13 if(WIFEXITED(status))
14 {
15 printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); //取得cmdstring執行結果
16 }
17 else if(WIFSIGNALED(status))
18 {
19 printf("abnormal termination,signal number =%d\n", WTERMSIG(status)); //如果cmdstring被訊號中斷,取得訊號值
20 }
21 else if(WIFSTOPPED(status))
22 {
23 printf("process stopped, signal number =%d\n", WSTOPSIG(status)); //如果cmdstring被訊號暫停執行,取得訊號值
24 }

system()函式用起來很容易出錯,返回值太多,而且返回值很容易跟command的返回值混淆。這裡推薦使用popen()函式替代,關於popen()函式的簡單使用也可以通過上面的連結檢視。

popen()函式較於system()函式的優勢在於使用簡單,popen()函式只返回兩個值:
成功返回子程序的status,使用WIFEXITED相關巨集就可以取得command的返回結果;
失敗返回-1,我們可以使用perro()函式或strerror()函式得到有用的錯誤資訊。

這篇文章只涉及了system()函式的簡單使用,還沒有談及SIGCHLD、SIGINT和SIGQUIT對system()函式的影響,事實上,之所以今天寫這篇文章,是因為專案中因有人使用了system()函式而造成了很嚴重的事故。現像是system()函式執行時會產生一個錯誤:“No child processes”。

相關推薦

C++SYSTEM用法

曾經的曾經,被system()函式折磨過,之所以這樣,是因為對system()函數了解不夠深入。只是簡單的知道用這個函式執行一個系統命令,這遠遠不夠,它的返回值、它所執行命令的返回值以及命令執行失敗原因如何定位,這才是重點。當初因為這個函式風險較多,故拋棄不用,改用其他的方

C++system函式的用法,有效配合控制檯程式

int system( const char *command ); int _wsystem( const wchar_t *command ); command: Command to be executed sample: //system.c #include <process.h&

C# System.Index 結構體和 Hat 運算子(^)的全新用法

> 翻譯自 John Demetriou 2019年2月17日 的文章 [《C# 8 – Introducing Index Struct And A Brand New Usage For The Hat Operator》](http://www.devsanon.com/c/c-8-introdu

c/c++const用法總結

沒有 pan 分配 值類型 變量初始化 _id 多少 部分 參數 1、修飾常量時:   const int temp1; //temp1為常量,不可變   int const temp2; //temp2為常量,不可變 2、修飾指針時:   主要看const在*的前後,

C#Split用法~字符串分隔

rec get 字符 說明 logs sep bbs options tle 1、用字符串分隔: using System.Text.RegularExpressions;string str="aaajsbbbjsccc";string[] sArray=

C#const用法詳解

htm 鏈接 服務器 span img body 用法詳解 -s 設計 本文實例講述了C#中const用法。分享給大家供大家參考。具體用法分析如下: const是一個c語言的關鍵字,它限定一個變量不允許被改變。使用const在一定程度上可以提高程序的安全性和可靠性,另外,

C#FormsAuthentication用法實例

clear tick brush esp void 轉載 地址 功能 def using System; using System.Web; using System.Web.Security; namespace AuthTest { public class Aut

C#protected用法詳解

base 而是 報錯 public 我們 此刻 訪問 .html 定義 轉自(https://www.cnblogs.com/wangyt223/archive/2012/08/08/2627801.html) 在c#的可訪問性級別中,public和private算是最

c/c++system函式

原文地址:http://www.cnblogs.com/tianzeng/p/9550379.html   在windows下的system函式中命令可以不區別大小寫!  函式名: system  功 能: 發出一個DOS命令  用 法: #inc

C Format用法

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C++STL用法總結【轉】

(轉自:https://blog.csdn.net/piaoxuezhong/article/details/54348787?utm_source=blogxgwz8) 1.1 什麼是STL? STL(Standard Template Library),即標準模板庫,是一個具有工業強度的

C++memset()用法

memset()函式原型是extern void *memset(void *buffer, int c, int count) buffer:為指標或是陣列 c:是賦給buffer的值 count:是buffer的長度 1. memset是以位元組為單位,初始化記憶體塊。 當初

C++CONST用法總結

1、修飾常量時: ? 1 2 const int temp1; //temp1為常量,不可變 int const temp2; //temp2為常量,不可變 2、修飾指標時:   主要看const在*的前後,

C# ??,:,?:的用法

private void button1_Click(object sender, EventArgs e) { int a = 0; object flag = null; Boolean t = true; Boolean temp = f

c++set用法

1.關於set C++ STL 之所以得到廣泛的讚譽,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封裝了許多複雜的資料結構演算法和大量常用資料結構操作。vector封裝陣列,list封裝了連結串列,map

C#Enum用法小結

列舉   列舉型別宣告為一組相關的符號常數定義了一個型別名稱。列舉用於“多項選擇”場合,就是程式執行時從編譯時已經設定的固定數目的“選擇”中做出決定。   列舉型別(也稱為列舉)為定義一組可以賦給變數的命名整數常量提供了一種有效的方法。例如,假設您必須定義一個變數,該變數的值表示一週中的一天

C++set用法詳解

1.關於set C++ STL 之所以得到廣泛的讚譽,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封裝了許多複雜的資料結構演算法和大量常用資料結構操作。vector封裝陣列,list封裝了連結串列,map和se

C++STL用法總結

函式庫對資料型別的選擇對其可重用性起著至關重要的作用。舉例來說,一個求方根的函式,在使用浮點數作為其引數型別的情況下的可重用性肯定比使用整型作為它的引數類性要高。而C++通過模板的機制允許推遲對某些型別的選擇,直到真正想使用模板或者說對模板進行特化的時候,STL就利用了這一點提供了相當多的有用演算法。它是在一

C#MessageBox用法大全(附效果圖)

我們在程式中經常會用到MessageBox。    MessageBox.Show()共有21中過載方法。現將其常見用法總結如下:    1.MessageBox.Show("Hello~~~~"); 最簡單的,只顯示提示資訊。 2.MessageBox.Show("

C++_onexit()用法簡述

引問:main 主函式執行完畢後,是否可能會再執行一段程式碼? 答案:可以,可以用_onexit 註冊一個函式,它會在main 之後執行。 知識瞭解: (1)使用格式:_onexit(int fun()) ,其中函式fun()必須是帶有int型別返回值的無引數函式; (2