dup2()不执行

这是我的第一个问题,所以我很抱歉,如果我忽略了任何重要的事情。 所以我一直在研究通过分叉处理管道的任务。 我的代码非常混乱,散布着printf语句,所以我看到发生了什么。

我在网上查了一下,我想我知道如何处理管道,但是我遇到的问题是我的代码在除了inFD和outFD之外的任何文件描述符上跳过dup2()。

这是我的功能的代码。 另外,据我所知,我的老师制作了一个名为CHK的宏来检查错误。 如果有错误(如dup2返回-1),它将以打印到stderr结束。

我包含全局变量和myhandler()用于信号

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <strings.h>
#include <math.h>
#include <signal.h>

// Function calls
void parse(char *w, char **ptrArray, char *inArray, char *outArray, int *pipeArray);
int flagHandler(char **ptrArray, char *inArray, char *outArray);
int pipeHandler(char **ptrArray, char *inArray, char *outArray, int *pipeArray);

// Global Variables
const int STORAGE = 254;
const int MAXITEM = 100;
int inFD;   // file descriptor for <
int outFD;  // file descriptor for >
int complete = 0; // for sighandler
int readDes = 0;
int writeDes = 1;
int numPipes = 0;
int status;
int forCounter = 0;

int fildes[4];
int pipeIndex = 0;

// MetaChar flags
int lessthanSign = 0; // < flag
int greaterthanSign = 0; // > flag
int firstChildFlag = 0;
int lastChildFlag = 0;

void myhandler(int signum)
{
    complete = 1;
}

我的主要功能

int main()
{
    char s[STORAGE]; // array of words
    char *newargv[MAXITEM];
    char inArray[STORAGE]; // for <
    char outArray[STORAGE]; // for >
    int firstCheck;
    int pidBackground; // holds value from fork(), used for background calls
    struct stat st; // for stat(), checks if file exists

    // dynamic array based on numPipes
    // first child doesn't use this array, as it uses newargv[0] and newargv
    // only the middle children and last child use this array, hence 10
    int *pipeArray = malloc(10 * sizeof(int));

    int numLoops = 0;
    int i = 0;

    signal(SIGTERM, myhandler);

    for(;;)
    {
        // Reset flags here
        lessthanSign = 0;
        greaterthanSign = 0;
        pipeSign = 0;
        firstChildFlag = 0;
        lastChildFlag = 0;
        pipeIndex = 0;


        parse(s, newargv, inArray, outArray, pipeArray);
        pipeHandler(newargv, inArray, outArray, pipeArray);
        wait(NULL);
        fflush(NULL);

    } // end for
    printf("Entering killpg; numLoops = %dn", numLoops);
    killpg(getpid(), SIGTERM);
    printf("p2 terminated.n");
    exit(0);
}   // end main

主要调用解析哪些填充newargv []。 它还分别在<and>后面紧接着填充inArray []和outArray []。 当检测到管道符号时,它会在newargv []上放置一个空值,并在pipeArray []中放置一个值,以便在newargv中将可执行文件的名称编入索引。 我省略了parse()和flagHandler()调用以使其保持最小。

我的parseHandler()函数

int pipeHandler(char **ptrArray, char *inArray, char *outArray, int *pipeArray)
{
    pid_t firstChild;
    pid_t firstChildBackground;
    pid_t middleChild;
    pid_t lastChild;
    pid_t lastChildBackground;
    int i = 0; // plain integer for for loops

    printf("Initializing pipesn");
    //pipe(fildes);
    //pipe(fildes + 2);
    for (i = 0; i < (2*numPipes); i+=2)
    {
        printf("pipe initializing; i is %dn", i);
        if (pipe(fildes + i) < 0)
        {
            perror("pipe initialization failed");
            exit(EXIT_FAILURE);
        }
    }


    fflush(stdout);
    if ((firstChild = fork()) < 0)
    {
        perror("First child's fork failed!");
        exit(EXIT_FAILURE);
    }
    printf("firstChild pid = %dn", getpid());
    if (firstChild == 0)
    {

        if (firstChildFlag == 1)
        {
            printf("inFD = open...n");
            inFD = open(inArray, O_RDONLY);
            printf("Doing dup2 inFDn");
            if (dup2(inFD, STDIN_FILENO) < 0)
            {
                perror("First child's < dup2 failed");
                exit(EXIT_FAILURE);
            }
        }

        printf("doing dup2 fildes[writeDes]n");
        if (dup2(fildes[writeDes], STDOUT_FILENO) < 0)
        {
            perror("First child's dup2 failed");
            exit(EXIT_FAILURE);
        }
        printf("*****doing dup2 fildes[writeDes] was a success!n");

        for (i = 0; i < 4; i++)
        {
            if (close(fildes[i]) < 0)
            {
                perror("close failed");
                exit(EXIT_FAILURE);
            }
        }
        if (firstChildFlag == 1)
        {
            lessthanSign = 0;
            firstChildFlag = 0;

            if (close(inFD) < 0)
            {
                perror("close inFD failed");
                exit(EXIT_FAILURE);
            }
        }

        writeDes += 2;

        printf("About to execvp first childn");
        if (execvp(ptrArray[0], ptrArray) < 0)
        {
            perror("execvp failed");
            exit(EXIT_FAILURE);
        }
    }
    else
    {
        fflush(stdout);
        if ((middleChild = fork() < 0))
        {
            perror("Middle child's fork failed");
            exit(EXIT_FAILURE);
        }
        printf("middleChild pid = %dn", getpid());
        if (middleChild == 0)
        {
            if (dup2(fildes[readDes], STDIN_FILENO) < 0)
            {
                perror("Middle child's dup2 on reading failed");
                exit(EXIT_FAILURE);
            }
            if (dup2(fildes[writeDes], STDOUT_FILENO) < 0)
            {
                perror("Middle child's dup2 on writing failed");
                exit(EXIT_FAILURE);
            }

            for (i = 0; i < 4; i++)
            {
                if (close(fildes[i]) < 0)
                {
                    perror("close failed");
                    exit(EXIT_FAILURE);
                }
            }

            readDes += 2;
            writeDes += 2;

            if (execvp(ptrArray[pipeArray[0]], ptrArray + pipeArray[0]) < 0)
            {
                perror("Middle child's execvp failed");
                exit(EXIT_FAILURE);
            }
        }
        else
        {
            fflush(stdout);
            if ((lastChild = fork() < 0))
            {
                perror("Last child's fork failed");
                exit(EXIT_FAILURE);
            }
            printf("lastChild pid = %dn", getpid());
            if (lastChild == 0)
            {
                if (dup2(fildes[readDes], STDOUT_FILENO) < 0)
                {
                    perror("Last child's dup2 on reading failed");
                    exit(EXIT_FAILURE);
                }
                if (lastChildFlag == 1)
                {
                    outFD = open(outArray, O_CREAT | O_RDWR, 0400 | 0200);
                    if (dup2(outFD, STDOUT_FILENO) < 0)
                    {
                        perror("Last child's > dup2 failed");
                        exit(EXIT_FAILURE);
                    }
                }

                for (i = 0; i < 4; i++)
                {
                    if (close(fildes[i]) < 0)
                    {
                        perror("close failed");
                        exit(EXIT_FAILURE);
                    }
                }
                if (lastChildFlag == 1)
                {
                    greaterthanSign = 0;
                    lastChildFlag = 0;
                    if (close(outFD) < 0)
                    {
                        perror("close on outFD failed");
                        exit(EXIT_FAILURE);
                    }
                }

                printf("Execvp last childn");
                if (execvp(ptrArray[pipeArray[1]], ptrArray + pipeArray[1]) < 0)
                {
                    perror("Last child's execvp failed");
                    exit(EXIT_FAILURE);
                }
                printf("Last child execvp finishedn");
            }
        }
    }


    // Only the parent gets here
    printf("Only the parent should be heren");
    printf("My pid is %dn", getpid());
    for (i = 0; i < 4; i++)
    {
        if (close(fildes[i]) < 0)
        {
            perror("close failed");
            exit(EXIT_FAILURE);
        }
    }

    for (;;)
    {
        pid_t pid;
        if (pid = wait(NULL) < 0)
        {
            perror("wait failed");
            exit(EXIT_FAILURE);
        }
        if (pid == lastChild)
        {
            printf("Parent is waiting for lastChildn");
            break;
        }
    }

    printf("Parent finished waiting. Returning...n");
    return 0;
}

我在任何分支前做过管道(fildes),以便所有的孩子和父母都有他们的副本。 因此,我必须关闭每个子文件中的所有文件描述符(在dup2之后但在execvp之前)和父文件。 父母将等待,直到它得到lastChild的pid。

通过大量的printf语句,我发现没有任何孩子执行dup2()命令(除非dup2(inFD ...)和dup2(outFD ...)在标记适当时)。 也没有打印错误。

我打印出我的(char)newargv []和我的(int)pipeArray [],它们包含正确的值。 这似乎只是dup2问题,我完全不知道它有什么问题。

我创建了一个名为test2的简单文本文件,其中包含ls | 排序| cat someString其中someString只是一些带有文本的文件。 使用pipeHandler()函数中的所有打印语句,我的输出是:

编辑:我修复了一些我有的错别字。 如果((firstChild = fork()0 <0),我忘记在3个ifs上添加一组额外的括号。

我现在有一个无限循环,因为父母正在等待lastChild的pid。 这是输出:

Initializing pipes
numpipes = 2
pipe initializing; i is 0
pipe initializing; i is 2
firstChild pid = 20521
firstChild pid = 20522
doing dup2 fildes[writeDes]
middleChild pid = 20521
middleChild pid = 20523
lastChild pid = 20521
Only the parent should be here
My pid is 20521
lastChild pid = 20524
 <infinite loop>

尽管至于发生了什么事情或者什么可能阻止了孩子,我仍然无能为力。


@MarkPlotnick你是对的! 这不是dup2没有执行或任何东西。 因为我做了dup2(fildes [1],STDOUT_FILENO),所有的打印语句都将被传送。

我修正了提及的错字。 我尝试了我的老师的测试文件<input1 cat |> your.outputc tr az AZ | tr q这应该导致一个名为your.outputc的文件。 它的确如此,内容是用tr的效果输入的。 不过,我在这个文件的顶部也有printf语句。

我认为dup2不工作,因为没有printf语句,不像dup2(inFD,STDIN_FILENO),但这可能是因为它是STDIN。

链接地址: http://www.djcxy.com/p/86037.html

上一篇: dup2() not executing

下一篇: How do I run a program with commandline args using gdb within a bash script?