2

Please, suggest good alternative for popen() to execute shell commands and then read the output.

EDIT: The alternative must be without fork() call. Because my server is already takes too much memory. Then ffmpeg need also memory and process size is increased! and I get the problems to fork() to memory weight server each time.

PeeHaa
  • 71,436
  • 58
  • 190
  • 262
abrahab
  • 2,430
  • 9
  • 39
  • 64

2 Answers2

5

If you worry about copying the memory of the parent process when forking, then you need to use vfork() - a special version of "fork" that does not copy the memory of a parent process but requires the forked process to immediately issue execve().

  • can you, please, add the example how to use it as alternative for popen() ? my current code of popen is here http://stackoverflow.com/questions/10962044/correct-code-non-blocking-pipe-with-popen . strangely, that popen does not use vfork() by default.... – abrahab Jun 11 '12 at 18:27
  • "The vfork() function also executes the child process first and resumes the parent process when the child terminates. " -- my server and users will wait 10 minutes while `ffmpeg` executed ? :) pitfall – abrahab Jun 11 '12 at 19:53
  • 2
    @abrahab: Please read manual page more carefully. Parent resumes as soon as child calls `execve`. –  Jun 11 '12 at 19:56
  • thanks, got it! its useful and seems will good replace for `system` calls at my width-memory and performance-sensitive server, but still can not understand how to call `vfork` and `execve` to get output from `execve` to parent. – abrahab Jun 11 '12 at 20:25
0

This is how I was taught in school :

int main(int argc, char *argv[]) {

    int pipefd[2];
    pid_t cpid;
    char buf;


    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    cpid = fork();
    if (cpid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (cpid == 0) {
        /* Child reads from pipe */
        close(pipefd[1]);

        //make the standard input to be the read end
        pipefd[0] = dup2(pipefd[0], STDIN_FILENO);

        system("more");

        write(STDOUT_FILENO, "\n", 1);
        close(pipefd[0]);


    } else {

        /* Parent writes argv[1] to pipe */
        close(pipefd[0]);
        /* Close unused read end */

        pipefd[1] = dup2(pipefd[1], STDOUT_FILENO);

        system("ps aux");
        /* Wait for child */
        wait(NULL);
        exit(EXIT_SUCCESS);
    }

    return 0;
}

this spawns two processes, one executing "ps aux" and feeding the output to the other one running "more".

Clément
  • 314
  • 1
  • 3
  • 1
    In that case you're stuck because `popen` just wraps up the usual `fork`/`exec` idiom. – dmckee --- ex-moderator kitten Jun 11 '12 at 17:55
  • @dmckee bingo! maybe-maybe! because its give 2-3 call to popen following one-by-one and usually server is 200-300 mbs. ok. how to solve this? What should I use that exec without fork() ? yes, seems I must found alternative for popen() – abrahab Jun 11 '12 at 18:01