1

A child process runs a bin file, which is provided by Qualcomm. The child process is invoked by my parent process, which is developed by me.

When the child process is running, it always prints lots pieces of logs in shell command.

So, am I able to redirect Qualcomm's outstream from stdout to another file in the parent process?

As you know, it's nearly impossible to push Qualcomm to update this bin file.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Perlman Soong
  • 111
  • 1
  • 9

3 Answers3

4

The key piece here is the POSIX function dup2, which lets you essentially replace one file descriptor with another. And if you use fork (not system), you actually have control of what happens in the child process between the fork and the exec* that loads the other executable.

#include <cstdlib>
extern "C" {
#include <fcntl.h>
#include <unistd.h>
}
#include <stdexcept>
#include <iostream>

pid_t start_child(const char* program, const char* output_filename)
{
    pid_t pid = fork();
    if (pid < 0) {
        // fork failed!
        std::perror("fork");
        throw std::runtime_error("fork failed");
    } else if (pid == 0) {
        // This code runs in the child process.
        int output_fd = open(output_filename, O_WRONLY | O_CREAT | O_TRUNC);
        if (output_fd < 0) {
            std::cerr << "Failed to open log file " << output_filename << ":"
                      << std::endl;
            std::perror("open");
            std::exit(1);
        }
        // Replace the child's stdout and stderr handles with the log file handle:
        if (dup2(output_fd, STDOUT_FILENO) < 0) {
            std::perror("dup2 (stdout)");
            std::exit(1);
        }
        if (dup2(output_fd, STDERR_FILENO) < 0) {
            std::perror("dup2 (stderr)");
            std::exit(1);
        }
        if (execl(program, program, (char*)nullptr) < 0) {
            // These messages will actually go into the file.
            std::cerr << "Failed to exec program " << program << ":"
                      << std::endl;
            std::perror("execl");
            std::exit(1);
        }
    }
    return pid;
}
aschepler
  • 70,891
  • 9
  • 107
  • 161
2

It is possible, for POSIX, because the POSIX shells do this. Executing a program has two steps, for POSIX. First use fork to clone the parent process to create the child process. Then have the child process use one of the exec family of system calls to execute the chosen program instead of the program of the parent. In between those two steps the code executing for the child process can do additional operations, which will affect the environment of the program to be executed. In particular, the code could open a file descriptor to the file to be redirected to, close the stdout file descriptor, then duplicate the file's file descriptor to the value (1) used for stdout.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
0

You could create own pipes and attach them to the child process.

  1. Create 3 pipes. they are going to replace stdin, stdout, stderr of the child.
  2. fork()
  3. In subprocess close() the parent end of the pipes. Close stdin,stdout and stderr.
  4. The parent process close() the child end of the pipes.
  5. dup2() the pipe ends in the child process that are intended to work as the new stdin,out,err
  6. exec() the child.

Now you got all Output from the child to the pipe in the parent. Ofcourse you need to read from the pipes that come from the child or it will block on any write to the stdout/stderr. For this you could use a select(), poll(), epoll() multiplexing algorithm.

See

https://linux.die.net/man/2/pipe

https://linux.die.net/man/2/dup2

https://linux.die.net/man/2/execve

https://linux.die.net/man/2/fork

schorsch_76
  • 794
  • 5
  • 19