IPC对象之共享内存

1. 共享内存特点

1)共享内存是一种最为高效的进程间通信方式,进程可以知点解读写内存,而不需要任何数据的拷贝。

2)为了在多个进程间交换信息,内核专门留出了一块内存,可以由需要访问的进程将其映射到自己的私有地址空间。

3)进程可以直接读写这一块内存而不需要进行数据的拷贝。

4)由于多个进程共享一段内存,因此需要依靠某种同步机制,如互斥锁和信号量等。

 

2. 共享内存实现

1)创建/打开共享内存

2)映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问

3)撤销共享内存映射

4)删除内存对象

3. 共享内存实现函数

使用共享内存编程通常需要调用shmget()、shmat()、shmdt()和shmctl()几个函数。

1)创建共享内存

函数shmget()

头文件:#include<sys/ipc.h>

              #include<sys/shm.h>

函数原型:int shmget(key_t key, size_t size, intshmflg)

函数参数:key     共享内存的键值,其他进程通过该值访问该共享内存,其中有个特殊值IPC_PRIVATE,表示创建当前进程的私有共享内存

                size     申请的共享内存段的大小

                shmflg 同open()函数的第三个参数,为共享内存设定权限,通常使用八进制表示。

函数返回值:成功:共享内存段的标识符(非负整数)

                  失败:-1

2)映射共享内存

函数shmat()

头文件:#include<sys/types.h>

              #include<sys/shm.h>

函数原型:void *shmat(int shmid, const void*shmaddr, int shmflg)

函数参数:shmid 要映射的共享内存区标识符(即shmget()函数的返回值)

                shmaddr    将共享内存映射到的指定内存地址,如果为NULL则会自动分配到一块合适的内存地址

                shmflg SHM_RDONLY表示共享内存为只读,0(默认值)表示共享内存可读可写

函数返回值:成功:被映射的内存地址

                 失败:-1

3)撤销共享内存映射

函数shmdt()

所需头文件:#include<sys/types.h>

                     #include<sys/shm.h>

函数原型:int shmdt(const void *shmaddr)

函数参数:shmaddr    需要解除映射的共享内存地址

函数返回值:成功:0

                  失败:-1

4)删除内存对象

函数shmctl()

所需头文件:#include<sys/ipc.h>

                  #include<sys/shm.h>

函数原型:int shmctl(int shmid, int cmd, structshmid_ds *buf)

函数参数:shmid 共享内存区标识符(即shmget()函数的返回值)

                cmd           需要对共享内存采取的操作。可取值有很多,常用的有:

                IPC_STAT   将shmid_ds结构体中的数据设置为共享内存的当前关联值,即用shmid覆盖shmid_ds内的值

                IPC_SET             如果进程权限允许,将共享内存的当前关联值设置为shmid_ds中给出的值

                IPC_RMID   删除共享内存

                buf             该参数是一个shmid_ds类型的结构体指针,使用时必须使用地址传递的方式。结构体成员很多,常用的有:

                     structshmid_ds

                     {

                            uid_tshm_perm.uid;           /* Effective UIDof owner */

                            uid_tshm_perm.gid;           /* Effective GIDof owner */

                            mode_tshm_perm.mode;   /* Permissions + SHM_DESTand SHM_LOCKED flags */

                            ……

                     };

函数返回值:成功:

                     IPC_INFO或SHM_INFO操作:内核内部记录的有关共享内存段的使用条目

                     SHM_STAT操作:shmid中指定的共享内存标识符

                     其他操作:0

                  失败:-1

示例代码:

文件一:

/*************************************************************************

 @Author: wanghao

 @Created Time : Wed 23 May 2018 04:48:19 AMPDT

 @File Name: shared_memory_demo.c

 @Description:

 ************************************************************************/

#include <sys/shm.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include "tell.h"

int main(void)

{

       intshmid;

       /*CreateShared Memory with 1024 bytes size*/

       if((shmid= shmget(1,1024,

              IPC_CREAT|IPC_EXCL|0777))< 0){

              perror("shmerror");

              exit(1);

       }

       pid_tpid;

       init();

       if((pid= fork())<0){

              perror("forkerror");

              exit(1);

       }elseif(pid >0){

              /*Mapshared memory*/

              int*pi = (int*)shmat(shmid,NULL,0);

              if(pi== (int*) -1){

                     perror("shmaterror");

                     exit(1);

             

              }

              /*Writenumbers in shared memory*/

              *pi= 111; *(pi+1) =222;

              /*Relieveshared memory mapping relationships*/

              shmdt(pi);

              /*Noticcechild process*/

              notify_pipe();

              destroy_pipe();

              wait(NULL);

       }else{

              /*Waitparent process to write*/

              wait_pipe();

              /*MapShared memory with shmid*/

              int*pi = (int*)shmat(shmid,NULL,0);

              if(pi== (int*) -1){

                     perror("shmaterror");

                     exit(1);

              }

              printf("start:%d,end: %d\n",*pi,*(pi+1));

              /*Sameas above*/

              shmdt(pi);

              /*Releaseshared memory*/

              shmctl(shmid,IPC_RMID,NULL);

              destroy_pipe();

       }

      

       exit(0);

}

文件二:

注:该文件通过无名管道实现同步机制(管道在没写数据前进行读取发生阻塞)

#include "tell.h"

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

static int fd[2];

void init()

{

       if(pipe(fd)< 0){

              perror("pipeerror");

       }

}

void notify_pipe()

{

       charc = 'c';

       if(write(fd[1],&c,1)!= 1) {

              perror("notifypipe error");

       }

}

void wait_pipe()

{

       charc;

       if(read(fd[0],&c,1)< 0) {

              perror("waitpipe error");

       }

}

void destroy_pipe()

{

       close(fd[0]);

       close(fd[1]);

}


猜你喜欢

转载自blog.csdn.net/weixin_42048417/article/details/80425111
今日推荐