Linux---管道
·
一、

read

一、管道的实现
//源代码
#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<string.h>
int main()
{
//1、创建管道
int pipefd[2]={0};
int n=pipe(pipefd);
if(n<0)
{
perror("pipe");
return 1;
}
printf("pipefd[0]:%d,pipefd[1]:%d\n",pipefd[0],pipefd[1]);
//2、fork创建子进程
pid_t id=fork();
if(id==0)
{
//child w
close(pipefd[0]);
char *msg="hello bit";
// write(pipefd[1],msg,strlen(msg));
int cnt=10;
char outbuffer[1024];
while(cnt)
{
snprintf(outbuffer,sizeof(outbuffer),"f->c# %s %d %d\n",msg,cnt--,getpid());
write(pipefd[1],outbuffer,strlen(outbuffer));
sleep(1);
}
exit(0);
}
//父进程 r
close(pipefd[1]);
char inbuffer[1024];
while(1)
{
ssize_t n= read(pipefd[0],inbuffer,sizeof((inbuffer)-1));
if (n>0)
{
inbuffer[n]=0;
printf("%s",inbuffer);
}
}
pid_t rid=waitpid(id,NULL,0);
(void)rid;//防止编译有警告
return 0;
}
//Makefile
code:code.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f code
运行结果:

二、匿名管道的特性(5种)
1、管道只能单向通信,单工通信
2、匿名管道只能用来进行父子通信(继承内核资源),具有血缘关系的进程之间。
3、管道是面向字节流的
4、管道的生命周期是随进程的。
5、管道通信,对于多进程而言,是自带互斥同步机制。
当进程退出时,PCB被释放,文件描述符表也会被释放,进程持有的文件描述符也会被关闭,内核会将对应的struct file 的引用计数减1,当引用计数减到0时,struct file会被释放,此时确实没有进程再关联这个打开的文件对象。
三、管道读写的4种情况
:1、子进程写的慢,父进程就要阻塞等,等管道有数据,父进程才能读;管道为空,读就要阻塞,给写 机会。
互斥与同步
(管道通信,前提是让不同的进程。看到同一份资源--->文件-->文件的内核缓冲区--->内存块。)
属于父子进程的共享资源,并发访问导致的问题--->需要通过互斥与同步机制来保证数据一致性。
互斥-->任何时刻只允许一个人访问资源,同步--->访问数据具有一定的顺序性。
2、子进程写的快,父进程不读,管道一旦被写满,子进程就必须阻塞了。写满就必须要让父进程读了。---》管道满了,写就要阻塞,给读机会。
3、 读端在读,写端关闭,读端读完管道中剩余数据,再读,就会读取“ ”(空串),read返回值为0,表明读管道,读到文件结尾。
4、 写端一直在写,读端不读关闭fd。(OS会直接杀掉写的进程)
内核会向写进程发送 SIGPIPE 信号,默认终止进程;若捕获或忽略该信号,write 会返回 -1,并设置 errno 为 EPIPE。告知写进程 “无人消费数据”,避免无效写入。
更多推荐



所有评论(0)