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!!!!)
}
答案 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”的混合。
希望它有所帮助。