C: How to set order of Child processes without using 'sleep'? - c

Let's say there is a card game which the parent is the host and Children are players.
There could be 3~6 players, and Parent needs communicate through Pipe with Children. If there are i children, we could let each child to sleep i*n seconds to set the order, but I don't think this is efficient.
How could let the parent ask something to Child 1, and after Child 1 comes back to the parent, the parent asks something to Child 2.. and so on?
for (i = 1; i <= numChild * 2; i++) { //creating 2n pipes for N children.
pipe(fd[i]);
if (pipe(fd[i]) < 0) {
printf("Pipe creating error\n");
exit(1);
}
}
int childPid[numChild+1];
int pid[6];
for(int i=0;i <numChild; i++){
pid[i] = fork();
if (pid[i] < 0){
printf("Error fork\n");
}
else if (pid[i] > 0){ //Parent Process
wait(NULL);
While(1){
// ** Some Process **
}
else if (pid[i] == 0){ //Child Process
While(1){
usleep(i*1000);
// ** Some Process **
}
exit(0);
}
}

Related

C, Creating multiple process with same parent [duplicate]

can someone help me about how to create multiple child processes which have the same parent in order to do "some" part of particular job?
for example, an external sorting algorithm which is applied with child processes; each child process sorts a part of data and finally the parent merges them..
EDIT: Maybe I should mention the forking multiple child processes with loop..
Here is how to fork 10 children and wait for them to finish:
pid_t pids[10];
int i;
int n = 10;
/* Start children. */
for (i = 0; i < n; ++i) {
if ((pids[i] = fork()) < 0) {
perror("fork");
abort();
} else if (pids[i] == 0) {
DoWorkInChild();
exit(0);
}
}
/* Wait for children to exit. */
int status;
pid_t pid;
while (n > 0) {
pid = wait(&status);
printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status);
--n; // TODO(pts): Remove pid from the pids array.
}
If you want to launch several forks, you should do it recursively. This is because you must call fork from the parent process. Otherwise, if you launch a second fork, you will duplicate both parent and first child process. Here's an example:
void forker(int nprocesses)
{
pid_t pid;
if(nprocesses > 0)
{
if ((pid = fork()) < 0)
{
perror("fork");
}
else if (pid == 0)
{
//Child stuff here
printf("Child %d end\n", nprocesses);
}
else if(pid > 0)
{
//parent
forker(nprocesses - 1);
}
}
}
I think it would be worth pointing out why threads are more appropriate here:
As you are trying to do a "part" of the job in parallel i assume that your program needs to know about the result of the computation. fork()s of a process don't share more then the initial information after fork(). Every change in one process is unknow to the other and you would need to pass the information as a message (e.g. through a pipe, see "man pipe").
Threads in a process share the same adress space and therefor are able to manipulate data and have them visible toeach other "immediatly". Also adding the benefits of being more lightweight, I'd go with pthreads().
After all: You will learn all you need to know about fork() if you use pthreads anyway.
You can do this with fork. A given parent can fork as may times as it wants. However, I agree with AviD pthreads may be more appropriate.
pid_t firstChild, secondChild;
firstChild = fork();
if(firstChild > 0)
{
// In parent
secondChild = fork();
if(secondChild > 0)
{
// In parent
}
else if(secondChild < 0)
{
// Error
}
else
{
// In secondChild
}
}
else if(firstChild < 0 )
{
// Error
}
else
{
// In firstChild
}

Multiple pipes and processes

I am trying to communicate with children processes and make them sort a part of a list. My problem is children processes read everything but do nothing after it.
int main(int argc, char *argv[]){
int i;
int num_children;
pid_t pid;
num_children= 3;
int fd[num_children][2]; //PIPES
for (i=0; i<num_children; i++)
{
if (pipe(fd[i]) == -1)
{
printf("couldnt create the pipe\n");
exit(EXIT_FAILURE);
}
}
for (i=0; i<num_children; i++)
{
pid = fork();
if (pid == -1)
{
printf("couldnt create child process %i\n",i);
exit(EXIT_FAILURE);
}
if (pid == 0)
{ //this is child process
close(fd[i][1]); //closing fd[1] the write end of the pipe
int received;
node *list = NULL;
while ( read(fd[i][0], &received, sizeof(int)) > 0)
{
list = insert(list, received);
printf("Process %i got the number: %i\n",i,received); //this part is working perfect
}
printf("Im process %i here is my list: \n",i); //i couldnt get any output from here
printList(list);
close(fd[i][0]);
exit(EXIT_SUCCESS);
}
}
for (i=0; i<num_children; i++) //closing the read end of pipe for parent
{
close(fd[i][0]);
}
int number;
int mod;
FILE *fileIn = fopen ("<file directory>","r");
while(fscanf(fileIn, "%i", &number)>=0)
{
mod = number % num_children;
write(fd[mod][1], &number, sizeof(int));
}
for (int i=0; i<num_children; i++)
{
if(close(fd[i][1])==0)
{
printf("cant close the pipe");
//tried to catch errors, but pipes are closing with no problem i think
}
}
return 0;
I tried to see if children process wait in the while(read) loop, but when i close the write end of pipes from the parent process they should leave the loop.
You're probably thinking that some specific pipe[2] is shared by the parent and it's respective child process. That's true ... However it is also shared by all the other children processes you create along the way - and because it's opened, those other children processes also inherit it as opened.
Doing this at the beginning of your child pid check worked for me:
if (pid == 0) {
int j;
for (j = 0; j < num_children; j++) {
if (j != i) {
close(fd[j][0]);
close(fd[j][1]);
}
}
...
}
I suspect that the reading from the pipe via:
while ( read(fd[i][0], &received, sizeof(int)) > 0)
is being blocked/haulted until data is available on the pipe. If so, this would explain the lack of response from your code after this point.

C pipe sends not all of the numbers

So I have this program where the initial process sends numbers to the child, then the child performs certain operations with numbers and sends them to the next child...
My problem is that where the program has to send the numbers starting from two (2), the first number the child gets is 3. What could the problem be?
Here is my code:
void start(int num_of_nums){
if (num_of_nums <= 0) return;
int pipefd[2];
pid_t cpid;
int pipe_res = pipe(pipefd);
if (pipe_res == -1) {
printf("pipe error in start\n");
perror("pipe error");
exit(EXIT_FAILURE);
}
//create a new process
cpid = fork();
if (cpid == -1) {
printf("fork error in start\n");
perror("fork error");
exit(EXIT_FAILURE);
}
if (cpid == 0) { // child
printf("child in start\n");
close(pipefd[1]); // close write end
int num_from_parent = pipefd[0]; //where the number is read
printf("num from parent is %d\n", num_from_parent); //prints out 3...
filter(num_from_parent);
} else { // parent
printf("parent in start\n");
close(pipefd[0]); // close read end
for (int i = 2; i <= num_of_nums + 1; i++){
write(pipefd[1], &i, sizeof(int)); //WHERE THE NUMBERS ARE SENT
}
close(pipefd[1]);
}
}
Help would be much appreciated...

Function to create n child processes

int proc_create(int n)
{
int pid;
n = n+1;
printf("The parent process id: %d\n", getpid());
while(1)
{
if(pid=fork() < 0){
perror("Fork Failed!");
exit(1);
}else{
printf("The child process ID is: %d\n", pid);
}
}
}
I have written the above function that will create n child processes and each child processes will print out it's own child id. Can someone tell me the flaws and how i can improve the above function.
n is a local variable, so you just do n + 1 which doesn't change anything.
It creates infinite child processes, because the fork is inside a while(1) loop
int *proc_create(int n) {
int *childs = malloc(sizeof *childs * n);
printf("The parent process id: %d\n", getpid());
for (int i = 0; i < n; i++) {
int pid = fork();
if (pid < 0) {
perror("Fork Failed!");
exit(1);
} else if (pid == 0) {
return NULL;
} else {
childs[i] = pid;
printf("The child process ID is: %d\n", pid);
}
}
return childs;
}
This process spawn N children, when they return from proc_create() they will return NULL. The parent will return an array with the pids of its N children.

Multiple child process

can someone help me about how to create multiple child processes which have the same parent in order to do "some" part of particular job?
for example, an external sorting algorithm which is applied with child processes; each child process sorts a part of data and finally the parent merges them..
EDIT: Maybe I should mention the forking multiple child processes with loop..
Here is how to fork 10 children and wait for them to finish:
pid_t pids[10];
int i;
int n = 10;
/* Start children. */
for (i = 0; i < n; ++i) {
if ((pids[i] = fork()) < 0) {
perror("fork");
abort();
} else if (pids[i] == 0) {
DoWorkInChild();
exit(0);
}
}
/* Wait for children to exit. */
int status;
pid_t pid;
while (n > 0) {
pid = wait(&status);
printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status);
--n; // TODO(pts): Remove pid from the pids array.
}
If you want to launch several forks, you should do it recursively. This is because you must call fork from the parent process. Otherwise, if you launch a second fork, you will duplicate both parent and first child process. Here's an example:
void forker(int nprocesses)
{
pid_t pid;
if(nprocesses > 0)
{
if ((pid = fork()) < 0)
{
perror("fork");
}
else if (pid == 0)
{
//Child stuff here
printf("Child %d end\n", nprocesses);
}
else if(pid > 0)
{
//parent
forker(nprocesses - 1);
}
}
}
I think it would be worth pointing out why threads are more appropriate here:
As you are trying to do a "part" of the job in parallel i assume that your program needs to know about the result of the computation. fork()s of a process don't share more then the initial information after fork(). Every change in one process is unknow to the other and you would need to pass the information as a message (e.g. through a pipe, see "man pipe").
Threads in a process share the same adress space and therefor are able to manipulate data and have them visible toeach other "immediatly". Also adding the benefits of being more lightweight, I'd go with pthreads().
After all: You will learn all you need to know about fork() if you use pthreads anyway.
You can do this with fork. A given parent can fork as may times as it wants. However, I agree with AviD pthreads may be more appropriate.
pid_t firstChild, secondChild;
firstChild = fork();
if(firstChild > 0)
{
// In parent
secondChild = fork();
if(secondChild > 0)
{
// In parent
}
else if(secondChild < 0)
{
// Error
}
else
{
// In secondChild
}
}
else if(firstChild < 0 )
{
// Error
}
else
{
// In firstChild
}

Resources