I have a parent process that forks two children. I need to force a certain order for when these child processes run.
For example, the parent process takes a "command" from a file, and depending on that command, the parent will either pass that command to child a or child b using unnamed pipes. I need stuff to happen in the children in the same order that the parent received the command from the file.
The way I was using semaphores did not work between processes. Any ideas?
Semaphores work just fine between processes. For example:
#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
int main(void)
{
// Error checking omitted for expository purposes
sem_t *sem = sem_open("test_semaphore", O_CREAT|O_EXCL, 0, 1);
sem_unlink("test_semaphore");
int child = fork();
printf("pid %d about to wait\n", getpid());
sem_wait(sem);
printf("pid %d done waiting\n", getpid());
sleep(1);
printf("pid %d done sleeping\n", getpid());
sem_post(sem);
if(child > 0)
{
int status;
printf("parent done, waiting for child\n");
wait(&status);
}
printf("pid %d exiting\n", getpid());
return 0;
}
Output:
$ time ./a.out
pid 61414 about to wait
pid 61414 done waiting
pid 61415 about to wait
pid 61414 done sleeping
parent done, waiting for child
pid 61415 done waiting
pid 61415 done sleeping
pid 61415 exiting
pid 61414 exiting
real 0m2.005s
user 0m0.001s
sys 0m0.003s
If you use IPC semaphores they also work for forks. Look here: http://www.advancedlinuxprogramming.com/alp-folder Chapter 5 will give you the informations you need.
Related
I am trying to understand the re-parenting process in linux. So when the parent process exits abruptly the child process is adopted by the init process. This is re-parenting.
I am not able to understand the below code that shows how re-parenting works.
First the process is forked and the child process runs.
The first "printf" statement is executed.
Then sleep() is called. Why is "terminated" printed after this?
Is the parent process ever called?
Please somebody explain me how does this work?
#include <stdio.h>
#include <unistd.h>
int main() {
if (fork() == 0) {
// child process
printf("My parent's PID is %d\n", getppid());
sleep(2);
printf("My parent's PID is %d\n", getppid());
} else {
// parent process
sleep(1);
}
// both processes
printf("Terminated\n");
}
The output:
My parent's PID is 18892
Terminated
shell $ My parent's PID is 1
Terminated
I want to write a program in which the parent creates exactly 1 child process. The child process should print its pid to the standard output and then finish. The parent process should waits until it is sure that the child has terminated. The parent terminates after it has waited for the child process.
Thats what I got so far:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int child;
child = fork();
if (child == 0)
{
printf("Child process has PID: %d. \n", getpid());
exit(0);
}
// how can the parent process find out it the child process was terminated successful?
printf("Child process terminated successfully\n");
return EXIT_SUCCESS;
}
How can the parent-process find out if the child process was terminated? I can't use wait() or waitpid() in this programm.
Thanks for your help!
When a child process terminates a SIGCHLD signal will be sent to the parent, by default the parent will ignore the SIGCHLD, however you can register a signal handler that will catch it.
You need to be careful what you do in the signal handler - quite a few standard function aren't safe to use.
The SIGCHLD approach turns up in code when the parent has it's own work to do and can't just wait for the child. If the parent just spawns children and then waits for them to finish the wait() and waitpid() are the best solution.
Finally if you don't call wait() or waitpid() you risk creating a zombie process, the child process expects it's parent to receive it's exit status through a call to one of these functions.
As I said in remark use the signal SIGCHLD, for instance :
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void handler(int sig)
{
pid_t chpid = wait(NULL);
/* WARNING : to show the call of the handler, do not do that
in a 'real' code, we are in a handler of a signal */
printf("Child pid %d ended (signal %s)\n", chpid, sig);
/* does 'something' to allow the parent to know chpid
terminated in a way compatible with parent requirement */
}
int main(void)
{
signal(SIGCHLD, handler);
if (!fork())
{
printf("Child pid is %d\n", getpid());
sleep(1);
return 0;
}
printf("Parent pid is %d\n", getpid());
getchar();
return 0;
}
Note when the signal arrive you have to call wait(NULL) but because by definition the child terminated the function returns immediately
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra s.c
pi#raspberrypi:/tmp $ ./a.out
Parent pid is 21743
Child pid is 21744
Child pid 21744 ended (signal 17)
<enter>
pi#raspberrypi:/tmp $
Of course the signal 17 is SIGCHLD because it is the only one the program catches
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
printf("pid : %d\n", getpid());
if( pid == 0)
{
printf("child: pid : %d \n", getpid());
while(1);
}
else
{
printf("parent: pid : %d \n", getpid());
//while(1);
}
}
In the above code snippet inside if statement if we put while(1), it doesn't remains blocked and when enter key is pressed program is exited, but in case of parent if we put while(1), parent remains blocked until we give ctrl+c. Please clarify this behaviour of child.
In the above code snippet inside if statement if we put while(1), it doesn't remains blocked
The child process doesn't exit actually; it just becomes an orphan process because its parent exits. The orphaned chuld process will be adopted by the init process of your system. You can see it via ps command.
But if you put the while(1); in the parent process it remains blocked.
Basically whichever process has while(1); infinite loop, it's still running. When parent exits you get the prompt back and the child becomes orphan. But the child process is still running.
In general, you need to wait(2) for the child process in the parent process to reap child processes.
I know that waitpid() is used to wait for a process to finish, but how would one use it exactly?
Here what I want to do is, create two children and wait for the first child to finish, then kill the second child before exiting.
//Create two children
pid_t child1;
pid_t child2;
child1 = fork();
//wait for child1 to finish, then kill child2
waitpid() ... child1 {
kill(child2) }
Syntax of waitpid():
pid_t waitpid(pid_t pid, int *status, int options);
The value of pid can be:
< -1: Wait for any child process whose process group ID is equal to the absolute value of pid.
-1: Wait for any child process.
0: Wait for any child process whose process group ID is equal to that of the calling process.
> 0: Wait for the child whose process ID is equal to the value of pid.
The value of options is an OR of zero or more of the following constants:
WNOHANG: Return immediately if no child has exited.
WUNTRACED: Also return if a child has stopped. Status for traced children which have stopped is provided even if this option is not specified.
WCONTINUED: Also return if a stopped child has been resumed by delivery of SIGCONT.
For more help, use man waitpid.
The syntax is
pid_t waitpid(pid_t pid, int *statusPtr, int options);
1.where pid is the process of the child it should wait.
2.statusPtr is a pointer to the location where status information for the terminating process is to be stored.
3.specifies optional actions for the waitpid function. Either of the following option flags may be specified, or they can be combined with a bitwise inclusive OR operator:
WNOHANG
WUNTRACED
WCONTINUED
If successful, waitpid returns the process ID of the terminated process whose status was reported. If unsuccessful, a -1 is returned.
benifits over wait
1.Waitpid can used when you have more than one child for the process and you want to wait for particular child to get its execution done before parent resumes
2.waitpid supports job control
3.it supports non blocking of the parent process
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main (){
int pid;
int status;
printf("Parent: %d\n", getpid());
pid = fork();
if (pid == 0){
printf("Child %d\n", getpid());
sleep(2);
exit(EXIT_SUCCESS);
}
//Comment from here to...
//Parent waits process pid (child)
waitpid(pid, &status, 0);
//Option is 0 since I check it later
if (WIFSIGNALED(status)){
printf("Error\n");
}
else if (WEXITSTATUS(status)){
printf("Exited Normally\n");
}
//To Here and see the difference
printf("Parent: %d\n", getpid());
return 0;
}
I'm writing a multi process program in C.
I hope parents process can wait all child processes finish then exit when
it receives SIGINT.
I have two questions.
How can parents record each pid of child process it forked.
Child process may finish before recording function run on
main process.
If parents has no idea about how many child processes it has. How can he wait
all child process finish.
Thanks in advance.
You record the pid of child processes as you fork them (if required).
call waitpid in a loop with pid = 0 it will either return a pid of a process that exited or return -1 and if errno = ECHILD you have no slaves left.
Keep calling wait(2) in a loop. Every time wait() returns, you'll get back the PID of the exited child and its status. The status will tell you, whether it exited normally (with an exit code) or due to a signal. Something like this (not tested):
#include <sys/types.h>
#include <sys/wait.h>
...
pid_t pid;
int status;
...
while ((pid = wait(&status)) > 0) {
printf("Child %lu ", (unsigned long)pid);
if (WIFEXITED(status))
printf("exited with status %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("killed by signal %d\n", WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("stopped by signal %d\n", WSTOPSIG(status));
else if (WIFCONTINUED(status))
printf("resumed\n");
else
warnx("wait(2) returned for no discernible reason");
}