进程间通信之共享存储区通信【Linux】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gnosed/article/details/82491040

一、共享存储区

1、共享存储区机制的概念

共享存储区(Share  Memory)是UNIX系统中通信速度最高的一种通信机制。该机制可使若干进程共享主存中的某一个区域,且使该区域出现(映射)在多个进程的虚地址空间中。另一方面,一个进程的虚地址空间中又可连接多个共享存储区,每个共享存储区都有自己的名字。当进程间欲利用共享存储区进行通信时,必须先在主存中建立一共享存储区,然后将它附接到自己的虚地址空间上。此后,进程对该区的访问操作,与对其虚地址空间的其它部分的操作完全相同。进程之间便可通过对共享存储区中数据的读、写来进行直接通信。图示列出二个进程通过共享一个共享存储区来进行通信的例子。其中,进程A将建立的共享存储区附接到自己的AA’区域,进程B将它附接到自己的BB’区域。

       进程A的虚空间              内存空间                  进程B的虚空间

应当指出,共享存储区机制只为进程提供了用于实现通信的共享存储区和对共享存储区进行操作的手段,然而并未提供对该区进行互斥访问及进程同步的措施。因而当用户需要使用该机制时,必须自己设置同步和互斥措施才能保证实现正确的通信。

 

二、涉及的系统调用

1shmget( )

创建、获得一个共享存储区。

系统调用格式:

                 shmid=shmget(key,size,flag)

该函数使用头文件如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

参数定义

         int  shmget(key,size,flag);

         key_t  key;

         int  size,flag;

其中,key是共享存储区的名字;size是其大小(以字节计);flag是用户设置的标志,如IPC_CREATIPC_CREAT表示若系统中尚无指名的共享存储区,则由核心建立一个共享存储区;若系统中已有共享存储区,便忽略IPC_CREAT

附:

        操作允许权                  八进制数

         用户可读                     00400

         用户可写                     00200

         小组可读                     00040

         小组可写                     00020

         其它可读                     00004

         其它可写                     00002

        

控制命令                   

IPC_CREAT                0001000

IPC_EXCL                 0002000

例:shmid=shmget(key,size,(IPC_CREAT|0400))

     创建一个关键字为key,长度为size的共享存储区

2shmat( )

    共享存储区的附接。从逻辑上将一个共享存储区附接到进程的虚拟地址空间上。

系统调用格式:

                 virtaddr=shmat(shmid,addr,flag)

该函数使用头文件如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

参数定义

         char  *shmat(shmid,addr,flag);

         int  shmid,flag;

         char  * addr;

其中,shmid是共享存储区的标识符;addr是用户给定的,将共享存储区附接到进程的虚地址空间;flag规定共享存储区的读、写权限,以及系统是否应对用户规定的地址做舍入操作。其值为SHM_RDONLY时,表示只能读;其值为0时,表示可读、可写;其值为SHM_RND(取整)时,表示操作系统在必要时舍去这个地址。该系统调用的返回值是共享存储区所附接到的进程虚地址viraddr

3shmdt( )

把一个共享存储区从指定进程的虚地址空间断开。

系统调用格式:

             shmdt(addr)

该函数使用头文件如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

参数定义

         int  shmdt(addr);

         char  addr;

其中,addr是要断开连接的虚地址,亦即以前由连接的系统调用shmat( )所返回的虚地址。调用成功时,返回0值,调用不成功,返回-1

4shmctl( )

共享存储区的控制,对其状态信息进行读取和修改。

系统调用格式:

               shmctl(shmid,cmd,buf)

该函数使用头文件如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

参数定义

             int  shmctl(shmid,cmd,buf);

             int  shmid,cmd;

             struct  shmid_ds  *buf;

其中,buf是用户缓冲区地址,cmd是操作命令。命令可分为多种类型:

1)用于查询有关共享存储区的情况。如其长度、当前连接的进程数、共享区的创建者标识符等;

2)用于设置或改变共享存储区的属性。如共享存储区的许可权、当前连接的进程计数等;

3)对共享存储区的加锁和解锁命令;

4)删除共享存储区标识符等。

上述的查询是将shmid所指示的数据结构中的有关成员,放入所指示的缓冲区中;而设置是用由buf所指示的缓冲区内容来设置由shmid所指示的数据结构中的相应成员。

三、编写程序

创建两个线程利用共享存储区进行通信,在主函数显示共享存储区的信息 ,程序利用整型指针变量控制线程中进行单次通信的次数。

#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#define  SHMKEY  75
int  shmid,i;
int  *addr;

void  client( )
{
    int i;
    shmid=shmget(SHMKEY,1024,0777);      /*打开共享存储区*/
    addr=shmat(shmid,0,0);           /*获得共享存储区首地址*/
    for (i=9; i>=0; i--)
    {
        while (*addr!=-1);
        printf("(client) sent\n");
        *addr=i;
    }
    exit(0);
}

void  server( )
{
    shmid=shmget(SHMKEY,1024,0777|IPC_CREAT); /*创建共享存储区*/
    addr=shmat(shmid,0,0);        /*获取首地址*/
    do
    {
        *addr=-1;
        while (*addr==-1);
        printf("(server) received\n");
    }
    while (*addr);
    shmctl(shmid,IPC_RMID,0);     /*撤消共享存储区,归还资源*/
    exit(0);
}

main( )
{
    while ((i=fork( ))==-1);
    if (!i)
        server( );
    system("ipcs  -m");
    while ((i=fork( ))==-1);
    if (!i)
        client( );
    wait(0);
    wait(0);
}

运行结果

猜你喜欢

转载自blog.csdn.net/gnosed/article/details/82491040
今日推荐