进程间通信(IPC)
进程间通信的类型:
半双工管道(FIFO)、全双工管道(命名全双工管道)、消息队列、信号量、共享内存、套接字(多机其它为单机)
IPC的通信方式:
管道(包括无名管道、命名管道)
消息队列
信号量
共享存储
Scoket
Streams
等。
其中,Scoket和Stream支持不同主机上的两个进程IPC。
一、管道
管道,通常指无名管道,是UNIX系统最古老的形式。
1、特点
1)半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。[管道中的数据读走就没有了,可以类似水管想象一下]
2)只能用于具有亲缘关系的进程之间的通信(父子进程或兄弟进程)
3)是一种特殊的文件,对于他的读写可以使用普通的read、write等函数。但是它不是普通文件,并不属于其它任何文件系统,并且只存在于内存中。
2、原型
#include<stdio.h>
int pipe(int fd[2]); //有返回值,若成功返回0;失败返回-1;
当一个管道建立时,它会创建两个文件描述符;
fd[0]为读而打开,
fd[1]为写而打开。
3、栗子
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main(){
int fd[2];
int pid;
char buf[24];
if(pipe(fd)==-1){
printf("creat pipe failed\n");
}
pid=fork();
if(pid<0){
printf("create child failed\n");
}else if(pid>0){
printf("this is father\n");
close(fd[0]); //关闭读端
write(fd[1],"hello everyone",strlen("hello everyone")); //开启写端进行写数据
wait(); //父进程等待子进程
}else{
printf("this is child\n");
close(fd[1]); //关闭写端
read(fd[0],buf,24); //打开读端,读buf里数据
printf("read from father %s\n",buf);
exit(-1); //子进程退出
}
return 0;
}
命名管道FIFO
FIOFO,亦称命名管道,是一种文件类型。
1、特点
1)可在无关的进程之间交换数据,与无名管道不同;
2)有路径名,以一种特殊设备文件形式存在于文件系统中。
2、原型
查找mkfifo在man手册第三页
#include <sys/stat.h>
int mkfifo(const char *pathname,mode_t mode); //返回值,成功返回0;失败返回-1;
mode参数与open函数中的mode相同,一旦创建了一个FIFO,就可以用一般的文件I/O函数操作它。
3、栗子
若指定了O_NONBLOCK,则只读open立即返回;而只写open将出错返回-1,如果没有进程已经为只读而打开该FIFO,其errno置ENXIO。
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
int main(){
int fd=mkfifo("./file",0600); //创建一个file文件,可读可写
if((fd==-1)&&errno==EEXIST){ //判断是否创建成功
printf("mkfifo failed\n");
perror("why:"); //打印失败的原因
}else{
printf("mkfifo success\n");
}
return 0;
}
若没有指定O_NONBLOCK(默认),只读open要阻塞到某个其它进程为写而打开此FIOFO;同理,只写open要阻塞到某个其它进程为读而打开它。
这是一个read.c程序
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
int main(){
char buf[32]={0};
int m=mkfifo("./file",0600);
if((m==-1)&&errno!=EEXIST){
printf("mkfifo failed\n");
perror("why:");
}
int fd=open("./file",O_RDONLY);
printf("open success\n");
int nread=read(fd,buf,32);
printf("read %d from fifo\r context:%s\n",nread,buf);
close(fd);
return 0;
}
这是一个write.c程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main() {
char *str = "hello,fifo!";
int fd = open("./file", O_WRONLY);
printf("write open success\n");
write(fd, str,strlen(str));
close(fd);
return 0;
}
先运行read.c程序,接着运行write.c程序就可以实现两个端的数据交互。
剩余的通信方式且听下回分解!
进程间通信(二)