zoukankan      html  css  js  c++  java
  • Linux c 基于内存的进程通信—共享内存、共享队列(消息队列)

    基于内存的进程通信:

    1.      内核共享内存

    编程模型:

        1.1.创建共享内存,得到一个ID  shmget

    1.2.把ID影射成虚拟地址(挂载)  shmat

           1.3.使用虚拟地址访问内核共享内存使用任何内存函数与运算符号                        1.4.卸载虚拟地址 shmdt

           1.5.删除共享内存 shctl(修改/获取共享内存的属性)

    案例:

    A.创建共享内存,并且修改内存数据

    1.      创建共享内存

                                  #include<sys/shm.h>

                                  intshmget(key_t key,//为什么需要key

                                                                           int size,//共享内存大小

                                                                           int flags//共享内存的属性与权限

                                                     )

                                              为什么要key_t:

                                                            约定创建与访问的是同一个共享内存。Key为两个进程之间访问同一块共享内存的约定

    注:key需要唯一性,因为我们不能保证我们自己定义的key的唯一性,所以为了保证kay的唯一性,我们需要用某个文件对应的整数来充当kay值,可以用ftok函数来将一个文件转化为一个kay值。(一般我们用两个进程的共同的工程目录文件来确定kay值)

                             ftok函数:

                                      #include<sys/ipc.h>

                                       key_t   ftok( const char * pathname,int  proj_id);

                                       参数二:一个控制因子。建议在0—255之间

                                              第三个参数:

                                                                   方式|权限

                                                                   方式:创建 IPC_CREAT  IPC_EXCL(如果内存已经创建,直接错误返回)

                                                                   打开:0

                                                            常见的两种方式:

                                                                          创建:IPC_CREAT|IPC_EXCL | 0666;

                                                                          打开:0

                                                                                

                                       返回:

                                                     成功返回共享内存ID

                                                     失败返回-1                 

                                失败返回-1                 

                         B.根据ID得到共享内存,并且访问内存数据。

                                       挂载共享内存

    void* shmat(int id,

                                                     void*startaddr,//0:系统指定首地址

                                                     intflags)//挂载方式,建议0默认读写,可以使用IPC_RDONLY

                                 返回值:合法地址成功,-1失败

                         C.删除

                                       intshmctl(int id,//被操作的共享内存ID

                                                     inthow,//操作方式:一共三种操作

                                                     structshmid_ds*ds)//共享内存属性

                                       how:

                                                     IPC_STAT   

                                                     IPC_SET     //修改属性

                                                     IPC_RMID   //删除   参数三无用

    案例代码:

    ShmA.c

    #include<stdio.h>

    #include<stdlib.h>

    #include<signal.h>

    #include<sys/shm.h>

    #include<sys/ipc.h>

    void   main()

    {

          key_t   key;

          int     shmid;

          int * p;

          //1.创建共享内存

          key=ftok( “.” , 255 );   //用当前路径的目录来确定kay值

          if(key == -1)  printf(“ftok error%m ”) ,  exit( - 1 );

          shmid=shmget( key , 4 , IPC_CREAT|IPC_EXCL | 0666 );

          if(shmid == -1) printf(“shmget error %m ”) , exit( -1 );

          //2.挂载共享内存

          p=shmat( shmid , 0 , 0);

          if(p==(int *) - 1) printf(“at error %m ”) , exit( -1 );

          //3.访问共享内存

          *p=999;

          //4.卸载共享内存

          shmdt(shmid);

          //删除共享内存

          shctl( shmid , IPC_RMID , 0);

    }

    不创建共享内存,只访问已有的

    shmB.c

    ShmA.c

    #include<stdio.h>

    #include<stdlib.h>

    #include<signal.h>

    #include<sys/shm.h>

    #include<sys/ipc.h>

    void   main()

    {

          key_t   key;

          int     shmid;

          int * p;

          //1.得到共享内存

          key=ftok( “.” , 255 );   //用当前路径的目录来确定kay值

          if(key == -1)  printf(“ftok error%m ”) ,  exit( - 1 );

          shmid=shmget( key , 4 ,0 );

          if(shmid == -1) printf(“shmget error %m ”) , exit( -1 );

          //2.挂载共享内存

           p=shmat( shmid , 0 , 0);

          if(p==(int *) - 1) printf(“at error %m ”) , exit( -1 );

          //3.访问共享内存

          printf(“%d ”,*p);

          //4.卸载共享内存

          shmdt(shmid);

        

    }

    2.      内核共享队列(有序)

                编程模型:

                                              2.1.创建共享队列/得到队列msgget

                                              2.2.使用队列(发送消息msgsnd/接收消息msgrcv)

                                              2.3.删除队列msgctl

    案例:

                         创建共享队列

               #include<sys/msg.h>

                                       intmsgget(key_t,int); 除了不用指定大小,和shmget函数的参数一样                             

                         发送消息

                                       intmsgsnd(

                                                     intid,//消息队列ID

                                                     constvoid *msg,//要发送消息

                                                     size_tlen,//消息的长度

                                                     int flags//发送消息的方式,建议为0

                                              );

                                       返回:

                                                     -1:失败

                                                      0:成功  

                                       第二个参数的消息有固定的格式

                                                            4字节:表示消息的类型

                                                            若干字节:消息内容。

                         消息格式:(该结构体需要我们自己定义)

                                  struct  msgbuf{

                                       long   mtype; //消息类型

                                       char   mtext[1]; //消息内容

                                  }

                                       第三个参数:

                                                            消息的大小,不包含类型的4个字节

                  接收消息:

                           size_t   msgrcv(int id ,

    void * msgp ,

    size_t msgsz, ,

    long msgtype , //那种类型的消息

    int  msgflg);

                          返回:

                               -1:失败

                               大小:成功

                   删除队列:msgctl 参数和shctl一样

    案例代码:

    #include<unistd.h>

    #include<sys/ipc.h>

    #include<sys/msg.h>

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

    struct  msgbuf

    {

         long  type;

         char  data[32];

    }

    void main()

    {

        key_t  key;

        int msgid;

        //1创建消息队列

         key= ftok(“ . ” , 254);

        if(key == -1) printf(“ftok error:%m ”) , exit(-1);

        msgid= msgget(key,IPC_CREAT | IPC_EXCL|0666);

         if(msgid==-1) printf(“get error : %m ”), exit(-1);

        //2构造消息

         struct  msgbuf msg;

        //3发送消息

         for(i=1;i<=10;i++)

        {

              msg.type=1;        //消息类型自己定义一个long类型

              sprintf(msg.data  , “Message:%d”,i);

              msgsnd(msgid ,&msg , strlen(msg.data) , 0);

        }

        //4删除队列

         //msgctl(msgid, IPC_RMID,0);

    }

    #include<unistd.h>

    #include<sys/ipc.h>

    #include<sys/msg.h>

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

    struct  msgbuf

    {

         long  type;

         char  data[32];

    }

    void main()

    {

        key_t  key;

        int msgid;

        //1得到消息队列

        key = ftok(“ . ” , 254);

        if(key == -1) printf(“ftok error:%m ”) , exit(-1);

        msgid= msgget(key,0);

        if(msgid== -1) printf(“get error : %m ”), exit(-1);

        //2构造消息

         struct  msgbuf msg;

        //3接收消息

         while(1)

        {

             bzero(&msg,sizeof(msg));

             msgrcv(msgid , & msg sizeof(msg.data) , 1 , 0);

             printf(“%s ”,msg.data);

        }

    }

    说明:如果消息队列中没有消息了读取消息的程序会阻塞等待

    当程序发送消息到队列中,一个程序读取了所以消息,队列中就没有消息,就无法再读取了,只能等待在发送消息后在读取消息。

     

     

  • 相关阅读:
    【Kubernetes学习笔记】-kubeadm 手动搭建kubernetes 集群
    教你快速搭建NFS服务
    【Kubernetes学习笔记】-服务访问之 IP & Port & Endpoint 辨析
    【Kubernetes学习笔记】-使用Minikube快速部署K8S单机学习环境
    Linux RDP 会话中无法打开VSCode 解决办法
    Jenkins 凭证管理
    linux 后台运行进程:& , nohup
    使用私有gitlab搭建gitbook持续集成
    VS Code 使用
    Markdown Rules 详解
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3260627.html
Copyright © 2011-2022 走看看