(一)管道
(1)管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
(2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
(3)数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据
fsd[0]:读端描述符
fsd[1] :写端描述符
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX 1024
main()
{
char buffer[1024];
int fds[2];
pid_t pid;
pipe(fds);
pid = fork();
if(pid < 0)
{
printf("fork error");
exit(0);
}
else if(pid > 0)
{
close(fds[0]);
write(fds[1], "i love my mother!", 100);
}
else
{
close(fds[1]);
read(fds[0], buffer, 100);
printf("%s/n", buffer);
}
}
输出:
i love my mother!
管道的读规则:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX 1024
main()
{
int num, shu;
int fds[2];
char a[100];
char b[100];
pid_t pid;
memset(a, 0, 10);
memset(b, 0, 10);
if(pipe(fds))
{
printf("creat error!");
exit(0);
}
pid = fork();
if(pid < 0)
{
printf("fork error!");
exit(0);
}
else if(pid == 0)
{
close(fds[1]);
sleep(2);
num = read(fds[0], a, 100);
shu = atoi(a);
printf("num = %d/nshu = %d/n", num, shu);
}
else if(pid > 0)
{
strcpy(b, "1234");
close(fds[0]);
if(write(fds[1], b, 100) == -1)
{
printf("parent write over!");
exit(0);
}
close(fds[1]);
sleep(5);
}
}
output:
num = 100;
shu = 1234;
结论:管道写端关闭后,写入的数据将一直存在,直到读出为止.
向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
管道的写规则
1.写端对读端存在的依赖性
例子:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX 1024
main()
{
int num, shu;
int fds[2];
char a[100];
char b[100];
pid_t pid;
memset(a, 0, 10);
memset(b, 0, 10);
if(pipe(fds))
{
printf("creat error!");
exit(0);
}
pid = fork();
if(pid < 0)
{
printf("fork error!");
exit(0);
}
else if(pid == 0)
{
close(fds[1]);
close(fds[0]);
sleep(3);
num = read(fds[0], a, 100);
shu = atoi(a);
printf("num = %d/nshu = %d/n", num, shu);
}
else if(pid > 0)
{
sleep(1);
strcpy(b, "1234");
printf("%s/n", b);
close(fds[0]);
if(write(fds[1], b, 100) == -1)
{
printf("parent write over!");
exit(0);
}
printf("%s/n", b);
// sleep(5);
}
}
output:
1234
num = -1
shu = 0
最后一个输出没有用了!
只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。
kill -l
pipe的不足:
1 没有名字
2 是单方向的
3 只能用于具有亲缘关系的进程间
4 管道的缓冲区是有限的 (管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小)
有名管道