Linux kernel: process management - process memory mapping

This article introduces memory mapping, which is very convenient when multiple processes access files to read and write.

1. Introduction to memory mapping mmap function

The mmap function can map files on disk into memory space and return the first address of the mapping.

related functions: mmap munmap msync

Function prototype and parameter introduction:

#include <unistd.h>
#include <sys/mman.h>
int msync(const void *start, size_t length, int flags);	
函数功能: 把对内存区域所做的更改同步到文件

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
函数功能: 用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。通过这样可以加快文件访问速度。
返回值:成功返回映射的内存的起始地址。
(1)	第一个参数start指向欲对应的内存起始地址,通常设为NULL,代表让系统自动选定地址,对应成功后该地址会返回。
(2)	第二个参数length代表将文件中多大的部分对应到内存。
(3)	第三个参数prot代表映射区域的保护方式有下列组合:
PROT_EXEC 映射区域可被执行
PROT_READ 映射区域可被读取
PROT_WRITE 映射区域可被写入
PROT_NONE 映射区域不能存取
(4)	第四个参数 flags会影响映射区域的各种特性:
MAP_FIXED  	如果参数start所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。通常不鼓励用此旗标。
MAP_SHARED  对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。
MAP_PRIVATE 对映射区域的写入操作会产生一个映射文件的复制,即私人的“写入时复制”, 对此区域作的任何修改都不会写回原来的文件内容。
MAP_ANONYMOUS 	建立匿名映射。此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。
MAP_DENYWRITE 	只允许对映射区域的写入操作,而不能对fd指向的文件进行读写,对该文件直接写入的操作将会被拒绝。
MAP_LOCKED  	将映射区域锁定住,这表示该区域不会被置换(swap)。
在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。
  
(5)	第五个参数fd为open()返回的文件描述词,代表欲映射到内存的文件。
(6)	第六个参数offset为文件映射的偏移量,通常设置为0,代表从文件最前方开始对应,offset必须是分页大小的整数倍。
  
用法示例:
fb_mem=mmap(NULL,smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
  
int munmap(void *addr, size_t length);
函数功能: 取消映射,用来取消参数start所指的映射内存起始地址,参数length则是欲取消的内存大小。当进程结束,映射内存会自动解除,但关闭对应的文件描述词时不会解除映射。返回值:如果解除映射成功则返回0,否则返回-1。
通过内存映射进行进程通信,多个进程可以同时映射同一个文件到内存空间,只要一个进程对文件进行了修改,其他进程都可以得到修改的数据。
注意: 打开文件的权限需要与映射的权限一致!

2. Case code: mmap usage example (1)

The function of the following code: Create a new file, set the file size, use the mmap function to map the file address, copy the data directly to the address, and then cancel the mapping. At this time, open the file again, and the data has been stored in the file. Demonstrate reading and writing files through mmap mapping file addresses.

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/mman.h>

int main(int argc,char **argv)
{
    if(argc!=2)
    {
        printf("./a.out <文件>\n");
        return 0;
    }
    /*1. 创建一个文件*/
    int fd;
    fd=open(argv[1],O_RDWR|O_CREAT,S_IRWXU);
    if(fd<0)
    {
        printf("%s 文件打开失败.\n",argv[1]);
        return 0;
    }
    /*2. 设置文件的大小*/
    ftruncate(fd, 1024);
    /*3. 获取文件大小*/
    struct stat s_buf;
    fstat(fd,&s_buf);
    printf("文件的大小:%d Byte\n",s_buf.st_size);
    /*4. 映射文件到内存空间*/
    unsigned char *mem_p=NULL;
    mem_p=mmap(NULL,s_buf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if(mem_p==NULL)
    {
        printf("文件映射失败.\n");
        close(fd);
        return 0;
    }
    /*5. 关闭文件*/
    close(fd);
    /*6. 实现文件读写*/
    strcpy(mem_p,"mmap函数测试.实现文件读写.");
    /*7. 打印文件里的内容*/
    printf("mem_p=%s\n",mem_p);
    /*8. 取消映射*/
    munmap(mem_p,s_buf.st_size);
    return 0;
}

3. Case code: mmap usage example (2)

The function of the following code: When the program is running, pass in an existing file path from the command line, then call open to open the file, then map the file address through mmap, and copy a string of string data to the file after getting the address.

Note: Write data through the address mapped by mmap to ensure that the range cannot exceed the size range of the file itself. If it exceeds, it will segfault.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

char buff[]="内存映射测试";
int main(int argc,char **argv)
{
	if(argc!=2)
	{
		printf("./app <文件>\n");
		return 0;
	}
	char *m_p;
	struct stat stat_buf;
	stat(argv[1],&stat_buf);
	int fd=open(argv[1],O_RDWR);
	m_p=mmap(0,stat_buf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if(m_p!=NULL)printf("映射成功!\n");
	printf("m_p=%s\n",m_p);
	//memset(m_p,0,stat_buf.st_size);
	memcpy(m_p,buff,strlen(buff));
	munmap(m_p,stat_buf.st_size);
	close(fd);
	return 0;
}

4. Case code: Multiple processes concurrently copy a large file

Code requirements: Use the mmap function to map files to memory. memcpy()
Use multiple processes to copy a large file concurrently, and consolidate the usage of mmap.
Detailed requirements: Create 5 sub-processes to copy a file at the same time, and each process copies a part of the file.
Set the size of the specified file:int truncate(const char *path, off_t length)

The copy structure diagram is as follows:

Sample code:

Kernel information through train: Linux kernel source code technology learning route + video tutorial code information

Learning through train: Linux kernel source code/memory tuning/file system/process management/device driver/network protocol stack

Original Author: Proficient in Linux Kernel

Original address: Linux Kernel: Process Management - Process Memory Mapping - Zhihu (Copyright belongs to the original author, contact to delete infringement message)

Guess you like

Origin blog.csdn.net/m0_74282605/article/details/130094423