2014-07-02 105 views
0

在Linux中,我使用「pidof process_name」命令打開管道,然後使用fgets函數讀取輸出,從而找到進程的pid。但它偶爾會發現一次失敗。以下是我的代碼,用於查找我的流程的pid。使用popen函數讀取命令輸出失敗

int FindPidByProcessName(char *pName) 
{ 
    int pid = -1; 
    char line[30] = { 0 }; 
    char buf[64] = { 0 }; 

    sprintf(buf, "pidof %s", pName); 

    //pipe stream to process 
    FILE *cmd = popen(buf, "r"); 

    if (NULL != cmd) 
    { 
     //get line from pipe stream 
     fgets(line, 30, cmd); 
     //close pipe 
     pclose(cmd); cmd = NULL; 

     //convert string to unsigned LONG integer 
     pid = strtoul(line, NULL, 10); 
    } 

    return pid; 
} 

即使進程在「ps」命令輸出中可用,輸出中也有時會出現pid = 0。 所以,我試圖找到這個問題背後的根本原因,我發現像輸入/輸出緩衝機制可能在我的方案中創建問題。

所以我嘗試在打開popen()之前使用sync()函數,奇怪的是我的函數開始以100%的精度工作。

現在sync()函數花費太多時間(大約2分鐘)來完成它的執行,這是不可取的。所以我嘗試使用fflush(),fsync()和fdatasync(),但這些都不能正常工作。

所以請任何人告訴我這個問題背後的確切根源以及如何正確解決這個問題?

+0

我不明白你的'while'循環 - 你只是調用'popen'一次,你爲什麼而循環讀取輸出? – Ariel

+0

抱歉誤會,這只是我用來編寫函數的編碼格式。它在這裏沒有意義,因爲它是(0)。它不會被循環。 – ravibhuva9955

+0

當'pid'爲'0'時,'line'的內容是什麼? – Ariel

回答

2

好吧,錯誤的根本原因存儲在errno變量(這btw你不需要初始化)。您可以使用溫控功能

perror("Error: "); 

如果u使用PERROR的變量errno解釋得到通知消息,你會得到一個描述性的消息。

查找根本原因的另一種方式(正確方法)是使用-g標誌編譯程序並使用gdb運行二進制文件。

編輯:我強烈建議使用gdb調試器,以便您可以確切地查看代碼遵循的路徑,以便您可以解釋所描述的奇怪行爲。

第二編輯:Errno存儲最後一個錯誤(返回值)。而不是調用函數爲你做什麼,你應該寫,並立即檢查錯誤號:

if ((<function>) <0) { 
    perror("<function>: "); 
    exit(1); 
} 
+0

我很欣賞你的想法。但我已經使用gdb進行調試以查找根本原因。這裏的東西是沒有輸出是在fgets()嘗試讀取FILE *時進入的。所以這是我的一些I/O緩衝機制的問題。 – ravibhuva9955

+0

@ ravibhuva9955 fgets()返回什麼?您可以使用strace命令來監視程序的系統調用(包括I/O操作)。 – sestus

+0

fgets在這種情況下返回NULL。 – ravibhuva9955