C程序重定向标准输出更改输出

时间:2017-02-17 02:48:26

标签: c linux fork file-descriptor

当我将标准输出重定向到文本文件时,我的程序输出不一致。那是./main./main > out.txt有不同的输出。

执行程序可以最好地理解问题。这是我的口头描述(如果你想阅读它)。

我用./main执行的行为是我想要的。重定向输出时,我在程序中使用的计数器似乎被重置,这是不可取的。我添加了一些额外的打印语句,以帮助使其更清晰。

我的目标是:生成五个子进程,每个进程写入一个缓冲区(由管道支持)。然后在主要打印每个子进程的缓冲区。

这是在不重定向输出的情况下发生的事情。当我重定向输出时,我得到一个递归/级联结果。第一个进程的结果是正确的,但每个后续进程都会打印在它之前返回的进程。

我使用了valgrind并且没有发现任何内存泄漏。我注意到有超过三个FD打开了,我认为这可能表明文件描述符泄漏。

  • 输出1:goo.gl/Yz534A - 无重定向
  • 输出2:goo.gl/zfAWQV - 带重定向

SO不允许使用网址缩短程序

没有重定向

单独生成;相当于但不同于Google doc图像。

Fork Instance:  0

Child Process (30869) Terminating...

Exit Status: Normal Value: 0
0 3 buf:    Message left from: 30869

The value of i is:  0

Fork Instance:  1

Child Process (30870) Terminating...

Exit Status: Normal Value: 0
1 5 buf:    Message left from: 30870

The value of i is:  1

Fork Instance:  2

Child Process (30871) Terminating...

Exit Status: Normal Value: 0
2 7 buf:    Message left from: 30871

The value of i is:  2

Fork Instance:  3

Child Process (30872) Terminating...

Exit Status: Normal Value: 0
3 9 buf:    Message left from: 30872

The value of i is:  3

Fork Instance:  4

Child Process (30873) Terminating...

Exit Status: Normal Value: 0
4 11 buf:   Message left from: 30873

The value of i is:  4

Parent Process (30868) Terminating...

使用重定向

单独生成;相当于但不同于Google doc图像。

Fork Instance:  0

Child Process (30791) Terminating...

Fork Instance:  0

Exit Status: Normal Value: 0
0 3 buf:    Message left from: 30791

The value of i is:  0

Fork Instance:  1

Child Process (30792) Terminating...

Fork Instance:  0

Exit Status: Normal Value: 0
0 3 buf:    Message left from: 30791

The value of i is:  0

Fork Instance:  1

Exit Status: Normal Value: 0
1 5 buf:    Message left from: 30792

The value of i is:  1

Fork Instance:  2

Child Process (30793) Terminating...

Fork Instance:  0

Exit Status: Normal Value: 0
0 3 buf:    Message left from: 30791

The value of i is:  0

Fork Instance:  1

Exit Status: Normal Value: 0
1 5 buf:    Message left from: 30792

The value of i is:  1

Fork Instance:  2

Exit Status: Normal Value: 0
2 7 buf:    Message left from: 30793

The value of i is:  2

Fork Instance:  3

Child Process (30794) Terminating...

Fork Instance:  0

Exit Status: Normal Value: 0
0 3 buf:    Message left from: 30791

The value of i is:  0

Fork Instance:  1

Exit Status: Normal Value: 0
1 5 buf:    Message left from: 30792

The value of i is:  1

Fork Instance:  2

Exit Status: Normal Value: 0
2 7 buf:    Message left from: 30793

The value of i is:  2

Fork Instance:  3

Exit Status: Normal Value: 0
3 9 buf:    Message left from: 30794

The value of i is:  3

Fork Instance:  4

Child Process (30795) Terminating...

Fork Instance:  0

Exit Status: Normal Value: 0
0 3 buf:    Message left from: 30791

The value of i is:  0

Fork Instance:  1

Exit Status: Normal Value: 0
1 5 buf:    Message left from: 30792

The value of i is:  1

Fork Instance:  2

Exit Status: Normal Value: 0
2 7 buf:    Message left from: 30793

The value of i is:  2

Fork Instance:  3

Exit Status: Normal Value: 0
3 9 buf:    Message left from: 30794

The value of i is:  3

Fork Instance:  4

Exit Status: Normal Value: 0
4 11 buf:   Message left from: 30795

The value of i is:  4

Parent Process (30789) Terminating...

代码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX_NUM 5

int main ()
{

char buf [100];
memset(buf, 0, sizeof buf);
int ret;
pid_t pid;

int mypipefd [MAX_NUM][2]; 


for (int i = 0; i < MAX_NUM; i++)
{
    ret = pipe(mypipefd[i]);

    if (ret == -1)
    {
    perror("\nPipe Error... Exiting\n");
    exit(1);
    }
}

for (int i = 0; i < MAX_NUM; i++)
{
  printf ("\nFork Instance:\t%d\n", i); //Removing trailing \n changes output
    pid = fork();
    if ( pid == -1)
    {
        perror("\nFork Error... Exiting\n");
        exit(1);
    }

    else if (pid == 0)
    {
        int dupRes = dup2(0, mypipefd[i][0]);
        if (dupRes == -1)
        {
            perror("\nDup2 Error... Exiting\n");
            exit(1);
        }
        close(mypipefd[i][0]); // Redundant?

        pid_t childID = getpid();

        char testString [50];
        sprintf(testString, "%s%ld", "Message left from: ", (long) childID );

    ssize_t writeResult =  write(mypipefd[i][1], testString,    strlen(testString));
    if (writeResult == -1)
      {
    perror("\nWriting Error... Exiting\n");
    exit(1);
      }
        printf("\nChild Process (%ld) Terminating...\n", (long) childID);

        return 0;
    }

    else
    {

 //Credit to:  Paul Griffiths [http://stackoverflow.com/questions/35471521/waitstatus-wexitstatusstatus-always-returns-0]
    int status;
    if ( waitpid( pid, &status, 0 ) != -1 ) 
        {
            if (WIFEXITED(status))
            {
                int retval = WEXITSTATUS(status);
                printf("\nExit Status: Normal\tValue: %d",retval);
            }

            else if (WIFSIGNALED(status))
            {
                int retSig = WTERMSIG(status);
                printf("\nExit Status:\tSignal Exit\tValue:\t%d",retSig);
            }

            else if (WIFSTOPPED(status))
            {
                int retSig = WSTOPSIG(status);
                printf("\nExit Status:\tStop\tValue:\t%d",retSig);
            }

            else
            {
                perror("\nExit Status:WAIT PID UNKNOWN INSTANCE... Terminating\n");
                exit(1);
            }
        }

        close(mypipefd[i][1]); 
        ssize_t readResult = read(mypipefd[i][0], buf, 100);
        if (readResult == -1)
        {
        perror("\nRead Error... Exiting\n");
        exit(1);
        }           
        printf("\n%d %d buf:\t%s\n", i, mypipefd[i][0], buf);
        memset(buf, 0, sizeof buf);
        printf("\nThe value of i is:\t%d\n",i);

    }
}


pid_t parentID = getpid();
printf("\nParent Process (%ld) Terminating...\n", (long) parentID);



return 0;
}

0 个答案:

没有答案