进程间交换信息的方法---进程间通信(IPC)
IPC的方式有单机通信与多机通信(是否在同一台机子上进行通信)
单机通信:
- 管道(包括无名管道和命名管道)
- 半双工管道,FIFO
- 全双工管道,命名全双工管道
- 消息队列
- 信号量
- 共享存储
多机通信:
- 套接字STREAMS
- Socket
一:管道
通常为无名管道
特点:
- 半双工,数据只能在一个方向上流动,有固定读端和写端
- 只适用于有亲缘关系的进程,如父子进程与兄弟进程
- 可以看作是一种特殊的文件,也可以使用fread和fwrite等函数进行读写,但是并不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。当进程结束之后,管道也随之消失,不储存数据
原型:
#include <unist.h>
int pipe(int fd[2]); //返回值,成功返回1,失败返回-1
- 当管道开启时,会创建两个文件描述符,fd[0]为读而打开,fd[1]为写而打开
- 关闭管道只要把文件描述符关闭即可
- 若要数据从父进程流向子进程,则要关闭父进程的读端和子进程的写端,反之则是从子进程流向父进程
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd[2];
int pid;
char buf[128];
if(pipe(fd) == -1){
printf("create pipe failed\n");
}
pid = fork();
if(pid == -1){
printf("create child failed\n");
}
else if(pid > 0){
printf("this is father\n");
close(fd[0]); //关闭读端,开始写
write(fd[1],"hello from father\n",strlen("hello from father\n"));
wait();
}
else{
printf("this is child\n");
close(fd[1]); //关闭写端,开始读
read(fd[0],buf,128);
printf("the message is %s\n",buf);
exit(0);
}
return 0;
}
二:FIFO
又称命名管道
特点:
- FIFO可以在无关的进程之间交换数据,与无名管道不同
- FIFO与路径名相关联,以一种特殊设备文件形式存在于文件系统中
原型:
int mkfifo(const char *pathname,mode_t mode);
mode参数与open中的mode参数使用相同
//创建管道
#include <sys/types.h>
#include <sys/stat.h>
// int mkfifo(const char *pathname, mode_t mode);
int main()
{
mkfifo("./file",0600);
return 0;
}
可以通过perror("why");了解失败原因
增加调试原因,避免随便报错
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
// int mkfifo(const char *pathname, mode_t mode);
int main()
{
if((mkfifo("./file",0600) == -1) && errno != EEXIST){
printf("create fifo failed\n");
}
return 0;
}
实现两个进程间通信
//read.c
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
// int mkfifo(const char *pathname, mode_t mode);
int main()
{
char buf[30] = {0};
int nread = 0;
if((mkfifo("./file",0600) == -1) && errno != EEXIST){
printf("create fifo failed\n");
}
int fd = open("./file",O_RDONLY);
printf("open success\n");
while(1){
nread = read(fd,buf,30);
printf("read %d byte,content: %s\n",nread,buf);
if(nread == 3){
break;
}
}
close(fd);
return 0;
}