管道文件是一个特殊的文件,是由内核环形队列来实现的。
函数形式: int pipe(int fd[2]) ,无需额外调用open,但需手动调用close来关闭fd[0]和fd[1]。
功能: 该系统调用,用于创建无名管道。无名管道作用于有血缘关系的进程之间,完成数据传递。
头文件:#include <unistd.h>
参数:两个文件描述符,fd[0]是读端,fd[1]是写端。
返回值: 成功返回0,出错返回-1。
特点:
** 管道是创建在内存中的,进程结束,空间释放,管道就不存在了。
** 管道中的数据,读完后就被删除了。
** 如果管道中没有数据可读,则会阻塞。
** 如果管道被写满了,也会阻塞。
局限性:
**数据一旦被读走,便不在管道中存在,不可反复读取。
**由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。
**只能在有公共祖先的进程间使用管道。
实验1 - 实现父子进程间通信
实验思路:
1. 父进程调用pipe函数创建无名管道,得到两个文件描述符fd[0]、fd[1]指向管道的读端和写端。
2. 父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。
3. 父进程关闭管道读端,子进程关闭管道写端。(这才是正确操作,只留一个入口,一个出口,这样才能保证数据只在一个方向上流动)
父进程可以向管道中写入数据,子进程将管道中的数据读出。
由于管道是利用环形队列实现的,数据从写端流入管道,从读端流出,这样就实现了进程间通信。
实验代码:
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(void)
{
pid_t pid;
char buf[1024];
int fd[2];
char *p = "test for pipe\n";
if (pipe(fd) == -1)
sys_err("pipe");
pid = fork();
if (pid < 0) {
sys_err("fork err");
}else if (pid == 0) {
close(fd[1]);
int len = read(fd[0], buf, sizeof(buf));
write(STDOUT_FILENO, buf, len);
close(fd[0]);
}else {
close(fd[0]);
write(fd[1], p, strlen(p));
wait(NULL); // 不获取子进程死因,传入NULL即可。
// 父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出。
close(fd[1]);
}
return 0;
}
.
/************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/