进程间通信(IPC)(1)—— 管道、共享内存
来源:互联网 发布:mac系统画流程图 编辑:程序博客网 时间:2024/06/04 03:40
一 有哪些进程间通信方式
IPC就是两个或者多个进程之间的数据交互。
IPC的方法:
1. 文件
2. 信号(signal)
3. 管道
4. 共享内存
5. 消息队列(会做一个综合练习)
6. 信号量集(与前面学的信号无关semaphore)
7. 网络编程(socket)
….
二 管道
管道是Unix最古老的IPC方式,现在已很少使用。
4 5 6 用法类似,统称为XSI IPC,遵守相同的规范。
管道分为有名管道和无名管道。有名管道由程序建立管道文件,用于进程间的通信。而无名管道由内核建立管道文件,用于fork()创建的父子进程之间的通信。
管道是通过管道文件(媒介) 进行交互的。管道文件和 普通文件有所区别。管道文件是 mkfifo命令创建的或者mkfifo()函数新建,管道文件的后缀 .pipe。
管道文件只是数据的中转站,不存储数据。因此,只有读写都ok时,才能畅通。(echo cat)
管道的使用和文件一样的,但管道文件的创建必须用mkfifo。
1 有名管道
pipea.c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>int main(){ int fd = open("a.pipe",O_WRONLY); //O_CREAT用不到,因为它无法创建管道文件 //O_RDWR同时开通了读管道和写管道 if(fd==-1) perror("open"),exit(-1); int i; for(i=0;i<100;i++){ write(fd,&i,4); } close(fd);}pipeb.c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>int main(){ int fd = open("a.pipe",O_RDONLY); if(fd==-1) perror("open"),exit(-1); int i; for(i=0;i<100;i++){ int x; read(fd,&x,4); printf("x=%d\n",x); } close(fd);}
2 无名管道
管道文件由内核管理,只能用于 fork()创建的父子进程之间。
借助pipe() 创建一个读管道,一个写管道。
#include <stdio.h>#include <unistd.h>#include <stdlib.h>int main(){ int fd[2] = {}; pipe(fd);//创建了两个管道,fd[0] 读 fd[1] 写 pid_t pid = fork(); if(pid == 0){//子进程 close(fd[1]);//关闭写端 int i; for(i=0;i<100;i++){ int x; read(fd[0],&x,4); printf("%d ",x); fflush(0); } close(fd[0]); exit(0); } close(fd[0]); int i; for(i=100;i<200;i++){ write(fd[1],&i,4); usleep(100000); } close(fd[1]);}
三 XSI IPC结构
XSI IPC 包括共享内存、消息队列、信号量集,隶属于同一个规范,有着共同的特征。
每个XSI IPC结构 都是在内核中存储和维护的,用ipcs命令可以查看,用ipcrm命令可以删除。
ipcs -a 查看全部IPC结构
-m 查看共享内存
-q 查看消息队列
-s 查看信号量集
ipcrm 用法和ipcs 类似,但后面要跟上ID。
每个XSI IPC结构都有两个东西定位:外部到内核要用key,内核中使用ID标识。
key的生成:
key的类型key_t,其实是一个长整形,有3种方法得到key:
1 使用宏 IPC_PRIVATE 做key,但这种方式无法实现 进程间的通信(私有),极少使用。
2 把所有的key定义在一个头文件中,用宏定义。
3 使用ftok()函数生成key,参数:真实存在的路径和项目编号(0-255)。
ID的生成:
IPC结构在内核中都用ID做唯一标识,创建/获取ID都有对应的函数,比如:
int shmid = shmget(key,…);
int msgid = msgget(key,…);
调用XXXget()时,都有一个flags,创建时的值为
权限|IPC_CREAT|IPC_EXCL
IPC_CREAT - 创建
IPC_EXCL - 如果存在会返回错误
和O_CREAT O_EXCL 类似。
IPC结构都有一个特殊的操作函数,提供查询、修改和删除的功能。
函数名:XXXctl(),比如:shmctl() msgctl()
参数cmd提供功能:
IPC_STAT - 查询IPC结构的属性/状态
IPC_SET - 修改IPC结构的相关属性,但只能修改权限
IPC_RMID - 删除IPC结构,按ID删除
3.1 共享内存
每个进程内存独立的,无法直接互访。共享内存就是内核管理一段内存(物理内存),这段物理内存允许 每个进程进行映射。
编程步骤:
1 系统创建/获取共享内存(拿到物理内存)
ftok()-> key
shmget() -> 创建/获取共享内存,返回ID
2 挂接共享内存(映射) shmat()
3 使用共享内存
4 脱接共享内存(解除映射) shmdt()
5 如果共享内存不再被使用,可以删除。 shmctl()
共享内存的优缺点:
优点:速度最快的IPC,高效率
缺点:如果有多个进程写数据,将会产生覆盖问题,导致数据的错误和不完整。
#include <stdio.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/shm.h>int main(){ key_t key = ftok(".",100);//生成key if(key==-1) perror("ftok"),exit(-1); int shmid = shmget(key,4, 0666|IPC_CREAT|IPC_EXCL);//创建shm if(shmid==-1) perror("shmget"),exit(-1); void* p = shmat(shmid,0,0);//挂接共享内存 int* pi = p; *pi = 1000; int res = shmdt(p);//脱接共享内存 if(res==-1) perror("shmdt"),exit(-1); printf("all ok\n");}//练习:写shmb.c,利用共享内存取出1000并打印#include <stdio.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/shm.h>int main(){ key_t key = ftok(".",100);//生成key if(key==-1) perror("ftok"),exit(-1); int shmid = shmget(key,0,0);//获取shm if(shmid==-1) perror("shmget"),exit(-1); void* p = shmat(shmid,0,0);//挂接共享内存 int* pi = p; printf("*pi=%d\n",*pi); int res = shmdt(p);//脱接共享内存 if(res==-1) perror("shmdt"),exit(-1);}
shmctl.c#include <stdio.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/shm.h>int main(){ key_t key = ftok(".",100); int shmid = shmget(key,0,0); if(shmid==-1) perror("shmget"),exit(-1); struct shmid_ds ds; shmctl(shmid,IPC_STAT,&ds);//取shm的状态 printf("key=%x\n",ds.shm_perm.__key); printf("mode=%o\n",ds.shm_perm.mode); printf("size=%d\n",ds.shm_segsz); printf("cpid=%d\n",ds.shm_cpid); printf("nattch=%d\n",ds.shm_nattch);//挂接数 ds.shm_perm.mode = 0640;//修改状态 可以改 ds.shm_segsz = 40;//不可以修改 shmctl(shmid,IPC_SET,&ds);//在修改状态 //shmctl(shmid,IPC_RMID,0); //删除}
- 进程间通信(IPC)(1)—— 管道、共享内存
- 进程间通信(IPC):共享内存
- 进程间通信(IPC)---共享内存
- Linux IPC(进程间通信)摘要(信号灯,共享内存,消息队列,管道)(一)
- 进程间通信(IPC)1 ------ 管道
- 进程通信(IPC)——实现共享内存
- 进程间通信(无名管道,有名管道,共享内存)
- Linux进程间通信(IPC)之一——管道
- Linux进程间通信(IPC)之一——管道
- Linux进程间通信(IPC)之一——管道
- 多进程通信(IPC)--共享内存
- 进程间通信(IPC)之————共享内存
- 进程间通信(IPC)——信号量、共享内存、消息队列
- 进程间通信(IPC)——信号量、共享内存、消息队列
- IPC—进程间的通信(信号量,共享内存,消息队列)
- 进程间通信IPC——共享内存
- uc笔记09---进程通信,管道,进程间通信,共享内存,消息队列,信号量,IPC 命令
- linux 进程间通信(IPC)一共享内存
- codeforces 632C
- 关于Fragment重叠问题分析和解决
- Fragment的声明周期整理
- 2016ACM暑假集训 - Sacrament of the sum
- 【ReactNative】真机上无法调试 could not connect to development server
- 进程间通信(IPC)(1)—— 管道、共享内存
- L2-003. 月饼-PAT团体程序设计天梯赛GPLT
- NYOJ118 修路方案 次小生成树
- LeetCode-JAVA-Valid Parentheses
- LeetCode-83:Remove Duplicates from Sorted List
- Spring事务管理(5)-开启事务
- POJ 3150 Cellular Automaton
- 跟我一起玩嵌入式开发-硬件抽象与汇编基础-1
- js中的history和location对象及节点