Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C dup2错误的文件描述符_C_Shell_Pipe - Fatal编程技术网

C dup2错误的文件描述符

C dup2错误的文件描述符,c,shell,pipe,C,Shell,Pipe,我正在尝试将管道实现到我的shell。现在它可以处理ls、who、date等常规命令 通过阅读大量内容,并进入其他堆栈溢出帖子,检查管道应该如何工作,我已经提出了这段代码,我将为大家演示。该函数基本上接受一个应该处理的命令 void runCommand(Command *cmd){ char **pl = cmd->pgm->pgmlist; int status; Pgm *p = cmd->pgm; //Count the number

我正在尝试将管道实现到我的shell。现在它可以处理ls、who、date等常规命令

通过阅读大量内容,并进入其他堆栈溢出帖子,检查管道应该如何工作,我已经提出了这段代码,我将为大家演示。该函数基本上接受一个应该处理的命令

void
runCommand(Command *cmd){

    char **pl = cmd->pgm->pgmlist;
    int status;
    Pgm *p = cmd->pgm;

    //Count the number of pipes and create the right number of filedescriptors
    int numPipes = countPipes(cmd->pgm);
    int pipefds[2*numPipes];

    //Pipe the file descriptors here and check if there was an error.
    for(int i = 0; i < (numPipes); i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("couldn't pipe");
            exit(EXIT_FAILURE);
        }
    }

    pid_t pid, wpid;


    int fdr;
    int fd;

    int j = 0;
    while(p != NULL) {

        pid = fork();

        if (pid == 0) {
            // Child process
            if (cmd->bakground == 1) // Check if it should be running in the background, if so, assign a new PID
            {
                setpgid(pid, 0);
            }

            // Check if RSTDOUT is on or not
            if(cmd->rstdout != NULL){

                fd = open(cmd->rstdout, O_WRONLY | O_CREAT | O_TRUNC , S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
                //fclose(fopen(cmd->rstdout, "w"));
                printf("in first\n");
                dup2(fd,1);
                close(fd);
            }

            // Check if RSTIN is on or not
            if(cmd->rstdin != NULL) {

                fdr = open(cmd->rstdin, O_RDONLY);
                printf("in second\n");
                dup2(fdr, 0);
                close(fdr);
            }

            //if not last command
            if(p->next){
                printf("in third\n");
                if(dup2(pipefds[j + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            //if not first command&& j!= 2*numPipes
            if(j != 0 ){

                printf("in fourth: %d\n", j);
                if(dup2(pipefds[j-2], 0) < 0){
                    perror(" dup2");///j-2 0 j+1 1
                    exit(EXIT_FAILURE);

                }

            }

            for(int i = 0; i < 2*numPipes; i++){
                    printf("in fifth\n");
                    close(pipefds[i]);
            }

            j += 2;
            printf("%s\n",pl[0] );
            if (execvp(pl[0], pl) == -1) {
                perror("lsh");
            }

            exit(EXIT_FAILURE);
        }

        else if (pid < 0) {
            // Error forking
            perror("lsh");
        } 
        else if(cmd->bakground != 1){ // check in the parent process if it was running in background, if so dont call for wait()
            // Parent process
            j+=2;

            pl = p->pgmlist;    
            p = p->next;
            for(int i = 0; i < 2 * numPipes; i++){
                printf("in sixth\n");
                close(pipefds[i]);
            }

            int returnStatus;    
            waitpid(pid, &returnStatus, 0);  // Parent process waits here for child to terminate.

            if (returnStatus == 0)  // Verify child process terminated without error.  
            {
               printf("The child process terminated normally.");    
            }

            if (returnStatus == 1)      
            {
               printf("The child process terminated with an error!.");    
            }

        } 
        else
            printf("Child process with ID %d is running in background\n",pid );
    }

}
当我读到这篇文章时,我认为这意味着我很快就要早起了,或者我对文件描述符的处理很糟糕。我试着修复它,但没有成功,我转向你们,他们可能会看到一些我看不到的东西。如果您需要任何进一步的信息,请发表意见,我将尽我所能提供帮助

******编辑1******

我将printf添加到我使用的每个dup2或close中,将它们命名为第一个、第二个、第三个等等,只是为了确切地知道我在哪个dup或close中得到了错误。这是我运行命令时的结果:

> ls | wc
in sixth
in sixth
in third
in sixth
in sixth
in fourth: 2
 dup2: Bad file descriptor
所以我们至少知道它在哪里失败

******编辑2******

我还添加了我们正在写入、读取或关闭的文件描述符:

In parent closing fd: 0
In parent closing fd: 1
in child third writing to fd: 1
In parent closing fd: 0
In parent closing fd: 1
in child fourth reading from fd: 0
 dup2: Bad file descriptor

我认为dup2的问题在于:

if(cmd->rstdin != NULL) {

                fdr = open(cmd->rstdin, O_RDONLY);
                dup2(fd, 0);
                close(fdr);
            }

您正在打开“fdr”,但在dup2中使用了“fd”。“fd”未打开或已在前一个if{}中关闭。此外,在这两个条件中,您不检查dup2的返回值。

只是在dup2中将其更改为fdr,但仍然不起作用。而且那部分和管道无关。如果我正在使用这些命令lstext.txt
gcc-Wall-Werror-g-o myprog&&gdb--args myprog
您忘了添加gcc myprog,您希望我添加输出中给出的错误吗@JonathonReinhartI忘了
myprog.c
,对不起。但是不,我希望您修复编译中的所有错误。我怀疑你的程序可能会在你这样做的时候起作用。这就是为什么我们要编译语言——在运行前检测编程问题“fork等人的隐式声明。在我看来,我没有实现fork或所有其他函数是错误的吗@JonathonReinhart假设使用Linux,您可以在
strace-f-o/path/to/output/file…
下运行,查看系统调用级别的情况。
if(cmd->rstdin != NULL) {

                fdr = open(cmd->rstdin, O_RDONLY);
                dup2(fd, 0);
                close(fdr);
            }