我试图实现一个C shell,允许使用字符'>'
的无限制单向管道所以它可以处理ls -A>尾巴> grep' .zip'
我知道管道应该在进程之间进行通信,但我认为我提出了一个可以使用一个管道和多个子进程的想法。
这是我到目前为止所拥有的
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
/*#include <wait.h>*/
char *args[1000][1000];//array of arguments
int args_count = 0;//count of the arguments in the array
int runCommand(char **arguments, int *fd, int pipeHasSomeData, int baseCase) {
pid_t pid;
int x = 0;
int status;
pid = fork();
if(pid != 0) {
waitpid(pid, &status, 0);
if(baseCase) {
if(WIFEXITED(status))
{
if(WEXITSTATUS(status) == 0)
{
/*it worked*/
} else if(WEXITSTATUS(status) == 255) {
printf("The program %s does not exist \n", arguments[0]);
} else {
printf("ERROR: Error code: %d", WEXITSTATUS(status));
}
}
else
{
printf("There was a problem that is not normal");
}
printf("\n \n");
}
return 1;
} else {
if(pipeHasSomeData == 1) {// read from the pipe
dup2(fd[0], 0);//read from pipe
}
if(baseCase == 0) {// not the base case
dup2(fd[1], 1);//write to pipe
} else {
close(fd[1]);//close write
}
exit(execvp(arguments[0], arguments));
return 0;
}
}
int execute_commands(char *arguments[1000][1000], int pd[2] = NULL) {
int current_count = args_count;
int iterator = 0;
int fd[2];
int useAPipeInCommand = 0;
pipe(fd);
while(iterator <= args_count) {//go through and execute all the commands
if(current_count == 0) {//base case
return runCommand(arguments[iterator], fd, useAPipeInCommand, 1);
} else {
runCommand(arguments[iterator], fd, useAPipeInCommand, 0);
useAPipeInCommand = 1;
}
iterator++;
current_count--;
}//end while
return 1;
}
int main () {
int i = 0;
char text[1024]; /* the input line */
char *tok2;
while (1) { /* repeat until done .... */
fflush(stdin);
fflush(stdout);
printf("Shell -> "); /* display a prompt */
*text = 0;
fgets(text, sizeof text, stdin); /* read in the command line */
fflush(stdout);
printf("\n");
char * tok = strtok(text, " \n\t");
if (strcmp(tok, "exit") == 0) { /* is it an "exit"? */
return 0; /* exit if it is */
}
if (strcmp(tok, " ") == 0) { /* is it an "exit"? */
continue; /* exit if it is */
}
tok2 = tok;
memset(args, 0, sizeof(args[0][0]) * 1000 * 1000);//clear the arguments array
args_count = 0;
int count = 0;
while(tok2 != NULL) {
if(strcmp(tok2, ">") != 0) {
args[args_count][count] = tok2;
count++;
tok2 = strtok(NULL, " \n\t");
} else {//pipe was found, up the argument counter and set count to 0
args[args_count][count] = NULL;
args_count++;
count = 0;
tok2 = strtok(NULL, " \n\t");
}
}
args[args_count][count] = NULL;
execute_commands(args);
}//end while
return 0;
}
运行单个基本情况没问题但是当我做管道时shell冻结了。关于这个问题的任何想法?
答案 0 :(得分:0)
来自@beau-bouchard和@rici的评论的正确答案:
管道有一个(小)有限缓冲区;除非正在读取管道的另一端,否则你不能不加阻塞地写入管道。
要获得正确的实施,请查看“C中的多个管道”Coding multiple pipe in C
- 更新:
以下是我遇到类似问题的最终工作代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <wait.h>
int READ = 0;
int WRITE = 1;
char *args[1000][1000];//array of arguments
int args_count = 0;//count of the arguments in the array
int execute_commands(char *arguments[1000][1000]) {
int pd[2];
int iterator = 0;
int fd[2];
int f_in = 0;
while(iterator <= args_count) {//go through and execute all the commands
pid_t pid;
int status;
pipe(fd);
pid = fork();
if(pid != 0) {
waitpid(pid, &status, 0);//wait for child to exit
close(fd[WRITE]);//close the writing end
if(WIFEXITED(status))
{
if(WEXITSTATUS(status) == 0)
{
/*it worked*/
} else if(WEXITSTATUS(status) == 255) {
printf("The program %s does not exist \n", arguments[iterator][0]);
} else {
printf("ERROR: Error code: %d", WEXITSTATUS(status));
}
}
else
{
printf("There was a problem that is not normal %d", status);
}
f_in = fd[READ];//set the pipe to the in
if(iterator == args_count) {
printf("\n \n");
}
//return 1;
} else {
dup2(f_in, 0);
if(iterator != args_count) {//its not the main value
dup2(fd[WRITE], 1);//write to pipe
}
close(fd[READ]);
exit(execvp(arguments[iterator][0], arguments[iterator]));
return 0;
}
iterator++;
}//end while
return 1;
}
int main () {
int i = 0;
char text[1024]; /* the input line */
char *tok2;
while (1) { /* repeat until done .... */
fflush(stdin);
fflush(stdout);
printf("Shell -> "); /* display a prompt */
*text = 0;
fgets(text, sizeof text, stdin); /* read in the command line */
fflush(stdout);
printf("\n");
char * tok = strtok(text, " \n\t");
if (strcmp(tok, "exit") == 0) { /* is it an "exit"? */
return 0; /* exit if it is */
}
if (strcmp(tok, " ") == 0) { /* is it an "exit"? */
continue; /* exit if it is */
}
tok2 = tok;
memset(args, 0, sizeof(args[0][0]) * 1000 * 1000);//clear the arguments array
args_count = 0;
int count = 0;
while(tok2 != NULL) {
if(strcmp(tok2, ">") != 0) {
args[args_count][count] = tok2;
count++;
tok2 = strtok(NULL, " \n\t");
} else {//pipe was found, up the argument counter and set count to 0
args[args_count][count] = NULL;
args_count++;
count = 0;
tok2 = strtok(NULL, " \n\t");
}
}
args[args_count][count] = NULL;
execute_commands(args);
}//end while
return 0;
}