Parallel processing and synchronization using semaphores in C [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Questions:
Are my processes running in parallel?
I want six processes running in parallel.
How can I sync these processes (parent with five child processes) using semaphores, in an infinite loop? So the output would be: 1 2 3 4 5 reset 1 2 3 4 5 reset etc...
Any simple and understanding semaphore documentation?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
parentWithFiveChildren()
{
printf("1 "); //Parent
fflush(stdout);
int i, status;
for (i = 2; i < 7; i++)
{
sleep(1);
if (fork() == 0) //Child Processes
{
if (i == 6)
{
printf("reset ");
fflush(stdout);
exit(0);
}
printf("%d ", i);
fflush(stdout);
sleep(7);
exit(i); //Exiting child processes
}
}
while ((wait(&status)) > 0)
printf("\a");
return 0;
}
int main(void)
{
parentWithFiveChildren();
}
Output:
1 2 3 4 5 reset

1. Parallelism
No, the processes are not running in parallel (or, at least, they're only running in parallel transiently, and only two processes at a time), but that's only because:
The sleep(1) gives the parent process a long time (at least a second) doing nothing.
The child finishes and exits during that second.
Your printing code in the child is odd; there is effectively no difference between the i == 6 and the other operations. In main(), return 0; and exit(0); are practically the same — there can be differences, but they're obscure and not germane to your code.
You should #include <sys/wait.h> and you should collect the dead children's PID (and status); it would make things clearer to you.
You could also have the children report sleep for a while (say 7 seconds each). That would give you all the child processes 'running' (actually, sleeping) in parallel, and the parent then waits for the children to exit:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
printf("[PARENT] with pid %d\n", getpid());
fflush(stdout);
for (int i = 2; i < 7; i++) // Odd loop conditions, but not wrong
{
sleep(1);
if (fork() == 0)
{
printf("[CHILD] with pid %d from parent with pid %d\n", getpid(), getppid());
fflush(stdout);
sleep(7);
printf("[CHILD] with pid %d exiting with status %d\n", getpid(), i);
exit(i);
}
}
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("%d: child %d exited with status 0x%.4X\n", getpid(), corpse, status);
return 0;
}
Sample output:
$ ./test-forking
[PARENT] with pid 13904
[CHILD] with pid 13905 from parent with pid 13904
[CHILD] with pid 13906 from parent with pid 13904
[CHILD] with pid 13907 from parent with pid 13904
[CHILD] with pid 13908 from parent with pid 13904
[CHILD] with pid 13909 from parent with pid 13904
[CHILD] with pid 13905 exiting with status 2
13904: child 13905 exited with status 0x0200
[CHILD] with pid 13906 exiting with status 3
13904: child 13906 exited with status 0x0300
[CHILD] with pid 13907 exiting with status 4
13904: child 13907 exited with status 0x0400
[CHILD] with pid 13908 exiting with status 5
13904: child 13908 exited with status 0x0500
[CHILD] with pid 13909 exiting with status 6
13904: child 13909 exited with status 0x0600
$
An upgrade to the code would print the time with each line of output too.
2. Killing
Any of the processes (in the set created by the parent) can kill any other process (in the set) that it knows about, using the kill() system call. It really isn't clear whether you want the first child or the last child to kill the parent, or something else. If the first child kills the parent, the first child will be the only child (because of the delays). It also isn't clear why you want to send signals between the processes.
3. Looping
Yes, you could do something — the question is, what are you really after. Simply printing parent and child multiple times doesn't require multiple processes. If you want the parent to say "I'm here", and each child to say "I'm here" periodically, you need to have the children looping and sleeping, and the parent looping and sleeping after all the children have been created. Not hard to do.

question 3). ...Can I put main function in an infinite loop...?
Sure you can:
int main(void)
{
int c=0;
while((c != 'q') && (c != EOF))//loops until c == q (and c!=EOF)
{
c = getchar();//waits until stdin sees a "q", (i.e. from keyboard)
//An EOF (-1) or `q` will exit the loop
//any other input will allow execution flow to continue, 1 loop at a time.
//Add additional forking code here.
//for each loop, spawn a new thread.
//All secondary threads spawned will run parallel to other threads.
}
//exiting here will kill all threads (secondary and primary.)
return 0;
}

1) Yes, your parent process and child are running in parallel after fork,
You can see this by infinite looping child process and printing it's name while parent and other processes are doing the same.
2) Yes, here's how:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/types.h>
#include <signal.h>
int main()
{
pid_t pid;
int i = 0;
if ((pid = fork()) == 0)
{
if ((pid = getppid()) == -1)
{
fprintf(stderr, "child error: getppid()\n");
exit(1);
}
if (kill(pid, 9) == -1)
{
fprintf(stderr, "child error: kill()\n");
exit(1);
}
while (true)
{
printf ("child %d\n", ++i);
}
}
else if (pid == -1)
{
fprintf(stderr, "error: fork()\n");
return 1;
}
while (true)
{
printf("parent %d\n", ++i);
}
return 0;
}
3) If you need that specific pattern, you need interprocess communication and synchronization. Suggest this

Related

Fork wait and pipe in C

I have this assignment where we are supposed to create a specific amount of child processes, lets say 3, and make the parent wait for each child to finish. Also we're supposed to have a pipe that all processes write to so that once the parent is done waiting, it would use the pipe's to output the sum of all the children's results.
This is my code so far but it seems that wait(NULL) isn't working as expected. I am not sure what I'm doing wrong.
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
for (int i=0; i<3; i++) {
pid_t child = fork();
if (child > 0) {
printf("Child %d created\n", child);
wait(NULL);
printf("Child %d terminated\n", child);
}
}
printf("Parent terminated\n");
return 0;
}
First of all, it's better to first run all child processes and then wait for all of them, instead of waiting for each one sequentially.
In addition, the child processes should exit immediately and not keep running the forked code.
Thirdly, you must pay attention and wait for all children after the loop, and not only for the first one that terminates:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
for (int i=0; i<3; i++) {
pid_t child = fork();
if (child > 0) {
printf("Child %d created\n", child);
}
else if (child == 0) {
printf("In child %d. Bye bye\n", i);
return 0; // exit the child process
}
}
while (wait(NULL) > 0); // wait for all child processes
printf("Parent terminated\n");
return 0;
}
EDIT:
The code above is just an improvement to the example given in the question. In order to implement the pipe of information from the child processes to the parent, a pipe can be created (using pipe()) and the write-end file descriptor would be accessible from child processes.
Here's a good example to do so.

How to kill all child processes after parent process termination?

I can kill a child process by the parent process. But what happen if a parent process has more than one child processes?
For example in below code , there are one parent process and 6 child processes. How to kill the other six child processes immediately after the parent process termination?
If you run this code, parent is terminated after 5 seconds.After that child process are terminated after another 5 seconds(totally 10 seconds).
But I want to kill 6 child processes immediately after the parent process termination.So parent and 6 child process should be terminated after 5 seconds.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if(fork() == 0)
{
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(10); //child waits 10 seconds,then it exitted.
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(5); //parent will wait 5 seconds than it will exit
printf("Parent terminated\n");
exit(0); //parent terminated.(how can I exit the the other 6 child processes too?)
}
Here's a probably more portable solution.
The fork(2) system call will return the PID of your child processes, you can store the PIDs, and then you can use kill(2) to send signal to the children and terminates them.
Notice that SIGKILL and SIGTERM signal may require some privileges of the parent process. If it doesn't have such privileges, you can send a SIGCONT to the child process, and modify the SIGCONT signal handler in your child process.
!!! Warning sign
From a signal handler using exit() is not safe. I've just checked the manual man 7 signal and found that it is not async safe. You can use _exit, _Exit or abort
Some pseudo code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void* handler(int sig){
_exit(0);
}
int main()
{
pid_t children[6];
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if((children[i] = fork()) == 0)
{
signal(SIGCONT,handler);
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(10); //child waits 10 seconds,then it exitted.
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(5); //parent will wait 5 seconds than it will exit
for(int i=0;i<6;i++)
kill(children[I],SIGCONT);
printf("Parent terminated\n");
exit(0); //parent terminated.(how can I exit the the other 6 child processes too?)
}
On Linux, you can use prctl to request to be informed about the death of your parent by means of a signal (error-checking skipped).
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/prctl.h> //<<<<<<<<
#include <signal.h> //<<<<<<<<
int main()
{
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if(fork() == 0)
{
prctl(PR_SET_PDEATHSIG, SIGTERM); //<<<<<<
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(2);
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(1);
printf("Parent terminated\n");
exit(0);
//<<< Linux auto-sends the deathsignal to all children
}
For a POSIX-compliant solution that doesn't require the parent process to explicitly kill its children when it dies, you can use async-IO pipes.
Async-IO relies on signals being sent on filedescriptor events. In this case you can get notified of a close-event caused by the kernel autoclosing the filedescriptors of a dying process just as long as you make sure the autoclose closes the last reference to the pipe-end file (error-checking skipped):
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main()
{
int pipes[6][2];
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
pipe(pipes[i]); //create a pipe
if(fork() == 0)
{
//get notified on an event on the read-end (we're aiming for the EOF event)
fcntl(pipes[i][0],F_SETOWN,getpid());
ioctl(pipes[i][0], FIOASYNC, &(int){1});
for(int j=0; j<=i; j++) close(pipes[j][1]); //close all write-end ends so the refcount is 1 and the parent has the last ref
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(2);
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(1);
printf("Parent terminated\n");
exit(0);
//<<<this closes all the last write ends of the pipes and so the children will get notified with a signal
//the signal is SIGIO by default, whose default disposition is to kill the process (this can be changed by fcntl(fd,F_SETSIG,TheSignal))
}

creating child process from child [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm not entirely sure when I'm using fork() for child process process
there is child process creating other child process even though child process which is parent for other process (has status 0)?
#include <stdio.h>
int main()
{
printf("new proces");
if (fork() == 0) {
printf("child parent");
if (fork() == 0)
printf("child child");
}
printf("\n");
}
I'm confused because I'm not sure that when child proces invokes fork() it creates new proces or not?
because in this code
#include<stdio.h>
int main(){
printf(" do ");
if(fork()!=0) printf("ma ");
if(fork()==0) printf("to \n");
else printf("\n");
}
i have result like in this code there is child parent process which doesn't have status 0 and I don't know why beacuse it is child process of first parent process
do ma
do ma to
do to
do
not like this
do ma
do do to
to
child process invoking fork doesn't return 0 beause I have two ma not only one and i don't have idea why
Yes. The process creates a child, which then creates another child, becoming it's parent.
You can differentiate child and parent by using fork return number. From fork:
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
You need to check fork() return value. If it returns 0, that means this process is a child. If it returns value greater then 0, then this process is the parent and the returned value is the childs process id.
Take a look at this program. I have added usleep calls to make processes print one after another:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
int main(){
// lets create a family!
pid_t grandpa_pid = getpid();
pid_t child_pid;
if ((child_pid = fork()) == 0){
pid_t parent_pid = getpid();
pid_t child_child_pid;
if ((child_child_pid = fork()) == 0) {
usleep(200);
printf("I am child and I will write third. My pid is %d, %d is my parent and %d is my parents parent, so my grandpa.", getpid(), parent_pid, grandpa_pid);
} else {
usleep(100);
// parent_pid = getpid()
printf("I am parent and I will write second. My pid is %d, %d is my child and %d is my parent.", getpid(), child_child_pid, grandpa_pid);
}
} else {
// grandpa_pid == getpid()
printf("I am grandpa and I will write first. My pid is %d and %d is my child.", getpid(), child_pid);
}
printf("\n");
}
Which produces the following output:
I am grandpa and I will write first. My pid is 5 and 6 is my child.
I am parent and I will write second. My pid is 6, 7 is my child and 5 is my parent.
I am child and I will write third. My pid is 7, 6 is my parent and 5 is my parents parent, so my grandpa.

Calling every child process at once to kill?

I have to write an program which will generate a random amount of processes, and then will kill them one after one, after they all were created.
My problem is that I can't stop the child processes after being created.
Also, I try to call the termination-output to stdout from a child process, but don't really know how to solve it (because pid = 0 is for every child process).
#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
//int status;
srand(time(NULL));
int amount = (rand())%9+1;
pid_t fatherid = getpid();
printf("Hello I am a parent process, my PID is %d and I will now create %d children.\n",fatherid,amount);
pid_t pid = 1;
pid_t pidarr[amount];
for(int i = 0;i<amount;i++){
if(pid != 0){
pid = fork();
pidarr[i] = pid;
if(pid ==0){
printf("Hello I am a child process, my PID is %d and my parent has the PID %d.\n",getpid(),fatherid);
}
sleep(1);
}
}
if(pid != 0){
wait(NULL);
}
for(int i = (amount-1);i >= 0;i--){
if(pidarr[(i-1)] != 0){
printf("Hello I am a child process %d, I will terminate now.\n",getpid());
}
sleep(rand()%4);
if(pid != 0){
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
}
if(pid != 0){
printf("All child processes were terminated. I will terminate myself now.\n");
}
return EXIT_SUCCESS;
}
the following code shows how to handle fork and child processes.
the code compiles cleanly, is tested and works
#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
int main( void )
{
//int status;
srand(time(NULL));
int amount = (rand())%9+1;
pid_t fatherid = getpid();
printf("Hello I am a parent process, my PID is %d and I will now create %d children.\n",fatherid,amount);
pid_t pid;
pid_t pidarr[amount];
for(int i = 0;i<amount;i++)
{
pid = fork();
if( -1 == pid )
{ //then, fork() error
perror( "fork() failed" );
exit(1);
}
// implied else, fork() successful
//pidarr[i] = pid;
if(!pid )
{ // then child process
printf("Hello I am a child process, my PID is %d and my parent has the PID %d.\n",getpid(),fatherid);
exit(0); // exit child process
}
// implied else, parent process
pidarr[i] = pid;
sleep(1);
} // end for
for(int i = (amount-1); i >= 0; i--)
{
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
printf("All child processes were terminated. I will terminate myself now.\n");
return(0);
} // end function: main
I am not sure about other parts of your logic (e.g. the if clause inside the fork loop), but
if(pid != 0){
wait(NULL);
}
looks suspiciously as of the parent process waits for a child to exit so that it doesn't get to the code which would kill the children at all (unless they exit on their own, but then the killing seems pointless).
Some issues in your code:
1) As #Peter Schneider points out,
parent process waits for a child to exit so that it doesn't get to the code which would kill the children
So first of all, you have to get rid of:
if(pid != 0){
wait(NULL);
}
2) The for loop that kills the children has to be executed only by the parent process, so the if clause embraces the for:
if(pid != 0){
for(int i = (amount-1);i >= 0;i--){
kill(pidarr[i],SIGKILL);
printf("Child Process %d was terminated.\n",pidarr[i]);
}
}
3) The child processes have to wait doing something until parent kills them, so append the following else clause to the above if:
else{
while(1){
printf("I am a child process %d. Will sleep for 2 senconds\n",getpid());
sleep(2);
}
}
4) the following code makes no sense, because when children are killed they simply stop working.
if(pidarr[(i-1)] != 0){
printf("Hello I am a child process %d, I will terminate now.\n",getpid());
}
If you want children to do something when the signal from kill() gets to them, you will have to use signals.

Creating a process that is not child of the process that created it

I want to create a process B from process A. However, I don't want B to be the child of A, which will be the case if I simply use fork. How can I achieve that? In other words I want process B to keep on executing even if process A is killed.
You can use the setsid() function.
Alternatively, as you have tagged your question "linux", maybe you want to use daemon() instead of fork() + setsid().
Why do you think that B would not keep executing after A is killed if B is a child of A? That's not true.
But if you still want B to not be a child of A then you can do this by fork()ing twice: once to create a child A½ and once to create B. B is a child of A½ and a grandchild of A. Then have A½ exit immediately. B will be inherited by init and will have no further relationship to A.
If you are concerned about signals like SIGHUP and SIGINT that are generated in response to events like a Control-C keypress that are broadcast to the entire foreground process group, see cnicutar's answer.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
switch(pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
printf(" CHILD: This is the child process!\n");
printf(" CHILD: My PID is %d\n", getpid());
printf(" CHILD: My parent's PID is %d\n", getppid());
/* you can exec another program here if you wish to */
printf(" CHILD: I'm outta here!\n");
break;
default:
printf("PARENT: This is the parent process!\n");
printf("PARENT: My PID is %d\n", getpid());
printf("PARENT: My child's PID is %d\n", pid);
printf("PARENT: I'm not going to wait for my child to exit\n");
signal(SIGCHLD, SIG_IGN);
printf("PARENT: I'm outta here!\n");
}
return 0;
}
If you don't send the signal(), then once after the parents completes the execution (and exits), the child process will be termed as a zombie process. For better understanding, execute the following program.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
/*
Execute this program and do 'ps ax | grep Z' to see that this
is put in a defunct state or zombie state
*/
int main()
{
pid_t child_pid;
child_pid = fork();
if (child_pid > 0) {
sleep(60);
} else {
return 0;
}
return 0;
}
The only way I see is having the child orphan (then adopted by init).
This may be achieved by terminating the father process before the child (but just take care of signal propagation).
Some nice samples may be found here

Resources