Unix选择系统调用

时间:2011-11-10 22:07:09

标签: c++ 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 个答案:

答案 0 :(得分:1)

几条评论:

  • dup2(mypipes[i][1],mypipes[i][1]);是一个noop - 你想要dup2(mypipes[i][1],1);
  • 所有进程都应关闭所有未使用的fds。每个管道的每一端都应该只在一个进程中打开一个fd,所有其他进程都关闭它。因此,每个子节点应该具有一个管道的写入端,并且父节点应该具有管道的读取端并且没有写入结束,并且应该关闭所有冗余的fds。使用FD_CLOEXEC可以帮助实现这一点变得更加简单 - 如果每个fd除了fd 1是CLOEXEC,那么孩子们在执行后会很干净。
  • 看起来您的选择循环位于您的设置循环中,因此您将在第一个孩子刚开始时选择,并在启动最后一个孩子后停止这样做。前者是无害的,后者是一个问题。你可能想要一个循环来设置子项(foring和execing),然后一个完全独立的while(1)循环调用select。

答案 1 :(得分:0)

您是不是要dup2(mypipes[i][1], 1);而不是dup2(mypipes[i][1],mypipes[i][1]);来替换子进程的stdout