day_13_管道、共享内存、消息队列

来源:互联网 发布:阿里云邮箱 彻底删除 编辑:程序博客网 时间:2024/05/22 07:48

    • 一使用管道实现进程间的通信
      • 1 基本概念
      • 2 使用有名管道实现进程间的通信
      • 3 使用无名管道实现进程间的通信
    • 二使用共享内存实现进程间的通信
      • 1 基本概念
      • 2 通信模型
      • 3 相关函数的解析
        • 1ftok
        • 2shmget
        • 3shmat
        • 4shmdt
        • 5shmctl
      • 4 常见的基本命令
    • 三使用消息队列实现进程间的通信
      • 1 基本概念
      • 2 通信模型
      • 3 相关函数的解析
        • 1msgget
        • 2msgsnd
        • 3msgrcv
        • 4msgctl
      • 4 常见的基本命令

一、使用管道实现进程间的通信

1.1 基本概念

  管道本质上还是以文件作为媒介,只是该文件比较特殊,叫做管道文件而已;
  管道主要分为两大类:有名管道 和 无名管道;
    有名管道 - - - - - - 可以用于任意两个进程间的通信
    无名管道 - - - - - - 主要用于父子进程之间的通信

1.2 使用有名管道实现进程间的通信

  $ mkfifo xxx.pipe:表示创建管道文件
如:
  $ touch a.txt      => 创建普通文件a.txt,ls -l该文件的类型是-
  $ echo hello > a.txt  => 表示写入hello到文件a.txt中,可以写入,文件大小改变
  $ cat a.txt        => 表示查看文件a.txt中的内容,可以看到写入的hello
  $ mkfifo a.pipe     => 创建管道文件a.pipe,ls -l该文件的类型是p
  $ echo hello > a.pipe =>表示写入hello到文件a.pipe中,不可以写入,大小不变
另起一个终端,执行命令:
  $ cat a.pipe      => 表示读取文件a.pipe中的内容,可以看到hello
               => 但是文件本身的大小还是不变;

#include <sys/types.h>#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);  //mode_t = unsigned int;
功能:
主要用于创建参数指定的有名管道文件;
参数:
第一个参数:字符串形式的路径名;
第二个参数:具体的权限信息,如:0664;

1.3 使用无名管道实现进程间的通信

#include <unistd.h>int pipe(int pipefd[2]);
功能:
主要用于创建一个无名管道,是一个单向的数据通道,可以实现两个进程之间的通信;
通过参数数组可以返回两个文件描述符,其中pipefd[0]代表管道的读端,pipefd[1]代表管道的写端;
注意:
管道文件的特殊性就在于仅仅作为两个进程间通信的媒介,但是该文件本身并不会存储任何数据内容;

二、使用共享内存实现进程间的通信

2.1 基本概念

  共享内存本质上就是一块由系统内核维护的内存空间,该内存空间被共享在两个进程之间,从而通过读写实现通信;

2.2 通信模型

 (1)获取key值,使用ftok();
 (2)创建 / 获取共享内存,使用shmget();
 (3)挂接共享内存,使用shmat();
 (4)访问共享内存;
 (5)脱接共享内存,使用shmdt();
 (6)如果不再使用,则删除共享内存,使用shmctl();

2.3 相关函数的解析

(1)ftok()

#include <sys/types.h>#include <sys/ipc.h>key_t ftok(const char *pathname, int proj_id);  //key_t = int;
功能:
主要用于根据路径名和项目的编号来生成key值;
参数:
第一个参数:字符串形式的路径名;(要求文件必须存在,并且可以访问)
第二个参数:项目的编号;(要求必须是非0,取低八位二进制位)
返回值:
success —- key_t类型的key值,error —- -1;
注意:
使用相同的文件路径和相同的项目编号时,生成的key值也相同;

(2)shmget()

#include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);
功能:
主要用于创建 / 获取一个共享内存段;
参数:
第一个参数:key值,ftok()的返回值;
第二个参数:共享内存的大小;
  0 - - - - - - - - - - - - - - - 获取已经存在的共享内存
第三个参数:具体的操作标志;
  IPC_CREAT - - - - - - 若存在则创建,存在则打开
  IPC_EXCL - - - - - - - 与IPC_CREAT搭配使用,若存在则创建失败
  0 - - - - - - - - - - - - - - -获取已经存在的共享内存
返回值:
success —- 共享内存的ID,error —- -1;
注意:
当创建新的共享内存时,需要在第三个参数中通过按位或的方式来指定权限信息,如:0664;

(3)shmat()

#include <sys/types.h>#include <sys/shm.h>void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:
主要用于挂接共享内存到当前进程的地址空间中;
参数:
第一个参数:共享内存的ID,shmget()的返回值;
第二个参数:共享内存的起始地址,给NULL由系统选择;
第三个参数:具体的操作标志,默认给0即可;
返回值:
success —- 共享内存段的挂接地址,error —- (void*)-1;

(4)shmdt()

#include <sys/types.h>#include <sys/shm.h>int shmdt(const void *shmaddr);
功能:
主要用于脱接参数指定的挂接地址,参数一般传递shmat()的返回值;

(5)shmctl()

#include <sys/ipc.h>#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
主要用于对指定的共享内存执行指定的操作;
参数:
第一个参数:共享内存的ID,shmget()的返回值;
第二个参数:具体的操作命令;
  IPC_RMID - - - - - 删除共享内存,此时第三个参数给NULL即可
第三个参数:结构体指针

2.4 常见的基本命令

  $ ipcs -m - - - - - - - - - - - - - - - - - 表示查看系统中已经存在的共享内存
  $ ipcrm -m 共享内存的ID - - - – 表示删除指定的共享内存


三、使用消息队列实现进程间的通信

3.1 基本概念

  一般来说,首先将传递的数据打包成消息,然后使用两个进程分别发送消息到消息队列中 / 接收消息队列中的消息,从而实现进程间的通信;

3.2 通信模型

 (1)获取key值,使用ftok();
 (2)创建 / 获取消息队列,使用msgget();
 (3)发送消息到消息队列 / 接收消息队列中的消息,使用msgsnd() / msgrcv();
 (4)如果不再使用,则删除消息队列,使用msgctl();

3.3 相关函数的解析

(1)msgget()

#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgget(key_t key, int msgflg);
功能:
主要用于创建 / 获取一个消息队列;
参数:
第一个参数:key值,ftok()的返回值;
第二个参数:具体的操作标志;
  IPC_CREAT - - - - - - 若不存在则创建,存在则打开;
  IPC_EXCL - - - - - - - 与IPC_CREAT搭配使用,若存在则创建失败
  0 - - - - - - - - - - - - - – 获取已经存在的消息队列
返回值:
success —- 消息队列的ID,error —- -1;
注意:
当创建新的消息队列时,在第二个参数中需要通过按位或的方式来指定权限信息,如:0664;

(2)msgsnd()

#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:
主要用于将指定的消息发送到指定的消息队列中;
参数:
第一个参数:消息队列的ID,msgget()的返回值;
第二个参数:消息的首地址,消息的一般格式如下:
struct msgbuf{    long mtype;       /* 消息的类型,必须大于0 */    char mtext[1];    /* 消息的内容,可以是其他类型 */};

   第三个参数:消息的大小;(用于指定消息内容的大小,不包括消息的类型)
   第四个参数:发送的标志,默认给0即可;

(3)msgrcv()

#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);/* ssize_t = long int; size_t = long unsigned int */
功能:
主要用于从指定的消息队列中接收指定的消息;
参数:
第一个参数:消息队列的ID,msgget()的返回值;
第二个参数:存放信息的首地址;
第三个参数:消息的大小;(用于指定消息内容的大小,不包括消息的类型)
第四个参数:消息的类型;
  0 - - - - - - - 表示始终读取消息队列中的第一个消息
  >0 - - - - - - 表示始终读取消息队列中第一个类型为msgtyp的消息
  <0 - - - - - - 表示读取消息队列中小于等于msgtyp绝对值的消息,其中最小的类型优先读取
第五个参数:具体的接收方式,默认给0即可;
返回值:
success —- 实际读取的字节数,error —- -1;

(4)msgctl()

#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:
主要用于删除消息队列;
参数:
第一个参数:消息队列的ID;
第二个参数:具体的操作命令;
  IPC_RMID - - - - - - - - 删除消息队列,此时第三个参数给NULL即可
第三个参数:结构体指针;

3.4 常见的基本命令

  $ ipcs -q - - - - - - - - - - - - - - - - - 表示查看系统中已经存在的消息队列
  $ ipcrm -q 消息队列的ID - - - – 表示删除指定的消息队列

明日预报:
(1)进程间的通信
阅读全文
0 0