zoukankan      html  css  js  c++  java
  • 第三季-第18课-共享内存通讯

    第18课-共享内存通讯

     

    18.1 基本概念

    共享内存是IPC机制中的一种. 顾名思义,它允许两个不相关的进程访问同一段内存,这是传递数据的一种非常有效的方式。即,可以让进程A和B同时访问一段内存。

    18.2 函数学习

    1. 创建/获取共享内存

    (1)函数名

    shmget

    (2)函数原型

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

    (3)函数功能

    创建或者获取共享内存,并返回其描述符。(allocates a shared memory segment)。

    (4)所属头文件

    #include<sys/ipc.h>

    #include<sys/shm.h>

    (5)返回值

    成功:返回创建或者获取到的共享内存的描述符

    失败:-1

    (6)参数说明

    key:共享内存的键值

    size:共享内存的大小

    shnflg:打开标志,如果使用了IPC_CREAT这个标志,就会新创建一个共享内存。

    2. 映射共享内存

    (1)函数名

    shmat

    (2)函数原型

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

    (3)函数功能

    把shmid指定的共享内存映射到进程的地址空间里。(shared memory operations)。

    (4)所属头文件

    #include<sys/types.h>

    #include<sys/shm.h>

    (5)返回值

    成功:返回映射到进程空间之后的内存地址

    失败:-1

    (6)参数说明

    shmid:要映射的共享内存的描述符

    shmaddr:指定映射之后的地址,一般的情况下,改参数都是NULL,表明让linux系统自动的选择地址

    shmflg:标志

    3. 分离(脱离)共享内存

    (1)函数名

    shmdt

    (2)函数原型

    int shmdt(const void *shmaddr);

    (3)函数功能

    从进程地址空间中,断掉与共享内存的联系。(shared memory operations)。

    (4)所属头文件

    #include<sys/types.h>

    #include<sys/shm.h>

    (5)返回值

    成功:0

    失败:-1

    (6)参数说明

    shmaddr:要断开的共享内存的地址

    4. 删除(控制)共享内存

    (1)函数名

    shmctl

    (2)函数原型

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

    (3)函数功能

    控制共享内存(performs the control operation specified by cmd on the shared memory segment whose identifier is given in shmid)。

    (4)所属头文件

    #include<sys/ipc.h>

    #include<sys/shm.h>

    (5)返回值

    成功:0

    失败:-1

    (6)参数说明

    shmid:要控制的共享内存的id

    cmd:决定执行什么样的控制操作,如IPC_RMID(表示删除)

    内核为每一个共享存储段设置了一个shmid_ds结构,该结构如下:

    struct shmid_ds        {

    struct ipc_perm    shm_perm;   /*see Section 15.6.2*/

    size_t            shm_segsz;   /*size of segment in bytes*/

    pid_t             shm_lpid;    /*pid of last shmop*/

    shmatt_t         shm_nattch;   /*number of current attaches*/

    time_t           shm_atime;   /*last-attach time*/

    time_t           shm_dtime;   /*last-detach time*/

    time_t           shm_ctime;   /*last-change time*/

    (按照支持共享存储段的需要,每种实现会在shmid_ds结构中增加其他成员)

    buf:获取linux中描述共享内存的shmid_ds结构。基本不使用。

    18.3 综合实例

    1. 流程:

    A和B两个进程,A先创建一个共享内存,然后再映射该共享内存。对于B进程先获取共享内存,然后再映射该共享内存。当用完了该共享内存后,A和B进程再分别分离该共享内存。A进程去删除共享内存。

    2. 程序解读

    我们设置两个进程,一个write进程,一个read进程。前一个进程是读取键盘上的输入的字符串,并且把字符串保存在共享内存之中。后一个进程的作用是,在共享内存中读取字符串,并且打印它们。

    write进程的流程:(1)创建共享内存;(2)映射共享内存;(3)获取用户输入,把字符串放入共享内存,循环来做直到用户终止;(4)脱离共享内存。

    write.c:

    #include<sys/ipc.h>

    #include<sys/shm.h>

    #include<sys/types.h>

    #include<stdio.h>

    #include<unistd.h>

    #include<stdlib.h>

    #define TEXT_SZ 2048

    struct shared_use_st

    {

             int written_by_you;

             char some_text[TEXT_SZ];

    };

    int main()

    {

             int running = 1;  //定义循环标志

             key_t key;

             key = ftok("/root",3);

             int shmid;

             struct shared_use_st *shared_stuff;

             char buffer[TEXT_SZ];    //fgets()函数用到的存储用的数组

             //1.创建共享内存;

             shmid = shmget(key, sizeof(struct shared_use_st),IPC_CREAT);

             if(shmid == -1)

             {

                      printf("creat share memory fail! ");

                      exit(EXIT_FAILURE);          //退出的标志

             }

             //2.映射共享内存.

             shared_stuff = (struct shared_use_st *)shmat(shmid, NULL, 0); //强制转换

             //3.循环

             while(running)

             {

                      //观看数据有没有被取走,没被取走一直等待

                      while(shared_stuff->written_by_you == 1)

                      {

                               sleep(1);

                               printf("wait read process! ");

                      }

                      //3.1 获取用户输入

                      fgets(buffer,TEXT_SZ,stdin);  //  char *fgets(char *s, int szie FILE *stream);

                      //3.2把字符串放入共享内存

                      strncpy(shared_stuff->some_text,buffer,TEXT_SZ);

                      shared_stuff->written_by_you = 1;

                      if(strncmp(buffer,"end",3)==0)

                      {

                               running = 0;             

                      }

             }

             //4.脱离共享内存

             shmdt((const void *)shared_stuff);   //强制转换

             return 1;

    }

    read进程流程:(1)创建/获取共享内存;(2)映射共享内存;(3)循环,打印共享内存中的字符串,直到收到结束的通知;(4)脱离共享内存;(5)删除共享内存。

    read.c

    #include<sys/ipc.h>

    #include<sys/shm.h>

    #include<sys/types.h>

    #include<stdio.h>

    #include<unistd.h>

    #include<stdlib.h>

    #define TEXT_SZ 2048

    struct shared_use_st

    {

             int written_by_you;

             char some_text[TEXT_SZ];

    };

    int main()

    {

             int running = 1;  //定义循环标志

             int shmid;

             key_t key;

             key = ftok("/root",3);

             struct shared_use_st *shared_stuff;

             char buffer[TEXT_SZ]; 

             //1.创建/获取共享内存;

             shmid = shmget(key, sizeof(struct shared_use_st),IPC_CREAT);

             //2.映射共享内存;

             shared_stuff = (struct shared_use_st *)shmat(shmid, NULL, 0); //强制转换

             shared_stuff->written_by_you = 0;  //最初的标识是0;

             //3.循环

             while(running)

             {

                      //打印共享内存中的字符串,直到收到结束的通知;

                      if(shared_stuff->written_by_you == 1)

                      {

                               printf("write process is %s ",shared_stuff->some_text);

                               shared_stuff->written_by_you = 0;

                               if(strncmp(shared_stuff->some_text,"end",3)==0)

                                        running = 0;

                      }

             }

             //4.脱离共享内存;

             shmdt((const void *)shared_stuff);  //强制转换

             //5.删除共享内存。

             shmctl(shmid,IPC_RMID,0);

             return 1;

    }

    运行结果:在两个一样的终端中,先运行./read,在运行./write。我们在./write中输入的字符串会在./read中显示,直到输入end,两个程序都停止。

  • 相关阅读:
    IE6 兼容问题总结
    WPF 带CheckBox、图标的TreeView
    Fast Report Data Filter
    【转】NHibernate入门教程
    【转】Spring.NET学习笔记——目录
    【转】.Net中通过反射技术的应用----插件程序的开发入门
    【转】ASP.NET常用数据绑定控件优劣总结
    【转】通用分页用户控件(DataGrid,DataList,Repeater都可以用它来分页)
    【转】ASP.NET MVC教程
    【转】设计模式介绍
  • 原文地址:https://www.cnblogs.com/free-1122/p/11352554.html
Copyright © 2011-2022 走看看