进程间同步
信号量
fork() vfork() clone()
进程的四要素:
(1)有一段程序供其执行(不一定是一个进程所专有的),就像一场戏必须有自己的剧本。(2)有自己的专用系统堆栈空间(私有财产)(3)有进程控制块(task_struct)(“有身份证,PID”)(4)有独立的存储空间。缺少第四条的称为线程,如果完全没有用户空间称为内核线程,共享用户空间的称为用户线程。
fork、v_fork、clone底层都是do_fork,追踪发现底层使用的是sys_clone
- fork
- 父进程fork之后创建子进程,子进程复制父进程的所有资源,子进程的代码段、数据段、堆栈都是指向父进程的物理空间,但此时仅仅是子进程的虚拟地址空间和父进程指向的物理地址空间建立了映射关系,并没有真正复制
- 由于fork()后会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,处于效率考虑,linux中引入了“写时复制技术-Copy-On-Write”
- 若两个进程一直只是读数据,则子进程一直不会复制,直到任一进程进行写操作
- 父进程和子进程执行顺序没有规定,可以乱序执行
- 读时共享,写时复制
- vfork
- vfork也是创建一个子进程,但是子进程共享父进程的空间。在vfork创建子进程之后,父进程阻塞,直到子进程执行了exec()或者exit()。
- 规定必须子进程先执行
- 严格意义上讲,vfork产生的不叫进程,因为他没有独立的地址空间,和父进程共享同一个
- clone
-
clone是Linux为创建线程设计的(虽然也可以用clone创建进程)。所以可以说clone是fork的升级版本,不仅可以创建进程或者线程,还可以指定创建新的命名空间(namespace)、有选择的继承父进程的内存、甚至可以将创建出来的进程变成父进程的兄弟进程等等。
-
clone函数功能强大,带了众多参数,它提供了一个非常灵活自由的常见进程的方法。因此由他创建的进程要比前面2种方法要复杂。clone可以让你有选择性的继承父进程的资源,你可以选择想vfork一样和父进程共享一个虚存空间,从而使创造的是线程,你也可以不和父进程共享,你甚至可以选择创造出来的进程和父进程不再是父子关系,而是兄弟关系。
-
问题:clone和fork的区别:
(1) clone和fork的调用方式很不相同,clone调用需要传入一个函数,该函数在子进程中执行。(2)clone和fork最大不同在于clone不再复制父进程的栈空间,而是自己创建一个新的。 (void *child_stack,)也就是第二个参数,需要分配栈指针的空间大小,所以它不再是继承或者复制,而是全新的创造。