一、共享内存

0、进程间的通讯方式

管道、信号、共享内存、消息队列、信号量、套接字

管道和信号:只能用于两个进程间进行通讯

IPC:可以用于多个进程间进行通讯

1、IPC是用于多个进程间进行通讯的手段(Inter-Process Communication,进程间通信

共享内存、消息队列、信号量

2、怎样去识别我的IPC

比如有A B C三个进程,这三个进程要想通讯,可以使用共享内存、消息队列、信号量。三个进程访问同一块共享内存,要确定操作的是同一个共享内存,确定共享内存的唯一性   键值

3、键值的创建于意义

唯一识别某个IPC

保证我多个进程打开的是同一个IPC

4、查看指令

ipcs -m 看Shared Memory 共享内存
        ipcs -s 看Semaphore Arrays 信号量
        ipcs -q 看Message Queues 消息队列
        删除指令ipcrm -q  id

1、获取一个键值 ftok        (file to key的缩写,即将文件转换成key)

函数功能:获取一个键值

函数头文件:#include <sys/types.h>
                             #include <sys/ipc.h>

函数原型:key_t ftok(const char *pathname, int proj_id);

函数的参数:const char *pathname:参考位置 (一般来说  写绝对路径)
                              int proj_id:参考的id  0-255

函数的返回值:成功返回   键值                              失败返回  -1

无论在任何位置 无论何时执行这个程序,只要你传入的参数是一致的   得到的键值就是唯一

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/ipc.h>4 #include<sys/shm.h>5 int main()6 {7         key_t keyid;8         int shmid;9         keyid=ftok("/home/ldw",5);10         if(keyid<0)11         {12                 perror("ftok");13                 return -1;14         }15         printf("keyid:%d\n",keyid);16         return 0;17 }
//keyid:83951618

共享内存

他就是一个加强版的全局变量

全局变量的特点

1、作用域  是整个工程
                2、存放于全局区
                3、在作用域范围之内   不能重名

共享内存:

1:范围是整个计算机的进程
                2:整个计算里的进程都可以对她进行操作

本质:本质就是内存里的一段空间

(1.作用域:系统下的所有的进程都可以访问到   2.一个进程对共享内存做修改   其他的进程都能看到)

2、创建一个共享内存 shmget

函数功能:创建一块共享内存

函数的头文件:#include <sys/ipc.h>
                                 #include <sys/shm.h>

函数的原型:int shmget(key_t key, size_t size, int shmflg);

函数的参数:key_t key:共享内存的键值
                             size_t size:要申请的共享内存的大小
                             int shmflg:标志                  IPC_CREAT | 0777
                        IPC_CREAT:没有则创建,有则打开

IPC(包括消息队列,共享内存,信号量)的xxxget()创建操作时,可以指定IPC_CREAT和IPC_EXCL选项。

以共享内存为例:①当只有IPC_CREAT选项打开时,不管是否已存在该块共享内存,则都返回该共享内存的ID,若不存在则创建共享内存;②当只有IPC_EXCL选项打开时,不管有没有该快共享内存,shmget()都返回-1;③所以当IPC_CREAT | IPC_EXCL时, 如果没有该块共享内存,则创建,并返回共享内存ID。若已有该块共享内存,则返回-1;

函数的返回值:返回值为共享内存的id号,后续的操作要用到这个id号

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/ipc.h>4 #include<sys/shm.h>5 int main()6 {7         key_t keyid;8         int shmid;9         keyid=ftok("/home/ldw",5);10         if(keyid<0)11         {12                 perror("ftok");13                 return -1;14         }15         printf("keyid:%d\n",keyid);16         shmid=shmget(keyid,20,IPC_CREAT|0777);17         printf("shmid:%d\n",shmid);18         return 0;19 }
//keyid:83951618
//shmid:8683532

3、将共享内存映射到进程空间 shmat

函数功能:将一段共享内存  映射到进程空间

函数的头文件:#include <sys/types.h>
                                 #include <sys/shm.h>

函数的原型:void *shmat(int shmid, const void *shmaddr, int shmflg);

函数的参数:int shmid:共享内存的id
                             const void *shmaddr:你要映射到的进程空间的地址
                                一般来说   我们不清楚  进程的哪段内存空间是可用
                                一般这个位置  写0 表示由系统自动分配空间

int shmflg:一般来说  也是写0     表示共享内存可读写

函数的返回值:返回的就是系统分配给你的空间的首地址

  1 #include<stdio.h>                                //写内容2 #include<sys/types.h>3 #include<sys/ipc.h>4 #include<sys/shm.h>5 #include<string.h>6 int main()7 {8         key_t keyid;9         int shmid;10         keyid=ftok("/home/ldw",5);11         if(keyid<0)12         {13                 perror("ftok");14                 return -1;15         }16         shmid=shmget(keyid,20,IPC_CREAT|0777);17         void *p=shmat(shmid,0,0);18         strcpy(p,"hello!");19         return 0;20 }
  1 #include<stdio.h>                          //读内容2 #include<sys/types.h>3 #include<sys/ipc.h>                        //读和写,在不同的终端中4 #include<sys/shm.h>5 #include<string.h>6 int main()7 {8         key_t keyid;9         int shmid;10         keyid=ftok("/home/ldw",5);11         if(keyid<0)12         {13                 perror("ftok");14                 return -1;15         }16         shmid=shmget(keyid,20,IPC_CREAT|0777);17         void *p=shmat(shmid,0,0);18         printf("said:%s\n",(char *)p);19         return 0;20 }
//said:hello!

4、解除映射 shmdt

函数的功能:解除共享内存的映射

函数的头文件:#include <sys/types.h>
                                 #include <sys/shm.h>

函数的原型:int shmdt(const void *shmaddr);

函数的参数:const void *shmaddr:系统分配给的内存空间的首地址

函数的返回值:成功返回  0                         失败返回     -1

5、删除一个共享内存 shmctl

函数功能:删除一个共享内存

函数的头文件:#include <sys/ipc.h>
                                #include <sys/shm.h>

函数原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);

函数的参数:int shmid:共享内存的id
                             int cmd:IPC_RMID  删除共享内存
                             struct shmid_ds *buf:NULL

函数的返回值:成功返回  0                                   失败返回  -1

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/ipc.h>4 #include<sys/shm.h>5 #include<string.h>6 int main()7 {8         key_t keyid;9         int shmid;10         keyid=ftok("/home/ldw",5);11         if(keyid<0)12         {13                 perror("ftok");14                 return -1;15         }16         shmid=shmget(keyid,20,IPC_CREAT|0777);17         void *p=shmat(shmid,0,0);18         strcpy(p,"hello!");19         shmdt(p);20         shmctl(shmid,IPC_RMID,NULL);21         return 0;22 }

二、信号量

就是用来解决多个进程间资源的冲突的问题的,信号量就是用来解决进程间的同步与互斥问题的一种进程间通信机制。

信号量:本质就是一个普通的数值,你操作信号量其实就是在操作这个数值
              对这个数字可以进行加或者减的操作,对应的就是 P V操作

当我的数字减到0的时候  表示无资源可以使用

P操作

消耗一个信号量

如果信号量的值大于零,就给它减1;

如果的值为零,就挂起该进程的执行

V操作:

释放一个信号量

1、创建或者打开一个信号量  semget

函数功能:创建或者打开一个信号量

函数的头文件:#include <sys/types.h>
                                #include <sys/ipc.h>
                                #include <sys/sem.h>

函数的原型:int semget(key_t key, int nsems, int semflg);

函数的参数:key_t key:键值
                             int nsems:你要创建的信号量的个数,这个位置一般填1
                             int semflg:IPC_CREAT | 0644     打开或创建信号量,并赋予权限

函数的返回值:成功返回信号量的id        失败返回 -1           默认信号量的初值为0

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/ipc.h>4 #include<sys/sem.h>5 int main()6 {7         key_t keyid;8         int semid;9         keyid=ftok("/home/ldw",2);10         semid=semget(keyid,1,IPC_CREAT|0644);11         printf("semid:%d\n",semid);12         return 0;13 }
//semid:32768

2、设置或者删除一个信号量  semctl

函数功能:设置或者删除一个信号量

函数头文件:#include <sys/types.h>
                             #include <sys/ipc.h>
                             #include <sys/sem.h>

函数的原型:int semctl(int semid, int semnum, int cmd, ...);

函数的参数:int semid:信号量的id
                              int semnum:要操作的信号量的数组的下标            一般写0
                              int cmd:① IPC_RMID:删除信号量、② SETVAL:设置信号量

①:如果此处为IPC_RMID:删除信号量,则后面第四个空没有参数
②:如果此处为SETVAL:设置信号量,则第四个参数需要传入一个共用体

union semun {
               short val;                      /*SETVAL用的值*/(给信号量赋的初值)
               struct semid_ds* buf;   /*IPC_STAT、IPC_SET用的semid_ds结构(则是一个内核结构体)*/
               unsigned short* array;  /*SETALL、GETALL用的数组值*/
               struct seminfo *buf;      /*为控制IPC_INFO提供的缓存(表示信号量系统资源配置信息)*/
          } ;

函数的返回值:成功返回  0                                 失败返回 -1

3、释放或者消耗一个信号量   semop

函数功能:释放或者消耗一个信号量

函数的头文件:#include <sys/types.h>
                                 #include <sys/ipc.h>
                                 #include <sys/sem.h>

函数的原型:int semop(int semid, struct sembuf *sops, size_t nsops);

函数的参数:int semid:信号量的 id
                             struct sembuf *sops:你要对信号量的操作是一个核心结构体

struct sembuf{
                    unsigned short      sem_num; //信号在信号集中的索引,0代表第一个信号,1代表第二个信号  (即信号量数组的下标)
                    short      sem_op;         //进行什么操作:①+1:V操作  释放一个信号量;②-1:P操作  消耗一个信号量
                    short      sem_flg;        //操作标志0 设置信号量的默认操作(表示申请不到信号量就阻塞)
                }

size_t nsops :你要操作的信号量个数,一般写1    
(进行操作信号量的个数,即sops结构变量的个数,需大于或等于1。最常见设置此值等于1,只完成对一个信号量的操作)

函数的返回值:成功返回 0                         失败返回 -1

  1 #include<stdio.h>2 #include <sys/types.h>3 #include <sys/stat.h>4 #include <fcntl.h>5 #include<unistd.h>6 #include <sys/types.h>7 #include <sys/ipc.h>8 #include <sys/sem.h>9 int main()10 {11         struct sembuf myops;12         int pd;13         pd=fork();14         if(pd == 0)15         {16                 key_t keyid;17                 int semid;18                 keyid=ftok("/home/ldw",2);19                 semid=semget(keyid,1,IPC_CREAT|0644);20                 semctl(semid,0,SETVAL,2);21                 myops.sem_num=0;22                 myops.sem_op=-1;23                 myops.sem_flg=0;24                 semop(semid,&myops,1);25                 int i;26                 for(i=0;i<5;i++)27                 {28                         printf("i==%d\n",i);29                         sleep(1);30                 }31                 myops.sem_op=1;32                 semop(semid,&myops,1);33         }34         if(pd > 0)35         {36                 sleep(1);37                 int j;38                 key_t keyid;39                 int semid;40                 keyid=ftok("/home/ldw",2);41                 semid=semget(keyid,1,IPC_CREAT|0644);42                 myops.sem_num=0;43                 myops.sem_op=-1;44                 myops.sem_flg=0;45                 semop(semid,&myops,1);46                 for(j=0;j<5;j++)47                 {48                         printf("j==%d\n",j);49                         sleep(1);50                 }51                 myops.sem_op=1;52                 semop(semid,&myops,1);53         semctl(semid,0,IPC_RMID);54         }55         return 0;56 }
//i==0 j==0 i==1 j==1 i==2 j==2 i==3 j==3 i==4 j==4

三、消息队列

消息队列才是最符合要求进程间的通讯

消息队列的特点:

①消息先进先出
                ②可以同时接收多条消息
                ③写消息的时候,你写的消息会暂存在消息队列;当有进程读消息的时候,读取的最先进队列的

消息队列的消息的分类:
        可以是 1类消息
        可以是 2类消息..........
比如现在有三个进程:
        A B C
        还有一个消息队列
        A往消息队列里写  1类消息
        B往消息队列写  2类消息
        C去消息队列里读 1类或者是2类消息
        C去消息队列里读  3类消息  会阻塞

1、创建或者打开一个消息队列  msgget

函数功能:创建或者打开一个消息队列

函数头文件:#include <sys/types.h>
                             #include <sys/ipc.h>
                            #include <sys/msg.h>

函数原型:int msgget(key_t key, int msgflg);

函数的参数:key_t key:键值
                             int msgflg:IPC_CREAT|0644

函数的返回值:成功返回 消息队列的 id                失败返回  -1

  1 #include<stdio.h>2 #include <sys/types.h>3 #include <sys/ipc.h>4 #include <sys/msg.h>5 int main()6 {7         int msqid;8         key_t keyid;9         keyid=ftok("/home/ldw",2);10         printf("keyid:%d\n",keyid);11         msqid=msgget(keyid,IPC_CREAT|0644);12         printf("msqid:%d\n",msqid);13         return 0;14 }
keyid:33619970
msqid:0

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);

函数的参数:int msqid:消息队列的 id
                             const void *msgp:消息结构体指针

struct msgbuf {
               long mtype;       /* message type, must be > 0 */消息的类型
               char mtext[1];    /* message data */要写的消息的正文
           };

size_t msgsz:消息的大小(<4k),不包括type。则 msgsz = sizeof(msgbuf) - sizeof(mtype)

msgflg:一般写 0      表示无法发送就阻塞(没有满足条件就阻塞当前进程)

函数的返回值:成功返回 0                              失败返回 -1

  1 #include<stdio.h>2 #include <sys/types.h>3 #include <sys/ipc.h>4 #include <sys/msg.h>5 #include<string.h>6 struct msgbuf{7         long mtype;8         char mtext[100];9         10 } mybuf;11 int main()12 {13         key_t keyid;14         int msgid;15         keyid=ftok("/home/ldw",2);16         msgid=msgget(keyid,IPC_CREAT|0644);17         mybuf.mtype=1;18         strcpy(mybuf.mtext,"hello");19         msgsnd(msgid,&mybuf,sizeof(mybuf)-sizeof(long),0);20         return 0;21 }

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);

函数的参数:int msqid:消息队列的 id
                             void *msgp:存放读取到的消息的位置

struct msgbuf {
               long mtype;       /* message type, must be > 0 */消息的类型
               char mtext[1];    /* message data */要读的消息的正文
           };

size_t msgsz:消息的大小,包括type  (否则段错误)
                             long msgtyp:接收消息的类型
                             int msgflg:0   表示读取不到就阻塞(调用阻塞直到条件满足为止)

函数的返回值:成功返回 0                       失败返回 -1

  1 #include<stdio.h>2 #include <sys/types.h>3 #include <sys/ipc.h>4 #include <sys/msg.h>5 #include<string.h>6 struct msgbuf{7         long mtype;8         char mtext[100];9 }mybuf;10 int main()11 {12         key_t keyid;13         char buf[120];14         int msgid;15         keyid=ftok("/home/ldw",2);16         msgid=msgget(keyid,IPC_CREAT|0644);17         msgrcv(msgid,buf,sizeof(mybuf),1,0);18         printf("buf=%s\n",(buf+8));19         msgctl(msgid,IPC_RMID,NULL);20         return 0;21 }
//buf=hello

4、删除一个消息队列  msgctl

函数功能:删除一个消息队列

函数头文件:#include <sys/types.h>
                             #include <sys/ipc.h>
                             #include <sys/msg.h>

函数原型:int msgctl(int msqid, int cmd, struct msqid_ds *buf);

函数的参数:int msqid:消息队列的 id
                              int cmd:IPC_RMID
                              struct msqid_ds *buf:NULL

函数的返回值:成功返回  0                                       失败返回  -1

IPC通信-------初学者入门相关推荐

  1. 微软不会放弃Electron:Electron 快速入门及IPC 通信

    最近,有媒体推文说"微软要放弃Electron了",很多不明真相的群众被带偏了节奏:我刚学了Electron就要过时了吗?求真相!那么我们还要不要学Electron呢? 实际上:只 ...

  2. 传统的Linux中IPC通信原理

    在了解 Binder 跨进程通信原理之前, 我们先了解一下 Linux 传统的进程间通信的概念和基本原理, 这样有助于我们更好的理解 Binder 的通信原理. 这个部分基本都是理论, 基础不是很好的 ...

  3. Node初学者入门,一本全面的NodeJS教程,微小的web框架,能实现文件上传功能以及数据解析功能...

    Node初学者入门,一本全面的NodeJS教程 转载于:https://www.cnblogs.com/hfultrastrong/p/8036672.html

  4. async function_Electron IPC 通信如何使用 async/await 调用?

    前言碎语 此想法是在使用 electron 进程间通信(IPC)过程中,无法忍受其 API 的使用不友好性而产生. 为了提高代码可读性.可维护性,而不得已造轮子了. 生命在于折腾,其乐无穷. Elec ...

  5. 首发:适合初学者入门人工智能的路线及资料下载

    本文为AI入门提供了一个简易的学习路线,并提供了代码和数据集下载.(黄海广) 一.前言 AI以及机器学习入门,初学者遇到的问题非常多,但最大的问题就是: 资料太多!!!看不完!!!不知道如何取舍!!! ...

  6. 4月25日 python学习总结 互斥锁 IPC通信 和 生产者消费者模型

    一.守护进程 import random import time from multiprocessing import Processdef task():print('name: egon')ti ...

  7. web前端培训分享Electron之IPC 通信

    本文由小千给大家分享Electron之IPC 通信. 1.index.html <!DOCTYPE html><html><head><meta charse ...

  8. web前端技术分享Electron之IPC 通信

    本文由小千给大家分享Electron之IPC 通信. 1.index.html <!DOCTYPE html><html><head><meta charse ...

  9. 用python公众号开书城步骤_资源 | 开放Python书籍:一本短小精悍的初学者入门指南...

    资源 | 开放Python书籍:一本短小精悍的初学者入门指南 作者:机器之心 来源:机器之心 公众号 分享到: 03-25 选自GitHub机器之心整理 参与:思源 如何快速熟悉 Python 编程一 ...

最新文章

  1. 求任意数阶乘最后一位
  2. 南京林业大学计算机专升本,2018江苏专转本学校之:南京林业大学
  3. ubuntu系统home(主文件夹)中的内容在桌面的显示
  4. Android自定义属性、控件三步法
  5. oracle em(Enterprise Manager) 收集贴
  6. 【转】GigE Vision简介
  7. ARM MOV和 LDR指令关系
  8. numpy 数组与矩阵的乘法理解
  9. 即这样的WZSZF01代码是错误的
  10. python可选参数定义_c#教程之定义可选参数
  11. leetcode - 98. 验证二叉搜索树
  12. Centos6.9下RocketMQ3.4.6高可用集群部署记录(双主双从+Nameserver+Console)
  13. CVPR 2021 出自港中文,对抗变换提高对抗样本的可迁移性
  14. [分享]N-Gage QD新手教程
  15. k8s mysql 查询_MySql | 为什么大家都在说 Select * 效率低
  16. html原生时间选择框,JS实现漂亮的时间选择框效果
  17. matlab计算四元方程解,求解四元二次方程,用matlab
  18. 类中成员方法和实例方法
  19. 慧荣SM2246主控开卡一直处于Pretest状态解决方案
  20. ubuntu的使用经验to新手

热门文章

  1. 我,机械工程硕士,工作一年,月入6K
  2. error: no such file or directory
  3. 使用PortTunnel工具截获前置机数据的操作
  4. 此次自驾车回家,途中吉凶情况如何?
  5. 缓存、缓存清理和HTTP缓存
  6. 【Python学习之鼠标悬停点击事件】
  7. 基于二分查找的抽签游戏算法的优化
  8. 树莓派4B 4G板子64位、32位系统下使用ncnn 推理yolov4
  9. 计算机主机中网络适配器,第三章计算机网络设备.ppt
  10. Biopython | 计算蛋白质的接触图(contact map)