以前感觉自己看东西还是不透彻,今天认真的去做学这个知识点,感觉收获挺大的。这几天一直看得内存管理。先做一部分笔记。
一个程序编译链接后形成的地址空间是一个虚拟地址空间,最终必须把用户空间中的虚地址最终映射到物理存储空间才行。而这种映射的建立和管理是由内核完成的。
一个进程的用户空间主要由两个数据结构来描述。一个是mm_struct结构,它对进程的整个用户空间进行描述,简称内存描述符,另一个是vm_area_struct结构,它对用户空间中各个区间(简称虚存区)进行描述。
进程控制快是内核中的核心数据结构,在进程的task_struct结构中包含一个mm域,它是指向mm_struct结构的指针。而进程的mm_struct结构则又包含进程的可执行影像信息以及进程的页目录指针PGD。如下就是其关系:
打印当前的进程虚存区如何实现呢?可以使用全局变量current来实现:
- static int mm_init(void)
- {
-
- struct mm_struct *mm=current->mm;
- struct vm_area_struct *temp;
- printk("The virtual memory areas(VMA) are:\n");
- printk("current:%s pid :%d\n",current->comm,current->pid);
- down_read(&mm->mmap_sem); 获取mm信号量
- temp=mm->mmap;
- while(temp)
- {
- printk("start :%p\t end:%p\n",(unsigned long *)temp->vm_start,(unsigned long *)temp->vm_end);
- temp=temp->vm_next;
- }
- up_read(&mm->mmap_sem);
- return 0;
- }
如果我们知道进程的PID,想要打印出该进程的虚存区应如何打印?最简单的办法可以从命令行传进去进程的PID给模块,然后通过函数找出进程,下面是具体的代码:
- static int pid=1; //初始值
- module_param(pid,int,S_IRUSR); //传递参数
- static int mm_init(void)
- {
- struct task_struct *p;
- struct vm_area_struct *temp;
- struct pid *k;
- printk("The virtual memory areas(VMA) are:\n");
- k=find_vpid(pid);
- p=pid_task(k,PIDTYPE_PID); //根据局部数字PID和UNIX进程ID找到进程
- temp=p->mm->mmap; //指向线性区域的链表头
- printk("process:%s pid :%d\n",p->comm,p->pid);
- while(temp)
- {
- printk("start :%p\t end:%p ",(unsigned long *)temp->vm_start,(unsigned long *)temp->vm_end);
- if(temp->vm_flags & VM_READ)
- printk("r");
- else
- printk("-");
- if(temp->vm_flags & VM_READ)
- printk("w");
- else
- printk("-");
- if(temp->vm_flags & VM_EXEC)
- printk("x");
- else
- printk("-");
- printk("\n");
- temp=temp->vm_next;
- }
- return 0;
- }
也可以从/proc/进程号/maps得到这些信息,进行对比。
阅读(2712) | 评论(2) | 转发(0) |