Even when I use sleep () in the parent process, my child process is executed last

can someone explain why the parent process always ends completely before the while loop in the child process is started, even if I let the parent sleep.

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char **argv) { int i = 10000, pid = fork(); if (pid == 0) { while(i > 50) { if(i%100==0) { sleep(20); } printf("Child: %d\n", i); i--; } } else { while(i < 15000) { if(i%50==0) { sleep(50); } printf("Parent: %d\n", i); i++; } } exit(EXIT_SUCCESS); } 

The result is as follows:

 Parent: .. Parent: .. Parent: .. 

until the Parent is complete, the same goes for Child.

Maybe the reason is that I'm testing a single core processor? Will the result be changed if I have a multi-core setup? Sleep (50) definitely works - since it is required until the script ends - why does the CPU not switch processes? Are there situations, for example, during a while loop, where the process has "more" or exclusive rights to the processor?

Thanks for the help.:)

+5
source share
1 answer

Are there situations, for example, during a while loop, where the process has "more" or exclusive rights to the processor?

Well, this is not defined, but it would be crazy.

I can not reproduce your problem. Reducing the waiting time to 2 and 5 seconds (so I do not need to wait forever), the child will first unlock, as expected. (Debian 8, Linux 3.16.1-ck1 [BFS Scheduler, custom] on AMD64)

I would say that your planner behaves very strangely and may just be broken. But as they say, it is never recommended to rely on any specific behavior of the scheduler. Always consider this to be broken and insane, damn it - if your code allows a certain sequence of execution, there will be a scheduler enough to select it. (*)

So use synchronization primitives ( semaphores and mutexes , for example, have common versions for use with different processes - you can also just use pipes in some scenarios) when you need to rely on some synchronization.

edit : add two examples to synchronize processes.

First version (ab) using pipe s:

 #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char **argv) { int i = 10000; int parent_done[2]; int child_done[2]; char dummy[1] = { 0 }; int pid; pipe(parent_done); pipe(child_done); /* stdio buffering would lead to intermingled output */ setvbuf(stdout, 0, _IONBF, 0); pid = fork(); if (pid == 0) { close(parent_done[1]); close(child_done[0]); while(i > 50) { if(i%100==0) { if (i < 10000) write(child_done[1], dummy, 1); read(parent_done[0], dummy, 1); } printf("Child: %d\n", i); i--; } } else { close(parent_done[0]); close(child_done[1]); while(i < 15000) { if(i%50==0) { write(parent_done[1], dummy, 1); read(child_done[0], dummy, 1); } printf("Parent: %d\n", i); i++; } } exit(EXIT_SUCCESS); } 

Then the same thing using POSIX semaphores (this is IMHO much cleaner because semaphores are meant to be synchronized):

 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/mman.h> #include <semaphore.h> #include <unistd.h> struct semaphores { sem_t child_done; sem_t parent_done; }; int main(int argc, char **argv) { int i = 10000; int pid; /* map shared memory for the semaphores */ struct semaphores *sems = mmap(0, sizeof(*sems), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); /* initialize both semaphores as "shared" and with an initial count * of 0 */ sem_init(&sems->parent_done, 1, 0); sem_init(&sems->child_done, 1, 0); /* stdio buffering would lead to intermingled output */ setvbuf(stdout, 0, _IONBF, 0); pid = fork(); if (pid == 0) { while(i > 50) { if(i%100==0) { if (i < 10000) sem_post(&sems->child_done); sem_wait(&sems->parent_done); } printf("Child: %d\n", i); i--; } sem_post(&sems->child_done); } else { while(i < 15000) { if(i%50==0) { sem_post(&sems->parent_done); sem_wait(&sems->child_done); } printf("Parent: %d\n", i); i++; } sem_post(&sems->parent_done); } exit(EXIT_SUCCESS); } 

Windows has another API for semaphores, see Semaphore objects on MSDN

(*) edit2 is suitable here: when creating examples, I noticed that stdio buffering prevents sleep. So, maybe even your scheduler behaves badly, but simply implements stdio with very unpredictable behavior when flushing buffers. Of course, these are just wild guesses. What you need to know: all FILE descriptors in C are buffered as part of the stdio library C. These include the predefined descriptors stdin , stdout and stderr . The consequence is that what you see on your output does not necessarily reflect the sequence in which the various threads or processes that are output are created. Unless, of course, you turn off buffering completely, as in my examples.

+3
source

Source: https://habr.com/ru/post/1234875/


All Articles