I know fork process does not share memory, and threads do, but then how can forked processes communicate one another?
Here is example, where one version with thread is commented out (and that version will end), and the other version with fork will never ends. The code is relying on the global variable done
:
#include <stdio.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
bool done = false;
void *foo(void *arg){
sleep(1);
done = true;
return 0;
}
int main(){
//pthread_t t1;
//pthread_create(&t1, NULL, foo, NULL);
//
//printf("waiting...\n");
//while(!done){}
//printf("Ok. Moving on.\n");
printf("waiting...\n");
if(!fork()){
foo(NULL);
} else {
while(!done){}
printf("OK. moving on.\n");
}
}
So if forked processes do not share data (i.e. global variables?) unlike threads, how do they otherwise communicate in unix?
EDIT: this is definitely not a duplicate as I already seen similar topics like Forking vs Threading and other documents about fork/threads in *nix. I just want to know use cases of both. (e.g windows has no fork, only threads, so they probably had different use cases in mind?)
fork()
copies the current process. Without any special preparations, almost no data is exchanged between child and parent. It is just so that the new process is identical to the old one, but as soon as you write a variable, a copy of the written region is created and the child gets a new physical memory location for this data. This means settings a variable in the child will not be visible for the parent and vice versa.
You can use shared memory, pipes, files, sockets, signals, and probably other IPC methods to communicate between child and parent. For your special case you can use the wait()
or waitpid()
function to wait till your child exits. But I assume you want to know how to exchange data.
You can use the mmap()
call to reserve memory that is shared between parent and child.
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
You can pass the flag MAP_SHARED | MAP_ANONYMOUS
to flags
to create a memory region that is shared. There you can place the shared variable and both can access it. Here is an example.
//creates a region of shared memory to store a bool
static bool *reserveSharedMemory(void)
{
void *data = mmap(NULL, sizeof(bool), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if(MAP_FAILED==data)
{
//do some error handling here
return NULL;
}
bool *p=data;
*p=false;
return p;
}
Sockets allow you send and receive data with something else. With socketpair()
you can create 2 socket file descriptors and you can communicate by writing to one of them and reading at the other file descriptor or verse visa. This way communication with the child process becomes almost the same as communicating with a network socket.