课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
Java编程开发语言是目前大多数人在转行互联网软件开发行业的时候都会去学习的一种编程开发语言,而本文我们就简单来了解一下,软件开发父子进程关系分析。
使用fork函数得到的子进程是父进程的一个复制品,每个进程都有自己的进程控制块PCB,再这个PCB中子进程从父进程中继承了整个进程的地址空间:包括进程上下文,进程堆栈,打开的文件描述符,信息控制设定,进程优先级,进程组号等等,但是进程的地址空间都是虚拟空间,子进程PCB继承的都是虚拟地址。
写时拷贝
通常情况下,父子进程共享一份代码,并且数据都是共享的,当任意一方试图写入更改数据的时候,那么这一份便要以写时拷贝的方式各自私有一份副本。
发生写时拷贝后,修改方将改变页表中对该份数据的映射关系,父子进程各自私有那一份数据,且权限由只读变成了只写,虚拟地址没有改变,改变的是物理内存页的物理地址。(涉及到虚拟地址,可以看我上面发的文章)
问题思考:
1.为什么代码要共享?
代码是不可以被修改的,所以各自私有很浪费空间,大多数情况下是共享的,但要注意的是,代码在特殊情况下也是会发生写时拷贝的,也就是进程的程序替换(后面会单独介绍)。
2.写实拷贝的作用?
可以减少空间的浪费,在双方都不对数据或代码进行修改的情况下,各自私有一根数据和代码是浪费空间的。
维护进程之间的独立性,虽然父子进程共享一份数据,但是父子中有一方对数据进行修改,那么久拷贝该份数据到给修改方,改变修改方中页表对这份数据的映射关系,然后对数据进行修改,这样不管哪一方对数据进行修改都不会影响另一方,这样就做到了独立性。
3.写时拷贝是对所有数据进行拷贝吗?
答案是否定的。如果没有修改的数据进行拷贝,那么这样还是会造成空间浪费的,没有被修改的数据还是可以共享的,我们只需要将修改的那份数据进行写时拷贝即可。
总结:
父子进程由独立的数据段、堆、栈、共享代码段(每个进程都有属于自己的PCB)。
Linux中每个进程都有4G的虚拟地址空间(独立的3G用户空间和共享的1G内核空间),fork创建的子进程也不例外。
(1)1G内核空间既然是所有进程共享,因此fork创建的子进程自然也将有用;
(2)3G的用户空间是从父进程而来。
fork创建子进程时继承了父进程的数据段、代码段、栈、堆,值得注意的是父进程继承来的是虚拟地址空间,进程上下文,打开的文件描述符,信息控制设定,进程优先级,进程组号,同时也复制了页表(没有复制物理块)。因此,此时父子进程拥有相同的虚拟地址,映射的物理内存也是一致的。(独立的虚拟地址空间,共享父进程的物理内存)。
由于父进程和子进程共享物理页面,内核将其标记为“只读”,父子双方均无法对其修改。无论父子进程尝试对共享的页面执行写操作,就产生一个错误,这时内核就把这个页复制到一个新的页面给这个进程,并把原来的只读页面标志为可写,留给另外一个进程使用----写时复制技术。
内核在子进程分配物理内存的时候,并没有将代码段对应的数据另外复制一份给子进程,终父子进程映射的时同一块物理内存。
【免责声明】本文系本网编辑部分转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与管理员联系,我们会予以更改或删除相关文章,以保证您的权益!更多内容请加danei0707学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。