2011-11-10 58 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子进程?