管道分为无名管道、有名管道。
1.无名管道
1.1 特点:
(1)无名管道只能用于父子进程或兄弟进程之间的通信。(亲缘进程)
(2)不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在于内存(RAM)中。(ls -i不可查)
(3)一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。(无名管道有两端,写入端与读取端)
(4)无名管道最大容量为64K
1.2 pipe创建无名管道
(1)pipe函数
头文件: #include<unistd.h> 函数原型: int pipe(int filedes[2]); 函数介绍: pipe()会建立管道,并将文件描述词由参数 filedes 数组返回。filedes[0]为管道里的读取端,filedes[1]则为管道的写入端。 返回值:若成功则返回零,否则返回-1,错误原因存于 errno 中。 |
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
//创建无名管道
int fd[2];
int val = pipe(fd);
if(val)
{
perror("pipe");
exit(1);
}
//创建成功
printf("f[0]:%d读端文件描述符\n",fd[0]);
printf("f[1]:%d写端文件描述符\n",fd[1]);
return 0;
}
(2)进程内通信
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
//创建无名管道
int fd[2];
char readbuff[10]={0};
int val = pipe(fd);
if(val)
{
perror("pipe");
exit(1);
}
//创建成功
printf("f[0]:%d读端文件描述符\n",fd[0]);//3
printf("f[1]:%d写端文件描述符\n",fd[1]);//4
//有文件描述符---->通过文件IO即可操作
write(fd[1],"hello",strlen("hello"));
read(fd[0],readbuff,sizeof(readbuff));
printf("读取到的内容为:%s\n",readbuff);
return 0;
}
(3)亲缘进程通信
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
//创建无名管道
int fd[2];
char readbuff[10]={0};
int val = pipe(fd);
if(val)
{
perror("pipe");
exit(1);
}
//创建成功
printf("f[0]:%d读端文件描述符\n",fd[0]);//3
printf("f[1]:%d写端文件描述符\n",fd[1]);//4
//创建进程
pid_t pid = fork();
//父进程
if(pid > 0)
{
while(1)
{
write(fd[1],"hello",strlen("hello"));
sleep(1);
}
}
//子进程
else if(pid == 0)
{
while(1)
{
char readbuff[512]={0};
read(fd[0],readbuff,sizeof(readbuff));
printf("读取到的数据:%s\n",readbuff);
}
}
else{
perror("fork");
exit(1);
}
return 0;
}
2.有名管道
2.1 特点
(1)可以用于任意进程间的通信
(2)遵循先进先出原则,没有固定的读端与写端
(3)可以通过ls -i查看
2.2 makefifo创建有名管道
(1)makefifo函数
头文件: #include<sys/types.h> #include<sys/stat.h> 函数原型: int mkfifo(const char * pathname,mode_t mode); 函数功能: mkfifo()会依参数 pathname 建立特殊的 FIFO 文件,该文件必须不存在,而参数 mode 为该文件的权限(mode%~umask),因此 umask值也会影响到 FIFO 文件的权限。mkfifo()建立的 FIFO 文件其他进程都可以用读写一般文件的方式存取。 返回值: 若成功则返回 0,否则返回-1,错误原因存于 errno 中。 |
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc,char *argv[])
{
//创建有名管道
int val = mkfifo(argv[1],0666);
if(val)
{
if(errno!=17)//通过错误代码解决文件已存在问题
{
perror("mkfifo");
exit(1);
}
}
return 0;
}
(2)进程内通信
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
char readbuff[512]={0};
//创建有名管道
int val = mkfifo(argv[1],0666);
if(val)
{
if(errno!=17)//通过错误代码解决文件已存在问题
{
perror("mkfifo");
exit(1);
}
}
//打开管道文件
int fd = open(argv[1],O_RDWR);
if(fd < 0)
{
perror("open");
exit(1);
}
//读写文件
write(fd,"hello",strlen("hello"));
read(fd,readbuff,sizeof(readbuff));
printf("读取到的数据为:%s\n",readbuff);
return 0;
}
(3)父子进程间通信
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
char readbuff[512]={0};
//创建有名管道
int val = mkfifo(argv[1],0666);
if(val)
{
if(errno!=17)//通过错误代码解决文件已存在问题
{
perror("mkfifo");
exit(1);
}
}
pid_t pid = fork();
if(pid > 0)
{
//打开管道文件
int fd = open(argv[1],O_WRONLY);
while(1)
{
write(fd,"hello",strlen("hello"));
sleep(1);
}
close(fd);
}
else if(pid == 0)
{
//打开管道文件
int fd = open(argv[1],O_RDONLY);
while(1)
{
read(fd,readbuff,sizeof(readbuff));
printf("读取到的数据为:%s\n",readbuff);
}
close(fd);
}
else
{
perror("fork");
exit(1);
}
return 0;
}
(4)无亲缘进程间的通信
进程1写入
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
if(argc == 0)
{
printf("缺少参数\n");
exit(1);
}
//创建有名管道
int val = mkfifo(argv[1],0666);
if(val)
{
if(errno!=17)//通过错误代码解决文件已存在问题
{
perror("mkfifo");
exit(1);
}
}
//打开管道文件
int fd = open(argv[1],O_WRONLY);
while(1)
{
char writebuff[512]={0};
printf("请输入数据:\n");
gets(writebuff);
write(fd,writebuff,strlen(writebuff));
}
close(fd);
return 0;
}
进程2读取
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
if(argc == 0)
{
printf("缺少参数\n");
exit(1);
}
//创建有名管道
int val = mkfifo(argv[1],0666);
if(val)
{
if(errno!=17)//通过错误代码解决文件已存在问题
{
perror("mkfifo");
exit(1);
}
}
//打开管道文件
int fd = open(argv[1],O_RDONLY);
while(1)
{
char readbuff[512]={0};
int len = read(fd,readbuff,sizeof(readbuff));
if(len>0)
{
printf("读取到的数据为:%s\n",readbuff);
}
else if(len == 0)
{
break;
}
}
close(fd);
return 0;
}
2.3 remove删除有名管道
头文件:#include<stdio.h> 删除文件:int remove(const char * pathname); 函数功能:remove()会删除参数 pathname 指定的文件。如果参数 pathname为一文件,则调用 unlink()处理,若参数 pathname 为一目录,则调用 rmdir()来处理。 返回值:成功则返回 0,失败则返回-1,错误原因存于 errno |