IPC(进程间通信 Inter Process Comnunication)
目前常用的通信方式:
- 管道 最简单
- 信号 开销最小
- 共享映射区域 在无关系的进程间通信
- 本地套接字 最复杂,最稳定
文件类型
-文件
d目录
l 符号链接
伪文件(不占用磁盘空间):
s套接字
b块设备
c字符设备
p管道 (内核缓冲区)
查看缓冲区大小 #ulimit -a 512字节*8
管道局限性(其实现方式为环形队列):
- 数据自己读不能自己写
- 数据一旦被读走,便不再存在
- 半双工,数据只能在一个方向上流动 (同时刻)
- 只能在有公共祖先的进程见使用管道通信
#include<stdio.h>
#include<unistd.h>
int main(){
int fd[2];
//fd[0] 读管道 fd[1]写管道
//pipe返回 0 则成功 否则返回-1
int ret=pipe(fd);
printf("ret==%d\n",ret);
if (ret==-1){
perror("pipe error:\n");
exit(1);
}
pid_t pid=fork();
if(pid<0){
perror("pipe error:\n");
exit(1);
}else if(0==pid){
// #子进程读数据
close(fd[1]);
char buf[1024];
//read返回值 是实际读取到的字节数。
ret=read(fd[0],buf,sizeof(buf));
printf("ret==%d\n",ret);
//末尾读到0
if(0==ret)
printf("--------\n");
//将buf写入第一个参数所指的文件内。
write(1,buf,ret);
printf("Son successfully output!\n");
}else {
sleep(1);
close(fd[0]);
write(fd[1],"strstr str\n",13);
// wait(NULL);
}
}
练习:借助共同的文件传递数据
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
pid_t pid;
pid=fork();
if(pid<0){
perror("fork error!\n");
exit(1);
}else if(pid==0){
int fd=open("new.txt",O_WRONLY);
char ame[]="acffdsds ss\n";
int len=strlen(ame);
write(fd,ame,len);
close(fd);
printf("Son exit_____\n");
}else{
sleep(1);
int fd=open("new.txt",O_RDONLY);
char buff[1024];
read(fd,buff,1024);
printf("%s\n",buff);
close(fd);
printf("father eixt_______\n");
}
return 0;
}
mmap函数
mmap获取文件指针操作文件
创建的映射区权限要小于打开文件的权限;
创建映射区时有一次隐式的读操作。
#include<stdio.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main(){
int fd=open("mytext.txt",O_CREAT|O_RDWR,0644);
if(fd<0)
perror("open error\n");
//文件截断为4字节 返回的len不代表大小
//注意truncate 和 ftruncate 的参数区别
ftruncate(fd,4);
//最后一个参数offset文件指针偏移量。必须是4096的整数倍 mmap对文件创建映射。
//映射区由MMU创建 单位为页。
// 映射区权限prot
//第二参数 文件大小 不可为0 -->映射区大小不可为0
char *p =mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//不检查返回值会死的很难看?
if(MAP_FAILED==p){
perror("mmap error:");
exit(1);
}
//通过指针操作内存
strcpy(p,"ac");
//关闭mmap
int ret=munmap(p,4);
close(fd);
}
mmap父子进程通信
通过flag参数的调整可以控制信息覆盖。
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/mman.h>
int var=100;
int main(){
pid_t pid;
int fd=open("com.txt",O_RDWR|O_CREAT|O_TRUNC,0644);
ftruncate(fd,10);
int* m=(int *)mmap(NULL,10,PROT_WRITE|PROT_READ,MAP_PRIVATE,fd,0);
if(0==MAP_FAILED){
perror("mmap error!\n");
exit(1);
}
close(fd);
pid=fork();
if(0==pid){
var=1000;
*m=20;
printf("Son var=%d m*=%d\n",var,*m);
}else if(pid>0){
sleep(1);
printf("Father var=%d m*=%d\n",var,*m);
munmap(m,10);
}
}
匿名映射(不通过文件传递信息)
flag参数应该为shared 不然没个屌用。
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/mman.h>
int main(){
pid_t pid;
int *p=mmap(NULL,10,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0);
pid=fork();
if(0==pid){
*p=666;
printf("Son *p=%d\n",*p);
}else if(pid>0){
sleep(1);
printf("Far *p=%d\n",*p);
munmap(p,10);
}
}
mmap 无血缘关系进程通信
文件····················