Linux Virtual Memory

  This is the 3rd assignment of course CS353, in which we are required to write a module to explore Linux virtual memory.

  Here is the content of ~/Documents/Makefile:

1 obj-m:=mtest.o
2 all:
3     make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
4 clean:
5     make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

  I wrote the source code in file ~/Documents/mtest.c:

  1 #include <linux/kernel.h>
  2 #include <linux/module.h>
  3 #include <linux/init.h>
  4 #include <linux/proc_fs.h>
  5 #include <linux/seq_file.h>
  6 #include <asm/uaccess.h>
  7 #include <linux/sched.h>
  8 #include <linux/mm.h>
  9 #include <asm/page.h>
 10 #include <asm/pgtable.h>
 11 #include <linux/highmem.h>
 12 #include <linux/mm_types.h>
 13
 14 #define SIZE 1024
 15 #define VMACACHE_BITS 2
 16 #define VMACACHE_SIZE (1U << VMACACHE_BITS)
 17
 18 char BUF[SIZE];
 19
 20 /* Translate hex string into unsigned long */
 21 static unsigned long atol(char *str,unsigned long *pos)
 22 {
 23     unsigned long val = 0L, tmp;
 24     for (;*(str+(*pos))==‘ ‘;(*pos)++);
 25     for (;*(str+(*pos))!=‘ ‘;(*pos)++) {
 26         char ch = *(str+(*pos));
 27         if (ch==‘x‘) {
 28             continue;
 29         } else if (ch>=‘0‘&&ch<=‘9‘) {
 30             tmp = ch-‘0‘;
 31         } else if (ch>=‘A‘&&ch<=‘F‘) {
 32             tmp = 10+ch-‘A‘;
 33         } else if (ch>=‘a‘&&ch<=‘f‘) {
 34             tmp = 10+ch-‘a‘;
 35         } else {
 36             return 0;
 37         }
 38         val <<= 4;
 39         val += tmp;
 40     }
 41     return val;
 42 }
 43
 44 /* List the virtual memory areas of *current */
 45 static void listvma(void)
 46 {
 47     struct vm_area_struct *vma;
 48     unsigned long start, end;
 49     vm_flags_t flags;
 50     /* traverse the virtual memory areas
 51         in the form of LINKED-LIST (mm->mmap)
 52         rather than RB-TREE (mm->mm_rb)    */
 53     for (vma=current->mm->mmap;vma;vma=vma->vm_next) {
 54         start = vma->vm_start;
 55         if (stack_guard_page_start(vma, start))
 56             start += PAGE_SIZE;
 57         end = vma->vm_end;
 58         if (stack_guard_page_end(vma, end))
 59             end -= PAGE_SIZE;
 60         flags = vma->vm_flags;
 61         printk(KERN_INFO "%lx-%lx %c%c%c%c\n",
 62                 start,
 63                 end,
 64                 (flags & VM_READ) ? ‘r‘ : ‘-‘,
 65                 (flags & VM_WRITE) ? ‘w‘ : ‘-‘,
 66                 (flags & VM_EXEC) ? ‘x‘ : ‘-‘,
 67                 (flags & VM_MAYSHARE) ? ‘s‘ : ‘p‘);
 68     }
 69
 70 }
 71
 72 /* Given a virtual address, return the page */
 73 static struct page *findpage(unsigned long va,unsigned char wrt)
 74 {
 75     struct page *pg = NULL ;
 76     struct vm_area_struct *vma = NULL;
 77     pgd_t *pgd = NULL;
 78     pud_t *pud = NULL;
 79     pmd_t *pmd = NULL;
 80     pte_t *ptep = NULL;
 81     spinlock_t *ptlp = NULL;
 82     printk(KERN_INFO "va = %lx\n",va);
 83     vma = find_vma(current->mm,va);
 84     if (!vma || va < vma->vm_start) {
 85         // the virtual address is not available
 86         goto OUT;
 87     } else if (wrt && !(vma->vm_flags&VM_WRITE)) {
 88         // the virtual memory area is not writable
 89         goto OUT;
 90     }
 91     printk(KERN_INFO "vma -> %p\n",vma);
 92     /* Page Global Directory */
 93     pgd = pgd_offset(current->mm,va);
 94     if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) {
 95         goto OUT;
 96     }
 97     printk(KERN_INFO "pgd = %lx\n",(long)pgd_val(*pgd));
 98     /* Page Upper Directory */
 99     pud = pud_offset(pgd,va);
100     if (pud_none(*pud) || unlikely(pud_bad(*pud))) {
101         goto OUT;
102     }
103     printk(KERN_INFO "pud = %lx\n",(long)pud_val(*pud));
104     /* Page Middle Directory */
105     pmd = pmd_offset(pud,va);
106     if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) {
107         goto OUT;
108     }
109     printk(KERN_INFO "pmd = %lx\n",(long)pmd_val(*pmd));
110     /* Page Table Entry */
111     ptep = pte_offset_map_lock(current->mm,pmd,va,&ptlp);
112     printk(KERN_INFO "ptep -> %p\n",ptep);
113     if (!ptep) {
114         goto OUT;
115     }
116     printk(KERN_INFO "pte = %lx\n",(long)pte_val(*ptep));
117     if (!pte_present(*ptep)) {
118         goto UNLOCK;
119     }
120     //pg = vm_normal_page(vma,va,*ptep);
121     pg = pfn_to_page(pte_pfn(*ptep));
122     if (pg) {
123         get_page(pg);
124     }
125 UNLOCK:
126     pte_unmap_unlock(ptep,ptlp);
127 OUT:
128     return pg;
129 }
130
131
132 static void mtest_operate(void)
133 {
134     BUF[strlen(BUF)-1] = ‘ ‘;
135     down_read(&current->mm->mmap_sem);
136     if (!strncmp(BUF,"listvma ",8)) {
137         listvma();
138     } else if (!strncmp(BUF,"findpage ",9)) {
139         unsigned long pos = 9, va;
140         struct page *pg = NULL;
141         va = atol(BUF,&pos);
142         if ((pg = findpage(va,0))) {
143             unsigned long pa;
144             pa = ((long)page_address(pg))|(va&~PAGE_MASK);
145             printk(KERN_INFO "%lx\n",pa);
146         } else {
147             printk(KERN_INFO "translation not found\n");
148         }
149     } else if (!strncmp(BUF,"writeval ",9)) {
150         unsigned long pos = 9, va;
151         struct page *pg = NULL;
152         va = atol(BUF,&pos);
153         if ((pg = findpage(va,1))) {
154             *(unsigned long *)va = atol(BUF,&pos);
155             put_page(pg);
156             printk(KERN_INFO "successful\n");
157         }  else {
158             printk(KERN_INFO "the page is not writable\n");
159         }
160     }
161     up_read(&current->mm->mmap_sem);
162 }
163
164
165 /*
166  *    Basic functions of the proc fs entry /proc/mtest
167  *    mtest_open and mtest_show supports command "cat"
168  *    mtest_write supports command "echo"
169  */
170
171 static int mtest_show(struct seq_file *m,void *v)
172 {
173     seq_printf(m,"%s\n",BUF);
174     return 0;
175 }
176
177 static int mtest_open(struct inode *inode,struct file *file)
178 {
179     return single_open(file,mtest_show,NULL);
180 }
181
182 static ssize_t mtest_write(struct file *filp,const char __user *buf,size_t len,loff_t *pos)
183 {
184     memset(BUF,0,SIZE);
185     if (copy_from_user(BUF,buf,len)){
186         return -EFAULT;
187     }
188     mtest_operate();
189     return len;
190 }
191
192 static const struct file_operations mtest_fops = {
193     .owner = THIS_MODULE,
194     .read = seq_read,
195     .write = mtest_write,
196     .llseek = seq_lseek,
197     .open = mtest_open,
198     .release = single_release,
199 };
200
201 static int __init mtest_init(void)
202 {
203     struct proc_dir_entry *entry = NULL;
204     entry = proc_create("mtest",0666,NULL,&mtest_fops);
205     if (!entry) {
206         printk(KERN_INFO "Error: create_proc_entry failed\n");
207         return -1;
208     } else {
209         printk(KERN_INFO "Kernel: mtest init\n");
210         return 0;
211     }
212 }
213
214 static void __exit mtest_exit(void)
215 {
216     remove_proc_entry("mtest",NULL);
217     printk(KERN_INFO "Kernel: mtest exit\n");
218 }
219
220 module_init(mtest_init);
221 module_exit(mtest_exit);
222
223 MODULE_LICENSE("GPL");
224 MODULE_AUTHOR("ZUO NAN");

  We are also required to design a user program to write data to a virtual address (./test/c):

 1 #include <stdio.h>
 2
 3 #define SIZE 128
 4
 5 unsigned char BUF[SIZE];
 6
 7 int main()
 8 {
 9     unsigned long val = 0;
10
11     while (1) {
12         printf("Command: ");
13         memset(BUF,0,SIZE);
14         scanf("%s",&BUF);
15         if (!strcmp(BUF,"write")) {
16             memset(BUF,0,SIZE);
17             scanf("%s",&BUF);
18             printf("writeval %p %s\n",&val,BUF);
19             if (!freopen("/proc/mtest","w",stdout)){
20                 printf("proc entry not found\n");
21                 exit(1);
22             }
23             printf("writeval %p %s\n",&val,BUF);
24             if (!freopen("/dev/tty","w",stdout)){
25                 printf("stdout not recovered\n");
26                 exit(2);
27             }
28         } else if (!strcmp(BUF,"print")) {
29             printf("%lx\n",val);
30         } else if (!strcmp(BUF,"exit")) {
31             break;
32         }
33     }
34     return 0;
35 }

  Here are some testing results of my programs.

  (1) To test the compilation and insertion of the module:

  (2) To test LISTVMA instruction:

  (3) To test FINDPAGE and WRITEVAL:

  (4) To test the user program:

  (5) To test the removal of the module:

时间: 2025-01-04 20:53:06

Linux Virtual Memory的相关文章

Linux Process Virtual Memory

目录 1. 简介 2. 进程虚拟地址空间 3. 内存映射的原理 4. 数据结构 5. 对区域的操作 6. 地址空间 7. 内存映射 8. 反向映射 9.堆的管理 10. 缺页异常的处理 11. 用户空间缺页异常的校正 12. 内核缺页异常 13. 在内核和用户空间之间复制数据 1. 简介 用户层进程的虚拟地址空间是Linux的一个重要抽象,它向每个运行进程提供了同样的系统视图,这使得多个进程可以同时运行,而不会干扰到其他进程内存中的内容,此外,它容许使用各种高级的程序设计技术,如内存映射,学习虚

virtual memory exhausted: Cannot allocate memory

问题描述: 购买的Linux服务器,Linux服务器的内存为512MB. 在编译PHP的时候会提示:virtual memory exhausted: Cannot allocate memory,编译失败. 解决方法: 发生该问题的原因是服务器的内存不够,从而导致编译失败. 而购买的Linux服务器,未给你分配虚拟内存,所以可以通过自行增加虚拟内存的方法予以解决 [[email protected] ~]# free -m total used free shared buffers cach

virtual memory、swap、mount point

1.virtual memory =  physical memory + swap 2. page fault :a type of interrupt, called trap, raised by the hardware when a running program accesses a memory page that is mapped into the virtual address space, but not loaded in physical memory. 3.mount

ADDM Reports bug:Significant virtual memory paging was detected on the host operating system

查看ADDM(数据库版本为ORACLE 10.2.0.5.0)报告时,发现其中有个结论非常不靠谱:Significant virtual memory paging was detected on the host operating system,具体内容如下所示: FINDING 2: 100% impact (3930 seconds) ------------------------------------- Significant virtual memory paging was d

JVM virtual memory

This has been a long-standing complaint with Java, but it's largely meaningless, and usually based on looking at the wrong information. The usual phrasing is something like "Hello World on Java takes 10 megabytes! Why does it need that?" Well, h

解决:virtual memory exhausted: Cannot allocate memor

问题描述: 购买的Linux服务器,Linux服务器的内存为512MB. 在编译PHP的时候会提示:virtual memory exhausted: Cannot allocate memory,编译失败. 解决方法: 发生该问题的原因是服务器的内存不够,从而导致编译失败. 而购买的Linux服务器,未给你分配虚拟内存,所以可以通过自行增加虚拟内存的方法予以解决: 1 2 3 4 dd if = / dev / zero of = / swap bs = 1024 count = 1M mks

[hadoop] - Container [xxxx] is running beyond physical/virtual memory limits.

当运行mapreduce的时候,有时候会出现异常信息,提示物理内存或者虚拟内存超出限制,默认情况下:虚拟内存是物理内存的2.1倍.异常信息类似如下: Container [pid=13026,containerID=container_1449820132317_0013_01_000012] is running beyond physical memory limits. Current usage: 1.0 GB of 1 GB physical memory used; 1.7 GB o

XenApp_XenDesktop_7.6实战篇之二十:Linux Virtual Desktop 1.0(上篇)

Linux Virtual Desktop 1.0在CitrixXenDesktop 7.6 Feature Pack 2中于2015年6月30日已经正式发布了,目前Linux Virtual Desktop 1.0只支持发布共享桌面,暂不支持发布独立桌面和应用程序.本章节将介绍和演示CitrixXenDesktop 7.6 Linux Virtual Desktop 1.0的整个过程,本次使用的Linux系统为Red Hat Enterprise Linux Server 6.6.整个Linu

XenApp_XenDesktop_7.6实战篇之二十一:Linux Virtual Desktop 1.0(下篇)

在Linux Virtual Desktop 1.0(上篇)完成了系统要求介绍.更新Delivery Controller和准备Linux系统三部分的内容,在本文章中我们将在上篇的基础上继续介绍创建计算机目录.创建交付组和Linux桌面发布的功能验证. 4. 创建计算机目录 4.1  在CTXDDC01服务器打开Citrix Studio,点击"计算机目录"-"创建计算机目录" 4.2  下一步 4.3 选择"Windows 服务器操作系统" 4