华清远见嵌入式学习day18——System V IPC

                                                               消息队列、共享内存、信号量集
【1】命令
    ipcs -l   查看IPC对象的属性
    
    ipcs -m 查看共享内存的标识符
    ipcs -q 查看消息队列的标识符
    ipcs -s 查看信号灯集的标识符
    
    ipcrm -m 删除共享内存的标识符
    ipcrm -q 删除消息队列的标识符
    ipcrm -s 删除信号灯集的标识符
    
【2】key值:相当于ipc对象通信的外部名字
       #include <sys/types.h>
       #include <sys/ipc.h>

       key_t ftok(const char *pathname, int proj_id);
       功能:获得key值,用于system V中的IPC通信
       参数:pathname  文件名(要求文件必须存在)
             proj_id   整形值(低八位不能为0,所以一般用一个字符)
       返回值:成功返回key值,失败-1

【3】消息队列
    一个消息的列表,用户可以在消息队列中添加信息,读取信息
    编写流程:
    1.创建或者打开消息队列
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/msg.h>

       int msgget(key_t key, int msgflg);
       功能:创建或打开一个消息队列
       参数:key    ftok获得的key值
             msgflg 打开的方式
                IPC_CREAT   创建
                IPC_EXCL    如果存在报错
                0666
       返回值:成功返回消息队列的id,失败返回-1
             
    2.添加消息-》入队
       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
       功能:向消息队列中添加一条消息(入队操作)
       参数:msqid    id,msgget获得的
             msgp     要发送的消息的地址
                struct msgbuf {
                    long mtype;        /* message type, must be > 0 */
                    char mtext[64];    /* message data */
               };
             msgsz    消息正文的大小
             msgflg   0  如果队列满了,它会阻塞等到
                      IPC_NOWAIT   如果队列满了,以非阻塞的方式发送
       返回值:成功返回0  失败-1
    3.读取消息 
       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);

       功能:读取消息(出队操作)
       参数:msqid   id,msgget获得的
             msgp    读到数据存放的地址(一定要和发送的地址长的一样)
             msgsz   消息正文的大小
                msgtyp  消息的类型     
                0   表示从第一个开始读取,按队列的规则
                >0  按指定的消息类型进行读取 
                <0  表示读取小于他的绝对值相等的类型按类型从小到大读取
                比如-400,它会按一下顺序读取
                300 100 200 400 100
                 4   1   3       2
             msgflg      0  如果队列空了,它会阻塞等待
                      IPC_NOWAIT   如果队列空了,直接结束
       返回值:成功返回正文的大小,失败-1
    4.控制消息队列
       int msgctl(int msqid, int cmd, struct msqid_ds *buf);
       功能:控制消息队列
       参数:msqid    id,msgget获得的
             cmd      决定了该函数的功能
                IPC_STAT  表示要获取消息队列的属性,存在第三个参数中
                IPC_SET   表示要设置消息队列的属性,属性存在第三个参数中
                IPC_RMID  删除消息队列,此时第三个参数为NULL
             buf  详见上方             
       返回值:    成功0   失败-1    
                
【4】共享内存                
    1.共享内存是一个最为高效的进程间通信方式,进程可以直接读写内存
    2.共享内存使用过程需要注意(打架),需要通过同步、互斥来解决

    
    编写流程:
    1.ftok获得key值
    2.创建或者打开一个共享内存
       #include <sys/ipc.h>
       #include <sys/shm.h>

       int shmget(key_t key, size_t size, int shmflg);
       功能:创建或者打开一个共享内存
       参数:key  ftok获得key值
             size  共享内存的大小
             shmflg  IPC_CREAT  IPC_EXCL  
       返回值:返回共享内存的id,失败-1
    3.共享内存的映射:把指定的共享内存映射到进程的用户空间
       void *shmat(int shmid, const void *shmaddr, int shmflg);
       功能:共享内存的映射
       参数:shmid     共享内存的id
             shmaddr   表示映射到进程的地址,一般用NULL,让系统自动匹配
             shmflg    0   可读可写
                       SHM_RDONLY   可读
       返回值:成功返回映射的地址,失败(void *)-1
       
    4.取消共享内存的映射
       int shmdt(const void *shmaddr);
       参数:shmaddr   共享内存映射完的地址
       返回值:成功返回0  失败-1
            
    4.共享内存的控制
        int shmctl(int shmid, int cmd, struct shmid_ds *buf);
        功能:共享内存的控制
        参数:shmid  共享内存的id 
              cmd    决定了该函数的功能
                IPC_STAT  表示要获取共享内存的属性,存在第三个参数中
                IPC_SET   表示要设置共享内存的属性,属性存在第三个参数中
                IPC_RMID  删除共享内存,此时第三个参数为NULL
             buf  详见上方    
       返回值:成功0  失败-1

【5】信号灯集
    信号灯集也叫做信号量;一般和共享内存一起使用
    
    编写流程:
    1.ftok获得key值
    2.创建或者打开一个信号灯集
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>

       int semget(key_t key, int nsems, int semflg);
       功能:创建或者打开一个信号灯集
       参数:key  ftok获得key值
             nsems  要创建的信号量的个数
             semflg  IPC_CREAT  IPC_EXCL 
       返回值:成功返回semid,失败返回-1
       
    3.初始化、P、V
    初始化:
    int semctl(int semid, int semnum, int cmd, ...);
 
   功能:控制一个信号灯集
    参数:semid   信号灯的id
          semnum  要对第几个信号灯进行操作,编号从0开始
          cmd     IPC_STAT  
                  IPC_SET
                  IPC_RMID
                  SETVAL    初始化,此时需要第四个参数
                  union semun {
                    int              val;    /* Value for SETVAL */
                    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
                    unsigned short  *array;  /* Array for GETALL, SETALL */
                    struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
                  };
                  GETVAL   获得信号量的值
    返回值:失败-1
    
    P、V操作
    int semop(int semid, struct sembuf *sops, unsigned nsops);
    功能:进行P、V操作
    参数:semid  信号灯集id
          sops   结构体指针
          struct sembuf{
           unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
                          0   等待,直到信号量的值变为0
                          >0  释放资源,V操作  
                          <0  申请资源,P操作
           short          sem_flg;  /* operation flags */
                          0  以阻塞的方式进行操作
                          IPC_NOWAIT  以非阻塞的方式   
          };
          nsops   执行一次,要操作的信号灯的个数
    返回值:成功返回0 失败返回-1
    4.删除
        详见semctl
                
【总结】
    1.标准IO、文件IO
    2.进程 
    3.线程
    4.线程的同步与互斥
    5.无名管道、有名管道、信号--传统间的通信方式
    6.消息队列、共享内存、信号量集--system V IPC
                
                
   

猜你喜欢

转载自blog.csdn.net/UemTuBXuR/article/details/89053738