赞
踩
管道pipe也称为匿名管道,只有在有血缘关系的进程间进行通信。管道的本质就是一块内核缓冲区。
进程间通过管道的一端写,通过管道的另一端读。管道的读端和写端默认都是阻塞的。
管道中的内容读取了就没了,不能重复读取
如果想要数据双向流动,那么需要两个管道
管道的内部实现是一个环形队列,通过命令 ulimit -a
进行查看大小
pipe size (512 bytes, -p) 8
printf("pipe size==[%ld]\n", fpathconf(fd[0], _PC_PIPE_BUF));
//输出
pipe size==[4096]
若pipe()函数调用成功,fd[0]存放管道的读端,fd[1]存放管道的写端
int pipe(int pipefd[2]);
返回值
成功返回0,然后使用pipefd[2]来操作管道的读写
失败返回-1
示例:
使用管道来进行进程间通信
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
// pid_t fork(void);
int fd[2];
int ret = pipe(fd);
if (ret < 0)
{
perror("pipe error");
return -1;
}
ret = fork();
if (ret > 0)
{
//father
//close read
printf("here is father,child is [%d]\n",ret);
close(fd[0]);
write(fd[1],"hello",strlen("hello"));
pid_t waitp = wait(NULL);
if (waitp>0)
{
printf("child [%d] is over\n",waitp);
}
}
else if (ret == 0)
{
//child
//close write
close(fd[1]);
char buf[64];
memset(buf,0x00,sizeof(buf));
read(fd[0],buf,sizeof(buf));
printf("father say:[%s]\n",buf);
}
else
{
perror("fork error");
exit(-1);
}
return 0;
}
//输出
here is father,child is [24961]
father say:[hello]
child [24961] is over
管道读写默认是阻塞的。
读操作
如果有数据,read正常读,返回读出的字节数
如果没有数据
- 如果写端全部关闭,read返回0
- 如果还有写端,read阻塞
写操作
如果读端全部关闭,管道破裂,进程终止,内核发送SIGPIPE信号给当前进程
如果读端没有没有全部关闭
- 如果缓冲区写满了,write阻塞
- 如果缓冲区没有满,继续执行write写操作
如果将管道读端或者写端设置为非阻塞的,需要进行如下操作
//下面是将读端修改为非阻塞
//1.获取读端的文件属性
int flags = fcntl(fd[0], F_GETFL, 0);
//2.添加非阻塞属性
flags |= O_NONBLOCK;
//3.设置读端属性
fcntl(fd[0], F_SETFL, flags);
若是读端设置为非阻塞:
写端没有关闭,管道中没有数据可读,则read返回-1;
写端没有关闭,管道中有数据可读,则read返回实际读到的字节数
写端已经关闭,管道中有数据可读,则read返回实际读到的字节数
写端已经关闭,管道中没有数据可读,则read返回0
使用单个进程对上述进行验证
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
// pid_t fork(void);
int fd[2];
int ret = pipe(fd);
if (ret < 0)
{
perror("pipe error");
return -1;
}
// 设置管道读端为非阻塞
int flags = fcntl(fd[0], F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd[0], F_SETFL, flags);
// 关闭写端
write(fd[1],"hello",strlen("hello"));
close(fd[1]);
char buf[64];
memset(buf, 0x00, sizeof(buf));
ssize_t len = read(fd[0], buf, sizeof(buf));
if (len == 0)
{
printf("len is [%ld]\n", len);
}
else if (len < 0)
{
printf("len is [%ld]\n", len);
}
else
{
printf("len is [%ld]\n", len);
printf("str is [%s]\n",buf);
}
return 0;
}
//输出
len is [5]
str is [hello]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。