标签:创建 == 总结 功能 现在 并且 sleep 大小 fork
函数原型:
#include <unistd.h>
int pipe(int fildes[2]);
fildes是我们传入的数组,也是一个传出参数。fildes[0]是读端,fildes[1]是写端。
现在实现一个用父进程读,子进程写的管道例子。
int main(int argc, char const *argv[])
{
int pipefd[2];
pipe(pipefd);
pid_t pid = fork();
if (pid == 0)
{
//子进程写
//关闭读
close(pipefd[0]);
write(pipefd[1], "hello fuck!", 15);
sleep(1);
}
else if (pid > 0)
{
//关闭写
close(pipefd[1]);
char buf[16] = {0};
read(pipefd[0], buf, sizeof(buf));
printf("%s\n", buf);
}
return 0;
}
在这个程序执行之后,父进程会读取到子进程所写的数据。在这个简单的例子中看不到什么坑点。
在亲缘进程中,我们使用管道要注意以下几点。就拿父子进程作为例子:
当前情况是,双方都掌控有读写端,都可以操作。
fork之后,共享管道的读写端。我们一方读一方写,最好要自己指定方向,使数据沿着固定的方向流动。如:
我们这样就指定了子进程来写,父进程来读。也就是说,我们仅仅只需要在代码上加上两个Close就可以完成这个功能:close父进程的写端,close子进程的读端。
如果我们不这样会发生什么?
其中特别要注意,写端没有全关闭的时候并且无数据的时候,读端会阻塞等待写。
此管道突破了匿名管道只能亲缘间通信的限制。
可以用命令直接创建一个有名管道:
mkfifo myfifo
就可以看到一个myfifo管道了。Linux下一切皆文件,打开这个管道和打开文件一样,用open函数即可。
下面写了一个读程序和写程序,可以参考:
//读进程,读了就会被取走,可同时执行两次看结果
int main(int argc, char const *argv[])
{
int fd = open("myfifo", O_RDONLY);
while (1)
{
char buf[128] = {0};
int ret = read(fd, buf, sizeof(buf)); //如果写端被关闭,读端返回0,就是读到末尾了。
if (ret) printf("%s\n", buf);
else break;
}
return 0;
}
写程序如下:
//写进程。
int main(int argc, char const *argv[])
{
int fd = open("myfifo", O_WRONLY);
int num = 1;
while (1)
{
char buf[128] = {0};
sprintf(buf, "read data:%04d", num++);
write(fd, buf, strlen(buf));
sleep(1);
}
return 0;
}
和普通文件操作并无区别。
假设我们先执行读程序,还没执行写程序时,会阻塞,直到写端被打开。
同理,我们先执行写程序,还没执行读程序时,也会阻塞,知道读端被打开。
以上告诉我们,fifo必须两端都打开的时候才能工作,否则阻塞。
标签:创建 == 总结 功能 现在 并且 sleep 大小 fork
原文地址:https://www.cnblogs.com/love-jelly-pig/p/10053054.html