Linux IPC 共享内存用法

Linux IPC 常见的方式

写 Linux Server 端程序,必然会涉及到进程间通信 IPC. 通信必然伴随着同步机制,下面是一些常见的通信与同步机制:

  1. 进程间通信:匿名管道,命名管道,消息队列,共享内存,Domain Socket, 本机 TCP Socket,文件
  2. 进程间同步:信号,信号量
  3. 线程间同步:条件变量,互斥量,读写锁,自旋锁,Barrier.

对于大部分的业务场景,本机 TCP Socket 足以,现在Linux 也对本机 TCP Socket做了很好的优化。而且如果以后需要分机器部署进程,那么程序不需要怎么改动,十分方便。至于 Domain Socket,应用也很广泛,可以看这篇文章:UNIX Domain Socket IPC

共享内存IPC的原理

用共享内存做IPC手段的最大优势是效率最高,缺点是需要借助其他同步机制

共享内存IPC的基本原理也很简单:把同一块物理内存映射到多个进程的虚拟地址空间,进程虚拟地址布局可以看这篇:Linux虚拟地址空间布局。Linux 在 <sys/shm.h> 提供了相关操作的接口:

  1. 获取 利用 key 创建或获取一个存在的共享内存对象;
  2. 关联 attach, 关联到当前进程的虚拟地址空间;
  3. 分离 detach, 从当前进程中分离;
  4. 控制 如: 设参数, 锁定, 释放等;

详细的函数接口说明可以看: Linux进程间通信——使用共享内存

共享内存 IPC 例子

下面的 demo 一个读,一个写,IPC采用共享内存,同步就用最简单的条件变量配合。最终实现在一个进程读标准输入,另外一个进程输出到控制台。

可以使用 ipcs -m 查看系统使用的共享内存 IPC资源列表。

公共头文件:

/* file: shm_comm.h */

#ifndef _SHM_COMM_H
#define _SHM_COMM_H

#define MY_SHM_KEY 0x12
#define READ_SHM 1
#define WRITE_SHM -1

typedef struct {
    int flag;
    char buff[1020];
}__attribute__((packed)) S_SHM_BUF;  // 单字节对齐,方便 ipcs -m 查看对比大小

#endif

读进程

/* file:shm_read.c */

#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include "shm_comm.h"

int main()
{
    void *shm = NULL;
    S_SHM_BUF *shbuf;
    int ret = 0;
    int shmid = 0;

    /* 由 key 申请共享内存, 得到 id */
    shmid = shmget(MY_SHM_KEY, sizeof(S_SHM_BUF), IPC_CREAT);
    if (-1 == shmid) {
        printf("get share memory failed!\n");
        exit(EXIT_FAILURE);
    }

    /* 根据 id 把共享内存 attach 到进程地址空间,得到首地址 */
    shm = shmat(shmid, 0, 0);
    if (-1L == (long)shm) {
        printf("share memory attach failed!\n");
    }
    printf("share memory attached at %p\n", shm);

    shbuf = (S_SHM_BUF*)shm;
    while (1) {
        if (READ_SHM == shbuf->flag) {
            printf("read: %s\n", shbuf->buff);
            shbuf->flag = WRITE_SHM;
            if (0 == strncmp(shbuf->buff, "end", 3)) {
                break;
            }
        } else {
            sleep(1);
        }
    }

    /* 根据首地址,把共享内存从进程空间 detach 掉 */
    ret = shmdt(shm);
    if (-1 == ret) {
        printf("share memory detach failed!\n");
        exit(EXIT_FAILURE);
    }

    /* 根据id,让操作系统删掉共享内存 */
    ret = shmctl(shmid, IPC_RMID, 0);
    if (-1 == ret) {
        printf("share memory remove failed!\n");
        exit(EXIT_FAILURE);
    }

    printf("program end ok!\n");
    return 0;
}

写进程

/* file: shm_write.c */

#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include "shm_comm.h"

int main()
{
    void *shm = NULL;
    S_SHM_BUF *shbuf;
    int ret = 0;
    int shmid = 0;

    shmid = shmget(MY_SHM_KEY, sizeof(S_SHM_BUF), IPC_CREAT);
    if (-1 == shmid) {
        printf("get share memory failed!\n");
        exit(EXIT_FAILURE);
    }

    shm = shmat(shmid, 0, 0);
    if (-1L == (long)shm) {
        printf("share memory attach failed!\n");
    }
    printf("share memory attached at %p\n", shm);

    shbuf = (S_SHM_BUF*)shm;
    memset(shbuf, 0, sizeof(*shbuf));
    shbuf->flag = WRITE_SHM;

    while (1) {
        if (WRITE_SHM == shbuf->flag) {
            printf("write: ");
            scanf("%s", shbuf->buff);
            shbuf->flag = READ_SHM;
            if (0 == strncmp(shbuf->buff, "end", 3)) {
                break;
            }
        } else {
            sleep(1);
        }
    }

    ret = shmdt(shm);
    if (-1 == ret) {
        printf("share memory detach failed!\n");
        exit(EXIT_FAILURE);
    }

    printf("program end ok!\n");
    return 0;
}

Makefile

# Makefile
CFLAGS  = -Wall -Werror -g -m64
compile = $(CC) $(CFLAGS) $^ -o [email protected]

.PHONY : all
all : shm_read.bin shm_write.bin

# 注意 makefile 的缩进要用<TAB>
shm_read.bin : shm_read.c shm_comm.h
    $(compile)

shm_write.bin : shm_write.c shm_comm.h
    $(compile)

.PHONY : clean
clean:
    rm *.bin
时间: 2024-10-28 20:46:03

Linux IPC 共享内存用法的相关文章

Linux进程间通信—共享内存

五.共享内存(shared memory) 共享内存映射为一段可以被其他进程访问的内存.该共享内存由一个进程所创建,然后其他进程可以挂载到该共享内存中.共享内存是最快的IPC机制,但由于linux本身不能实现对其同步控制,需要用户程序进行并发访问控制,因此它一般结合了其他通信机制实现了进程间的通信,例如信号量. 共享内存与多线程共享global data和heap类似.一个进程可以将自己内存空间中的一部分拿出来,允许其它进程读写.当使用共享内存的时候,我们要注意同步的问题.我们可以使用 sema

Linux进程间通信——共享内存

下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 特别提醒:共

linux进程间通信之Posix共享内存用法详解及代码举例

Posix共享内存有两种非亲缘进程间的共享内存方法:1).  使用内存映射文件,由open函数打开,再由mmap函数把返回的文件描述符映射到当前进程空间中的一个文件. 2). 使用共享内存区对象,由shm_open打开一个 Posix IPC名字.再由mmap把返回的描述符映射到当前进程的地址空间. Posix共享内存相关函数头文件及原型:#include <sys/mman.h>int shm_open(const char *name, int oflag, mode_t mode);功能

进程-IPC 共享内存和消息队列 (三)

详见:https://github.com/ZhangzheBJUT/linux/blob/master/IPC(%E4%B8%89).md 五 共享内存 5.1. 共享内存简介 共享内存指多个进程共享同一块物理内存,它只能用于同一台机器上的两个进程之间的通信.在进程的逻辑地址空间中有一段地址范围是用来进行内存映射使用的,该段逻辑地址空间可以映射到共享的物理内存地址上(进程空间介绍:http://blog.csdn.net/zhangzhebjut/article/details/3906025

Linux --进程间通信--共享内存

一.共享内存 共享内存是最高效的通信方式,因为不需要一个进程先拷贝到内核,另一个进程在存内核中读取. 二. ipcs -m 查看共享内存 ipcrm -m 删除共享内存 三.主要函数 shmget 创建 shmctl 删除 shmat 挂接 shmdt 取消挂接 ********* man 函数名 查看***** 四.代码实现 comm.h   1 #pragma once   2 #include<stdio.h>   3 #include<stdlib.h>   4 #incl

linux使用共享内存通信的进程同步退出问题

两个甚至多个进程使用共享内存(shm)通信,总遇到同步问题.这里的“同步问题”不是说进程读写同步问题,这个用信号量就好了.这里的同步问题说的是同步退出问题,到底谁先退出,怎么知道对方退出了.举个例子:进程负责读写数据库A,进程B负责处理数据.那么进程A得比进程B晚退出才行,因为要保存进程B处理完的数据.可是A不知道B什么时候退出啊.A.B是无关联的进程,也不知道对方的pid.它们唯一的关联就是读写同一块共享内存.正常情况下,进程B在共享内存中写个标识:进程A你可以退出了,也是可以的.不过进程B可

Linux 进程间通信 - 共享内存shmget方式

共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容.这块共享虚拟内存的页面,出现在每一个共享该页面的进程的页表中.但是它不需要在所有进程的虚拟内存中都有相同的虚拟地址 以下是使用共享内存机制进行进程间通信的基本操作: 需要包含的头文件: #include

linux程序设计——共享内存(第十四章)

14.2    共享内存 共享内存是3个IPC机制中的第二个,它允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间传递数据的一种非常有效的方式.大多数共享内存的具体实现,都把由不同进程之间共享的内存安排为同一段物理内存. 共享内存是由IPC为进程创建的一个特殊的地址访问,它将出现在该进程的地址空间中,其他进程可以将同一段共享内存连接到它们自己的地址空间中.所有进程都可以访问共享内存中的地址,就好像它们是由malloc分配的一样.如果某个进程向共享内存写入了数据,所做的改动

IPC——共享内存

Linux进程间通信——使用共享内存 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段