Is it possible to use fork / exec and guarantee that one starts before the other?

To a large extent, as the name says. I have a piece of code that looks like this:

pid_t = p; p = fork(); if (p == 0) { childfn(); } else if (p > 0) { parentfn(); } else { // error } 

I want either the parent or the child to perform (but not return) their respective functions in front of the other.

Something like calling sleep () will probably work, but is not guaranteed by any standard and will just use the details of the OS scheduler implementation ... is this possible? Will vfork work?

edit: both functions find their way to the system () call, one of which will not be returned until the other is launched. Therefore, for repeated iteration: I need to make sure that either the parent or the child only calls their respective functions (but does not return, because they will not, which is what all mutex-based solutions below offer) before the other. Any ideas? Sorry for the lack of clarity.

edit2: Having one sched_yield process call and sleep, I seem to get pretty reliable results. vfork does provide the semantics I am looking for, but has too many restrictions on what I can do in the child process (I can pretty much call call exec). So, I found some workarounds that are good enough, but there is no real solution. vfork is probably the closest to what I was looking for, but all of the solutions below will work more or less.

+6
source share
5 answers

This problem is usually solved with mutex or semaphore . For instance:

 // Get a page of shared memory int pagesize = getpagesize(); void *mem = mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if(!mem) { perror("mmap"); return 1; } // Put the semaphore at the start of the shared page. The rest of the page // is unused. sem_t *sem = mem; sem_init(sem, 1, 1); pid_t p = fork(); if (p == 0) { sem_wait(sem); childfn(); sem_post(sem); } else if (p > 0) { sem_wait(sem); parentfn(); sem_post(sem); int status; wait(&status); sem_destroy(sem); } else { // error } // Clean up munmap(mem, pagesize); 

You can also use the mutex in the shared memory area, but you need to make sure that you have created with attributes other than the default parameters, with the shared process attribute that is shared (via pthread_mutexattr_setpshared(&mutex, PTHREAD_PROCESS_SHARED) ) to make it work.

This ensures that only one of childfn or parentfn will execute at any given time, but they can execute in any order. If you need to start one of them first, run the semaphore with the number 1 instead of 0, and the function that should be started, first do not wait for the semaphore (but still must be set after completion). You can also use a state variable that has different semantics.

+5
source

Mutex should solve this problem. Lock the mutex before calling fork and execute the first excute function as usual, and the second will try to request the mutex. The first should unlock the mutex when it is done, and the second will wait until it becomes free.

EDIT: Mutex must be in a shared memory segment for two processes

+5
source

The safest way is to use a (named) pipe or socket. One side writes to him, the other reads. The reader cannot read what has not yet been written.

+3
source

Use semphore to ensure that one runs before the other.

+1
source

You can use an atomic variable. Set it to zero before fork / thread / exec, the first process set it before (or better, after) it enters this function, and you will have a second wait (flag == 0).

0
source

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


All Articles