使用execvp连接stdin吗?

时间:2014-02-25 07:27:07

标签: c linux shell stdin execvp

execvp()是否连接stdin,然后执行?

我不完全理解这个命令

我的一个同学让我看看他的代码(在终端中执行的shell)来计算整个事情, 但我不太明白为什么stdin被改为指向最后一个孩子的输出。我可以做出的唯一意义是execvp必须连接stdin,以便我们可以在前一个输出上运行管道命令。任何见解都会有所帮助,谢谢。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "ourhdr.h"


extern int makeargv(char *, char * , char ***);
void execfunction(int z, char **args);
int main() // starts main function 
{
    char buffer[80];
    char **myargv;          // The array we put the tokens into
    char delim[] = "|\n";       // delimit the array by this value 
    pid_t pid;
    pid_t currentpid = getpid();    // recognize the master parent process
    int tokey;              // number of tokens
    int x;                  // counter
    int fdl[2];             // piping file descriptors 0 for reading
    int fdr[2];             // and 1 for writing

    printf("Prompt: ");         // start output prompt
    while(getpid() == currentpid && strcmp(fgets(buffer, 80, stdin), "exit\n") != 0)
    {
        tokey = makeargv(buffer, "|\n", &myargv);       // tokenize args into commands
        x = tokey;
        char **myargs;                  
        char delim2[] = " \n";
        int subargument;

        subargument = makeargv(myargv[0], delim2, &myargs);

        if (strcmp(myargv[0], "pwd") == 0) // pwd command
        {
            getcwd(buffer,80);
            write(1,buffer,strlen(buffer));
            write(1, "\n",1);
        }
        else if (strcmp(myargs[0], "cd") == 0) // cd command
        {
            chdir(myargs[1]);
        } 
        else
        {
            pid = fork();
        }
        while(pid == 0 && x > 0) // if child 
        {
            x--;
            if(x == 0) // leftmost 
            {
                pipe(fdr);
                fdr[0] = fdl[0];
                fdr[1] = fdl[1];
                close(fdr[0]);

                char * redir;
                redir = strchr(myargv[0], '<');
                if(redir != NULL)
                {
                    int y;
                    y = open(redir + 1,0x1ff);
                    redir = 0;
                }
                fdr[1] = dup2(fdr[1], STDOUT_FILENO);
                execfunction(x,myargv); 
            }
            else if (x == tokey - 1) // rightmost
            {
                pipe(fdl);
                pid = fork();
                if(pid > 0)
                {
                    close(fdl[1]);
                    fdl[0] = dup2(fdl[0], STDIN_FILENO);
                    execfunction(x,myargv);
                }
            }
            else // middle
            {
                pipe(fdr);
                fdr[1] = fdl[1];
                fdr[1] = dup2(fdr[1], STDOUT_FILENO);
                fdr[0] = fdl[0];
                pipe(fdl);
                pid = fork();
                if(pid > 0)
                {
                    close(fdl[1]);
                    fdl[0] = dup2(fdl[0], STDIN_FILENO);
                    execfunction(x, myargv);
                }
            }
        }
        waitpid(pid, NULL, 0);
        if(getpid() == currentpid)
        {
            printf("Prompt: "); // starts prompt output again
        }
    }
}

void execfunction(int z, char **args) // exec method
{
    char **myargs;     
        char delim3[] = " \n";
        int subarguments;
        subarguments = makeargv(args[z], delim3, &myargs); 
    execvp(myargs[0], myargs); // executes here (MAGIC!!!!)

}

1 个答案:

答案 0 :(得分:2)

因此execvp将用新的进程(程序)替换当前正在运行的进程(程序)。

所以让我们运行一个例子,我跳过一些语法来正确使用execvp

计划A

int main(){
    while(1){
        execvp( Program B );
        printf("Hello\n);
    }
}

计划B

int main(){
    while(1)
        printf("Bye\n");
}

因此,如果我们启动程序A,execvp将REPLACE,当前正在运行的程序与程序B.它在一段时间(真实)循环并不重要。程序A一旦到达execvp就不再存在,而PID将是相同的,不会留下程序A的痕迹。 输出将是“再见...”

因此,我们将程序A修改为:

int main(){
    if( fork() == 0 ){
         execvp( Program B);
    } else {
        while(1){
            printf("Hello\n);
        }
    }
}

Fork创建当前正在运行的程序的EXACT克隆,并且START立即运行。它将返回0到CHILD,它将向PARENT返回一个新的PID。如果得到CHILD的PID并将其与fork()返回给PARENT的PID进行比较,您将看到它匹配。

那么,修改后的程序A做了什么? 好吧,程序A创建一个子程序,它在程序B上调用execvp。因此,CHILD将使用程序B替换自身,并在同一时间打印“Bye”,程序A的父程序将跳转到else语句并打印“你好”。

终端输出将是“Hello”和“Bye”的混合。

希望它有所帮助。