Process communication -- mmap file memory mapping

Process communication - mmap file memory mapping

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags,
           int fd, off_t offset);
int munmap(void *addr, size_t length);

PROT_EXEC   //Pages may be executed.
PROT_READ   // Pages may be read.
PROT_WRITE  // Pages may be written.
PROT_NONE   // Pages may not be accessed.

MAP_SHARED
MAP_PRIVATE
    

MAP_ANON
MAP_ANONYMOUS

mmap – create

  • parameter
    • addr pass NULL
    • Length the length of the mapping area must be less than or equal to the file size
    • prot
      • PROT_READ readable
      • PROT_WRITE writable
    • flags
      • MAP_SHARED – changes to memory affect source files
      • MAP_PRIVATE - this cannot be selected if the process wants to share
    • fd file descriptor
    • Offset offset
  • Return value
    • Successfully returned the first available memory address
    • Failed to return MAP_FAILED (that is, (void *) -1)

munmap – release

  • parameter
    • Address of addr mapping (return value of mmap)
    • length mmap created length
  • Return value
    • 0 returned successfully
    • Failure returned - 1

Example

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

int main(int argc, char* argv[])
{
    int fd = open("map.txt",O_RDWR);
    if(fd == -1){
        printf("File open failed\n");
        return -1;
    }

    // establish
    char* buf = mmap(NULL,1024,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0);
    if(buf == MAP_FAILED){
        printf("Mapping failed\n");
        return 0;
    }
    // write in
    printf("output:%s\n",buf);
    sprintf(buf,"aaa:%d",10);
    printf("output:%s\n",buf);
    // delete
    int ret = munmap(buf,1024);
    if(ret == -1)    printf("Deletion failed\n");
    
    close(fd);

    return 0;
}

Note: if there is a bus error, please insert content into the mapped file (larger than what you want to insert). Please refer to the answer to question 2

mmap nine questions

  1. If you change the address of the mem variable and release the munmap, can you succeed in passing in mem?

    A: No

  2. What happens if the mem is out of bounds?

    A: the file size has an impact on the operation of the mapping area. Although when the original content of the file is larger than the application range, the number of out of bounds is smaller than the original content size of the file, there will be no problem. However, this is not recommended. Try to make the file and the application size the same and operate within the application size

  3. What happens if the file offset is filled in casually?

    A: creation failed. offset must be an integer multiple of 4K

  4. If the file descriptor is closed first, will it affect the mmap mapping?

    A: no impact

  5. Can I create a file to create a mapping area when open ing?

    A: Yes, but you can't use a file with size 0. You can use ftruncat to set the size

  6. open file select O_WRONLY, okay?

    A: No, because it needs to be read once when loading

  7. When mat is selected_ When shared, open and select O_RDONLY, prot can select PROT_READ | PROT_WRITE?

    A: you cannot map area permission < = open file permission

  8. Under what circumstances will mmap report an error?

    A: errors will be reported in many cases

  9. What happens if you don't judge the return value?

    A: it's ugly to die

    Be sure to judge the return value

Final revision

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

#define MAX_SIZE 1024

int main(int argc, char* argv[])
{
    int fd = open("map.txt",O_RDWR|O_CREAT|O_TRUNC,0664);
    if(fd == -1){
        printf("File open failed\n");
        return -1;
    }
    // enlarge file
    ftruncate(fd,MAX_SIZE);

    // establish
    char* buf = mmap(NULL,MAX_SIZE,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0);
    if(buf == MAP_FAILED){
        printf("Mapping failed\n");
        return 0;
    }
    // write in
    int i=0;
    char *p = buf;
    for(i; i< 10; i++)
    {
        sprintf(p,"aaa:%d ",i);
        p+=6;
    }
    printf("output:%s\n",buf);
    // delete
    int ret = munmap(buf,MAX_SIZE);
    if(ret == -1)    printf("Deletion failed\n");
    
    close(fd);

    return 0;
}

Using mmap to realize the communication between parent and child processes

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

#define MAX_SIZE 1024

int main()
{
    int fd = open("map.txt",O_RDWR|O_CREAT|O_TRUNC,0664);
    if(fd == -1){
        printf("File open failed\n");
        return -1;
    }
    ftruncate(fd,MAX_SIZE);
    // mapping
    char *buf = mmap(NULL,MAX_SIZE,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0);
    if(buf == MAP_FAILED){
        printf("Mapping failed\n");
        return -1;
    }
    // After mapping, the file descriptor can be closed
    close(fd);
    
    // Create child process
    pid_t pid = fork();
    if(pid == 0)    // Subprocess
    {
        printf("Child process starts writing\n");
        int i = 0;
        char *p = buf;
        for(i; i<10; i++)
        {
            sprintf(p,"DAI %2d\n",i);
            p+=8;
        }
        sleep(2);
        printf("The child process views the last modification of the parent process:%s\n",p);
        return 0;   // Subprocess exit
    }
    else if(pid > 0)     // Parent process
    {
        sleep(1);
        printf("Parent process starts reading\n");
        char name[10] = {0};
        int id = 0, i = 0;
        for(i; i< 10; i++)
        {
            sscanf(buf+i*8,"%s %2d",name,&id);
            printf("Read is: %s %2d\n",name,id);
        }
        sprintf(buf+i*8,"I finished reading it\n");
        wait(NULL); // Recycle child process
    }


    int ret = munmap(buf,MAX_SIZE);
    if(ret == -1){
        printf("Failed to unmap file\n");
        return -1;
    }
    
    return 0;
}

anonymous mapping

Through our use, we found that it is very convenient to use the mapping area to complete file reading and writing operations, and it is also convenient for parent-child process communication. However, the defect is that each time we create the mapping area, we must rely on a file. Usually, in order to create the mapping area, we need to open a temp file, In fact, the linux system provides us with a method to create an anonymous mapping area without relying on a file. It also needs to be specified with the help of flag bit flag

Using map_ Anonymous (or MAP_ANON), such as:

MAP_ANONYMOUS MAP_ANON macros are not unique to Linux on some UNIX, but the "/ dev/zero" file can be used

Zero can be regarded as infinity

Extension: / dev/null is called a bottomless hole (you can install files wirelessly and put them down) - general error messages are redirected to this file

int * p = mmap(NULL, 4, PROT_READ|PORT_WRITE, MAP_SHARED|MAP_ANONYMOUS,-1,0);

// Put the above code
int fd = open("map.txt",O_RDWR|O_CREAT|O_TRUNC,0664);
if(fd == -1) {
	printf("File open failed\n");
	return -1;
}
ftruncate(fd,MAX_SIZE);
// mapping
char *buf = mmap(NULL,MAX_SIZE,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0);
if(buf == MAP_FAILED) {
	printf("Mapping failed\n");
	return -1;
}
// After mapping, the file descriptor can be closed
close(fd);

// Replace with
char *buf = mmap(NULL,MAX_SIZE,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0);
if(buf == MAP_FAILED) {
	printf("Mapping failed\n");
	return -1;
}

Supporting unrelated process communication with mmap

Procedure A

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

typedef struct _Student
{
    int sid;
    char sname[20];
}Student;

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        printf("Please add the file name\n");
        return -1;
    }
    
    // 1. open file
    int fd = open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0666);
    int length = sizeof(Student);
    ftruncate(fd,length);

    // 2. mmap
    Student *stu = mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if(stu == MAP_FAILED){
        perror("mmap error");
        return -1;
    }

    // 3. Modify memory data
    int num = 1;
    while(1)
    {
        stu->sid = num;
        sprintf(stu->sname,"Dai Denghui %3d",num++);
        printf("sid = %d, sname = %s\n",stu->sid, stu->sname);
        sleep(1);   // It is equivalent to modifying the content of the mapping area every second
    }

    // 4. Release the mapping area and close the file descriptor
    int ret = mnumap(stu,length);
    if(ret == -1){
        printf("Release failed\n");
    }
    close(fd);

    return 0;
}

Procedure B

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

typedef struct _Student
{
    int sid;
    char sname[20];
}Student;

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        printf("Please add the file name\n");
        return -1;
    }
    
    // 1. open file
    int fd = open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0666);
    int length = sizeof(Student);
    ftruncate(fd,length);

    // 2. mmap
    Student *stu = mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if(stu == MAP_FAILED){
        perror("mmap error");
        return -1;
    }

    // 3. Read memory data
    int num = 1;
    while(1)
    {
        printf("sid = %d, sname = %s\n",stu->sid, stu->sname);
        sleep(1);
    }

    // 4. Release the mapping area and close the file descriptor
    int ret = mnumap(stu,length);
    if(ret == -1){
        printf("Release failed\n");
    }
    close(fd);

    return 0;
}

Keywords: C C++ Linux

Added by Drace on Wed, 08 Sep 2021 21:08:43 +0300