首页 > 其他分享 >mmap

mmap

时间:2023-02-03 22:24:04浏览次数:60  
标签:MAP int mmap file printf include ptr

C Programming

原文链接:https://linuxhint.com/using_mmap_function_linux/

How to use mmap function in C language?

3 years ago by Bamdeb Ghosh The mmap() function is used for mapping between a process address space and either files or devices. When a file is mapped to a process address space, the file can be accessed like an array in the program. This is one of the most efficient ways to access data in the file and provides a seamless coding interface that is natural for a data structure that can be assessed without he abstraction of reading and writing from files. In this article, we are going to discuss how to use the mmap() function in Linux. So, let’s get started.

 

Header File:

#include <sys/mman.h>

Syntax:

void * mmap (void *address, size_t length, int protect, int flags, int filedes,
off_t offset)

Arguments:

The function takes 6 arguments:

   

1. address:

This argument gives a preferred starting address for the mapping. If another mapping does not exist there, then the kernel will pick a nearby page boundary and create the mapping; otherwise, the kernel picks a new address. If this argument is NULL, then the kernel can place the mapping anywhere it sees fit.

2. length:

This is the number of bytes which to be mapped.

3. protect:

This argument is used to control what kind of access is permitted. This argument may be logical ‘OR’ of the following flags PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NONE.  The access types of read, write and execute are the permissions on the content.

 

4. flags:

This argument is used to control the nature of the map. Following are some common values of the flags:

  • MAP_SHARED: This flag is used to share the mapping with all other processes, which are mapped to this object. Changes made to the mapping region will be written back to the file.
  • MAP_PRIVATE: When this flag is used, the mapping will not be seen by any other processes, and the changes made will not be written to the file.
  • MAP_ANONYMOUS / MAP_ANON: This flag is used to create an anonymous mapping. Anonymous mapping means the mapping is not connected to any files. This mapping is used as the basic primitive to extend the heap.
  • MAP_FIXED: When this flag is used, the system has to be forced to use the exact mapping address specified in the address If this is not possible, then the mapping will be failed.

5. filedes:

This is the file descriptor which has to be mapped.

 

6. offset:

This is offset from where the file mapping started. In simple terms, the mapping connects to (offset) to (offset+length-1) bytes for the file open on filedes descriptor.

Return values:

On success, the mmap() returns 0; for failure, the function returns MAP_FAILED.

Pictorially, we can represent the map function as follows:

 

 

For unmap the mapped region munmap() function is used :

Syntax:

int munmap(void *address, size_t length);

Return values:

On success, the munmap() returns 0; for failure, the function returns -1.

Examples:

Now we will see an example program for each of the following using mmap() system call:

 
  • Memory allocation (Example1.c)
  • Reading file (Example2.c)
  • Writing file (Example3.c)
  • Interprocess communication (Example4.c)

Example1.c

#include <stdio.h>
#include <sys/mman.h>

int main(){

int N=5;
int *ptr = mmap ( NULL, N*sizeof(int),
 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );

if(ptr == MAP_FAILED){
    printf("Mapping Failed\n");
    return 1;
}

for(int i=0; i<N; i++)
    ptr[i] = i*10;

for(int i=0; i<N; i++)
    printf("[%d] ",ptr[i]);

printf("\n");
int err = munmap(ptr, 10*sizeof(int));
if(err != 0){
    printf("UnMapping Failed\n");
    return 1;
}

return 0;
}

 

In Example1.c we allocate memory using mmap. Here we used PROT_READ | PROT_WRITE protection for reading and writing to the mapped region. We used the MAP_PRIVATE | MAP_ANONYMOUS flag. MAP_PRIVATE is used because the mapping region is not shared with other processes, and MAP_ANONYMOUS is used because here, we have not mapped any file. For the same reason, the file descriptor and the offset value is set to 0.

Example2.c

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

int main(int argc, char *argv[]){

    if(argc < 2){
        printf("File path not mentioned\n");
        exit(0);
    }
   
    const char *filepath = argv[1];
    int fd = open(filepath, O_RDONLY);
    if(fd < 0){
        printf("\n\"%s \" could not open\n",
               filepath);
        exit(1);
    }

    struct stat statbuf;
    int err = fstat(fd, &statbuf);
    if(err < 0){
        printf("\n\"%s \" could not open\n",
                       filepath);
        exit(2);
    }

    char *ptr = mmap(NULL,statbuf.st_size,
            PROT_READ|PROT_WRITE,MAP_SHARED,
            fd,0);
    if(ptr == MAP_FAILED){
        printf("Mapping Failed\n");
        return 1;
    }
    close(fd);

    ssize_t n = write(1,ptr,statbuf.st_size);
    if(n != statbuf.st_size){
        printf("Write failed");
    }

   

    err = munmap(ptr, statbuf.st_size);

    if(err != 0){
        printf("UnMapping Failed\n");
        return 1;
    }
    return 0;
}

 

In Example2.c we have mapped the file “file1.txt”. First, we have created the file, then mapped the file with the process. We open the file in O_RDONLY mode because here, we only want to read the file.

Example3.c

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

int main(int argc, char *argv[]){

    if(argc < 2){
        printf("File path not mentioned\n");
        exit(0);
    }
   
    const char *filepath = argv[1];
    int fd = open(filepath, O_RDWR);
    if(fd < 0){
        printf("\n\"%s \" could not open\n",
               filepath);
        exit(1);
    }

    struct stat statbuf;
    int err = fstat(fd, &statbuf);
    if(err < 0){
        printf("\n\"%s \" could not open\n",
                       filepath);
        exit(2);
    }

    char *ptr = mmap(NULL,statbuf.st_size,
            PROT_READ|PROT_WRITE,
                        MAP_SHARED,
            fd,0);
    if(ptr == MAP_FAILED){
        printf("Mapping Failed\n");
        return 1;
    }
    close(fd);

    ssize_t n = write(1,ptr,statbuf.st_size);
    if(n != statbuf.st_size){
        printf("Write failed\n");
    }


    // Reverse the file contents
    for(size_t i=0; i \n");
    n = write(1,ptr,statbuf.st_size);
    if(n != statbuf.st_size){
        printf("Write failed\n");
    }

    err = munmap(ptr, statbuf.st_size);

    if(err != 0){
        printf("UnMapping Failed\n");
        return 1;
    }
    return 0;
}

 

In Example3.c we have read and then write to the file.

Example4.c

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/mman.h>

int main(){

    int N=5; // Number of elements for the array
   
    int *ptr = mmap(NULL,N*sizeof(int),
     PROT_READ | PROT_WRITE,
     MAP_SHARED | MAP_ANONYMOUS,
     0,0);    

    if(ptr == MAP_FAILED){
     printf("Mapping Failed\n");
     return 1;
    }

    for(int i=0; i < N; i++){
     ptr[i] = i + 1;
    }

    printf("Initial values of the array elements :\n");
    for (int i = 0; i < N; i++ ){
     printf(" %d", ptr[i] );
    }
    printf("\n");

    pid_t child_pid = fork();
   
    if ( child_pid == 0 ){
     //child
     for (int i = 0; i < N; i++){
         ptr[i] = ptr[i] * 10;
     }
    }
    else{
     //parent
     waitpid ( child_pid, NULL, 0);
     printf("\nParent:\n");

     printf("Updated values of the array elements :\n");
     for (int i = 0; i < N; i++ ){
         printf(" %d", ptr[i] );
     }
     printf("\n");
    }

    int err = munmap(ptr, N*sizeof(int));

    if(err != 0){
     printf("UnMapping Failed\n");
     return 1;
    }
    return 0;
}

 

In Example4.c first the array is initialized with some values, then the child process updates the values. The parent process reads the values updated by the child because the mapped memory is shared by both processes.

Conclusion:

The mmap() is a powerful system call. This function should not be used when there are portability issues because this function is only supported by the Linux environment.

   

ABOUT THE AUTHOR

Bamdeb Ghosh

Bamdeb Ghosh is having hands-on experience in Wireless networking domain.He's an expert in Wireshark capture analysis on Wireless or Wired Networking along with knowledge of Android, Bluetooth, Linux commands and python. Follow his site: wifisharks.com

 

其他有用的链接:

https://man7.org/linux/man-pages/man2/mmap.2.html

标签:MAP,int,mmap,file,printf,include,ptr
From: https://www.cnblogs.com/memoryart/p/linux_mmap.html

相关文章

  • 修改文件时mmap如何处理
    拷贝二进制(elf)文件在拷贝二进制文件的时候,如果文件是一个可执行文件,并且有一个进程在运行这个可执行文件,那么拷贝的时候会出现"文本忙"(ETXTBSY)的错误提示,并且拷贝失败......
  • Linux的mmap文件内存映射机制
    在讲述文件映射的概念时,不可避免的要牵涉到虚存(SVR4的VM).实际上,文件映射是虚存的中心概念,文件映射一方面给用户提供了一组措施,好似用户将文件映射到自己地址空......
  • mmap详解
    p107内存映射,简而言之就是将内核空间的一段内存区域映射到用户空间。映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,相反,内核空间对这段区域的修改也直接反映......
  • linux 内存管理(四)malloc--mmap--brk
    用strace分析malloc内存申请过程。长话短说,申请内存空间一般就两种方法,一种是malloc,另一种是mmap映射空间。 在使用malloc()分配内存的时候,可能系统调用brk(),也可能调用m......
  • mmap: Operation not permitted
    char*map_shm=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0);该种情况下会报mmap:Operationnotpermitted修改为char*map_shm=mmap(NULL,size,PROT_READ,......
  • 【OSTEP】动态内存开辟 | 内存API常见错误 | UNIX: brk/sbrk 系统调用 | mmap创建匿名
     ......
  • Linux 零拷贝技术-mmap与sendFile
    零拷贝是网络编程的关键,很多性能优化都离不开数据角度分析:在零拷贝机制中,整个数据在内存中只有一份数据,非零拷贝机制中,内核缓冲区,用户缓冲区,Socket......
  • EnumSet 和 EnumMap 简单理解
    在阅读《EffectiveJava》时,看到了EnumSet,就去查了下。EnumSet首先看一下类图:内部实现上,每个EnumSet内容都表示为位矢量(区别于HashSet底层使用HashMap实现),一般(......
  • mmap_sew延迟问题
    最近项目上遇到一个延迟问题。问题的现象如下:  程序运行在arm上,linux版本是Linuxversion5.10.35-dirty(root@Newu)(aarch64-linux-gnu-gcc(Ubuntu9.4.0-1ubuntu......
  • mmap
    学习bolt源码 bbolt,发现有一处使用到mmap, 开始的时候不明白是什么东西,很是好奇,怎么就把硬盘上的文件读到内存了,并没有看到read方法,后来查了资料,知道原来使用了mmap,所谓......