OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4274|回复: 0

使用共享内存进行进程间通信

[复制链接]

12

主题

20

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
422
金钱
422
注册时间
2015-9-15
在线时间
49 小时
发表于 2021-7-2 16:59:04 | 显示全部楼层 |阅读模式
以两个不相关的进程来说明进程间如何通过共享内存来进行通信。其中一个文件shmread.c创建共享内存,并读取其中的信息,另一个文件shmwrite.c向共享内存中写入数据。为了方便操作和数据结构的统一,为这两个文件定义了相同的数据结构,定义在文件shmdata.c中。结构shared_use_st中的written作为一个可读或可写的标志,非0:表示可读,0:表示可写,text则是内存中的文件。
shmdata.h的源代码如下:
#ifndef _SHMDATA_H_HEADER
#define _SHMDATA_H_HEADER

#define TEXT_SZ 2048

struct  shared_use_st
{
     int  written;  // 作为一个标志,非0:表示可读,0:表示可写
     char  text[TEXT_SZ];  // 记录写入 和 读取 的文本
};

#endif
源文件shmread.c的源代码如下:
#include <stddef.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "shmdata.h"
int main( int argc, char **argv)
{
void *shm = NULL;
struct shared_use_st *shared; // 指向shm
int shmid; // 共享内存标识符
// 创建共享内存
shmid = shmget((key_t)1234, sizeof ( struct shared_use_st), 0666|IPC_CREAT);
if (shmid == -1)
{
fprintf (stderr, "shmat failed\n" );
exit (EXIT_FAILURE);
}
// 将共享内存连接到当前进程的地址空间
shm = shmat(shmid, 0, 0);
if (shm == ( void *)-1)
{
fprintf (stderr, "shmat failed\n" );
exit (EXIT_FAILURE);
}
printf ( "\nMemory attached at %X\n" , ( int )shm);
// 设置共享内存
shared = ( struct shared_use_st*)shm; // 注意: shm有点类似通过 malloc() 获取到的内存,所以这&#12197;需要做个 类型强制转换
shared->written = 0;
while (1) // 读取共享内存中的数据
{
// 没有进程向内存写数据,有数据可读取
if (shared->written == 1)
{
printf ( "You wrote: %s" , shared->text);
sleep(1);
// 读取完数据,设置written使共享内存段可写
shared->written = 0;
// 输&#12042;了 end,退出循环(程序)
if ( strncmp (shared->text, "end" , 3) == 0)
{
break ;
}
}
else // 有其他进程在写数据,不能读取数据
{
sleep(1);
}
}
// 把共享内存从当前进程中分离
if (shmdt(shm) == -1)
{
fprintf (stderr, "shmdt failed\n" );
exit (EXIT_FAILURE);
}
// 删除共享内存
if (shmctl(shmid, IPC_RMID, 0) == -1)
{
fprintf (stderr, "shmctl(IPC_RMID) failed\n" );
exit (EXIT_FAILURE);
}
exit (EXIT_SUCCESS);
}
源&#12098;件shmwrite.c的源代码
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include "shmdata.h"
int  main( int  argc,  char  **argv)
{
     void  *shm = NULL;
     struct  shared_use_st *shared = NULL;
     char  buffer[BUFSIZ + 1];  // 用于保存输入的文本
     int  shmid;
     // 创建共享内存
     shmid = shmget((key_t)1234,  sizeof ( struct  shared_use_st), 0666|IPC_CREAT);
     if  (shmid == -1)
     {
         fprintf (stderr,  "shmget failed\n" );
         exit (EXIT_FAILURE);
     }
     // 将共享内存连接到当前的进程地址空间
     shm = shmat(shmid, ( void  *)0, 0);
     if  (shm == ( void  *)-1)
     {
         fprintf (stderr,  "shmat failed\n" );
         exit (EXIT_FAILURE);
     }
     printf ( "Memory attched at %X\n" , ( int )shm);
     // 设置共享内存
     shared = ( struct  shared_use_st *)shm;
     while  (1)  // 向共享内存中写数据
     {
         // 数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本
         while  (shared->written == 1)
         {
             sleep(1);
             printf ( "Waiting...\n" );
         }
         // 向共享内存中写入数据
         printf ( "Enter some text: " );
         fgets (buffer, BUFSIZ, stdin);
         strncpy (shared->text, buffer, TEXT_SZ);
         // 写完数据,设置written使共享内存段可读
         shared->written = 1;
         // 输入了end,退出循环(程序)
         if  ( strncmp (buffer,  "end" , 3) == 0)
         {
             break ;
         }
     }
     // 把共享内存从当前进程中分离
     if  (shmdt(shm) == -1)
     {
         fprintf (stderr,  "shmdt failed\n" );
         exit (EXIT_FAILURE);
     }
     sleep(2);
     exit (EXIT_SUCCESS);
}
再来看看运行的结果:
分析:
1、程序shmread创建共享内存,然后将它连接到自己的地址空间。在共享内存的开始处使用了一个结构struct_use_st。该结构中有个标志written,当共享内存中有其他进程向它写入数据时,共享内存中的written被设置为0,程序等待。当它不为0时,表示没有进程对共享内存写入数据,程序就从共享内存中读取数据并输出,然后重置设置共享内存中的written为0,即让其可被shmwrite进程写入数据。
2、程序shmwrite取得共享内存并连接到自己的地址空间中。检查共享内存中的written,是否为0,若不是,表示共享内存中的数据还没有被完,则等待其他进程读取完成,并提示用户等待。若共享内存的written为0,表示没有其他进程对共享内存进行读取,则提示用户输入文本,并再次设置共享内存中的written为1,表示写完成,其他进程可对共享内存进行读操作。


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 16:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表