Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am new to C , So i only know simple functions.(ex: wait(NULL) ).
Here is my main question :
Modify the program so that only the parent process creates 3 child processes, and each
new created process calls a function CPU(). In addition, make the parent process wait for
each child’s termination.
I know this one is the correct answer
#include<stdio.h>
int main(void)
{
int i ;
for( i = 0; i < 3; i++)
{
int ret = fork();
if(ret == 0){
printf("My process ID is %d\n", getpid());
return 0;
}
}
for (i = 0; i < 3; i++) //Line B
wait(NULL);
}
but my problems are
why below code is wrong when wait is executed by the parent in the loop
#include <stdio.h>
int main(void)
{
int i ;
for( i = 0; i < 3; i++)
{
int ret = fork();
if(ret == 0) {
printf("My process ID is %d\n", getpid());
return 0;
}
else
wait(NULL);
}
}
in very first code why do we write wait(NULL) inside a for loop?
can't we write it without a for loop
if there is no "return 0" in child process, should the for loop be changed to
for (i = 0; i <7; i++)
wait(NULL);
I don't know how to write the CPU function
This code would not execute the child processes in parallel but execute each one sequentially. The difference does not show until the child processes do something beyond printing one message and exiting (you could add sleep(1)).
wait function will wait for the termination of one child process (whichever finishes first). If you've got 3 child processes, you must call wait successfully at least that 3 times to ensure that each one of them has terminated. Perhaps easier would be to call wait until it sets errno to ECHILD, meaning that there are no children left:
while (1) {
errno = 0;
if (wait(NULL) == -1) {
if (errno != ECHILD) {
perror("Unexpected error from wait");
}
break;
}
}
Each parent process should wait for its own children (or set the SIGCHLD disposition to SIG_IGN). Instead of counting the number of waits, use the code above
This means just: "call a function by the name CPU", i.e.
void CPU(void) {
}
in the child process.
BTW, your code is missing the necessary headers for a couple functions -
#include <sys/types.h>
#include <sys/wait.h>
for wait,
#include <unistd.h>
for fork and additionally #include <errno.h> for my errno addition.
Related
I'm a bit confused with the creation of processes with fork(), sleep() and wait() in c. Take the following piece of code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
void childProcess(void);
void childProcess(void)
{
for(int i = 0; i < 5; i++)
{
printf("pid: %d email: myemail\n", getpid());
sleep(1);
}
}
int main(int argc, char *argv[])
{
for (int i = 0; i < 5; i++)
{
pid_t childpid;
if ((childpid = fork()) == 0)
{
childProcess();
exit(0);
}
}
int status;
while (wait(&status) > 0)
{
}
return 0;
}
After this piece of code has been executed,executes processes but does not remove repetitions from 5 processes. I'm a little confused with the process.
The initial process creates 5 child processes, and waits for them to finish.
Each child process performs 5 repetitions, where in each repetition:
Prints the message
pid: PID email: USER_EMAIL
where PID is the child PID of the process, while USER_EMAIL is the email
Suspends its operation for 1 second (at a time) with the sleep call
The parent process prints the children's PIDs when they are finished
P.S I EDIT THE CODE
#mixalispetros, you have multiple things to fix, and they all have to be fixed together for your code to work as intended.
exit(0);
for (int i = 0; i < 5; i++) {
wait(NULL);
}
The process ends on exit(0). wait is never called.
if (fork() == 0) {
// what code runs here? The code in the new process
}
What code runs within the fork() conditional? The new process's code. Which process should run wait()? The original process. So in addition to being after an exit, the wait() is also in the wrong process.
Where to move it? The for loop wait()s for 5 child processes. Why would there be 5 child processes for which to to wait()? Because we had already started all 5 child processes before we went into our loop of 5 wait()s.
The wait()s must happen not just outside the child process conditional block, but also outside the loop around the call to fork().
I'm a bit confused with the creation of processes with fork(), sleep() and wait() in c
It is confusing. Refer to the documentation often to keep it straight.
Remember, fork() returns twice - in the original process (returning the process ID of the new process), and in the new process (returning 0). wait(), will wait for the next child process to exit.
In summary, put the wait loop outside the loop that fork()s child processes. This will also move it ouside the block of code that executes in the child process.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
// this loop creates 5 processes
for (int i = 0; i < 5; i++) {
if (fork() == 0) {
printf("Child %d, PID %d\n", i, getpid());
sleep(i);
exit(0);
}
}
// now, all subprocesses were started
// wait for the same number of child processes to end
for (int i = 0; i < 5; i++) {
wait(NULL);
}
}
Good afternoon.
I am currently working on a C program that takes one and only one parameter which designates the number of "child generation"s to be created (the own father counts as 1 already). "wait()" system calls are not to be used for this exercise (the version with "wait" calls happens to work exactly as expected).
For instance, the call $program 4 should generate a hierarchy like this:
Process A creates B
Process B creates C
Process C creates D
The printed messages are not important, as they are merely orientative for the task. With the following code (which happens to work exactly how I want with a "wait()" call) states that all the child processes derive from the same father, which I don't understand why it's happening.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int counter; pid_t result; int i;
/*
We are going to create as many processes as indicated in argv[1] taking into account that the main father already counts as 1!
*/
if (argc > 2 || argc == 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
int lim = atoi(argv[1]);
//We eliminate the impossible cases
if (lim < 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
if (lim == 1) {puts("The father himself constitutes a process all by his own, therefore:\n");
printf("Process%d, I'm %d and my father: %d\n", counter, getpid(), getppid());
}
else {
for (i = 0; i < lim; i++) {
result = fork();
if (result < 0) {
printf("Call%d \n", counter); perror("Has failed!");
exit(-1);
}
else if (result) {
break; //Father process
}
else {
counter++; //Child processes increment the counter
printf("Process%d, I am %d and my father: %d\n", counter, getpid(), getppid());
}
}
}
The hierarchy generated by the code above is not the one I expected...
All help is greatly appreciated.
Thank you
With the following code (which happens to work exactly how I want with
a "wait()" call) states that all the child processes derive from the
same father, which I don't understand why it's happening.
I don't see that in my tests, nor do I have any reason to expect that it's actually the case for you. HOWEVER, it might appear to be the case for you if what you see is some or all of the child processes reporting process 1 as their parent. That would happen if their original parent terminates before the child's getppid() call is handled. Processes that are orphaned in that way inherit process 1 as their parent. If the parent wait()s for the child to terminate first then that cannot happen, but if instead the parent terminates very soon after forking the child then that result is entirely plausible.
Here's a variation on your loop that will report the original parent process ID in every case:
pid_t my_pid = getpid();
for (i = 0; i < lim; i++) {
result = fork();
if (result < 0) {
printf("Call%d \n", counter); perror("Has failed!");
exit(-1);
} else if (result) {
break; //Father process
} else {
pid_t ppid = my_pid; // inherited from the parent
my_pid = getpid();
counter++; //Child processes increment the counter
printf("Process%d, I am %d and my father: %d\n", counter, (int) my_pid, (int) ppid);
}
}
You are missing a crucial function call.
for (i = 0; i < lim; i++) {
fflush(stdout); // <============== here
result = fork();
Without it, your fork duplicates parent's stdout buffer into the child process. This is why you are seeing parent process output repeated several times --- its children and grandchildren inherit the output buffer.
Live demo (with fixed formatting for your reading convenience).
I'm trying to figure out how the following program i wrote for a raspberry pi with led matrix works.
The program is supposed to have a child process forked by the main process light up the LED from 0,0 -0,8 in first iteration for num=0. But instead, the LEDs light up randomly in the 0th column.
Example : in 0th column 0,6,4,5,2,3,1
in 1st column 0,6,5,4,2,3,1
and so on till 8th column.
I'm confused as to why the "main" for loop controlling the rows runs randomly ,but the second loop controlling the columns works in an orderly increasing fashion.
What am I missing in the working of fork together with a for loop?
From the output I can only guess that the parent is somehow creating random child processes all at once that are calling function2 with their randomized num argument.
<header files>
function1
{ creates a delay of a second through calculations }
function2(n)
{ for(int i = 0; i<=8 ;i++)
function1;
printf("LED(%d,%d)\n",n,i);
}
main()
{
for(int num = 0; num <=7; num++)
{
pid_t pid = fork();
if (pid ==0)
{ function2(num); }
}
for (int num =0; num <= 7; num++)
{ wait(NULL);}
}
Father and child processes do run concurrently, and it is not predictable which process is running at what time.
From a first inspection you have a loop that starts from the father process and creates 8 child processes, that on their hand each creates other child processes! You should terminate the child process after calling the function2, otherwise the child processes will create other processes.
I think the solution to your problem is something like this:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void function1() {
//0.5 seconds sleep
usleep(500000);
}
void function2(int n) {
for(int i = 0; i <= 8; i++) {
function1();
printf("LED(%d,%d)\n", n, i);
}
}
int main()
{
pid_t pid;
for(int num = 0; num <= 7; num++) {
pid = fork();
if (pid == 0) {
function2(num);
exit(0);
}
}
for (int num = 0; num <= 7; num++){
wait(NULL);
}
return 0;
}
Please for future questions please post a Minimal, Complete, and Verifiable example.
The code could also have a concurrency problem, I don't think the printf is an atomic function, so a semaphore may be necessary to avoid having multiple processes calling the printf.
Another note is that a check should be fork() to check if the child process was successfully generated.
I am trying to develop a simple railroad simulation following the answer to the question Make children process wait until receiving parent's signal.
My task: I have exactly 5 process representing trains. I need to create these 5 process (T1, T2, T3, T4, and T5) via fork(), and pause each one until all of them are created. After that the parent process will send a signal to the children, and each child will use an execl (i.e. execl(execl_path_name, CHILDETCONE, i, NULL);). After signaling, the parent waits for all the children to complete their tasks.
I quite understand the handler function, but I am not clear on these points:
Do I need to insert my execl inside the handler function?
I don't understand the significance of this last loop from the answer to the previous question:
for (int i = 0; i < NUMBER_TRAINS; i++)
{
wait(NULL);
}
This is my code:
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include "accessory.h"
#define NUMBER_TRACKS 16
#define NUMBER_STATIONS 8
#define NUMBER_TRAINS 5
#define TRACKS_INITIALS "MA"
#define STATION_INITIALS "S"
#define SIZE 256
#define CHILDETCONE "childETCone"
void handler(int sig);
int main(int argc , char *argv[]) {
pid_t pid;
pid_t pid_array[NUMBER_TRAINS];
char track_name[2];
char track_number[2];
int execl_return;
char str[2];
char * execl_path_name;
memset(pid_array, 0, sizeof(pid_array));
/* create the MAx file initialized to zero */
for (int i = 1; i < (NUMBER_TRACKS + 1); i++) {
memset(track_name, '\0', sizeof(track_name));
memset(track_number, '\0', sizeof(track_number));
strcpy(track_name, TRACKS_INITIALS);
sprintf(track_number, "%d", i);
strcat(track_name, track_number);
create_track_file(track_name, "", SIZE);
}
execl_path_name = get_file_name(CHILDETCONE, "", SIZE);
printf("path %p\n", execl_path_name);
for(int i = 0; i < NUMBER_TRAINS; i++) {
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { //child
//sprintf(str, "%d", i+1);
//execl_return = execl(execl_path_name, CHILDETCONE, i, NULL);
signal(SIGUSR1, handler);
pause();
exit(0);
}
//parent
pid_array[i] = pid;
}
for (int j = 0; j < NUMBER_TRAINS; j++) {
kill(pid_array[j], SIGUSR1);
sleep(1);
}
for (int i = 0; i < NUMBER_TRAINS; i++) {
wait(NULL);
}
return 0;
}
void handler(int sig) {
printf("printed from child [%d]\n", getpid());
printf("signal [%d]\n", sig);
}
Do I need to insert my execl inside the handler function?
No. pause() will return only after the process in which it is called catches a signal that causes a signal-handling function to run. The execl call can therefore go just after the pause call. I think that would be clearer in your case.
Note, too, that POSIX standardizes a list of "async-signal-safe" functions that are safe for a signal handler to call, and that it is unsafe for a handler to call others. execl is on the list, but printf and other stream I/O functions are not. Signal handlers should not call printf. Your particular signal handler does not need to do anything at all.
Additionally, consider using sigsuspend() in place of pause(), as the former will give you more control over which signals cause your trains to start.
I don't understand the significance of this last loop from the answer
to the previous question:
for (int i = 0; i < NUMBER_TRAINS; i++)
{
wait(NULL);
}
The wait() function instructs the calling process to block until one of its children terminates. The loop makes as many wait() calls as there are children, so that, in the absence of errors, the main program does not proceed until all its children have terminated.
It looks like you may have tried to achieve something similar by calling sleep() in the loop with the kill call, but that strategy is plain wrong. In the first place,
waiting after each kill means that the children's execl calls will be spaced out by at least the sleep time, which is not what I understood you to want. In the second place, you cannot know in advance how long it will take the children to finish, so the one second you allow may not be enough under some circumstances. In the third place, since you seem to expect that the children will run very quickly, one second is probably much more than you need most of the time.
I have an application which creates many processes via fork(). At some point I want to pause them all and wait until all of them finish earlier tasks. Then start them all at once.
for (int i = 0; i < N; i++)
{
if(fork() == 0)
{
//some operations here
<----- wait here for all N forked processes
//some operations I want all processes start at similiar time
I don't want any of children to quit.
This seems tailor-made for a semaphore. Specifically, this is easy to implement with "System V semaphores". See semget(2) and semop(2).
The idea is that you obtain a semaphore in the parent, initialize its value to N, then have each child as it's "ready" decrement the value by 1. All children wait for the result to become 0. Voila.
Here's a sample program
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define N 5
int main(int ac, char **av)
{
int i, n, sem_id;
sem_id = semget(IPC_PRIVATE, 1, 0777);
struct sembuf buf;
buf.sem_num = 0;
buf.sem_flg = 0;
// Initialize semaphore value to N
buf.sem_op = N;
n = semop(sem_id, &buf, 1);
// All children will do the same thing:
// decrement semaphore value by 1
// wait for semaphore value == 0
for (i = 0; i < N; ++i) {
if (fork() == 0) {
printf("Child %d (%d) started\n", i, getpid());
sleep(i + 1); // Sleep awhile.
buf.sem_op = -1;
n = semop(sem_id, &buf, 1);
buf.sem_op = 0;
n = semop(sem_id, &buf, 1);
printf("Child %d (%d) done\n", i, getpid());
return 0;
}
}
return 0;
}
There are many ways to communicate with processes, it is called IPC (Inter Process Communication). It depends on what kind of information you need to send, how large etc. Process signals is also a way to control processes.
Here are a few resources to get you started:
Personally I like Beej Guides, which are awsome, clear, concise and FREE!
http://beej.us/guide/bgipc/
There is also Advanced Linux Programming by CodeSourcery LLC.
http://www.advancedlinuxprogramming.com/
And of course, once you have some notions of the basics, you can look up more specifically http://stackoverflow.com, i.e. right here :-)
What you can use is a synchronization construct like semaphore.
At the point of code where you want to stop all childrens make them wait in queue (call wait on a semaphore with 0 as initial value )of semaphore and thus they all will block.
In parent then you can signal semaphore and thus start them all.
I would highly recommend Message Passing Interface (MPI) for this, since it has MPI_Barrier that you can used to achieve exactly what you want with almost no logic you have to code yourself. There are alternatives such as OpenMP as well.
I've managed to resolve this via group signals:
for (int i = 0; i < N; i++)
{
if(fork() == 0)
{
/* save first process pid in shared memory */
if(localID == 0)
*sh_temp = getpid();
/* wait in all processes for shared memory with group id to be set */
while(*sh_temp == 0)
usleep(10000);
/* set group id to first process PID */
setpgid(getpid(), *sh_temp);
//some operations here
fprintf(stderr, "Process %d paused... W8ing for signal to resume\n", getpid());
raise(SIGSTOP);
//some operations I want all processes start at similiar time
}
}
if(parentPID == getpid())
{
fprintf(stderr, "Wake-up signal sent to group %ld.\n", *sh_temp);
killpg(*sh_temp, SIGCONT);
}
But - if anyone has better solution please post it.