ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

8-1 mmap设备方法

2022-07-17 12:05:57  阅读:165  来源: 互联网

标签:pfc 映射 int mmap vma include 方法 设备


1、mmap函数原型

void *mmap(void *addr, size_t len, int prot, int flag, int fd, offset_t offset)
作用:
(1)内存映射函数mmap,负责把文件内容映射到进程的虚拟地址空间。这样做的目的就是减少read和write操作。
(2)也可以通过匿名映射实现进程通信。
addr:指定映射起始地址,通常为NULL,一般由内核指定
length:映射的内存文件长度
prot:映射区的保护方式:
PROT_EXEC:映射区可被执行
PROT_READ:映射区可被读取
PROT_WRITE:映射区可被读写
flags:映射区的特性
MAP_SHARED:写入映射区的数据会复制回文件,且允许其他映射 该文件的进程分享
MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制(copy-on-write技术),对此区域的修改不会写回文件。
fd:文件
offset:文件的偏移,一般是0,从文件开头映射。

匿名映射:匿名内存映射适用于具有亲属关系的进程之间;由于父子进程之间的这种特殊的父子关系,在父进程中先调用mmap(),然后调用fork(),那么,在调用fork() 之后,子进程继承了父进程的所有资源,当然也包括匿名映射后的地址空间和mmap()返回的地址,这样父子进程就可以通过映射区域进行通信了;

 

 

2、int munmap(void *start, size_t length)
作用:解除映射。start地址是mmap的返回值。

3、虚拟内存区域
cat /proc/pid/maps可以查看所有的vma

linux内核通过vm_area_struct结构体来记录一个vma的数据:
主要包括几个成员:
vm_start,vm_end,vm_flags.等等

 

4、mmap实例

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

int main(void)
{
    int fd;
    char *start;
    
    fd=open("testfile",O_RDWR);
    start=mmap(NULL, 100, PROT_READ|PROT_WRITE, MAP_SHARED,fd, 0);
    
    strcpy(buf, start);//读数据
    printf("buf=%s\n", buf);
    
    strcpy(start,"buf is not null!" );//写数据
    munmap(start, 100);
    close(fd);
    return 0;
}

5、匿名映射实例

(20条消息) mmap匿名映射_SweeNeil的博客-CSDN博客_mmap匿名映射

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <semaphore.h>
 
struct file_content
{
    sem_t st;
    void *pv;
}file_content;
 
#define NINT 16
 
int main (int argc, char *argv[])
{
    struct file_content *pfc;
    pfc =mmap (NULL, sizeof (file_content) + sizeof (int) * NINT, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
    if (pfc == MAP_FAILED)
    {
        printf ("map failed!\n");
        exit(3);
    }
 
    //信号量初始化为1,用于互斥
    sem_init (&(pfc->st), 1, 1);        
    //pv指向结构体下一个字节的地址
    pfc->pv = (void *) ((char *) pfc + sizeof (struct file_content));     
    printf("结构体地址:\t\t%x\n结构体下一位置地址:\t\t%x\n", (int)pfc, (int)pfc->pv);
 
    //不加上这句的话,可能输出会卡在那里!
    setbuf(stdout,NULL);//和fflush函数没什么区别吧
 
    //子进程
    if (fork() == 0)        
    {
        int i;
        while (1)
        {
            sem_wait (&(pfc->st));
            printf ("Child process\n");
            int *p = pfc->pv;
            for (i = 0; i < NINT; i++)
            {
                p[i] = 2 * i;
            }   
            for (i = 0; i < NINT; i++)
            {
                printf ("%d ", p[i]);
            }
            printf ("\n"); 
            sem_post (&(pfc->st)); 
            sleep(2); 
        }
    }
    else// 父进程
    {
        int i;
        while (1)
        {
            sem_wait (&(pfc->st));
            printf ("Father process\n");
            int *p = pfc->pv;

            for (i = 0; i < NINT; i++)
            {
                printf ("%d ", p[i]);
            }
            printf ("\n");
            sem_post (&(pfc->st));
            sleep(2);
        }
    }
 
    if (munmap (pfc, sizeof (file_content) + sizeof (int) * NINT) == -1)
    {
          printf ("ummap!\n");
          exit (2);
    }
    return 0;
}

 

6、mmap设备操作
映射一个设备是指用户空间的一段地址关联到设备内存上。然后直接通过用户空间内存对设备内存进行访问。
mmap方法是file_oprations结构的成员,在mmap系统调用发出时被调用。在此之前,内核已经完成了很多工作。mmap设备方法所需要做的就是建立虚拟地址到物理地址的页表。

如何建立页表?建立什么页表?
(1)使用remap_pfn_range一次建立所有页表
(2)使用nopage VMA方法每次建立一个页表
函数原型:
int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn,unsigned long size, pgprot_t prot);
参数:
vma:虚拟内存区域指针
pfn: 要映射的物理地址所在的物理页帧号,可将物理地址>>PAG_SHIFT得到。物理地址如何得到呢???
addr:虚拟地址的起始值
size:要映射的区域大小
prot:VMA的保护属性

实例:
int memdev_mmap(struct file *filep, struct vma_area_struct *vma)//参数是如何获取到的??
{
  vma->vm_flags |= VM_IO;
  vma->vm_flags |= VM_RESERVED;

  remap_pfn_range(vma,vma->vm_start,virt_to_phys(dev->data)>>PAGE_SHIFT, size, vma->vm_page_prot);
  return 0;
}

 

标签:pfc,映射,int,mmap,vma,include,方法,设备
来源: https://www.cnblogs.com/luckdog0623/p/16486213.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有