fork函数用户创建一个和自身一样的子进程,子进程是父进程的副本,子进程得到与父进程用户级虚拟地址空间相同的(但是独立的)一份拷贝,包括文本、数据和bss段、堆以及用户栈等。子进程还获得与父进程任何打开文件描述符相同的拷贝(比如子进程可以读写父进程中任何打开的文件),他们有完全独立的拷贝(当然linux使用了cow技术,只有改变才会真的拷贝),就是说两边的修改互不影响,父进程和子进程之间最大的区别在于它们有着不同的PID。一次调用两次返回,> 0表示是父进程, == 0表示是子进程。fork产生的问题主要是:
1) 拷贝了父进程的资源,缓冲区等,所以子进程是有状态的,比如我们调用printf的时候会把数据写入缓冲区,子进程也会继承过来,那么在子进程进行打印的时候就可能会打印出本来在父进程写入缓冲区的内容。
2)fork的时候只复制当前线程到子进程,其他线程就没有了,这就会导致很多问题,比较典型的问题就是锁不被释放。
比如我们在父进程中有一段代码 加锁之后进行了fork,而这个解锁工作是在另外一个线程进行的,那么子进程会继承这个锁(处于锁住状态),导致锁不能被释放。
那么一般解决这个问题的方法有几种:
a. 确保父进程是单线程的;
b. fork之后立马调用exec函数,这样会使用完全新的地址空间替换原有的空间。
c. fork_atfork函数原型为 int pthread_atfork(void (*prepare)(void), void (*parent)void(),