我想制作一个可以使用管道的shell。当我使用此代码在我的shell中运行管道时,即使所有内容都在WHILE(1)循环中,我的shell也会终止。为什么?使用dup
函数是否有问题?
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void)
{
int pfds[2];
pipe(pfds);
char *ar1;
const char sp = ' ';
int temp, temp1, temp2, acc;
int i, j;
int t = 0;
char *line=(char *) malloc(1024*sizeof(char));
char *frsarg=(char *) malloc(1024*sizeof(char));
char *firstcmd=(char *) malloc(1024*sizeof(char));
char *seccmd=(char *) malloc(1024*sizeof(char));
char *scmd=(char *) malloc(1024*sizeof(char));
char *secondcmd=(char *) malloc(1024*sizeof(char));
char *secarg=(char *) malloc(1024*sizeof(char));
char *frscmd=(char *) malloc(1024*sizeof(char));
char *cmd1=(char *) malloc(1024*sizeof(char));
char *cmd=(char *) malloc(1024*sizeof(char));
char *cmdf=(char *) malloc(1024*sizeof(char));
char *arg1=(char *) malloc(1024*sizeof(char));
char *allarg=(char *) malloc(1024*sizeof(char));
char *arg2=(char *) malloc(1024*sizeof(char));
char *arg3=(char *) malloc(1024*sizeof(char));
while (1) {
/* Ektypwse to command prompt */
printf("$ ");
fflush(stdout);
fgets(line, 1024, stdin); //Reads the command.
for(i=0;i<1024;i++){
if(line[i]=='\n') //Deletes the "Enter" from the end of the string.
{
line[i]='\0'; //Replace "Enter" with \0.
}
if(line[i] == 'e' && line[i+1] == 'x' && line[i+2] == 'i' && line[i+3] == 't' ) {
exit(1);
}
}
seccmd = strchr(line, '|');
acc = 0;
for(i=0;i<1024;i++){
if(line[i]=='|'){
acc = i;
t=t+1;
} //Finds the second space.
}
/*FIRST COMMAND AND ARGUMENT*/
if(acc != 0 ){
//printf("OKIF\n");
for(j=0;j<acc;j++){
//printf("OKFOR\n");
frscmd[j]= line[j];
}
//printf("FIRST COMMAND %s\n", frscmd);
}
/*FIRST ARG*/
frsarg = strchr(frscmd, sp);
if(frsarg != NULL){
while(isspace(*frsarg)) ++frsarg;
}
for (i=0;i<1024;i++){
if (frsarg[i] == ' '){
frsarg[i] = '\0';
}
}
/*FIRST COMMAND*/
acc = 0;
for(i=0;i<1024;i++){
if(frscmd[i]==' '){
acc = i;
break;
}
}
if(acc != 0 ){
//printf("OKIF\n");
for(j=0;j<acc;j++){
//printf("OKFOR\n");
firstcmd[j]= frscmd[j];
}
}
if(firstcmd != NULL){
while(isspace(*firstcmd)) ++firstcmd;
}
printf("FIRST COMMAND TEST %s TEST\n", firstcmd);
printf("FIRST ARGUMENT TEST %s TEST\n", frsarg);
// firstcmd == "ls" ,frsarg == "-l"
/*SECOND COMMAND AND ARGUMENTS */
//seccmd = " | ws -l
//SECOND COMMAND WITHOUT "|" secondcmd = _wc_-l
secondcmd = strchr(seccmd, sp);
if(secondcmd != NULL){
while(isspace(*secondcmd)) ++secondcmd;
}
//SECCOND COMMAND scmd
acc = 0;
for(i=0;i<1024;i++){
if(secondcmd[i]==' '){
acc = i+1;
}
}
if(acc != 0 ){
for(j=0;j<acc;j++){
scmd[j]= secondcmd[j];
}
}
for (i=0;i<1024;i++){
if (scmd[i] == ' '){
scmd[i] = '\0';
}
}
printf("SECOND COMMAND TEST %s TEST\n", scmd);
//SECOND ARGUMENT secarg
secarg = strchr(secondcmd, sp);
if(secarg != NULL){
while(isspace(*secarg)) ++secarg;
}
printf("SECOND ARGUMENT TEST %s TEST\n", secarg);
//FIRST COMMAND = firstcmd____FIRST ARGUMENT = frsarg_____SECOND COMMAND = scmd_____SECOND ARGUMENT = secarg
if (!fork()) {
close(1); /* close normal stdout */
dup(pfds[1]); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
execlp(firstcmd, firstcmd, frsarg,(char*) NULL);
} else {
close(0); /* close normal stdin */
dup(pfds[0]); /* make stdin same as pfds[0] */
close(pfds[1]); /* we don't need this */
execlp(scmd, scmd, secarg,(char*) NULL);
}
return 0;
}
}
答案 0 :(得分:1)
嗯,这是一段非常漫长而复杂的代码,逻辑似乎如此 而 ad hoc 。剖析整体将花费我太长时间 的事情。
我确实观察到你fork()
只有一次,然后每个分支都会调用
execlp()
运行管道中的两个进程之一。离开了
没有进程继续运行shell。所以你真的需要fork()
两次。
让我们说原始流程是A
。第一次打电话给
fork()
我们有原始流程A
和子A1
。 A
然后打电话
wait()
暂停,直到A1
终止。 A1
再次致电fork()
运行流水线命令。
或类似的东西。看着我的代码库,我看到了最后一次 试验这些东西是在2000年,而我并没有做两件事 子过程就像你一样。但这应该是正确的一步 无论如何,方向。