管道通信有两种:无名管道、有名管道
无名管道:
无名管道只能作用于亲缘关系的进程,例如父子进程。无名管道其实是数组来的,里面有读端与写端,进程只需要将数据写入/读取到管道中,就可以实现通信。
下面是初始化无名管道中的读写端文件描述符
1)申请数组 -> int fd[2]; -> 里面的数据不是文件描述符
2)调用API函数初始化数组 pipe() man 2 手册
功能: create pipe
使用格式:
#include <unistd.h>
int pipe(int pipefd[2]);
pipefd: 一个具有2个int类型数据的数组
返回值:
成功:0
失败:-1
3)初始化完毕
pipefd[0] -> 读端
pipefd[1] -> 写端
实例:
(子进程写入数据,父进程读取并打印出来)
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd[2]={0}; //资源,会继承给子进程 f[0]:读 / f[1]:写
pipe(fd);
pid_t x;
x = fork();
if(x > 0) //父进程
{
char buf[10] = {0};
read(fd[0],buf,sizeof(buf)); //进程执行到这里是阻塞状态,等待子进程写入数据,然后读取
printf("child to parent:%s\n",buf);
}
if(x == 0) //子进程
{
char buf[10] = "hello";
write(fd[1],buf,strlen(buf));
}
return 0;
}
有名管道:
无名管道是一个数组来的,而有名管道是文件来的,因为在整个linux系统下,都可以看到这个文件,所以有名管道作用范围是整个linux系统的任意两个进程。
如何创建有名管道? mkfifo() man 3 手册
功能: make a FIFO special file (a named pipe) -> 创建有名管道
使用格式:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
pathname:有名管道的路径
mode:八进制权限 0777
返回值:
成功:0
失败:-1
实例:
(两.c文件同时运行,写端每次写入数据,读端就会读取数据出来,写入quit时程序结束)
读端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>
int main()
{
//判断是否有该管道文件,有就返回0,没有就返回-1(非零即是真)
if(access("/home/gec/fifo",F_OK))
{
int ret;
ret = mkfifo("/home/gec/fifo",0777); //创建管道文件,八进制权限为0777
if(ret == -1)
printf("mkfifo error!\n");
}
//打开管道文件(必须是读写方式打开)
int fd;
fd = open("/home/gec/fifo",O_RDWR);
if(fd < 0)
printf("open error!\n");
//不断读取管道中内容
char buf[20];
while(1)
{
bzero(buf,sizeof(buf));
read(fd,buf,sizeof(buf));
printf("from fifo:%s\n",buf);
if(strncmp(buf,"quit",4) == 0)
{
break;
}
}
close(fd);
return 0;
}
写端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
int main()
{
//判断是否有该管道文件,有就返回0,没有就返回-1(非零即是真)
if(access("/home/gec/fifo",F_OK))
{
int ret;
ret = mkfifo("/home/gec/fifo",0777); //创建管道文件,八进制权限为0777
if(ret == -1)
printf("mkfifo error!\n");
}
//打开管道文件(必须是读写方式打开)
int fd;
fd = open("/home/gec/fifo",O_RDWR);
if(fd < 0)
printf("open error!\n");
//不断写入内容进管道中
char buf[20];
while(1)
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
write(fd,buf,strlen(buf));
if(strncmp(buf,"quit",4) == 0)
{
break;
}
}
close(fd);
return 0;
}