Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What does Linux memory mapping mean?

2025-01-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

Linux memory mapping refers to what, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, I hope you can gain something.

Memory mapping is a section of memory area of the user space that is mapped to the kernel space. After the mapping is successful, the user's modification of this memory area can be directly reflected to the kernel space. On the contrary, the modification of this area in the kernel space also directly reflects the user space.

one。 Memory mapping principle because the total virtual address space of all user processes is much larger than the available physical memory, only the most commonly used parts are associated with physical page frames. This is not a problem because most programs take up only a small portion of the actual available memory. When mapping data on disk to the virtual address space of a process, the kernel must provide a data structure to establish the relationship between the area of the virtual address space and the location of the related data. Linux software system multi-level page table mapping mechanism Note: the rightmost page in the figure above represents the page frame rate at the software level, not real physical memory. The real physical memory is also paged, called a page frame, and the conversion from page frame to page frame is done automatically by MMU. MMU is not considered in the following discussion (the work done by MMU is treated as a black box).

two。 The Linux page table implements a 32-bit logical address space computer system with a total address of 4G bytes and a page size of 4KB, then there are 4G/4K = 1m pages, then 1m entries (each entry represents a page) need to be stored in the page table. Assuming that each entry occupies 4B, 4m bytes of memory is required to hold the page table. Each process needs to manage all 4G memory, so each process needs 4m to store page tables, which is extremely wasteful.

The translation process from a secondary page table virtual address to a physical page address is as follows:

Combine the physical address of this page of the page directory (page directory, PGD) stored in the CR3 register, and extract from the virtual address a portion of the higher 10 bits called the page directory entry (also known as pgd in the kernel) as an offset, that is, locate the pgd that can describe the address.

The physical address of the page table that can describe the address can be obtained from the pgd, and the middle 10 bits are extracted from the virtual address as an offset, that is, the pte that can describe the address is located.

In this pte, you can obtain the physical address of the page corresponding to the address, and add the last 12 bits extracted from the virtual address to form the intra-page offset of the page, and finally complete the translation from the virtual address to the physical address.

The composition of the virtual address: DIRECTORY [22:31] can represent 1024 page directories (PGD) TABLE [12:21] can represent 1024 page tables (PTE) OFFSET [22:31] can represent 4096 physical memory, so the maximum mapped physical memory size is 102410244096 = 4G/Byte

When X86 introduces physical address extension (Pisycal Addrress Extension, PAE), it can support more than 4G physical memory (36 bits), but the virtual address is still 32 bits, the original page table entry is not applicable, it is actually expanded from 4 bytes to 8 bytes, which means that each page can now store the number of pte from 1024 to 512 (4k/8). Accordingly, the page table level has changed, and Linus has added a new level, called the page middle directory (page middle directory, PMD). The method is to abstract the PMD away from the architecture that uses the 2-level page table, that is, to assume a PMD table entry. So in the page table walk process, PGD would point directly to PTE, but now no longer, point to a virtual PMD, and then point to PTE by PMD. This abstraction maintains the unity of the code structure. This method actually uses several bits in the original virtual address composition as the PMD index: | 31 |-- PGD-- | 29 |-- PMD-- | 20 |-- PTE-- | 11 |-- OFFSET |-- | 0 |

The hardware of the level 4 page table is developing, and the level 3 page table is soon stretched again, due to the emergence of 64-bit CPU, such as X86 page 64, whose hardware actually supports level 4 page tables. It supports 48-bit virtual address space (although the Linux kernel initially used only 47 bits). It should be noted that the page table mapping of the software depends on the mapping level supported by the hardware. At present, ARM64 supports level 3 mapping. If the mapping level configured by ARM is level 3, then PGD=PUD in the mapping table of linux is actually a level 3 mapping.

The file index node has seven address items in the file index node, of which four address entries are direct address indexes, two address entries are primary indirect address indexes, and one address entry is secondary indirect address index, each address entry size is 4B. If the disk index block and disk data block size are 256B, please calculate the maximum length of a single file that can be represented.

The index entries that can be stored on each index block are 256B/4B=26 = 64. There are 4 blocks for direct index, 2 × 26 blocks for two first-level indirect indexes, and 1 × 26 × 26 blocks for a second-level indirect index. So a single file can have up to 4270212 (= 4228) blocks. The file size is 4228 × 256B = (42270212) × 28=33KB+1MB=1057KB

three。 Virtual space distribution linux divides the whole virtual space into user space and kernel space, and each user process occupies a complete user virtual space. The virtual address space distribution of the 64-bit system is 512G. The user space of the 32-bit system is 0xc0000000, and the size is 3G.

User space the size of the user virtual address space is 3G, and each application occupies a complete 3G virtual space. It should be seen here that real physical memory cannot be equal to virtual memory, because there will be many processes running at the same time, each process has 3G memory, and the actual physical memory cannot meet the needs of all processes. At this point the memory mapping mentioned above comes into play.

Generally speaking, although a process has access to 3G virtual memory, it may actually need very little memory, and most of the bodies of another process, such as code segments, read-only data segments, and so on, do not need to reside in memory in real time. because these contents are "dead" most of the time. So the first function of memory mapping is to map only the amount of memory needed by a process to physical memory, and swap other things that are not needed for the time being to hard disk storage. When the process needs to use the content in the hard disk or dynamically request memory, the operating system will use the page-missing operation to trigger a memory mapping to map additional physical memory to virtual memory for use by the program. Memory is always considered adequate for the process.

Each process has 3G virtual memory, so how does the operating system ensure that the actual physical memory used by each process does not occupy each other? In fact, each process has its own memory mapping table. There is only one process running on a CPU at any one time. So for this CPU, at this moment, there is only one 4GB virtual address space in the whole system, which is oriented to this process. When the process is switched, the virtual address space is also switched. From this, you can see that each process has its own virtual address space, and only when the process is running, its virtual address space is known by the CPU running it. At other times, its virtual address space is unknown to CPU. So although each process can have a virtual address space of 4 GB, in the eyes of CPU, only one virtual address space exists. The change of the virtual address space changes with the process switching.

Kernel space has relatively independent characteristics. That is, the scope of the virtual address space of the kernel is unique and is not shared with any user process (the kernel is essentially a process). This ensures the security of the kernel space. However, because the kernel virtual address space is small, 0xc000000~0xFFFFFFFF is only 1G in size, which is often smaller than the actual physical memory, so the kernel space needs additional ways to access all physical memory.

As can be seen from the image above, the kernel space is divided into three major parts: ZONE_DMA: 0XC000000 + 16m linear mapping area where the physical page is dedicated to the DMA of the iMacro device. The reason why you need to manage the physical pages of DMA separately is because DMA accesses memory using physical addresses, does not pass through MMU, and requires contiguous buffers, so in order to provide physically contiguous buffers, a special area must be divided from the physical address space for DMA. For example, the memory obtained by the dma_alloc_coherent function is ZONE_DMA memory ZONE_NORMAL: 0XC100000 + 880m linear mapping area where the physical pages can be directly used by the kernel, such as code snippets, global variables and heap memory obtained by kmalloc. Getting memory from here is generally continuous, but not too large. ZONE_HIGHMEM: 0xF8000000 + 28m this area is responsible and can be subdivided into three parts:

Discontiguous memory area discontinuous memory allocation refers to mapping page frames with discontinuous physical addresses to linear address spaces with continuous linear addresses, which is mainly used in large-capacity memory allocation. The main advantage of allocating memory in this way is that external fragmentation is avoided, while the disadvantage is that kernel page tables must be disrupted and access is slower than continuously allocated physical page frames. The function vmalloc maps physical memory through this part of the virtual address.

If the permanent kernel mapping area obtains the page corresponding to the high-end memory through alloc_page (), how do you find a linear space for it? The kernel sets aside a linear space for this purpose, from PKMAP_BASE to FIXADDR_START, to map high-end memory. On the 2. 6 kernel, this address range is from 4G-8M to 4G-4M. This space is called "kernel permanent mapping space" or "permanent kernel mapping space". This space uses the same page catalog table as other spaces, which for the kernel is swapper_pg_dir, and for ordinary processes, it is pointed to through the CR3 register. Typically, this space is 4m in size, so you only need a page table, which the kernel looks for by pkmap_page_table. With kmap (), you can map a page to this space. Because this space is 4m, it can map up to 1024 page at the same time. Therefore, for unused page, and when released from this space (that is, de-mapping), a linear address corresponding to page can be released from this space through kunmap ().

The biggest difference between temporary fixed mapping area fixmap and pkmap is that fixmap is not blocked, so it can be used in an interrupt context. In fact, every time fixmap can successfully perform the mapping, because fixmap will not dynamically apply for mapping, it is done in a fixed mapping way. If we pass in a mapping type, it will certainly execute the corresponding mapping and wash out the previous mapping, so the mapping relationship of fixmap is maintained by kernel code, so the kernel needs to ensure that the same mapping area is not reused, resulting in errors.

Previously we explained the origin of high-end memory. Linux divides the kernel address space into three parts: ZONE_DMA, ZONE_NORMAL and ZONE_HIGHMEM, and the high-end memory HIGH_MEM address space ranges from 0xF8000000 to 0xFFFFFFFF (896MB~1024MB). So how does the kernel access all physical memory with the help of 128MB high-end memory address space?

When the kernel wants to access memory higher than the 896MB physical address, find a logical address space of the corresponding size from the 0xF8000000-0xFFFFFFFF address space and borrow it for a while. Borrow this logical address space, create a map to the physical memory you want to access (that is, fill the kernel PTE page table), temporarily use it for a while, and return it after use. In this way, others can also use this address space to access other physical memory, using a limited address space to access all physical memory. For example, if the kernel wants to access a piece of physical memory with the size of 1MB starting from 2G, that is, the physical address range is 0 × 80000000 ~ 0x800FFFFF. Before access, find a section of free address space of 1MB size. Assume that the free address space found is 0xF8700000 ~ 0xF87FFFFF, and use the logical address space of this 1MB to map to the memory of physical address space 0 × 80000000 ~ 0x800FFFFF.

four。 The interaction between kernel space and user space the realizable process of system call is switched from user mode to kernel mode. But from the above analysis, we already know that the user process and the kernel process are separated from each other, so how is the parameter passing when making the system call? The idea to solve this problem is to copy data. Because both the user address space and the kernel address space are virtual address space, when passing parameters, you only need to copy the parameters stored in the user address space to the kernel address space. The function to complete the copy is known as copy_from_user () & copy_to_user (). The figure above shows that a user process passes a set of data to the kernel, and the kernel processes the data back to the user process. This process involves the transfer of data in two memory areas: the physical memory corresponding to the user virtual memory address and the physical memory corresponding to the kernel virtual memory address.

Mmap function prototype:

Void * mmap {void * addr; / / the first address of the mapping area. The size of the NULL size_t length; / / mapping area will be automatically adjusted to an integer multiple of 4k / / cannot be 0 / / the size of the normal file. Length specifies the size of the int prot; / / mapping area permission / / PROT_READ mapping area ratio must have read permission / / PROT_WRITE / / PROT_READ | PROT_WRITE int flags / / flag bit parameter / / MAP_SHARED modified memory data will be synchronized to disk / / MAP_PRIVATE modified memory data will not be synchronized to disk int fd; / / the fd off_t offset corresponding to the file to be mapped / / offset of the mapping file, where to start the operation / / when mapping, the offset of the file pointer / / must be an integer multiple of 4k / / generally set to 0 user space mmap calls user space to read and write files, it needs to go through the kernel, and the data is copied once more. Through the mmap function, you can establish a direct mapping of the user virtual space to the physical page where the file resides. After establishing this mapping, you can read and write files (such as read-write array) as if you were directly manipulating memory, reducing a user-to-kernel data copy.

Fd = open (argv [1], O_RDWR); / * Map the file to the address space of the process. Mmaped is the virtual memory address corresponding to the physical page of the file * / mmaped = (char *) mmap (NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); / * after mapping, you can also manipulate memory by closing the file * / close (fd) Mmaped [5] ='$'; msync (mmaped, sb.st_size, MS_SYNC) 1234567 Kernel Space mmap implementation opens a disk file directly, actually calling the mmap version provided by the file system. However, for engineers who develop linux drivers, they need to implement mmap functions for corresponding device files. For example, devices like framebuffer require high frequency of big data read and write, so they cannot tolerate data copy from kernel space to user space. Therefore, the driver needs to develop its own mmap function for user processes to call. The mmap implementation flow of the driver is roughly as follows:

Assign a virtual address through kmalloc, get_free_pages, vmalloc, etc.

If you are using a virtual address assigned by kmalloc and get_free_pages, use virt_to_phys () to convert it into a physical address, and then get the corresponding physical page frame number with the resulting physical address through "phys > > PAGE_SHIFT". Or use virt_to_page directly to get the corresponding physical page frame number from the virtual address. If you are using a virtual address assigned by vmalloc, use vmalloc_to_pfn to get the frame number of the physical page corresponding to the virtual address.

Call SetPageReserved () on each page to mark it as reserved.

Create a page table for the frame number of a physical page through remap_pfn_range and map it to user space.

/ / memory allocation buffer = (unsigned char *) kmalloc (PAGE_SIZE,GFP_KERNEL); / / set this memory to reserve SetPageReserved (virt_to_page (buffer)); / / get the physical address phys = virt_to_phys (buffer) / / Map a vma virtual memory area in user space to a continuous physical page starting with page remap_pfn_range (vma, vma- > vm_start, phys > > PAGE_SHIFT,//. The third parameter is the page frame number. Move PAGE_SHIFT to the right to vma- > vm_end-vma- > vm_start, vma- > vm_page_prot) the 123456789101112mmap function does not realize the interaction between the user space and the kernel space, but the user space tries to bypass the kernel space and directly manipulate the physical page.

four。 Complete memory distribution map under linux system

What are the versions of Linux? the versions of Linux are Deepin, UbuntuKylin, Manjaro, LinuxMint, Ubuntu and so on. Among them, Deepin is one of the best-developed Linux distributions in China; UbuntuKylin is a derivative release based on Ubuntu; Manjaro is a Linux release based on Arch; LinuxMint's default Cinnamon desktop is similar to Windows XP's easy-to-use; Ubuntu is the Linux operating system based on desktop applications.

Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report