一.无名管道
1.1无名管道的原理
无名管道只能用于亲缘间进程的通信,无名管道的大小是64K。无名管道是内核空间实现的机制。
1.2功能
1) Pipe()创建一个管道,这是一个单向的数据通道,可用于进程间通信。
2)数组pipefd用于返回两个指向管道末端的文件描述符。
3)Pipefd[0]指的是管道的读端。Pipefd[1]指的是管道的写入端,写入管道的写入端数据由内核进行缓冲(64k),直到从管道的读取端读取为止。
1.3无名管道通信特点
1.只能用于亲缘间进程的通信
2.无名管道数据半双工的通信的方式
单工 : A -------------->B
半双工 : 同一时刻 A----->B B------>A
全双工 : 同一时刻 A<---->B
3.无名管道的大小是64K
4.无名管道不能够使用lseek函数
5.读写的特点
如果读端存在写管道:有多少写多少,直到写满为止(64k)写阻塞
如果读端不存写管道,管道破裂(SIGPIPE) (可以通过gdb调试看现象)
如果写端存在读管道:有多少读多少,没有数据的时候阻塞等待
如果写端不存在读管道:有多少读多少,没有数据的时候立即返回
1.4无名管道的实例
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define ERROR(msg) do{\
printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
printf(msg);\
exit(-1); \
}while(0)
int main(int argc, char const *argv[])
{
pid_t pid;
int num[2];
char buff[128] = {0};
if (pipe(num)){
ERROR("pipe error");
}
if ((pid = fork()) == -1){
ERROR("fork error");
}else if(pid == 0){
close(num[0]);
while (1){
memset(buff, 0, sizeof(buff));
printf("请输入您要输入的数值>>");
fgets(buff, sizeof(buff), stdin);
buff[strlen(buff) -1] = '\0';
write(num[1], buff, strlen(buff));
if (!strncmp(buff, "quit", 4)){
break;
}
}
close(num[1]);
exit(EXIT_SUCCESS);
}else{
close(num[1]);
while (1){
memset(buff, 0, sizeof(buff));
read(num[0], buff, sizeof(buff));
if (!strncmp(buff, "quit", 4)){
break;
}
printf("%s\n",buff);
}
close(num[0]);
wait(NULL);
}
return 0;
}
二.有名管道
2.1有名管道的原理
1)可以用于亲缘间进程的通信,也可以用于非亲缘间的进程的通信。
2)有名管道会创建一个文件,需要通信的进程打开这个文件,产生文件描述符后就可以通信了,有名管道的文件存在内存上。
3)有名管道的大小也是64K,也不能使用lseek函数
2.2有名管道的特点
1.可以用于任意进程间的通信
2.有名管道数据半双工的通信的方式
3.有名管道的大小是64K
4.有名管道不能够使用lseek函数
5.读写的特点
如果读端存在写管道:有多少写多少,直到写满为止(64k)写阻塞
如果读端不存写管道
1.读权限没有打开,写端在open的位置阻塞
2.读端打开后关闭,管道破裂(SIGPIPE) (可以通过gdb调试看现象)
如果写端存在读管道:有多少读多少,没有数据的时候阻塞等待
如果写端不存在读管道
1.写权限没有打开,读端在open的位置阻塞
2.写端打开后关闭,有多少读多少,没有数据的时候立即返回
2.3有名管道实例:
mkfifo文件:
#include <stdio.h>
#include <stdlib.h>
#define ERROR(msg) do{\
printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
printf(msg);\
exit(-1); \
}while(0)
int main(int argc, char const *argv[])
{
if (mkfifo("./fifo",0666)){
ERROR("mkfifo error");
}
//有名管道没有阻塞,手动加一个阻塞
getchar();
system("rm ./fifo -rf");
return 0;
}
write文件:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define ERROR(msg) do{\
printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
printf(msg);\
exit(-1); \
}while(0)
int main(int argc, char const *argv[])
{
int fd;
char buff[128] = {0};
if ((fd = open("./fifo",O_WRONLY)) == -1){
ERROR("open fifo error\n");
}
while(1){
printf("input >");
fgets(buff, sizeof(buff), stdin);
buff[strlen(buff) - 1] = '\0';
write(fd, buff, strlen(buff));
if(!strncmp("quit",buff,4))break;
}
close(fd);
return 0;
}
read文件:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.