zoukankan      html  css  js  c++  java
  • 通信与实际用例应用(消息队列和进程撰写的ATM机与消息队列的五子棋对站)

    int semget(key_t key, int nsems, int semflg);
     功能:创建信号量或获取信号量
     nsems:信号量的数量
     semflg:
      IPC_CREAT|IPC_EXEC|0644
     
     int semop(int semid, struct sembuf *sops, unsigned nsops);
     功能:对信号量增加或减少
     struct sembuf {
      unsigned short sem_num;信号量的编号
            short          sem_op; 对信号量的操作
            short          sem_flg; 
             IPC_NOWAIT:不阻塞
        }
        
        int semctl(int semid, int semnum, int cmd, ...);
        功能:对信号量控制或释放
        semnum:信号量的编号
        cmd:
         IPC_SET 设置信号量的属性
         IPC_STAT 获取信号量的属性
         IPC_RMID 删除信号量
         IPC_INFO 获取信号的信号
         GETVAL
         SETVAL
    https://files.cnblogs.com/files/mingyoujizao/msg_gobang1.0.zip
    https://files.cnblogs.com/files/mingyoujizao/ATM_spf1.0.zip
    一、基本概念

     进程间通信(IPC):进程之间交换数据的过程叫进程间通信。
     进程间通信的方式:
      简单的进程间通信:
       命令行:父进程通过exec函数创建子进程时可以附加一些数据。
       环境变量:父进程通过exec函数创建子进程顺便传递一张环境变量表。
       信号:父子进程之间可以根据进程号相互发送信号,进程简单通信。
       文件:一个进程向文件中写入数据,另一个进程从文件中读取出来。
       命令行、环境变量只能单身传递,信号太过于简单,文件通信不能实时。
      
      XSI通信方式:X/open 计算机制造商组织。
       共享内存、消息队列、信号量
      网络进程间通信方式:
       网络通信就是不同机器的进程间通信方式。
      
      传统的进程间通信方式:管道
    二、管道
     1、管道是一种古老的通信的方式(基本上不再使用)
     2、早期的管道是一种半双工,现在大多数是全双工。
     3、有名管道(这种管道是以文件方式存在的)。
     int mkfifo(const char *pathname, mode_t mode);
       
     管道通信的编程模式:
      进程A    进程B
      创建管道mkfifo
      打开管道open   打开管道
      写/读数据read/write 读/写数据
      关闭管道close   关闭管道
       
     4、无名管道:由内核帮助创建,只返回管道的文件描述符,看不到管道文件,但这种管道只能用在fork创建的父子进程之间。
      int pipe(int pipefd[2]);
      pipefd[0] 用来读数据
      pipefd[1] 用来写数据
       
      练习:使用无名管道,让父子进程通信。
    三、XSI IPC进程间通信
     1、XSI通信是靠内核的IPC对象进程通信。
     2、每一个IPC对象都有一个IPC标识(类似文件描述符),IPC标识它是一个非的整数。
     3、IPC对象必须要先创建,创建后才能进程获取、设置、操作、删除。
     4、创建IPC对象必须要提供一个键值(key_t),键值是创建、获取IPC对象的依据。
     5、产生键值的方法:
      固定的字面值:1980014
      使用函数计算:键值=ftok(项目路径,项目id)
      使用宏让操作系统随机分配:IPC_PRIVTE
       必须把获取到IPC对象标识符记录下来,告诉其它进程
     6、XSI可以创建的IPC对象有:
      共享内存,消息队列,信号量
    四、共享内存
     1、由内存维护一个共享的内存区域,其它进程把自己的虚拟地址映射到这块内存,然后多个进程之间就可以共享这块内存了。
     2、这种进程间通信的好处是不需要信息复制,是进程间通信最快的一种方式。
     3、但这种通信方式会面临同步的问题,需要与其它通信方式配合,最合适的就是信号。
     
     共享内存的编程模式:
      1、进程之间要约定一个键值
      进程A  进程B 
      创建共享内存  
      加载共享内存 加载共享内存
      卸载共享内存 卸载共享内存
      销毁共享内存
     
     int shmget(key_t key, size_t size, int shmflg);
     功能:创建共享内存
     size:共享的大小,尽量是4096的位数
     shmflg:IPC_CREAT|IPC_EXCL
     返回值:IPC对象标识符(类似文件描述符)
     
     void *shmat(int shmid, const void *shmaddr, int shmflg);
     功能:加载共享内存(进程的虚拟地址与共享的内存映射)
     shmid:shmget的返回值
     shmaddr:进程提供的虚拟地址,如果为NULL,操作系统会自动选择一块地址映射。
     shmflg:
      SHM_RDONLY:限制内存的权限为只读
      SHM_REMAP:映射已经存的共享内存。
      SHM_RND:当shmaddr为空时自动分配
      SHMLBA:shmaddr的值不能为空,否则出错
     返回值:映射后的虚拟内存地址
      
     int shmdt(const void *shmaddr);
     功能:卸载共享内存(进程的虚拟地址与共享的内存取消映射关系)
     
     int shmctl(int shmid, int cmd, struct shmid_ds *buf);
     功能:控制/销毁共享内存
     cmd:
      IPC_STAT:获取共享内存的属性
      IPC_SET:设置共享内存的属性
           IPC_RMID:删除共享内存
        buf:
         记录共享内存属性的对象
         
    五、消息队列
     1、消息队列是一个由系统内核负责存储和管理、并通过IPC对象标识符获取的数据链表。
     
     int msgget(key_t key, int msgflg);
     功能:创建或获取消息队列
     msgflg:
      创建:IPC_CREAT|IPC_EXEC
      获取:0
      
     int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
     功能:向消息队列发送消息
     msqid:msgget的返回人值
     msgp:消息(消息类型+消息内容)的首地址
     msgsz:消息内存的长度(不包括消息类型)
       
        ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
        功能:从消息队列接收消息
        msgp:存储消息的缓冲区
        msgsz:要接收的消息长度
        msgtyp:消息的的类型(它包含消息的前4个字节)
        msgflg:
         MSG_NOERROR:当消息的实际长比msgsz比要接长的话,则按照msgsz长度截取再发送,否则产生错误。
         MSG_NOWAIT:如果要接收的消息不存在,直接返回。
          否则阻塞等待。
         MSG_EXCEPT:从消息队列中接收第一个不msgtyp类型的第一个消息。
         
        int msgctl(int msqid, int cmd, struct msqid_ds *buf);
     功能:控制/销毁消息队列
     cmd:
      IPC_STAT:获取消息队的属性
      IPC_SET:设置消息队列的属性
      IPC_RMID:删除消息队列
    六、信号量
     信号量(信号灯),可以当作进程与进程之间共享的全局变量,一般用来为共享的资源计数。
     信号量的使用方法:
      1、进程A,创建信号量,并设置初始化(设置资源的数)
      2、进程B,获取信号量,查看信号量(查询剩余资源的数量),减少信号量(使用资源),增加信号量(资源使用完毕归还还)。
      3、当一进程尝试减少信号量,如果不能减(资源使用完毕),则进程可以进入等待状态,当信号量能够被减时(其它进程把资源还回来了),进程会被唤醒。
     
     
  • 相关阅读:
    gitlab11.5.4 配置邮件提醒
    docker 安装 mongodb
    dd测试
    k8s部署rocketmq 双主
    rocketmq 多master集群部署
    Kubernetes中的Taint污点和Toleration容忍
    Zookeeper分布式集群搭建
    初识ZooKeeper
    hdu 5071(2014鞍山现场赛B题,大模拟)
    hdu 5073
  • 原文地址:https://www.cnblogs.com/mingyoujizao/p/9393934.html
Copyright © 2011-2022 走看看