2011-11-10 98 views
-2

對於那些想要幫助的人,或者指向正確的方向。我有一個程序,其他程序和命令行參數讀取這樣的:Unix選擇系統調用

./mainprogram ./prog1 5 ./prog2 9 ./prog3 4 

到目前爲止我有工作在第一程序讀取,但是當我嘗試在2個程序讀取它不工作。我認爲第二組眼睛可能會有所幫助。

#include <errno.h> 
#include <cstdio> 
#include <iostream> 
#include <sys/wait.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/select.h> 
#define BUFSIZE 1024 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    char buf[BUFSIZE]; 
    int bytesread; 
    int checkfd[((argc-1)/2)]; 
    int ready; 
    int maxfd= 0; 
    int programs= ((argc-1)/2); 
    fd_set readset; 


    typedef int pipe_t[2]; 
    pipe_t *mypipes =(pipe_t*)calloc(programs,sizeof(pipe_t)); 

    for(int k=0; k<= programs;k++){ 
     pipe(mypipes[k]); 
     checkfd[k]=true; 
    } 

    for(int i=1; i<=argc-1; i+2){ 
     pid_t childpid =fork(); 

     //child code 
     if(childpid==0){ 

      dup2(mypipes[i][1],mypipes[i][1]); 
      //for(int q=0; q<= programs;q++){ 
      // close(mypipes[q][0]); 
      // close(mypipes[q][1]); 
      // } 

      int a=execl(argv[i],argv[i],(char*)argv[i+1],(char *)NULL); 
      if(a==-1){ 
       perror("The following error occurred at a"); 
       exit(1); 

      } 
     } 
     //parent code 
     else{ 

      int result; 
      dup2(mypipes[i][0],mypipes[i][0]); 

      for(int z=0; z<programs; z++){ 

       FD_ZERO(&readset); 

       if(checkfd[z]){ 
        FD_SET(mypipes[z][0],&readset); 
        if(mypipes[z][0] >= maxfd){ 
         maxfd= mypipes[z][0]+1; 
        } 

       } 
       else{ 
        continue; 
       } 

       ready=select(maxfd,&readset,NULL,NULL,NULL); 

       if((ready==-1) && (errno== EINTR)){ 
        continue; 
       } 
       else if(ready== -1){ 
        break; 
       } 


       for(int k=0; k<programs; k++){ 

        if(FD_ISSET(mypipes[k][0], &readset)){ 

         bytesread= read(mypipes[k][0], buf, BUFSIZE); 

         if(bytesread < 0){ 

          close(mypipes[k][0]); 

         } 
        } 
       } 
      } 
     } 
    } 

    for(int q=0; q<= programs;q++){ 
     close(mypipes[q][0]); 
     close(mypipes[q][1]); 
     wait(NULL); 
    } 

    return 0; 

} 

這裏是我在讀的程序之一:

#include <cstdlib> 
#include <iostream> 
#include <string.h> 
#include <stdio.h> 

using namespace std; 

int main(int argc, char** argv) 
{ 
    int cube(int); 
    void process(int(*)(int),int); 

    if (argc != 2){ 
     cerr << "Usage " << argv[0] << " number"; 
     return 1; 
    } 

    int n = atoi(argv[1]); 
    process(cube, n); 
    return 0; 
} 

int cube(int n){ 
    return n*n*n; 
} 
void process(int(*f)(int), int n){ 
    sleep(f(3) % 4); 
    for (int k = 1; k <= n; k++){ 
     int result = f(k); 
     char buffer[1024]; 
     sprintf(buffer, "cube: %d\n", result); 
     write(1,buffer, strlen(buffer)); 
     //write(1, &result, sizeof(int)); 
     // cout<<result<<endl; 
     sleep(rand() %3); 
    } 
} 

其餘的都是相同的結構只是一個不同的序列。好的問題是,當我嘗試傳遞兩個程序時,第一個傳遞的數據輸出它應該執行的順序,但第二個,第三個,第四個等等不輸出。

+2

是否可以調試到一個更簡單的例子?另外,你可以清理你的代碼格式,以免閱讀這麼痛苦嗎? – ObscureRobot

+0

-1。 「不起作用」不是有效的問題描述。另外,投票結束爲「太局部」。 –

+0

問題到底是什麼?你有沒有閱讀過http://linux.die.net/man/2/select_tut –

回答

1

一對夫婦的意見:

  • dup2(mypipes[i][1],mypipes[i][1]);是一個空操作 - 你想dup2(mypipes[i][1],1);
  • 所有進程應該關閉它們沒有使用所有FDS。每個管道的每一端最終應該在一個進程中以一個fd打開,所有其他進程已關閉。因此,每個孩子應該有一個管道的寫入結束,並且父級應該具有管道的讀取結束,並且不寫入結束,並且應該關閉所有冗餘的fds。使用FD_CLOEXEC可以使這個變得更簡單 - 如果每一個fd除了fd 1都是CLOEXEC,那麼在執行exec之後,子元素將會變得乾淨。
  • 它看起來像您的選擇循環在您的設置循環中,所以您將開始選擇只有第一個孩子已經開始,並將在開始最後一個孩子後停止這樣做。前者是無害的,後者是個問題。您可能需要一個循環來設置子項(foring和execing),然後完全獨立的while(1)循環調用select。
+0

非常感謝您的幫助,我會嘗試一下您的建議,看看它能讓我獲益多少 – user975044

0

沒你的意思做dup2(mypipes[i][1], 1);,而不是dup2(mypipes[i][1],mypipes[i][1]);更換stdout子進程?