进程的地址空间

时间:2022-08-28 21:56:54

链接:http://www.cnblogs.com/lfsblack/archive/2012/09/08/2676791.html
说明:以下内容来自上面的链接中内容的简捷,人家的写的真不错,一下了解了fork的实现和进程,线程的实质。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
内核管理用户空间进程的内存,是虚拟的内存,不是物理的地址,可以通过页表找到物理内存,它是一个范围,有起始位置,叫内存区域。
(1)什么是虚拟内存:是一种内存管理的技术,,它通常是被分隔成多个 物理内存碎片,还有部分暂时存储在外部 磁盘存储器上,但是它使应用程序认为自己就在一块连续的内存上跑。
(2)
进程的地址空间
(2)进程空间之间是相互独立的。
(3)一个进程的地址空间与另一个进程的地址空间即使有相同的内存地址,实际上也彼此互不相干。我们称这样的进程为线程
(4)如果果父进程希望和其子进程共享地址空间,可以在调用clone()时,设置CLONE_VM标志。我们把这样的进程称作线程。
当CLONE_VM被指定后,内核就不再需要调用allocate_mm()函数了,而仅仅需要在调用copy_mm函数中将mm域指向其父进程的内存描述符就可以了。
是否共享地址空间几乎是进程和Linux中所谓的线程间本质上的唯一区别。除此之外,Linux内核并不区别对待它们,线程对内核来说仅仅是一个共享特定资源的进程而已。

(4)每个进程拥有唯一的mm_struct结构体,唯一的进程地址空间
(5)struct mm_struct
(1.1)mm_count是mm_user的增量
mm_count :指向该mm_struct结构体的引用了。
(1.2)mmap和mm_rb描述的对象是相同的:该地址空间中的全部内存区域。前者链表形式,后者红黑树形式
(1.3)内核并没有复制mm_struct结构体,而仅仅被包含其中。
(1.4)所有的mm_struct结构体都通过自身的mmlist域连接在一个双向链表中,该链表的首元素是init_mm内存描述符,它代表init进程的地址空间。另外操作该链表的时候需要使用mmlist_lock锁来防止并发问题.
(6)fork()函数利用copy_mm()复制父进程的内存描述符,也就是current->mm域给其子进程,而子进程中的mm_struct结构体实际是通过allocate_mm()宏从mm_cachep slab缓存中分配得到的。
每个进程拥有唯一的mm_struct结构体,唯一的进程地址空间
(7)内核线程:,因为内核线程并不需要访问任何用户空间的内存而且因为内核线程在用户空间中没有任何页,所以实际上它们并不需要有自己的内存描述符和页表。,所以内核线程将直接使用前一个进程的内存描述符
(8)vm_area_struct描述内存区域,结构体描述内存描述符都对应于进程地址空间之中的唯一区间
(9)还有一些内存空间的指定内存的操作函数,添加,删除,查找等
(10)内核使用do_mmap()函数创建一个新的线性地址空间。
如果可能的话,将新区域和邻近区域进行合并,否则内核从vm_area_cachep长字节(slab)缓存中分配一个vm_area_struct结构体,并且使用vm_link()函数将新分配的内存区域添加到地址空间的内存区域链表和红黑树中,随后还要更新内存描述符中total_vm域,然后才返回新分配的地址区间的初始地址。