OK6410A 开发板 (八) 102 linux-5.11 OK6410A glibc提供的mmap的四种用途之一

发布者:HarmonySpirit最新更新时间:2022-08-15 来源: csdn关键字:OK6410A  开发板  mmap 手机看文章 扫描二维码
随时随地手机看文章

OK6410A 开发板 (八) 102 linux-5.11 OK6410A glibc提供的mmap的四种用途之一


共享匿名映射两种方式

当使用参数 fd = -1 且 flags = MAP_ANONYMOUS | MAP_SHARED 时,创建的mmap 映射是共享匿名映射.

共享匿名映射让相关进程共享一块内存区域,通常用于父子进程之间的通信.

创建共享匿名映射有如下两种方式,这两种方法最终都调用shmem 模块来创建共享匿名映射

1. fd = -1,且 使用这个文件句柄来创建mmap(lags = MAP_ANONYMOUS | MAP_SHARED) . 

在这种情况下,do_mmap_pgoff()->mmap_region() 函数

最终会调用shmem_zero_setup 来打开一个 "/dev/zero"


2. fd = 打开 "/dev/zero"返回的 fd ,且 使用这个文件句柄来创建mmap(flags = MAP_ANONYMOUS | MAP_SHARED)


注意 : 以下三个实例 都调用了 shmem_zero_setup

实例1 : 走了 mmap_region-> mm/mmap.c(1844)shmem_zero_setup

实例2 : 走了 mmap_region-> mm/mmap.c(1844)shmem_zero_setup 

// 实例2 虽然打开了文件,但是还是走的共享匿名映射

// 共享匿名映射实例 mmap_dev-zero-fd.c 中 匿名和 fd(大于等于0)同时置,是有问题的

实例3 : 走了 mmap_region-> mm/mmap.c(1807)call_mmap(即mmap_zero)->shmem_zero_setup // 走了 共享文件映射


mmap 做共享文件映射的时候可以用 磁盘文件,也可以用 内存文件。 

mmap 做共享匿名映射的时候 ,本质上用的是 /dev/zero(其文件是内存文件/dev/zero) 

至于说这些/dev/下的内存文件 底下藏着什么东西,要看驱动(因为/dev下都是驱动)的实现


tmpfs或其他(udev或devtmpfs) 一般挂载到 /dev下 . shmemfs 一般挂载到 /dev/shm 下

在 /dev 下的 文件 一般都有自己(独有)的 file_operations 

在 /dev/shm 下的 所有文件共享同一个 file_operations 


[5] = { "zero", 0666, &zero_fops, 0 },

/dev/zero 下的 是

static const struct file_operations zero_fops

.mmap       = mmap_zero,

.get_unmapped_area = get_unmapped_area_zero,


[DEVMEM_MINOR] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },

/dev/mem 下的是

static const struct file_operations __maybe_unused mem_fops

.mmap       = mmap_mem,

.get_unmapped_area = get_unmapped_area_mem,


/dev/shm/xxx

tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)

shmem_init

register_filesystem(&shmem_fs_type);

.name       = "tmpfs",

为什么在 /dev/shm 下 创建,是因为

/dev/shm 下 为 shmemfs(tmpfs) 挂载到的目录

也就是说 在 shmemfs 下创建文件.

而对 该文件的 的mmap 是 的底层是  分为两种

//1.

static const struct file_operations shmem_file_operations = {

.mmap       = shmem_mmap,

.get_unmapped_area = shmem_get_unmapped_area,

//2.

#define shmem_file_operations           ramfs_file_operations

const struct file_operations ramfs_file_operations = {

.mmap       = generic_file_mmap,

.get_unmapped_area  = ramfs_mmu_get_unmapped_area,

posix 和 systemv 的 共享内存 都是 基于 shmem 文件系统的 file_operations 的 mmap 做的


共享匿名映射实例 mmap_negtivefd.c

// gcc     mmap_negtivefd.c   -o mmap_negtivefd -lpthread

// mmap_negtivefd.c

#include

#include

#include

#include

#include

#include

#include


struct file_content

{

  sem_t st;

  void *pv;

}file_content;


#define NINT 16


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

{

  int fd;

  fd = -1;

  struct file_content *pfc;

  pfc =mmap (NULL, sizeof (file_content) + sizeof (int) * NINT,

      PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANON, fd, 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 ("结构体地址:tt%xn结构体下一位置地址:tt%xn", (int)pfc, (int)pfc->pv);


  // 不加上这句的话,可能输出会卡在那里!

  setbuf(stdout,NULL);


  //子进程

  if (fork () == 0)

  {

    static int count_child = 0;

    int i;

    while (1)

    {

      sem_wait (&(pfc->st));

      printf ("Child processn");

      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);

      count_child ++;

      if (count_child == 2)

        break;

    }

  }

  // 父进程

  else

  {

    static int count_father = 0;

    int i;

    while (1)

    {

      sem_wait (&(pfc->st));

      printf ("Father processn");

      int *p = pfc->pv;

      /*

         for (i = 0; i < NINT; i++)

         {

         p[i] = 3 * i;

         }

         */


      for (i = 0; i < NINT; i++)

      {

        printf ("%d ", p[i]);

      }

      printf ("n");

      sem_post (&(pfc->st));

      sleep(2);

      count_father ++;

      if (count_father == 2)

        break;

    }

  }


  if (munmap (pfc, sizeof (file_content) + sizeof (int) * NINT) == -1)

  {

    printf ("ummap!n");

    exit (2);

  }

  return 0;

}


共享匿名映射实例 mmap_dev-zero-fd.c

// gcc     mmap_dev-zero-fd.c   -o mmap_dev-zero-fd -lpthread

// mmap_dev-zero-fd.c

#include

#include

#include

#include

#include

#include

#include


struct file_content

{

  sem_t st;

  void *pv;

}file_content;


#define NINT 16


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

{

  int fd;

  #define FILE_PATH "/dev/zero"

  fd = open(FILE_PATH,O_RDWR);

  if(fd < 0)

  {

    printf("open zero fail n");

    exit(2);

  }


  struct file_content *pfc;

  pfc =mmap (NULL, sizeof (file_content) + sizeof (int) * NINT,

      PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANON, fd, 0);


  close(fd);


  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 ("结构体地址:tt%xn结构体下一位置地址:tt%xn", (int)pfc, (int)pfc->pv);


  // 不加上这句的话,可能输出会卡在那里!

  setbuf(stdout,NULL);


  //子进程

  if (fork () == 0)

  {

    static int count_child = 0;

    int i;

    while (1)

    {

      sem_wait (&(pfc->st));

      printf ("Child processn");

      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);

      count_child ++;

      if (count_child == 2)

        break;

    }

  }

  // 父进程

  else

  {

    static int count_father = 0;

    int i;

    while (1)

    {

      sem_wait (&(pfc->st));

      printf ("Father processn");

      int *p = pfc->pv;

      /*

         for (i = 0; i < NINT; i++)

         {

         p[i] = 3 * i;

         }

         */


      for (i = 0; i < NINT; i++)

      {

        printf ("%d ", p[i]);

      }

      printf ("n");

      sem_post (&(pfc->st));

      sleep(2);

      count_father ++;

      if (count_father == 2)

        break;

    }

  }


  if (munmap (pfc, sizeof (file_content) + sizeof (int) * NINT) == -1)

  {

    printf ("ummap!n");

    exit (2);

  }

  return 0;

}


其他

共享文件映射实例 mmap_dev-zero-fd2.c

这个 在文本上 比 "共享匿名映射实例 mmap_dev-zero-fd.c" 少了一个  "|MAP_ANON" , 其他都一样

这个 在效果上 和 "共享匿名映射实例 mmap_dev-zero-fd.c" 完全一样

这个 和 "共享匿名映射实例 mmap_dev-zero-fd.c" 在本质上有什么不同 ??? TODO

这个 和 "共享匿名映射实例 mmap_dev-zero-fd.c" 都调用了 shmem_zero_setup


// gcc     mmap_dev-zero-fd2.c   -o mmap_dev-zero-fd2 -lpthread

// mmap_dev-zero-fd.c

#include

#include

#include

#include

#include

#include

#include


struct file_content

{

  sem_t st;

  void *pv;

}file_content;



#define NINT 16




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

{

  int fd;

  #define FILE_PATH "/dev/zero"

  fd = open(FILE_PATH,O_RDWR);

  if(fd < 0)

  {

    printf("open zero fail n");

    exit(2);

  }


  struct file_content *pfc;

  pfc =mmap (NULL, sizeof (file_content) + sizeof (int) * NINT,

      PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);


  close(fd);


  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 ("结构体地址:tt%xn结构体下一位置地址:tt%xn", (int)pfc, (int)pfc->pv);


  // 不加上这句的话,可能输出会卡在那里!

  setbuf(stdout,NULL);

[1] [2]
关键字:OK6410A  开发板  mmap 引用地址:OK6410A 开发板 (八) 102 linux-5.11 OK6410A glibc提供的mmap的四种用途之一

上一篇:OK6410A 开发板 (八) 104 linux-5.11 OK6410A mmap四种用途参数及扩展
下一篇:OK6410A 开发板 (八) 101 linux-5.11 OK6410A printf 在 glibc 和 linux 中的流程

推荐阅读最新更新时间:2024-11-16 18:15

JLink+GDBServer调试S3C6410裸板的初始化代码 For OK6410开发板
要调试裸板,有两种初始化方法,一个是用烧好的uboot初始化,再有就是直接用JLink+GDBServer初始化。代码参考了网上的资料,根据手头的OK6410开发板做了修改。整体代码如下: # Connect to the J-Link GDBServer target remote localhost:2331 # Set JTAG speed to 30 kHz monitor endian little monitor speed 30 # Reset the target monitor reset monitor sleep 10 # # CPU core initialization # # Set the pr
[单片机]
MSP430 DM430-A开发板学习笔记(三)测速模块(计数传对射感器)的使用
1.传感器说明 简要说明: 一、长尺寸:32mm X宽11mm X高20mm 二、主要芯片:LM393、对射式红外头 三、工作电压:直流5伏 四、特点: 1、具有信号输出指示。 2、单路信号输出。 3、输出有效信号为低电平。 4、灵敏度不可调。 5、可用于工件计数、电机测速。。。。 6、电路板输出开关量! 2.传感器连接实物图及测试代码 将传感器供电 将其out接到msp430的io口上 在iar编程软件中设置好相应的io口p1.2为输入端,检测p1.2是否输入低电平,若是低电平,则让另外一个io口p1.4输出低电平,从而使与之相连的led灯亮 代码如下 #include msp430x14x.h int ma
[单片机]
MSP430 DM430-A<font color='red'>开发板</font>学习笔记(三)测速模块(计数传对射感器)的使用
OK6410A 开发板 (八) 117 linux-5.11 OK6410A linux系统调用
访问内核空间,linux提供了系统调用,分为多类, 1.文件系统相关的接口open,read,等file_operations中的接口(具体有什么,看具体文件系统) 2.进程控制 3.进程通信 4.内存管理 5.系统控制 reboot 6.用户管理 如何查看当前运行或者编译的 linux系统中有多少个 系统调用,以及分别是什么 编译时 : cat System.mmap |grep sys_ , 这里面不仅包括系统调用,还有一些其他的东西,例如 sys_mmap_pgoff // 注意:sys_mmap_pgoff 不是 系统调用 编译时 : arch/arm/kernel/e
[单片机]
基于ARM开发板平台的嵌入式软件保护方案
从软件到软硬件联合攻击给嵌入式系统造成严峻的安全威胁。安全性已成为嵌入式系统设计中必不可少的一部分,同时这又是一个折衷的过程,不能单靠软件来保证,而全硬件的解决方式很昂贵且不具有弹性。很多产品开始从设计之初就从系统架构上考虑了安全性,如ARM公司的TruSTZONe技术开辟了一片可信代码区,近年来。通过一个S比特来区分系统的安全状态,IBMPowerPC中使用了多核单元宽带引擎(BE进行安全引导和物理隔离。 嵌入式软件与嵌入式系统是密不可分的,嵌入式系统是“控制、监视或者辅助设备、机器和车间运行的装置”,就是以应用为中心,以计算机技术为基础,并且软硬件可裁剪,适用于应用系统对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系
[单片机]
基于ARM<font color='red'>开发板</font>平台的嵌入式软件保护方案
S3C2440—1.熟悉裸机开发板
一.板载资源介绍 开发板使用了三星的JZ2440V3(基于S3C2440改进的版本),网上有丰富的资源,有助于学习,板载资源如图所示: 需要特别注意以下几点: 一般使用JTAG烧写口来烧写程序,用eop即可 有俩个USB接口,其中USB-SERIAL可以连接开发板与上位机,通过串口进行调试 另外一个USB口,可以用来下载程序 板载2M的 Nor FLASH,可将程序直接烧写在此 板载256M的 Nand FLASH,作为主要的数据存储中心,可以将程序烧写在此 启动方式可以选择:Nor 或 Nand 启动,一般用Nand 二.安装驱动及上位机 入门开始要安装以下这几个: 1.要安装USB串口的驱动以及上位机 2.要安装
[单片机]
S3C2440—1.熟悉裸机<font color='red'>开发板</font>
Moser现货供应STMicroelectronics Nucleo 开发板
贸泽电子(Mouser Electronics)现库存并供应 STMicroelectronics 新型 Nucleo 开发板。此类开发板专为欲使用 ST 的 STM32 产品系列(具有 ARM Cortex M0、Cortex M3 及 Cortex M4 微控制器)进行开发的人士而设计,并与多种扩展板兼容。 Mouser提供的 STMicroelectronics 新型 Nucleo 开发板 支持开发及评估 ST 的 32 位 STM32 微控制器。此新型开发板具有其他微控制器开发生态系统所不具有的多项高级特性。除了惯有的按钮、LED 和一个 USB 调试接口的组合外,Nucleo 板还独具特色地配有两组扩展接口。第一
[单片机]
Linux常用的命令及ARM开发板的一些技能用法
Linux 开发板UBUNTU18.04 注意 qt5.8 网络配置基本命令 ifconfig eth0 XXX.XXX.XXX df -hl df --help 硬盘 free -h free --help 内存 ps -ef 查看所有进程 top #实时显示进程状态 Ipcs -a/q/m/s 进程管理命令,共享内存,消息队列,信号量等 Ipcrm -m/M 查看与/dev/input目录下的event对应的设备:cat /proc/bus/input/devices 查看CPU信息:cat /proc/cpuinfo 查看内存信息:cat /proc/meminfo 查看USB设备:cat /p
[单片机]
Linux常用的命令及ARM<font color='red'>开发板</font>的一些技能用法
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • ARM裸机篇--按键中断
    先看看GPOI的输入实验:按键电路图:GPF1管教的功能:EINT1要使用GPF1作为EINT1的功能时,只要将GPFCON的3:2位配置成10就可以了!GPF1先配 ...
  • 网上下的--ARM入门笔记
    简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所 ...
  • 学习ARM开发(23)
    三个任务准备与运行结果下来看看创建任务和任运的栈空间怎么样的,以及运行输出。Made in china by UCSDN(caijunsheng)Lichee 1 0 0 ...
  • 学习ARM开发(22)
    关闭中断与打开中断中断是一种高效的对话机制,但有时并不想程序运行的过程中中断运行,比如正在打印东西,但程序突然中断了,又让另外一个 ...
  • 学习ARM开发(21)
    先要声明任务指针,因为后面需要使用。 任务指针 volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • 学习ARM开发(20)
  • 学习ARM开发(19)
  • 学习ARM开发(14)
  • 学习ARM开发(15)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved