无名管道 int pipe(int pipefd[2])
特点:
- 因为管道没有名字,因此无法用open()函数打开。
- 只能用于亲缘间进程通信,不能在无关联的进程中通信
- 半双工工作模式,pipefp[0]一端读操作,pipefp[1]一端写操作,不能同时进行读写。
- 是一种特殊文件,在内存中存储,由内核进行管理
- 读写可以使用文件IO中read,write函数
- 无名管道操作属于一次性操作,如果对无名管道进行读操作,数据会被全部读走
注意事项
- 当管道无数据时,执行读操作,读操作阻塞
- 无名管道大小是固定的,管道一旦满,写操作就会导致进程阻塞 大小为:1024*64
- 写入数据不会覆盖前面的数据,会存储到后面,像队列一样,读数据会将读取到数据从管道中直接拿走
- 将读端关闭,向无名管道写入数据,管道会破裂,进程收到信号(SIGPIPE),会将进程杀死
- 当管道中有数据时,关闭写端,读操作可以继续执行,数据读完后,读取的返回值为0
代码示例
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *a = fopen("./1.txt","r");
FILE *fd = fopen("./2.txt","w");
int fp[2];
int ret = pipe(fp);
if(-1 == ret)
{
perror("pipe");
exit(-1);
}
pid_t pid = fork();
if(pid < 0)
{
perror("fork");
exit(-1);
}
else if (0 == pid)
{
while(1)
{
close(fp[0]);//关闭从管道中读取操作
char buf[200] = {0};
fgets(buf,sizeof(buf),a);//从标准输入中读取数据到数组buf中
write(fp[1],buf,strlen(buf));//将buf中的数据通过管道写入到内存中
}
}
else
{
while(1)
{
close(fp[1]);//关闭从管道中写入操作
char arr[200] = {0};
char buf[200] = {0};
read(fp[0],arr,sizeof(arr));//从内存中将数据通过管道读取到arr数组中
printf("%s",arr);
}
}
//while(1);
fclose(a);
fclose(fd);
return 0;
}
有名管道int mkfifo(const char *pathname, mode_t mode);
特点;
- 有名管道存在文件系统中,数据在内存中
- 可以用于无亲缘关系的进程
- 只有读端和写端同时存在管道才能打开成功
注意事项
- 读端不存在时,写端写入数据将会阻塞
- 读端意外结束,写端再写入数据将会管道破裂,进程结束
- 有名管道的数据存储在内存中,数据交互在内核中
聊天程序的实现原理
- 创建两个有名管道,fp1,fp2
- 编写两个程序,一个主程序自己接收和发送信息,另一个程序其他人接收你发的数据和发送数据给你。
- 程序主要函数:open(),write(),read(),fgets(),close(),memset,
聊天软件代码1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
pid_t pid = fork();
if(pid < 0)
{
perror("fork");
exit(-1);
}
else if(pid == 0)
{
int fp2 = open("./f2",O_WRONLY);
char buf[100] = {0};
while(1)
{
//printf("mesend:");
fgets(buf,sizeof(buf),stdin);
write(fp2,buf,strlen(buf)-1);
//memset(buf,0,sizeof(buf));
}
}
else
{
int fp1 = open("./f1",O_RDONLY);
char buf[100] = {0};
int n = 1;
while(1)
{
n = read(fp1,buf,sizeof(buf));
if(0 == n)
break;
printf("mereceived:%s\n",buf);
memset(buf,0,sizeof(buf));
}
}
return 0;
}
聊天软件代码2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
pid_t pid = fork();
if(pid <0)
{
perror("fork");
exit(-1);
}
else if(pid == 0)
{
int fp1 = open("./f1",O_WRONLY);
char buf[100] = {0};
while(1)
{
//printf("yousend:");
fgets(buf,sizeof(buf),stdin);
write(fp1,buf,strlen(buf)-1);
}
}
else
{
int fp2 = open("./f2",O_RDONLY);
char buf[100] = {0};
int n = 1;
while(1)
{
n = read(fp2,buf,sizeof(buf));
if(0 == n)
break;
printf("youreceived:%s\n",buf);
memset(buf,0,sizeof(buf));
}
}
return 0;
}
实现效果通信
me:
Can you show me your photos
mereceived:No, mom won't let me play with bad guys
Then I won't play with you
mereceived:baibai
you:
youreceived:Can you show me your photos
No, mom won't let me play with bad guys
youreceived:Then I won't play with you
baibai