共享内存区是可用IPC形式中最快的。一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核。然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步。不再涉及内核是指:进程不再通过运行不论什么进入内核的系统调用来彼此传递数据。内核必须建立同意各个进程共享该内存区的内存映射关系。然后一直管理内存区。

默认情况下通过fork派生的子进程并不与其父进程共享内存区。

mmap函数把一个文件或一个Posix共享内存区对象映射到调用进程的地址空间。使用该函数的目的有:

1、使用普通文件以提供内存映射I/O。

2、使用特殊文件以提供匿名内存映射。

3、使用shm_open以提供无亲缘关系进程间的Posix共享内存区。

#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);

addr指定描写叙述符fd应被映射到的进程内空间的起始地址。

若为空指针,则由内核自己去选择起始地址。不管哪种情况。该函数的返回值都是描写叙述符fd所映射到内存区的起始地址。

len是映射到调用进程地址空间中的字节数,它从被映射文件开头起第offset个字节处開始算。

offset通常设置为0。

prot參数指定内存区映射区的保护。

有下面四种:PROT_READ(数据可读)、PROT_WRITE(数据可写)、PROT_EXEC(数据可运行)、PROT_NONE(数据不可訪问)。

flags有下面三种:MAP_SHARED(变动是共享的)、MAP_PRIVATE(变动是私有的)、MAP_FIXED(准确地解释addr參数)。

父子进程之间共享内存区的方法之中的一个是,父进程在调用fork前先指定MAP_SHARED调用mmap。

mmap成功返回后,fd參数能够关闭。该操作对由mmap建立的映射关系没有影响。

为某个进程的地址空间删除一个映射关系,我们调用munmap。

(int munmap(void *addr, size_t len))

调用msync来运行同步。

(int msync(void *addr, size_t len, int flags))

注意:不是全部文件都能进程内存映射,比如:试图把一个訪问终端或套接字的描写叙述符映射到内存将导致mmap返回一个错误。这些类型的描写叙述符必须使用read和write来訪问。

mmap的还有一个用途是在无亲缘关系的进程间提供共享的内存区。

程序实例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h> #define SEM_NAME "mysem"
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) int
main(int argc, char **argv)
{
int fd, i, nloop, zero = 0;
int *ptr;
sem_t *mutex; if(argc != 3){
printf("usage:incrl <pathname> <#nloops>\n");
return -1;
}
nloop = atoi(argv[2]); /*open file , initialize to 0, map into memory*/
fd = open(argv[1], O_RDWR | O_CREAT, FILE_MODE);
write(fd, &zero, sizeof(int));
ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd); /*create, initialize, and unlink semaphore*/
mutex = sem_open(SEM_NAME, O_CREAT | O_EXCL, FILE_MODE, 1);
if(mutex < 0){
printf("sem_open error.\n");
return -1;
}
sem_unlink(SEM_NAME); setbuf(stdout, NULL); /*stdout is unbuffered*/
if(fork() == 0){
for(i = 0; i < nloop; i++){
sem_wait(mutex);
printf("child:%d\n", (*ptr)++);
sem_post(mutex);
}
exit(0);
} /*parent*/
for(i = 0; i < nloop; i++){
sem_wait(mutex);
printf("parent:%d\n", (*ptr)++);
sem_post(mutex);
}
exit(0);
}

注意:内存映射一个普通文件时,内存中映射区的大小通常等于该文件的大小。然而文件大小和内存映射区大小能够不同。

Linux环境编程之共享内存区(一):共享内存区简单介绍的更多相关文章

  1. Linux环境编程相关的文章

    Linux环境编程相关的文章 好几年没有接触Linux环境下编程了,好多东西都有点生疏了.趁着现在有空打算把相关的一些技能重拾一下,顺手写一些相关的文章加深印象. 因为不是写书,也受到许多外部因素限制 ...

  2. 【转】Linux环境搭建FTP服务器与Python实现FTP客户端的交互介绍

    Linux环境搭建FTP服务器与Python实现FTP客户端的交互介绍 FTP 是File Transfer Protocol(文件传输协议)的英文简称,它基于传输层协议TCP建立,用于Interne ...

  3. (转)Linux环境进程间通信系列(五):共享内存

    原文地址:http://www.cppblog.com/mydriverc/articles/29741.html 共享内存可以说是最有用的进程间通信方式,也是最快的 IPC 形式.两个不同进程 A ...

  4. Linux环境编程导引

    计算机系统硬件组成 总线 贯穿整个系统的一组电子管道称为总线, 分为: 片内总线 系统总线 数据总线DB 地址总线AB 控制总线CB 外部总线 I/O设备 I/O设备是系统与外界联系的通道 键盘鼠标是 ...

  5. Linux环境编程之同步(四):Posix信号量

    信号量是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语.有三种类型:Posix有名信号量,使用Posix IPC名字标识.Posix基于内存的信号量,存放在共享内存区中:System ...

  6. Linux 环境编程:dirfd参数 有关解析

    背景 在Unix环境编程中,系统提供了很多以at结尾的函数,如openat.fstatat等,而这类函数通常有一个特点,就是形参列表中多了int dirfd 例如: int open(const ch ...

  7. Linux环境编程--waitpid与fork与execlp

    waitpid waitpid(等待子进程中断或结束) 表头文件 #include<sys/types.h> #include<sys/wait.h> 定义函数 pid_t w ...

  8. Linux环境编程进程间通信机制理解

    一.Linux系统调用主要函数 二.创建进程 1.创建子进程系统调用fork() 2.验证fork()创建子进程效果 3.系统调用fork()与挂起系统调用wait() 三.模拟进程管道通信 四.pi ...

  9. 笔记整理:计算CPU使用率 ----linux 环境编程 从应用到内核

    linux 提供time命令统计进程在用户态和内核态消耗的CPU时间: [root@localhost ~]# time sleep real 0m2.001s user 0m0.001s sys 0 ...

随机推荐

  1. #学习笔记#——JavaScript 数组部分编程(二)

    2.移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回 function removeWithoutCopy(arr, item) { if(!A ...

  2. 【深入篇】Android常用布局方式简介

    LinearLayout 线性布局是程序中最常见的布局方式.一般分为水平线性布局和竖直线性布局,通过android.orientation属性可以设置线性布局的方向. 在布局中操作颜色时,要用的是十六 ...

  3. svg(1) path路径

    注: 笔记来自于http://www.jb51.net/html5/72250.html  以及http://blog.csdn.net/u013291076/article/details/2707 ...

  4. jQuery对象与js对象转换

    前言 jq方法和js的方法属性是不能互相使用的,所以有时候就需要转一下,下面就介绍下方法. js对象转化为jQuery对象 var box=document.getElementById(" ...

  5. git把本地文件上传到github上的步骤

    1.清除clean 2.返回上一级cd .. 3.克隆仓库地址git clone+地址 4.添加忽悠文件vim .gitignore 5查看cat .gitignore 6.进入到test,并且添加所 ...

  6. IE兼容性开发的笔记

    当前项目组开发的产品对外承诺支持IE9和IE11,但在推广应用过程中发现存在相当比例的用户实际上还在使用IE8.而这相当比例中的用户还包含了大部分的公司领导.为了满足公司内部各阶层人士体验我们产品的诉 ...

  7. Cannot use isset() on the result of an expression (you can use "null !== expression" instead)

    if (isset($array[2])){ 抛出错误  Cannot use isset() on the result of an expression (you can use "nu ...

  8. 10lession-if-else条件语句

    python的条件选择语句跟其他语言的及其相似,这里就不做详细记录,仅仅是看个例子好了 #!/usr/bin/python "]: print('1 in [1,2,3,"4&qu ...

  9. Codefroces 812 B. Sagheer, the Hausmeister

    http://codeforces.com/problemset/problem/812/B B. Sagheer, the Hausmeister time limit per test 1 sec ...

  10. [原创]react-vio-form 快速构建React表单应用

    react-vio-form 是一个react的快速轻量表单库,能快速实现表单构建.提供自定义表单格式.表单校验.表单信息反馈.表单信息隔离等功能.可采用组件声明或者API的形式来实现表单的功能 de ...