嵌入式linux 共享内存,linux 共享内存

本文关键字: linux 共享内存,linux 共享内存编程

可以说,共享内存是一种为高效的进程间通信方式,因为进程可以直接读写内存,不需要任何数据的复制。为了在多个进程间交换信息,内核专门留出了一块内存区,这段内存区可以由需要访问的进程将其映射到自己的私有地址空间。因此,进程就可以直接读写这一内存区而不需要进行数据的复制,从而大大提高了效率。当然,由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等。其原理示意图如图1所示。

7435318a2092cd00afbc86853b5a877c.png

图1 共享内存原理示意图

共享内存的实现分为两个步骤:第一步是创建共享内存,这里用到的函数是shmget(),也就是从内存中获得一段共享内存区域;第二步是映射共享内存,也就是把这段创建的共享内存映射到具体的进程空间中,这里使用的函数是shmat()。到这里,就可以使用这段共享内存了,也就是可以使用不带缓冲的I/O读写命令对其进行操作。除此之外,还有撤销映射的操作,其函数为shmdt()。这里主要介绍这3个函数。

表1 列举了shmget()函数的语法要点。

表1 shmget()函数语法要点

所需头文件

#include

#include

#include

函数原型

int shmget(key_t key, int size, int shmflg)

函数传入值

key:共享内存的键值,多个进程可以通过它访问同一个共享内存,其中有个特殊值IPC_PRIVATE,用于创建当前进程的私有共享内存

size:共享内存区大小

shmflg:同open()函数的权限位,也可以用八进制表示法

函数返回值

成功:共享内存段标识符

出错:-1

表2列举了shmat()函数的语法要点。

表2 shmat()函数语法要点

所需头文件

#include

#include

#include

函数原型

char *shmat(int shmid, const void *shmaddr, int shmflg)

函数传入值

shmid:要映射的共享内存区标识符

shmaddr:将共享内存映射到指定地址(若为0则表示系统自动分配地址并把该段共享内存映射到调用进程的地址空间)

shmflg

SHM_RDONLY:共享内存只读

默认0:共享内存可读写

函数返回值

成功:被映射的段地址

出错:-1

表3列举了shmdt()函数的语法要点。

表3 shmdt()函数语法要点

所需头文件

#include

#include

#include

函数原型

int shmdt(const void *shmaddr)

函数传入值

shmaddr:被映射的共享内存段地址

函数返回值

成功:0

出错:-1

以下实例说明了如何使用基本的共享内存函数。首先创建一个共享内存区(采用的共享内存的键值为IPC_PRIVATE,是因为本实例中创建的共享内存是父子进程间的共用部分),然后创建子进程,在父子两个进程中将共享内存分别映射到各自的进程地址空间中。

父进程先等待用户输入,然后将用户输入的字符串写入到共享内存,之后向共享内存的头部写入“WROTE”字符串表示父进程已成功写入数据。子进程一直等到共享内存的头部字符串为“WROTE”,然后将共享内存的有效数据(在父进程中用户输入的字符串)在屏幕上打印。父子两个进程在完成以上工作后,分别解除与共享内存的映射关系。

后在子进程中删除共享内存。因为共享内存自身并不提供同步机制,所以应额外实现不同进程间的同步(如信号量)。为了简单起见,在本实例中用标志字符串来实现非常简单的父子进程间的同步。

这里要介绍的一个命令是ipcs,用于报告进程间通信机制状态,它可以查看共享内存、消息队列等各种进程间通信机制的情况,这里使用了system()函数调用shell命令“ipcs”。程序源代码如下:

/* shmem.c */

#include

#include

#include

#include

#include

#include

#define BUFFER_SIZE 2048

int main()

{

pid_t pid;

int shmid;

char *shm_addr;

char flag[] = "WROTE";

char *buff;

/* 创建共享内存 */

if ((shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, 0666)) < 0)

{

perror("shmget");

exit(1);

}

else

{

printf("Create shared-memory: %d\n",shmid);

}

/* 显示共享内存情况 */

system("ipcs -m");

pid = fork();

if (pid == -1)

{

perror("fork");

exit(1);

}

else if (pid == 0) /* 子进程处理 */

{

/* 映射共享内存 */

if ((shm_addr = shmat(shmid, 0, 0)) == (void*)-1)

{

perror("Child: shmat");

exit(1);

}

else

{

printf("Child: Attach shared-memory: %p\n", shm_addr);

}

system("ipcs -m");

/* 通过检查在共享内存的头部是否有标志字符串“WROTE”来确认父进程已经向共享内存写入有效数据 */

while (strncmp(shm_addr, flag, strlen(flag)))

{

printf("Child: Wait for enable data...\n");

sleep(5);

}

/* 获取共享内存的有效数据并显示 */

strcpy(buff, shm_addr + strlen(flag));

printf("Child: Shared-memory :%s\n", buff);

/* 解除共享内存映射 */

if ((shmdt(shm_addr)) < 0)

{

perror("shmdt");

exit(1);

}

else

{

printf("Child: Deattach shared-memory\n");

}

system("ipcs -m");

/* 删除共享内存 */

if (shmctl(shmid, IPC_RMID, NULL) == -1)

{

perror("Child: shmctl(IPC_RMID)\n");

exit(1);

}

else

{

printf("Delete shared-memory\n");

}

system("ipcs -m");

}

else /* 父进程处理 */

{

/* 映射共享内存 */

if ((shm_addr = shmat(shmid, 0, 0)) == (void*)-1)

{

perror("Parent: shmat");

exit(1);

}

else

{

printf("Parent: Attach shared-memory: %p\n", shm_addr);

}

sleep(1);

printf("\nInput some string:\n");

fgets(buff, BUFFER_SIZE, stdin);

strncpy(shm_addr + strlen(flag), buff, strlen(buff));

strncpy(shm_addr, flag, strlen(flag));

/* 解除共享内存映射 */

if ((shmdt(shm_addr)) < 0)

{

perror("Parent: shmdt");

exit(1);

}

else

{

printf("Parent: Deattach shared-memory\n");

}

system("ipcs -m");

waitpid(pid, NULL, 0);

printf("Finished\n");

}

exit(0);

}

下面是运行结果,从该结果中可以看出,nattch的值随着共享内存状态的变化而变化,共享内存的值根据不同的系统会有所不同。

$ ./shmem

Create shared-memory: 753665

/* 在刚创建共享内存时(尚未有任何地址映射)共享内存的情况 */

------ Shared Memory Segments --------

key        shmid    owner    perms    bytes    nattch    status

0x00000000 753665   david    666      2048      0

Child: Attach shared-memory: 0xb7f59000 /* 共享内存的映射地址 */

Parent: Attach shared-memory: 0xb7f59000

/* 在父子进程中进行共享内存的地址映射后共享内存的情况 */

------ Shared Memory Segments --------

key        shmid    owner    perms    bytes    nattch    status

0x00000000 753665   david    666      2048      2

Child: Wait for enable data...

Input some string:

Hello /* 用户输入字符串“Hello” */

Parent: Deattach shared-memory

/* 在父进程中解除共享内存的映射关系后共享内存的情况 */

------ Shared Memory Segments --------

key        shmid    owner    perms    bytes    nattch    status

0x00000000 753665   david    666      2048      1

/* 在子进程中读取共享内存的有效数据并打印 */

Child: Shared-memory :hello

Child: Deattach shared-memory

/* 在子进程中解除共享内存的映射关系后共享内存的情况 */

------ Shared Memory Segments --------

key        shmid    owner    perms    bytes    nattch    status

0x00000000 753665   david    666      2048      0

Delete shared-memory

/* 在删除共享内存后共享内存的情况 */

------ Shared Memory Segments --------

key        shmid    owner    perms    bytes    nattch    status

Finished

热点链接:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嵌入式Linux中的共享内存通信是一种高效的进程间通信方式,它允许多个进程在内存共享数据,从而实现数据的快速传输和共享。下面是一种基本的共享内存通信的实现方法: 1. 创建共享内存区域: 在Linux中,可以使用shmget系统调用来创建共享内存区域。该系统调用需要指定共享内存的大小和权限等参数。创建成功后,会返回一个唯一的标识符。 2. 连接共享内存区域: 使用shmat系统调用将共享内存区域连接到进程的地址空间中。该系统调用需要指定共享内存的标识符,连接成功后,返回共享内存区域的起始地址。 3. 使用共享内存区域: 连接成功后,进程可以直接通过该内存区域的起始地址访问共享数据。可以使用指针或偏移量来访问不同的数据。 4. 分离共享内存区域: 当进程不再需要使用共享内存区域时,可以使用shmdt系统调用将其从进程的地址空间中分离。该系统调用需要指定共享内存的起始地址。 5. 删除共享内存区域: 当所有进程都不再使用该共享内存区域时,可以使用shmctl系统调用来删除共享内存区域。该系统调用需要指定共享内存的标识符。 需要注意的是,共享内存通信需要进程之间进行同步和互斥,以避免数据的不一致性和冲突。可以使用信号量、互斥锁等机制来实现进程间的同步和互斥操作。 以上是嵌入式Linux实现共享内存通信的基本步骤,具体的实现方式可以根据需要进行调整和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值