版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39956356/article/details/86648643
目录
- 特点及使用对象
- 参数的定义
- 案例
(一)特点及使用对象
(1)伴随unix的产生,无名管道的通信方式就存在,有点类似硬
件中的串口
(2)是种半双工通信方式,即同一时刻只有读进程在读或写进程在写
(3)只有血缘关系的进程才可以通信,如fork创建的子进程
(4)写入管道写端的数据由内核缓冲,直到从读取端读取管道,必须要有读进程,读可以阻塞的
(二)参数的定义
int pipe(int pipefd[2]);
管道有两个文件描述符相当于管道的两端,一端只负责读数据,一端只负责写数据
pipefd[0]:用于读管道
pipefd[1]:用于写管道
上面两句话特别重要!!!
还有个习惯(也是必要的):
操作写端,先关闭读端close(pipes[0]);
操作读端,先关写读端close(pipes[1]);
(三)案例
问题描述:先用fork创建子进程,子进程读,父进程写。
结果:你输入什么,输出什么。
一个一个分析:
读函数:
写函数:
源码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> //exit(1);头文件
/****************************************************************************************
** 无名管道
** pipe():
** int pipe(int pipefd[2]);
** RETURN VALUE
** On success, zero is returned. On error, -1 is returned
** 注意:a unidirectional data channel that can be used for interprocess communication
一种单向数据通道,只能用于内部进程通信----父子进程间
pipefd[0] refers to the read end of the pipe. pipefd[1] refers to the write end of the pipe.
pipefd[0]:用于读管道; 参数pipefd[1]:用于写管道
Data written to the write end of the pipe is buffered by the kernel until it is read from the read end of the pipe.
写入管道写端的数据由内核缓冲,直到从读取端读取管道。
****************************************************************************************/
int pipe(int pipefd[2]);
//读数据--pipe[0]
void read_data(int *);
//写数据--pipe[1]
void write_data(int *);
int main(int argc, char *argv[])
{
int pipes[2], rc;
pid_t pid; //为了调用fork
//新建管道
rc = pipe(pipes);
if(rc == -1)
{
perror("pipe error!!!\n");
exit(1);
}
//创建进程
pid = fork();
switch(pid)
{
case -1:
perror("fork error!!!\n");
exit(1);
case 0: //子进程,也可以传一个
read_data(pipes);
default: //父进程,也可以传一个
write_data(pipes);
}
}
void read_data(int pipes[])
{
int ret, buffer;
close(pipes[1]); //关闭写通道
printf("pipe[0] data: ");
while((ret = read(pipes[0],&buffer, 1)) > 0) //每次读一个数据
{
putchar(buffer);
if(buffer == '\n')
printf("pipe[0] data: "); //输出提示
}
printf("Read pipes[0] failed!!!\n");
exit(1);
}
void write_data(int pipes[])
{
int ret, buffer;
close(pipes[0]); //关闭读通道
printf("write pipe[1]: ");
while((buffer = getchar()) > 0)
{
ret = write(pipes[1], &buffer, 1); //每次写一个数据
if(ret == -1)
{
perror("Write pipes[1] error!!!\n");
close(pipes[1]); //关闭写端
exit(1);
}
/* if(buffer == '\n')
printf("write pipe[1]: "); //输出提示 */
}
close(pipes[1]); //关闭写端
exit(0);
}
**输出:**输入什么,输出什么,ok.
注: 上面提到了一个pid能否用尽的问题?
其实几乎不可能的,原因如下:
- (1)pid的最大值PID_MAX=0x8000(可改),因此进程号的最大值为0x7fff,即32767(short int的最大值)
- (2)pid按照递增加1的方式分配给新进程,一旦达到最大值32767,就会从低位开始检测空的pid,继续分配,每一时刻pid都是唯一确定的。
- (3) 进程号0-299保留给daemon进程
- (4)位置修改:/proc/sys/kernel/pid_max–看看就行啦,确实内部机制就是这样的。