I'm not sure if I am even barking up the right tree here... but here goes.
I'm trying to pass data from my parent process to all children. It's a simple server program that basically will keep a list of connected clients and then send the routing table of connected clients to every client. This is eventually going to include a struct of information about each client... but for right now I just want to get every forked process to get the same information from the parent.
In the parent process, first I set up my pipes and set them to nonblocking (for when there isn't any new data available in the pipe). After a connection is made with a client the number of entries variable is increased to reflect this new connection. I then fork a child process to a new function and update my array of pipes with the new number of table entries (I have 10 pipes at the moment to see if I needed to keep a separate pipe for each child).
pid_t pid;
int numchildren;
int i, n;
/* Create the pipes. */
for(i = 0; i < 10; i++)
{
if (pipe (mypipe[i]))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
}
for(i = 0; i < 10; i++)
{
for(n=0; n<2; n++)
{
// Get previous flags
int f = fcntl(mypipe[i][n], F_GETFL, 0);
// Set bit for non-blocking flag
f |= O_NONBLOCK;
// Change flags on fd
fcntl(mypipe[i][n], F_SETFL, f);
}
//close(mypipe[i][0]);
}
pid = fork();
if (pid == (pid_t) 0)
{
close (mypipe[numentries-1][1]);
recievecmds(new_fd, mypipe[numentries-1][0]);
close(new_fd);
return EXIT_SUCCESS;
}
else if (pid < (pid_t) 0)
{
fprintf (stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else
{
sprintf (buf,"%d",numentries);
for(i = 0; i < 10; i++)
write(mypipe[i][1], buf, strlen(buf));
memset(&buf, 0, sizeof buf);
}
And then I try to read whats in the pipe in the recievecmds() function:
nbytes = read(mypipe[childindex][0], buf, sizeof(buf));
The first client connected tells me numentries = 1, the second client tells me numentries = 2 and so on. I mean I really don't even see the point for a pipe since it seems that whatever I put in the pipe I could just pass it in the function I called on the fork. Am I going about this the wrong way? It's been very frustrating trying to figure this out. How can I keep all of my child processes updated concurrently from my parent process?
Thank you so much in advance.
edit - My main problem was that I was redeclaring the pipe everytime in an infinite while loop. Very dumb mistake, immediately realized that was probably the root of my problem. However, while now the first child/pipe combo contains the correct data... the second does not. I'll see if I can figure this out on my own, thanks for the advice!
Of course now I'm running into problems because I manually select an option to get the data off the pipe. I'm going to have to think up a way to maybe either get the data for all pipes every time it's updated or make sure to get just the newest data (probably just one char at a time).
Thanks for putting up with me guys! And I apologize about not posting the whole program... but there's quite a bit. I definitely should have mentioned that I have it in an infinite loop.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
enum { NUM_CHILDREN = 10 };
enum { NUM_MESSAGES = 10 };
static int write_pipes[NUM_CHILDREN];
static int n_pipes;
static void be_childish(int *pipe)
{
int i;
char buffer[32];
int nbytes;
int pid = getpid();
close(pipe[1]);
for (i = 0; i < n_pipes; i++)
close(write_pipes[i]);
printf("Child %d\n", pid);
while ((nbytes = read(pipe[0], buffer, sizeof(buffer))) > 0)
{
printf("Child %d: %d %.*s\n", pid, nbytes, nbytes, buffer);
fflush(0);
}
printf("Child %d: finished\n", pid);
exit(0);
}
int main(void)
{
pid_t pid;
int i, j;
/* Create the pipes and the children. */
for (i = 0; i < NUM_CHILDREN; i++)
{
int new_pipe[2];
if (pipe(new_pipe))
{
int errnum = errno;
fprintf(stderr, "Pipe failed (%d: %s)\n", errnum, strerror(errnum));
return EXIT_FAILURE;
}
if ((pid = fork()) < 0)
{
int errnum = errno;
fprintf(stderr, "Fork failed (%d: %s)\n", errnum, strerror(errnum));
return EXIT_FAILURE;
}
else if (pid == 0)
{
be_childish(new_pipe);
}
else
{
close(new_pipe[0]);
write_pipes[n_pipes++] = new_pipe[1];
}
}
for (i = 0; i < NUM_MESSAGES; i++)
{
char message[30];
int len;
snprintf(message, sizeof(message), "Message %d", i);
len = strlen(message);
for (j = 0; j < n_pipes; j++)
{
if (write(write_pipes[j], message, len) != len)
{
/* Inferior error handling; first failure causes termination */
fprintf(stderr, "Write failed (child %d)\n", j);
exit(1);
}
}
sleep(1);
}
printf("Parent complete\n");
return 0;
}
I'd suggest using a shared memory segment. Your parent and child processes can mmap the same file, and read/write state to it. This can be an actual file, or an anonymous memory segment. This is exactly what Apache does with their ScoreBoardFile .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.