} else//parent process { if(!will_wait) { wait(NULL); } will_wait=0; }
}
直接开到子进程里面去,同时父进程看是不是要根据&&来执行等待。引用恐龙书的话,就是:
II. Executing Command in a Child Process
The first task is to modify the main() function in Figure 3.36 so that a child process is forked and executes the command specified by the user. This will require parsing what the user has entered into separate tokens and storing the tokens in an array of character strings (args in Figure 3.36). For example, if the user enters the command ps -ael at the osh> prompt, the values stored in the args array are: args[0] = “ps” args[1] = “-ael” args[2] = NULL This args array will be passed to the execvp() function, which has the following prototype:
execvp(char *command, char *params[])
Here, command represents the command to be performed and params stores the parameters to this command. For this project, the execvp() function should be invoked as execvp(args[0], args). Be sure to check whether the user included & to determine whether or not the parent process is to wait for the child to exit.
This child will also create another child process (which will execute less) and will establish a pipe between itself and the child process it creates. Implementing pipe functionality will also require using the dup2() function .
intmain(void){ char *args[MAX_LINE / 2 + 1]; /* command line (of 80) has max of 40 arguments */ char *history[HIST_SIZE]; for (int i = 0; i < HIST_SIZE; i++)history[i] = NULL;
int should_run = 1;
while (should_run) { will_wait = 0; printf("@_@>"); fflush(stdout); //read the order as a string char *cutorder; cutorder = (char *) malloc(sizeof(char) * MAX_LINE); fgets(cutorder, MAX_LINE, stdin); //处理!!的情况 if (cutorder[0] == '!' && cutorder[1] == '!')//!! { free(cutorder); cutorder = find_history(history); if (cutorder == NULL) { printf("No command in history! What the hell are you doing?\n "); continue; } } else//not !! add_to_hist(cutorder, history); //decode the order decode(cutorder, args); free(cutorder); /** * After reading user input, the steps are: * (1) fork a child process * (2) the child process will invoke execvp() * (3) if command includes &, parent and child will run concurrently */ //dealing with exit if (args[0] && !strcmp(args[0], "exit")) { should_run = 0; continue; } //now we have a complete args for (int i = 0; args[i] != NULL; i++) { if (strcmp(args[i], "&&") == 0 && args[i + 1] == NULL)//with && at the end { will_wait = 1; free(args[i]); args[i] = NULL; } } //dealing with pipes //管道的一般用法是,进程在使用fork函数创建子进程前先创建一个管道,该管道用于在父子进程间通信,然后创建子进程, //之后父进程关闭管道的读端,子进程关闭管道的写端。父进程负责向管道写数据而子进程负责读数据。当然父进程可以关闭管道的写端而子进程关闭管道的读端。 int pipe_pos= get_pipe_pos(args); if(pipe_pos!=-1)//has pipes { pid_t pid; pid=fork(); if(pid==0)//child process_1 { int fd[2];//管道端口 pid_t subpid; //create pipe if(pipe(fd)==-1)//fail to create pipe { fprintf(stderr,"HaHaHa your pipe failed"); return1; } subpid=fork();
if(subpid>0)//that is child process_1 { for(int i=pipe_pos;args[i]!=NULL&&i<MAX_LINE/2+1;i++) { free(args[i]); args[i]=NULL; }//the params after pipe_pos is useless close(fd[0]); dup2(fd[1],STDOUT_FILENO); execvp(args[0],args); } elseif(subpid==0)//child of childprocess1 { int num_param=0; for(int i=pipe_pos;i+1<MAX_LINE/2+1&&args[i+1]!=NULL;i++) { num_param++; strcpy(args[i-pipe_pos],args[i+1]); } for(int i=num_param;i<MAX_LINE/2+1&&args[i]!=NULL;i++) { free(args[i]); args[i]=NULL; } close(fd[1]); dup2(fd[0],STDIN_FILENO); execvp(args[0],args); }
} else//big father process { wait(NULL); } } else { pid_t pid; pid = fork(); if(pid==0)//child process { should_run=0; output_redirect(args); input_redirect(args); execvp(args[0],args);
} else//parent process { if(!will_wait) { wait(NULL); } will_wait=0; }