linux ipc 共享内存,Linux IPC 共享内存用法

Linux IPC 常见的方式

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

进程间通信:匿名管道,命名管道,消息队列,共享内存,Domain Socket, 本机 TCP Socket,文件

进程间同步:信号,信号量

线程间同步:条件变量,互斥量,读写锁,自旋锁,Barrier.

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

共享内存IPC的原理

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

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

获取 利用 key 创建或获取一个存在的共享内存对象;

关联 attach, 关联到当前进程的虚拟地址空间;

分离 detach, 从当前进程中分离;

控制 如: 设参数, 锁定, 释放等;

共享内存 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

#include

#include

#include

#include

#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

#include

#include

#include

#include

#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 $@

.PHONY : all

all : shm_read.bin shm_write.bin

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值