作者 主題: Linux C , 請問以 system() 執行的指令如何取得 pid ???  (閱讀 27065 次)

0 會員 與 1 訪客 正在閱讀本文。

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
 ??? 如題,
程式理有些動作需要呼叫外部的程式,
這時我都會用 system()呼叫 (因為也需要回傳值)
如果子程式失敗卡死, 希望能用 pid 移除他.
但是我不知道怎麼取得子程式 pid ?
請各位大大教教肉腳的我吧~~~

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5396
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
system() 是用 block 的方式去執行的吧, 執行的程式沒結束是不會返回的.... 你的程式是暫停等待的狀態, 有沒有 pid 又有什麼作用呢?

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
system() 是用 block 的方式去執行的吧, 執行的程式沒結束是不會返回的.... 你的程式是暫停等待的狀態, 有沒有 pid 又有什麼作用呢?


我的呼叫有加入 "&" 也就是背景執行~
所以還是需要pid停止他

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5396
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
既然要同步執行, 就用 fork() 加上 exec()  去跑不就好了.
母程式用 fork() 取得子程式的 pid, 然後在子程式用 exec() 去執行就可以了.

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
既然要同步執行, 就用 fork() 加上 exec()  去跑不就好了.
母程式用 fork() 取得子程式的 pid, 然後在子程式用 exec() 去執行就可以了.

但是我希望接收程式的回傳值, exec() 好像不行的樣子?

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5396
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
在母程式用 waitpid() 去取得子程式的資料.

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
 :o 原來如此! 真上了一課, 我太依賴 system("&") 了
有恍然大悟的感覺 謝謝 twu2 大大!!!

我的理解如下:

////////////////////////////////////////
int c_rtn = 0;
int c_status = 0;
int c_pid = fork();

if(c_pid == 0)
{
   c_rtn = system("OXABC");
   return c_rtn;
}else
{
  waitpid(c_pid,&c_status,0);
  // 其 c_status 即為回傳值
}
////////////////////////////////////////
學到了! thx  :D

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5396
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
我是沒寫程式去測過, 不過你的理解與我看 man 上頭那些 function 的用法與參數回傳值的認知並不一樣.

elleryq

  • 鑽研的研究生
  • *****
  • 文章數: 908
  • 性別: 男
    • 檢視個人資料
    • Thinking more...
既然已經用 system() 了
乾脆再用 killall

system("wget http://somewhere/somefile &");
system("killall wget");

Plan your work, then work your plan.
我的首頁:http://blog.elleryq.idv.tw
351899by http://counter.li.org

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
既然已經用 system() 了
乾脆再用 killall

system("wget http://somewhere/somefile &");
system("killall wget");

恩...雖說 killall 也是一個方法~
但這樣也可能會影響其他使用者, 所以比較堅持用 pid
就可以 system("kill -9 [pid]");
(我還是對 system() 很依賴阿~)
還是謝謝提醒 thx  ;)

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5396
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
用 system() 就一定不是你 fork() 出來的那個 pid, 你是要 kill 誰啊? 請改用 exec() 系列來執行.

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
傷腦經, 這樣好像又回到原點的感覺~
exec() 系列我看了看好像沒有回傳指定程式的回傳值
而system()又無法取得pid
還是我漏了什麼 ?

stlee

  • 鑽研的研究生
  • *****
  • 文章數: 817
    • 檢視個人資料
我能想到的是......

system()叫用一個可以列出所有程序pid的指令

並令其將結果導入到一個檔案裏面

再來就是去分析這個檔案

然後應該也是以system()叫用的方式砍了

哈!沒試過~~您參考參考

不過以前倒是有兩個以上程序間的資料互傳用這個"暫存檔"的方法解決的

程式是人寫的,別讓工具的限制成為您想像力的極限
~程式中最重要的部份應該是註解而不是程式碼,這是因為解讀註解一定比解讀程式碼簡單
~程式寫好後約一個月就會忘的差不多了,所以花點時間把註解寫好至少能讓自己(或別人)看的懂當初在寫什麼

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
我能想到的是......

system()叫用一個可以列出所有程序pid的指令

並令其將結果導入到一個檔案裏面

再來就是去分析這個檔案

然後應該也是以system()叫用的方式砍了

哈!沒試過~~您參考參考

不過以前倒是有兩個以上程序間的資料互傳用這個"暫存檔"的方法解決的

恩...這個方法雖說是可以...
像是說用 pstree -ap 或是 ps -a
但是想想, 如果同時有多個同名程式在運作呢?
比如使用 cdrecord 燒錄, 但已經有其他使用者用 cdrecord 呼叫了另一台燒錄器
如果用新舊清單比對(執行前先列一次,完成後又列一次,然後作比對)
還是有風險~如果新舊清單建立其間有程式插隊或結束 那就糟了~


kenduest

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 3675
    • 檢視個人資料
    • http://kenduest.sayya.org

不好意思插個嘴,我看完整篇討論不懂原本作者的意思。

twu2 前面說 fork + exec 方式,最後用 waitpid() 作法方式,請問為何你說無法在 waitpid() 那邊取得傳回值呢?
I am kenduest - 小州

my website: http://kenduest.sayya.org/

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
恩?是不是我對exec()的認識有錯誤?
我一直以為exec()跟system()一樣,是執行其中指定的程式完畢後就回到本程式
聽了kenduest 大大的講法, exec()會在執行後直接取代呼叫的程式
當 exec()內的程式執行完成後, 即子程式也結束了, 所以 exec()的回傳值即子程式的回傳值
而 exec() 後面所寫的程式也不會被執行.
是不是這樣呢? THX

kenduest

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 3675
    • 檢視個人資料
    • http://kenduest.sayya.org

啊?

所以使用 fork() + exec() 不是呼?

代碼: [選擇]
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
  pid_t child_pid;
  int status;
  char prog[]="/bin/ls";

  printf("** Execuing program: ls -l /bin/gzip **\n\n");

  child_pid = fork();

  if (child_pid < 0) {
        exit(1);
  }

  if (child_pid != 0) // parent
    waitpid(child_pid,&status,0);

  else
     execl(prog,prog,"-l","/bin/gzip",NULL);

  printf("\nchild return exit code: %d\n",WEXITSTATUS(status));
  return 0;
}

代碼: [選擇]
** Execuing program: ls -l /bin/gzip **

-rwxr-xr-x 1 root root 63080 2008-12-20 02:23 /bin/gzip

child return exit code: 0
I am kenduest - 小州

my website: http://kenduest.sayya.org/

id4fox

  • 憂鬱的高中生
  • ***
  • 文章數: 103
  • 40 oz 挑戰成功!
    • 檢視個人資料
原來如此, 真是誤會大了
太倚賴system()果然不好導致跟exec()都不熟
又上了一課, 謝謝各位學長姐的指導!