• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • linux 內存管理(8) —內存描述符(mm_struct)

    標簽: linux  內存管理  

    • 了解進程內存描述符mm_struct

    1.概述

    ??每個進程都只有一個mm_struct結構,該結構是對整個用戶空間的描述。一個進程的虛擬地址空間主要由兩個數據結來描述。

    • 最高層次的:mm_struct,描述一個進程的整個虛擬地址空間。
    • 較高層次的:vm_area_structs,描述虛擬地址空間的一個區間(簡稱虛擬區)。

    內存管理大致結構:
    在這里插入圖片描述

    2.mm_struct 結構體

    ??task_struct結構體包括指向mm_struct結構的指針,mm_struct用來描述進程的虛擬地址空間。mm_struct包括裝入的可履行映像信息和進程的頁目錄指針pgd,還包括有指向vm_area_struct結構的幾個指針,每一個vm_area_struct代表進程的1個虛擬地址區間。

    ??vm_area_struct結構含有指向vm_operations_struct結構的1個指針,vm_operations_struct描寫了在這個區間的操作。vm_operations_struct結構中包括的是函數指針,其中open、close分別用于虛擬區間的打開、關閉,而nopage用于當虛擬頁面不再物理內存而引發的"缺頁異常"時所調用的函數,當linux處理缺頁異常時,就能夠為新的虛擬內存分配實際的物理內存。

    ??mm_struct是對進程的地址空間(虛擬內存)的描寫。1個進程的虛擬空間中可能有多個虛擬區間,對這些虛擬空間的組織方式有兩種:

    • 當虛擬區較少時采取單鏈表,由mmap指針指向這個鏈表;
    • 當虛擬區間多時采取紅黑樹進行管理,由mm_rb指向這棵樹。由于程序中用到的地址常常具有局部性,因此,最近1次用到的虛擬區間極可能下1次還要用到,因此把最近用到的虛擬區間結構放到高速緩存,這個虛擬區間就由mmap_cache指向。

    結構體如下圖所示:
    在這里插入圖片描述
    2.1.struct mm_struct

    struct mm_struct {
    	struct {
    		struct vm_area_struct *mmap;		/* list of VMAs */
    		struct rb_root mm_rb;
    		u64 vmacache_seqnum;                   /* per-thread vmacache */
    #ifdef CONFIG_MMU
    		unsigned long (*get_unmapped_area) (struct file *filp,
    				unsigned long addr, unsigned long len,
    				unsigned long pgoff, unsigned long flags);
    #endif
    		unsigned long mmap_base;	/* base of mmap area */
    		unsigned long mmap_legacy_base;	/* base of mmap area in bottom-up allocations */
    #ifdef CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES
    		/* Base adresses for compatible mmap() */
    		unsigned long mmap_compat_base;
    		unsigned long mmap_compat_legacy_base;
    #endif
    		unsigned long task_size;	/* size of task vm space */
    		unsigned long highest_vm_end;	/* highest vma end address */
    		pgd_t * pgd;
    
    #ifdef CONFIG_MEMBARRIER
    		atomic_t membarrier_state;
    #endif
    
    
    		atomic_t mm_users;
    		atomic_t mm_count;
    
    #ifdef CONFIG_MMU
    		atomic_long_t pgtables_bytes;	/* PTE page table pages */
    #endif
    		int map_count;			/* number of VMAs */
    
    		spinlock_t page_table_lock; /* Protects page tables and some
    					     * counters
    					     */
    		struct rw_semaphore mmap_sem;
    
    		struct list_head mmlist; /* List of maybe swapped mm's.	These
    					  * are globally strung together off
    					  * init_mm.mmlist, and are protected
    					  * by mmlist_lock
    					  */
    		unsigned long hiwater_rss; /* High-watermark of RSS usage */
    		unsigned long hiwater_vm;  /* High-water virtual memory usage */
    
    		unsigned long total_vm;	   /* Total pages mapped */
    		unsigned long locked_vm;   /* Pages that have PG_mlocked set */
    		atomic64_t    pinned_vm;   /* Refcount permanently increased */
    		unsigned long data_vm;	   /* VM_WRITE & ~VM_SHARED & ~VM_STACK */
    		unsigned long exec_vm;	   /* VM_EXEC & ~VM_WRITE & ~VM_STACK */
    		unsigned long stack_vm;	   /* VM_STACK */
    		unsigned long def_flags;
    
    		spinlock_t arg_lock; /* protect the below fields */
    		unsigned long start_code, end_code, start_data, end_data;
    		unsigned long start_brk, brk, start_stack;
    		unsigned long arg_start, arg_end, env_start, env_end;
    
    		unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
    
    		struct mm_rss_stat rss_stat;
    		struct linux_binfmt *binfmt;
    		/* Architecture-specific MM context */
    		mm_context_t context;
    
    		unsigned long flags; /* Must use atomic bitops to access */
    		struct core_state *core_state; /* coredumping support */
    
    #ifdef CONFIG_AIO
    		spinlock_t			ioctx_lock;
    		struct kioctx_table __rcu	*ioctx_table;
    #endif
    #ifdef CONFIG_MEMCG
    		struct task_struct __rcu *owner;
    #endif
    		struct user_namespace *user_ns;
    
    		/* store ref to file /proc/<pid>/exe symlink points to */
    		struct file __rcu *exe_file;
    #ifdef CONFIG_MMU_NOTIFIER
    		struct mmu_notifier_mm *mmu_notifier_mm;
    #endif
    #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS
    		pgtable_t pmd_huge_pte; /* protected by page_table_lock */
    #endif
    #ifdef CONFIG_NUMA_BALANCING
    		unsigned long numa_next_scan;
    
    		/* Restart point for scanning and setting pte_numa */
    		unsigned long numa_scan_offset;
    
    		/* numa_scan_seq prevents two threads setting pte_numa */
    		int numa_scan_seq;
    #endif
    		atomic_t tlb_flush_pending;
    #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
    		/* See flush_tlb_batched_pending() */
    		bool tlb_flush_batched;
    #endif
    		struct uprobes_state uprobes_state;
    #ifdef CONFIG_HUGETLB_PAGE
    		atomic_long_t hugetlb_usage;
    #endif
    		struct work_struct async_put_work;
    	} __randomize_layout;
    
    	unsigned long cpu_bitmap[];
    };
    

    2.2.struct vm_area_struct

    ??虛擬地址區間vm_area_struct是虛擬內存的一部份,內存描寫符mm_struct指向全部虛擬空間,而vm_area_struct只是指向了虛擬空間的一段。

    ??vm_area_struct是由雙向鏈表鏈接起來的,它們是依照虛擬地址降序排序的,每一個這樣的結構都對應描寫一個相鄰的地址空間范圍。之所以這樣分隔是由于每一個虛擬區間可能來源不同,有的可能來自可履行映像,有的可能來自同享庫,而有的多是動態內存分配的內存區,所以對每一個由vm_area_struct結構所描寫的區間的處理操作和它前后范圍的處理操作不同,因此linux把虛擬內存分割管理,并利用了虛擬內存處理例程vm_ops來抽象對不同來源虛擬內存的處理方法。不同的虛擬區間其處理操作可能不同,linux在這里利用了面向對象的思想,即把1個虛擬區間看成是1個對象,用vm_area_struct描寫這個對象的屬性,其中的vm_operation結構描寫了在這個對象上的操作。

    struct vm_area_struct {
    	/* The first cache line has the info for VMA tree walking. */
    	unsigned long vm_start;		/* Our start address within vm_mm. */
    	unsigned long vm_end;		/* The first byte after our end address within vm_mm. */
    
    	/* linked list of VM areas per task, sorted by address */
    	struct vm_area_struct *vm_next, *vm_prev;
    	struct rb_node vm_rb;
    	unsigned long rb_subtree_gap;
    
    	/* Second cache line starts here. */
    	struct mm_struct *vm_mm;	/* The address space we belong to. */
    	pgprot_t vm_page_prot;		/* Access permissions of this VMA. */
    	unsigned long vm_flags;		/* Flags, see mm.h. */
    
    	struct {
    		struct rb_node rb;
    		unsigned long rb_subtree_last;
    	} shared;
    
    	struct list_head anon_vma_chain; /* Serialized by mmap_sem & * page_table_lock */
    	struct anon_vma *anon_vma;	/* Serialized by page_table_lock */
    
    	/* Function pointers to deal with this struct. */
    	const struct vm_operations_struct *vm_ops;
    
    	/* Information about our backing store: */
    	unsigned long vm_pgoff;		/* Offset (within vm_file) in PAGE_SIZE units */
    	struct file * vm_file;		/* File we map to (can be NULL). */
    	void * vm_private_data;		/* was vm_pte (shared mem) */
    
    #ifdef CONFIG_SWAP
    	atomic_long_t swap_readahead_info;
    #endif
    #ifndef CONFIG_MMU
    	struct vm_region *vm_region;	/* NOMMU mapping region */
    #endif
    #ifdef CONFIG_NUMA
    	struct mempolicy *vm_policy;	/* NUMA policy for the VMA */
    #endif
    	struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
    } __randomize_layout;
    

    2.3.vm_operations_struct

    ??vm_operations_struct結構中包含函數指針,其中open、close分別用于虛擬內存的打開、關閉,而nopage用于當虛擬內存頁面沒有實際的物理內存映照而引發的”缺頁異常”時所調用的函數指針。

    struct vm_operations_struct {
    	void (*open)(struct vm_area_struct * area);
    	void (*close)(struct vm_area_struct * area);
    	int (*split)(struct vm_area_struct * area, unsigned long addr);
    	int (*mremap)(struct vm_area_struct * area);
    	vm_fault_t (*fault)(struct vm_fault *vmf);
    	vm_fault_t (*huge_fault)(struct vm_fault *vmf,
    			enum page_entry_size pe_size);
    	void (*map_pages)(struct vm_fault *vmf,
    			pgoff_t start_pgoff, pgoff_t end_pgoff);
    	unsigned long (*pagesize)(struct vm_area_struct * area);
    
    	vm_fault_t (*page_mkwrite)(struct vm_fault *vmf);
    
    	/* same as page_mkwrite when using VM_PFNMAP|VM_MIXEDMAP */
    	vm_fault_t (*pfn_mkwrite)(struct vm_fault *vmf);
    
    	int (*access)(struct vm_area_struct *vma, unsigned long addr,
    		      void *buf, int len, int write);
    		      
    	const char *(*name)(struct vm_area_struct *vma);
    
    #ifdef CONFIG_NUMA
    	int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
    	struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
    					unsigned long addr);
    #endif
    	struct page *(*find_special_page)(struct vm_area_struct *vma,
    					  unsigned long addr);
    };
    

    虛擬內存管理數據結構圖:
    在這里插入圖片描述
    在這里插入圖片描述

    2.4.proc/pid/maps

    ??顯示進程映射了的內存區域和訪問權限。對應內核中的操作集為proc_pid_maps_op,具體的導出函數為show_map。內核中進程的一段地址空間用一個vm_area_struct結構體表示,所有地址空間存儲在task->mm->mmap鏈表中。

    ??一個文件可以映射到進程的一段內存區域中,映射的文件描述符保存在vm_area_struct->vm_file域中,這種內存區域叫做有名內存區域,相反,屬于匿名映射內存區域。vm_area_struct每項對應解析如下表所示:
    在這里插入圖片描述
    例如:

    cat /proc/19970/maps
    001f7000-00212000 r-xp 00000000 fd:00 2719760    /lib/ld-2.5.so
    00212000-00213000 r-xp 0001a000 fd:00 2719760    /lib/ld-2.5.so
    00213000-00214000 rwxp 0001b000 fd:00 2719760    /lib/ld-2.5.so
    00214000-0036b000 r-xp 00000000 fd:00 2719767    /lib/libc-2.5.so
    0036b000-0036d000 r-xp 00157000 fd:00 2719767    /lib/libc-2.5.so
    0036d000-0036e000 rwxp 00159000 fd:00 2719767    /lib/libc-2.5.so
    0036e000-00371000 rwxp 0036e000 00:00 0
    0054f000-00565000 r-xp 00000000 fd:00 2719791    /lib/libpthread-2.5.so
    00565000-00566000 r-xp 00015000 fd:00 2719791    /lib/libpthread-2.5.so
    00566000-00567000 rwxp 00016000 fd:00 2719791    /lib/libpthread-2.5.so
    00567000-00569000 rwxp 00567000 00:00 0
    006f5000-006f6000 r-xp 006f5000 00:00 0          [vdso]
    
    08048000-08049000 r-xp 00000000 fd:00 3145810    /home/lijz/code/pthread
    08049000-0804a000 rw-p 00000000 fd:00 3145810    /home/lijz/code/pthread
    
    08c50000-08c71000 rw-p 08c50000 00:00 0          [heap]
    b75d7000-b75d8000 ---p b75d7000 00:00 0
    b75d8000-b7fda000 rw-p b75d8000 00:00 0
    b7fe4000-b7fe5000 rw-p b7fe4000 00:00 0
    bf987000-bf99c000 rw-p bffea000 00:00 0          [stack]
    
    • 第一列:08049000-0804a000-----本段內存映射的虛擬地址空間范圍,對應vm_area_struct中的vm_start和vm_end。

    • 第二列:rw-p----權限 r-讀,w-寫 x-可執行 p-私有,對應vm_flags。

    • 第三列:00000000----針對有名映射,指本段映射地址在文件中的偏移,對應vm_pgoff。對匿名映射而言,為vm_area_struct->vm_start。

    • 第四列:fd:00----所映射的文件所屬設備的設備號,對應vm_file->f_dentry->d_inode->i_sb->s_dev。匿名映射為0。其中fd為主設備號,00為次設備號。

    • 第五列:3145810----文件的索引節點號,對應vm_file->f_dentry->d_inode->i_ino,與ls –i顯示的內容相符。匿名映射為0。

    • 第六列:/home/lijz/code/pthread—所映射的文件名。對有名映射而言,是映射的文件名,對匿名映射來說,是此段內存在進程中的作用。[stack]表示本段內存作為棧來使用,[heap]作為堆來使用,其他情況則為無。

    3.mmap內存映射

    mmap_driver.c的源代碼:

    //所有的模塊代碼都包含下面兩個頭文件  
    #include <linux/module.h>  
    #include <linux/init.h>  
    
    #include <linux/fs.h>  
    #include <linux/cdev.h> //定義struct cdev結構體及相關操作  
      
    #include <linux/types.h> //定義dev_t類型  
    #include <linux/slab.h> //定義kmalloc接口  
    #include <asm/io.h>		//定義virt_to_phys接口  
    #include <linux/mm.h>	//remap_pfn_range  
      
    #define MAJOR_NUM 100 
    static int dev_major = MAJOR_NUM;  
    
    #define MM_SIZE 4096  
    static char driver_name[] = "mmap_driver";  //驅動模塊名字  
    //static int dev_major = 0;  
    static int dev_minor = 0;  
    char *buf = NULL;  
    struct cdev *cdev = NULL;  
      
    static int device_open(struct inode *inode, struct file *file)  
    {  
        printk(KERN_ALERT"device open\n");  
        buf = (char *)kmalloc(MM_SIZE, GFP_KERNEL);//內核申請內存只能按頁申請,申請該內存以便后面把它當作虛擬設備  
        printk(KERN_ALERT"albert:%s,buf=%p\n", __func__, buf);  
        return 0;  
    }  
      
    static int device_close(struct inode *indoe, struct file *file)  
    {  
        printk("device close\n");  
        if(buf)  
        {  
            kfree(buf);  
        }  
        return 0;  
    }  
      
    static int device_mmap(struct file *file, struct vm_area_struct *vma)  
    {  
        printk("device ap\n");  
        vma->vm_flags |= VM_IO;//表示對設備IO空間的映射  
    	vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);//標志該內存區不能被換出,在設備驅動中虛擬頁和物理頁的關系應該是長期的,應該保留起來,不能隨便被別的虛擬頁換出  
        if(remap_pfn_range(vma,//虛擬內存區域,即設備地址將要映射到這里  
                           vma->vm_start,//虛擬空間的起始地址  
                           virt_to_phys(buf)>>PAGE_SHIFT,//與物理內存對應的頁幀號,物理地址右移12位  
                           vma->vm_end - vma->vm_start,//映射區域大小,一般是頁大小的整數倍  
                           vma->vm_page_prot))//保護屬性,  
        {  
            return -EAGAIN;  
        }  
        return 0;  
    }  
      
    static struct file_operations device_fops =  {  
        .owner = THIS_MODULE,  
        .open  = device_open,  
        .release = device_close,  
        .mmap = device_mmap,  
    };  
      
    static int __init char_device_init(void)  
    {  
        int result;  
        dev_t dev;//高12位表示主設備號,低20位表示次設備號  
    
        printk(KERN_ALERT"module init2323\n");  
        printk("dev=%d", dev);  
    
        dev = MKDEV(dev_major, dev_minor);  
        cdev = cdev_alloc();//為字符設備cdev分配空間  
    
        printk(KERN_ALERT"module init\n");  
        if(dev_major) {  
            result = register_chrdev_region(dev, 1, driver_name);//靜態分配設備號  
            printk("result = %d\n", result);  
        }  
        else  
        {  
            result = alloc_chrdev_region(&dev, 0, 1, driver_name);//動態分配設備號  
            dev_major = MAJOR(dev);  
        }  
          
        if(result < 0)  
        {  
            printk(KERN_WARNING"Cant't get major %d\n", dev_major);  
            return result;  
        }  
          
          
        cdev_init(cdev, &device_fops);//初始化字符設備cdev  
        cdev->ops = &device_fops;  
        cdev->owner = THIS_MODULE;  
          
        result = cdev_add(cdev, dev, 1);//向內核注冊字符設備  
        printk("dffd = %d\n", result);  
        return 0;  
    }  
      
    static void __exit char_device_exit(void)  
    {  
        printk(KERN_ALERT"module exit\n");  
        cdev_del(cdev);  
        unregister_chrdev_region(MKDEV(dev_major, dev_minor), 1);  
    }  
      
    module_init(char_device_init);//模塊加載  
    module_exit(char_device_exit);//模塊退出  
      
    MODULE_LICENSE("GPL");  
    MODULE_AUTHOR("ChenShengfa");  
    

    測試代碼test_mmap.c:

    #include <fcntl.h>  
    #include <sys/mman.h>  
    #include <stdio.h>
    #include <stdlib.h>  
    #include <string.h>  
      
    int main( void )  
    {  
        int fd;  
        char *buffer;  
        char *mapBuf;  
    
        fd = open("/dev/mmap_driver", O_RDWR);//打開設備文件,內核就能獲取設備文件的索引節點,填充inode結構  
        if(fd<0) {  
            printf("open device is error,fd = %d\n",fd); 
            return -1;  
        }  
    
        /*測試一:查看內存映射段*/  
        printf("before mmap\n");  
        sleep(20);//睡眠20秒,查看映射前的內存圖cat /proc/pid/maps  
        buffer = (char *)malloc(4096);  
        printf("buffer=%p\n", (void *)buffer);  
        memset(buffer, 0, 4096);  
        mapBuf = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);//內存映射,會調用驅動的mmap函數  
        printf("mapbuf=%p\n", (void *)mapBuf);  
        printf("after mmap\n");  
        sleep(10);//睡眠10秒,在命令行查看映射后的內存圖,如果多出了映射段,說明映射成功  
          
        /*測試二:往映射段讀寫數據,看是否成功*/  
    	strcpy(mapBuf, "albert driver test");//向映射段寫數據  
    	memset(buffer, 0, 4096);  
    	strcpy(buffer, mapBuf);//從映射段讀取數據  
    	printf("buf = %s\n", buffer);//如果讀取出來的數據和寫入的數據一致,說明映射段的確成功了  
          
        munmap(mapBuf, 4096);//去除映射  
        free(buffer);  
        close(fd);//關閉文件,最終調用驅動的close  
        return 0;  
    }  
    

    測試步驟:

    # make    //編譯驅動
    # insmod mmap_driver.ko    //安裝驅動
    # mknod /dev/mmap_driver c 100 0    //創建設備文件
    # gcc test_mmap.c -o test   //編譯應用程序
    # ./test    //運行應用程序來測試驅動程序
    

    查看proc/pid/maps:

    執行$ ./test
    before mmap
    buffer=0x1345010
    mapbuf=0x7f185d01d000

    查看ps -aux,找到pid 為28586,然后執行cat proc/28586/maps

    root 28586 0.0 0.0 4208 652 pts/7 S+ 16:21 0:00 ./test_mmap

    如下所示:

    00400000-00401000 r-xp 00000000 08:01 2542484                            /home/zhaoxiao/Documents/work/code/albert/linux/mmap/test_mmap
    00600000-00601000 r--p 00000000 08:01 2542484                            /home/zhaoxiao/Documents/work/code/albert/linux/mmap/test_mmap
    00601000-00602000 rw-p 00001000 08:01 2542484                            /home/zhaoxiao/Documents/work/code/albert/linux/mmap/test_mmap
    7f185ca34000-7f185cbf2000 r-xp 00000000 08:01 1847071                    /lib/x86_64-linux-gnu/libc-2.19.so
    7f185cbf2000-7f185cdf2000 ---p 001be000 08:01 1847071                    /lib/x86_64-linux-gnu/libc-2.19.so
    7f185cdf2000-7f185cdf6000 r--p 001be000 08:01 1847071                    /lib/x86_64-linux-gnu/libc-2.19.so
    7f185cdf6000-7f185cdf8000 rw-p 001c2000 08:01 1847071                    /lib/x86_64-linux-gnu/libc-2.19.so
    7f185cdf8000-7f185cdfd000 rw-p 00000000 00:00 0 
    7f185cdfd000-7f185ce20000 r-xp 00000000 08:01 1847068                    /lib/x86_64-linux-gnu/ld-2.19.so
    7f185cfff000-7f185d002000 rw-p 00000000 00:00 0 
    7f185d01e000-7f185d01f000 rw-p 00000000 00:00 0 
    7f185d01f000-7f185d020000 r--p 00022000 08:01 1847068                    /lib/x86_64-linux-gnu/ld-2.19.so
    7f185d020000-7f185d021000 rw-p 00023000 08:01 1847068                    /lib/x86_64-linux-gnu/ld-2.19.so
    7f185d021000-7f185d022000 rw-p 00000000 00:00 0 
    7fff1e4f6000-7fff1e517000 rw-p 00000000 00:00 0                          [stack]
    7fff1e52d000-7fff1e530000 r--p 00000000 00:00 0                          [vvar]
    7fff1e530000-7fff1e532000 r-xp 00000000 00:00 0                          [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
    

    等待出現after mmap之后,再次查看cat proc/28586/maps:

    00400000-00401000 r-xp 00000000 08:01 2542484                            /home/zhaoxiao/Documents/work/code/albert/linux/mmap/test_mmap
    00600000-00601000 r--p 00000000 08:01 2542484                            /home/zhaoxiao/Documents/work/code/albert/linux/mmap/test_mmap
    00601000-00602000 rw-p 00001000 08:01 2542484                            /home/zhaoxiao/Documents/work/code/albert/linux/mmap/test_mmap
    
    01345000-01367000 rw-p 00000000 00:00 0                                  [heap]
    
    7f185ca34000-7f185cbf2000 r-xp 00000000 08:01 1847071                    /lib/x86_64-linux-gnu/libc-2.19.so
    7f185cbf2000-7f185cdf2000 ---p 001be000 08:01 1847071                    /lib/x86_64-linux-gnu/libc-2.19.so
    7f185cdf2000-7f185cdf6000 r--p 001be000 08:01 1847071                    /lib/x86_64-linux-gnu/libc-2.19.so
    7f185cdf6000-7f185cdf8000 rw-p 001c2000 08:01 1847071                    /lib/x86_64-linux-gnu/libc-2.19.so
    7f185cdf8000-7f185cdfd000 rw-p 00000000 00:00 0 
    7f185cdfd000-7f185ce20000 r-xp 00000000 08:01 1847068                    /lib/x86_64-linux-gnu/ld-2.19.so
    7f185cfff000-7f185d002000 rw-p 00000000 00:00 0 
    7f185d01d000-7f185d01e000 rw-s 00000000 00:06 108404                     /dev/mmap_driver
    7f185d01e000-7f185d01f000 rw-p 00000000 00:00 0 
    7f185d01f000-7f185d020000 r--p 00022000 08:01 1847068                    /lib/x86_64-linux-gnu/ld-2.19.so
    7f185d020000-7f185d021000 rw-p 00023000 08:01 1847068                    /lib/x86_64-linux-gnu/ld-2.19.so
    7f185d021000-7f185d022000 rw-p 00000000 00:00 0 
    7fff1e4f6000-7fff1e517000 rw-p 00000000 00:00 0                          [stack]
    7fff1e52d000-7fff1e530000 r--p 00000000 00:00 0                          [vvar]
    7fff1e530000-7fff1e532000 r-xp 00000000 00:00 0                          [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
    

    兩次對比不同之處:

    01345000-01367000 rw-p 00000000 00:00 0 [heap]
    7f185d01d000-7f185d01e000 rw-s 00000000 00:06 108404 /dev/mmap_driver

    版權聲明:本文為weixin_41028621原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/weixin_41028621/article/details/104455327

    智能推薦

    linux內存管理

    1. 分析圖1(注:圖1是2級頁表,對應于IA-32位系統),解釋圖中每一類方框和箭頭的含義,在代碼樹中尋找相關數據結構片段,做簡單解釋。 (1)Linux進程描述符task_struct結構體 在上次大作業中我們同樣分析task_struct結構體,上次分析的部分是關于進程調度的,而由圖中可以看出結構體中的mm_struct與這次內存管理實驗主要相關 (2)內存描述符 mm_struct 一個進...

    淺談Linux內存管理

    淺談Linux內存管理 lecury ? 百度(中國)有限公司 高級軟件研發工程師 已關注 464 人贊同了該文章 1. 掃盲篇 1.1 操作系統存儲層次 常見的計算機存儲層次如下: 寄存器:CPU提供的,讀寫ns級別,容量字節級別。 CPU緩存:CPU和CPU間的緩存,讀寫10ns級別,容量較大一些,百到千節。 主存:動態內存,讀寫100ns級別,容量GB級別。 外部存儲介質:磁盤、SSD,讀寫...

    Linux內存管理總結

    1 學習路線 2 3種系統架構與2種存儲器共享方式 2.1 SMP 2.2 NUMA 2.3 MPP 3 內存空間分層 4 Linux物理內存組織形式 4.1 Node 4.1.1 結點的內存管理域 4.1.2 結點的內存頁面 4.1.3 交換守護進程 4.1.4 節點狀態 4.1.5 查找內存節點 4.2 zone 4.2.1 高速緩存行 4.2.2 水位watermark[NR_WMARK]與...

    Linux內存管理基礎

    參考: http://blog.csdn.net/unclerunning/article/details/51917605 http://blog.csdn.net/gatieme/article/details/52403148 系統啟動之Linux內存管理基礎 Keywords 非一致內存訪問(NUMA)模型、節點(node)、內存管理區(Zone)、一致內存訪問(UMA)模型、內核頁表、內...

    Linux 內存管理框架

      目錄 1.    內存管理框架概覽    2 1.1.    內存管理各個數據結構之間關系    2 1.2.    主要數據結構說明    3 ...

    猜你喜歡

    神奇的Batch Normalization 如果一個模型僅訓練BN層會是什么樣的

    您可能會感到驚訝,但這是有效的。 ? 最近,我閱讀了arXiv平臺上的Jonathan Frankle,David J. Schwab和Ari S. Morcos撰寫的論文“Training BatchNorm and Only BatchNorm: On the Expressive Power of Random Features in CNNs”。 這個主意立刻引起了...

    用Python實現校園通知更新提醒

    前言 這個項目實已經在一個月前已經完成了,一直都想寫一篇博客來總結這個過程中遇到的一些問題。但最近一個月來都比較忙,所以一直拖到了現在。 首先說說起因吧,我沒事的時候,總喜歡依次點開學校主頁、教務處、圖書館以及學院的網站,看看有沒有什么新通知,雖然大多與我無關。恰逢最近正在學Python,經常聽到別人說用Python寫爬蟲很簡單,但自己尚未接觸過爬蟲。于是抱著試一試的心態看了幾篇關于Python爬...

    spring_ioc相關_第一章

    1 spring是一站式框架,在javaee的三層結構中,每一層都提供不提并的解決技術 web層:springMVC service層:spring的ioc dao層:spring的jdbcTemplate 2 javaee為避免兩個類之間出現耦合,則把對象的創建交給spring進行管理,spring的ioc操作:(1)ioc的配置文件方式;(2)ioc注解方式 3 ioc的底層原理使用技術(1)...

    【Python+OpenCV】視頻流局部區域像素值處理-一種特征提取方法

    參考我之前寫的處理圖片的文章:Python+OpenCV實現【圖片】局部區域像素值處理(改進版) 開發環境:Python3.6.0 + OpenCV3.2.0 任務目標:攝像頭采集圖像(例如:480*640),并對視頻流每一幀(灰度圖)特定矩形區域(480*30)像素值進行行求和,得到一個480*1的數組,用這480個數據繪制條形圖,即在逐幀采集視頻流并處理后“實時”顯示采...

    JavaWeb——【前端】——注冊頁面

    頁面效果 實現代碼 注意事項 主要使用的bootstrap樣式 如果想引用,不要直接復制,沒用的。 先介紹下所引用的文件: boostrap的js、bootstrap的css、jquery的js、以及自己編寫的register.css。 因為博主用的thymeleaf語法,所以有th符號。 若要使用時,根據個人情況導入相應的依賴。...

    精品国产乱码久久久久久蜜桃不卡