Ok, I searched for this one but couldn't find it. Apologize if it's already been answered before.
Basically I have a program for class that creates two unnamed pipes and uses them to communicate between the parent and child proce开发者_StackOverflowss. The command is passed from the parent to the child, where the child executes it and returns a Success/Error message to the parent. Parent then prints out the Success/Error message. Easy enough, I have that working. Problem is now I need to loop it until the user gives the "exit" command. I think I need a while loop, but after experimenting with placement the program still only runs once and then exits. Here's what I have. Hopefully this makes sense, I left out the processing portion of the code since that part works (like I said, for a class) but if there's anything that doesn't make sense I'll clarify. Thanks in advance for any help.
while (strcmp(cmd,"exit") != 0)
{
/* Create Pipe P to pass command from the
parent process to the child process and check for errors.*/
pipe(p);
/*Create Pipe Q to pass command from the
child process to the parent process and check for errors. */
pipe(q);
/* Create child process */
pid = fork();
switch(pid){
case -1: /* fork failed */
perror("main: fork");
exit(1);
case 0: /* Child process */
/*****************************************
Stuff being executed in the child process
*****************************************/
default: /* Parent process */
printf ("Choose from the following list of commands.\n");
printf ("display\n");
printf ("chars\n");
printf ("lines\n");
printf ("words\n");
printf ("find\n");
printf ("exit\n");
fgets (cmd,10,stdin);
if ((c = strchr(cmd, '\n')) != NULL)
{
*c = '\0';
}
/**********************************
Pipes being opened and closed for
communication between parent and child
**************************************/
break;
}
return 0;
}
}
You need to create the child before you enter the loop.
You also need to be a lot more careful with the plumbing. The main (parent) process must close the ends of the pipes that it won't use, and the child likewise (noting that the child closes the opposite ends from the parent). Of course, if the child is reading standard input and writing on standard output, then you have to arrange for the pipes to be duplicated to the correct descriptors, and then the child closes all the descriptors returned by the pipe()
call.
Try this for size - you'd have to expand be_childish()
to do the real work...
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
static void be_childish(int p[2], int q[2]);
static void be_parental(int p[2], int q[2]);
static void err_exit(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n%d: %s\n", errnum, strerror(errnum));
exit(1);
}
int main(void)
{
int p[2]; /* Pipe to child */
int q[2]; /* Pipe to parent */
pid_t pid;
if (pipe(p) != 0)
err_exit("Failed to create pipe 1");
if (pipe(q) != 0)
err_exit("Failed to create pipe 2");
if ((pid = fork()) < 0)
err_exit("Failed to create child process");
else if (pid == 0)
be_childish(p, q);
else
be_parental(p, q);
return(0);
}
static int prompt(char *buffer, size_t buflen)
{
char *c;
printf("Choose from the following list of commands.\n");
printf("display\n");
printf("chars\n");
printf("lines\n");
printf("words\n");
printf("find\n");
printf("exit\n");
if (fgets(buffer, buflen, stdin) == 0)
return EOF;
if ((c = strchr(buffer, '\n')) != NULL)
*c = '\0';
if (strcmp(buffer, "exit") == 0)
return EOF;
return 0;
}
static void be_parental(int p[2], int q[2])
{
char cmd[10] = "";
if (close(p[0]) != 0 || close(q[1]) != 0)
err_exit("Parent: failed to close pipe");
while (prompt(cmd, sizeof(cmd)) != EOF)
{
char buffer[4096];
ssize_t nbytes;
if (write(p[1], cmd, strlen(cmd)) != (ssize_t)strlen(cmd))
err_exit("Write to child failed");
if ((nbytes = read(q[0], buffer, sizeof(buffer))) < 0)
err_exit("Read from child failed");
if (nbytes == 0)
return;
printf("%s\n", buffer);
}
}
static void be_childish(int p[2], int q[2])
{
char cmd[10] = "";
ssize_t nbytes;
if (close(p[1]) != 0 || close(q[0]) != 0)
err_exit("Child: failed to close pipe");
while ((nbytes = read(p[0], cmd, sizeof(cmd))) > 0)
{
char buffer[4096];
cmd[nbytes] = '\0';
/* Process command */
strcpy(buffer, "Response from child: ");
strcat(buffer, cmd);
if (write(q[1], buffer, strlen(buffer)) != (ssize_t)strlen(buffer))
err_exit("Write to parent failed");
}
}
精彩评论