進程管理之system

来源:http://www.cnblogs.com/cjaaron/archive/2017/09/05/7476706.html
-Advertisement-
Play Games

system定義 首先要知道,system函數是c庫中的函數,而不是系統調用。其實system函數使用起來並不複雜,難就難在對其返回值的理解。這個問題,下文會詳細分析。參數的話,很簡單,就是終端的命令即可。這是因為system函數的實現中調用了shell的緣故。 system優缺點 優點: 可以讓c ...


system定義

#include<stdlib.h>
int system(const char *command);

首先要知道,system函數是c庫中的函數,而不是系統調用。其實system函數使用起來並不複雜,難就難在對其返回值的理解。這個問題,下文會詳細分析。參數的話,很簡單,就是終端的命令即可。這是因為system函數的實現中調用了shell的緣故。

system優缺點

  • 優點:可以讓c程式猿很方便地調用其他語言編寫的程式,當然調用c程式自然也沒問題;
  • 缺點:第一:效率低,第二:返回值難理解;
    效率低是因為system函數的實現過程至少要創建兩個進程,一個是shell進程,還有一個或著多個shell命令運行的進程。所以在對效率高有要求的程式中,直接用fork和exec函數族比較合適;返回值的問題下文會講;

system函數返回值

先寫個簡化版的system函數的實現過程。簡化是沒有考慮處理信號的問題。代碼如下:

#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>

int system(char * command)
{
    int status;
    pid_t child;
    
    swicth(child = fork())
    {
        case -1:
            return -1;
        case 0:
            execl("/bin/sh","sh","-c",command,NULL);
            _exit(127);
        default:
            while(waitpid(child,&status,0)<0)
            {
                if(errno != EINTR)
                {
                    status = -1;
                    break;
                }
            }
            return status;
    }
}

1)返回值為 “0” 或 “1”
這中情況一般不會出現,只有當寫成system(NULL)時,才會出現這種結果。目的是為了檢測系統的shell是否可用。返回1表示shell可用,返回0表示shell不可用;這種情況在上訴代碼中看不出來,通過glibc庫中的源碼可以看出:

glibc-2.17/sysdeps/posix/system.c
int __libc_system(const char *line)
{
    if(line == NULL)
    return do_system("exit 0") == 0;
    ......
}

line指針指向的就是command命令行參數,system函數調用do_system系統調用,當執行“exit 0”(表示結束當前shell),執行成功do_system返回0,說明shell可用。反之,shell不可用。

2)返回值為 -1
有兩個原因造成這樣的結果。第一,因為fork創建子進程失敗導致的。即“case -1”的情況,這中情況比較少見;第二,是不能正常處理子進程的“墓誌銘”導致的,說白了,就是子進程的進程表在子進程結束時,沒有經過父進程處理,而自己銷毀了。這樣的效果是因為父進程中安插的處理SIGCHLD信號的處理函數是SIG_IGN,或者用戶設置了SA_NOCLDWAIT標誌位導致,waitpid函數返回值為-1且全局變數errno的值為ECHLD;
例如:

signal(SIGCHLD,SIG_IGN); //出錯的根源

if( (status = system(command)) < 0 )
{
    fprintf(stderr,"system return %d (%s)\n",status,strerror(errno));
    return -2;
}

所以在使用system函數時,一定要判斷SIGCHLD是否被設置為SIG_IGN。

3)返回值為 _exit(127)的返回值
這種情況是因為程式運行到“case 0”中,execl函數執行失敗後,執行_exit函數導致的。說明子進程無法執行shell該shell命令。

4)返回值為shell執行的進程的返回值
shell的終止狀態是其執行最後一條命令的退出狀態。這種情況下和獲取子進程的退出狀態一樣。通過如下巨集獲取其退出狀態:

  • WIFEXITED(status)
  • WEXITSATUS(status)
  • WIFSIGNALED(status)
  • WTERMSIG(status)
  • WCOREDUMP(satus)

綜上所述,可以給出一個system函數返回值判斷的常式:

if( (status == system(command))==-1 )
{
    fprintf(stderr,"system() function return -1 (%s)\n",strerror(errno));
}
else if(WIFEXITED(status)&&WEXITSTATUS(status) == 127)
{
    fprintf(stderr,"cannot invoke shell to exec command (%s)\n",strerror(enrrno));
}
else
    print_wait_exit(status);

print_wait_exit函數就是上文中提到的獲取shell退出狀態的巨集,根據需要去實現即可。

system函數和信號

影響system函數執行的信號有三個:SIGCHLD、SIGINT和SIGQUIT信號。

SIGCHLD信號:上文已經提過,它會影響waitpid函數,產生競爭現象的出現。調用system函數的進程可能還有其他的子進程,當然同樣也會有wait或waitpid函數。當有SIGCHLD信號到來時,system函數中的waitpid函數和其他的wait或waitpid函數產生競爭狀態,從而使得system執行異常。所以system執行期間會暫時屏蔽SIGCHLD信號;

SIGINT信號和SIGQUIT信號:調用system函數的進程會屏蔽這兩個信號。system函數創建的進程會恢復這兩個信號的預設處理狀態。調用system函數的進程其實已經放棄了控制權,所以不能夠去終止進程。反之,system函數創建的進程當然就有了控制權,所以要恢復控制權。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • orcal資料庫使用mybatis接收參數,如果傳的是多個參數,需要使用#{0},#{1},。。。等代替具體參數名,0 代表第一個參數,1 代表第二個參數,以此類推。 錯誤語句: 正確語句: ...
  • 在mapper.xml中 , 如果單參數是String類型 , 且在sql語句中對參數進行了判斷 , 如下 when 中的判斷 , 如果出現 if 判斷也是一樣的。都需要把判斷中的參數用 _parameter 來代替 ,。 另外orcal中判斷欄位是否為空需要使用 is null , 同理,判斷不為 ...
  • SSIS 其全稱是Sql Server Integration Services ,是Microsoft BI 解決方案的一大利器. SSIS 的體繫結構主要由四部分組成:Integration Services 服務、Integration Services 對象模型、Integration Se ...
  • 本文主要講解了linux下的at命令的使用和周期性任務計劃crond的用法。 ...
  • 1.1 關於運維人員 1.1.1 運維的職責 1.保證伺服器7*24小時 運行 2.保證數據不能丟 3.提高用戶的體驗(網站打開的速度) 1.1.2 運維原則 簡單、易用、高效 簡單、粗暴 第2章 電腦的組成 2.1 電腦組成 包含: 1.顯示器、 2.機箱(主機)| | CPU | 硬碟 | ...
  • 我一直無法解決Ubuntu QQ問題,而最近我重裝ubuntu之後在網路上找到與QQ相關的內容,網上有大神開發出了新版的wineQQ,解決了我們對QQ的需求。經過嘗試,完成了QQ安裝 如圖 安裝的是wine QQ 那麼 1.首先安裝wine 第一條命令 添加源 第二條 第三條 2.下載wineQQ  ...
  • 本文不進行大量的原理敘述,主要講解實操 實驗環境: 虛擬機:vm Ubuntu:16.04(需要安裝桌面),作為服務端 服務端IP:192.168.193.128 實踐: 1.安裝dhcp服務 apt-get install isc-dhcp-server -y #如果提示E: 無法定位軟體包 is ...
  • 簡單來說內網穿透的目的是:讓外網能訪問你本地的應用,例如在外網打開你本地http://127.0.0.1指向的Web站點。 最近公司的花生殼到期了,要續費,發現價格一直在漲,都是5年以上的老用戶,旗艦版都沒有實現內網完全穿透,打算自己動手替換這個服務,中間走了不少的彎路,這裡記錄一些文字為大家提供參 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...