Linux-共享内存通讯

Linux共享存储通讯

内容

  • 建立共享存储区实现进程通讯

机理说明

共享存储区(Share Memory)是Linux系统中通讯速度最高的通讯机制。该机制中共享内存空间和进程的虚地址空间知足多对多的关系。即一个共享内存空间能够映射多个进程的虚地址空间,一个进程的虚地址空间又能够链接多个共享存储区。当进程间预利用共享存储区通讯时,先要在主存中创建一个共享存储区,而后将它附接到本身的虚地址空间。该机制只为进程提供了用于实现通讯的共享存储区和对共享存储区进行操做的手段,然而并未提供对该区进行互斥访问及进程同步的措施linux

调用函数说明

建立共享内存

shmget(key ,size ,flag)数组

功能:得到一个内部标识为shmid的共享存储区。数据结构

语法:int shmget = int shmget(key_t key ,int size ,int flag);函数

参数说明:操作系统

​ key 共享存储区关键字,可由用户指定。若使用IPC_PRIVATE则其值由系统产生。3d

​ size 存储区大小(字节数)。若存储区定义为字符型,则大小为定义的字符个数;若定义为整型,大小能够用sizeof(int)加以定义code

​ flag 用户设置的标志或访问方式,如0666|IPC_CREAT,表示任意进程皆可读可写blog

操做容许权 八进制数 操做容许权 八进制数
用户可读 0400 小组可写 0020
用户可写 0200 其它可读 0004
小组可读 0040 其它可写 0002

附接共享内存

字符型共享内存:进程

shmat(int shmid ,char shmadddr ,int msgflg ,ulong raddr);内存

数值型共享内存:

shmat(int shmid ,int shmadddr ,int msgflg ,ulong raddr);

语法格式:

字符型共享内存:

viraddr = (char *) shmat (shmid ,shmaddr ,shmflag);

viraddr = (int *) shmat (shmid ,shmaddr ,shmflag);

参数说明:

​ shmid共享存储区的描述符,可由shmget()的返回值获得。

​ shmaddr用户提供的共享存储区附接的虚地址。

​ shmflag规定存储区的操做权限。如,SHM_RND则表示操做系统在必要时舍去地址;SHM_RDONLY则表示只容许读,shmflag为0表示可读可写。

断开共享内存

shmdt(viraddr)

参数说明:

​ viraddr系统调用shmat()所返回的虚地址。

返回值:

​ 函数被正确调用则返回0,错误返回-1

shmctl(int shmid ,int cmd ,struct shmid_ds * buf);

功能:对共享内存进行操做控制

参数说明:

​ shmid共享存储区的描述符,可由shmget()的返回值获得。

​ buf用户级数据结构地址,可为0。

​ cmd规定的操做类型

操做代码 含义
IPC_STAT 返回指定shmid数据结构的状态信息,放置于*buf中,必须有读取容许权
IPC_SET 设置指定shmid的有效用户和操做存取权
IPC_RMID 删除指定shmid以及与它相关的共享存储区的数据结构
SHM_LOCK 在内存中锁定指定的共享存储区,必须是root才能执行

shmctl(shmid ,IPC_RMID ,0); //撤销共享内存区

实现思路

send:

  • shmget()建立或者获取指定key值的共享内存
  • shmat()将该内存附接到本身的虚拟地址空间
  • 将消息写入共享内存
    • 字符:
      • 以追加方式写入,strcat(viraddr ,buffer)
      • 以覆盖方式写入,strcpy(viraddr ,buffer)
    • 数字:
      • 直接赋值
      • 操做数组
  • shmdt()断开共享内存

receive:

  • shmget()建立或者获取指定key值的共享内存
  • shmat()将该内存附接到本身的虚拟地址空间
  • 输出信息
  • shmdt()断开共享内存
  • shmctl()撤销内存

实例

send

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
/*共享内存 share memory 实现的进程通讯*/
main()
{
    int shmid;
    char *viraddr;
    char buffer[BUFSIZ];
    
    shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT);
    viraddr=(char*)shmat(shmid,0,0);
    
    while(1)
    {
        puts("Enter some text:");
        fgets(buffer,BUFSIZ,stdin);/*从标准输入设备读入一行字符串,stdin是标准输入,C标准库里面的一                                     个全局变量*/
        strcat(viraddr,buffer);     /*字符串追加函数*/
        if(strncmp(buffer,"end",3)==0)/*比较两个字符串数组*/
            break;
    }
    shmdt(viraddr);
    exit(0);
}

receive

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

main()
{
    int shmid;
    char *viraddr;
    
    shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT);
    viraddr=(char*)shmat(shmid,0,0);
    
    printf("Your message is :\n%s",viraddr);
    shmdt(viraddr);                         /*断开链接*/
    shmctl(shmid,IPC_RMID,0);               /*撤销共享内存*/
    exit(0); 
}

运行结果

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
/* 父进程与子进程间的通讯,子进程写信息到共享内存中,父进程读取该信息
BUFSIZ为全局量定义在<stdlib.h>,8192 
使用exit(0)和wait(0)进行同步*/
main()
{
    int chld,shmid;
    char *viraddr;
    char buffer[BUFSIZ];
    
    shmid=shmget(IPC_PRIVATE,BUFSIZ,0666|IPC_CREAT);
    viraddr=(char*)shmat(shmid,0,0);
    
    while((chld=fork())==-1);
    if(chld==0)
    {                                   /*子进程块*/
        while(1)
        {
            puts("Enter some text:");   /*写信息到共享内存*/
            fgets(buffer,BUFSIZ,stdin); /*用户输入信息*/
            strcat(viraddr,buffer);     /*附接到进程的虚拟空间*/
            if(strncmp(buffer,"end",3)==0)
                break;                  /*输入end结束*/
        }
        exit(0);
    }
    else
    {                                   /*父进程块*/
        wait(0);
        printf("Your message is:\n%s",viraddr);
        
        shmdt(viraddr);                 /*断开共享内存*/
        shmctl(shmid,IPC_RMID,0);       /*释放共享内存*/
        exit(0);
    }
}

运行结果

相关文章
相关标签/搜索