管道
有名管道
有名管道可以在任意两个进程之间通信
有名管道的创建:
- 命令创建: mkfifo FIFO
- 系统调用创建
#include <sys/types.h>
#include <sys/stat.h>
//filename 是管道名 mode 是创建的文件访问权限
int mkfifo(const char *filename, mode_t mode);
在a.c上写数据在b.c上读数据,在两个窗口运行两个程序,一个写数据,另一个同步读出数据
a.c写文件
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
int main()
{
int fd=open("FIFO",O_WRONLY);
printf("fd=%d\n",fd);
while(1)
{
printf("input:");
char buff[128]={0};
fgets(buff,128,stdin);
if(strncmp(buff,"end",3)==0)
{
break;
}
write(fd,buff,strlen(buff));
}
close(fd);
exit(0);
}
b.c读文件
#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
int main()
{
int fd=open("FIFO",O_RDONLY);
printf("fd=%d",fd);
while(1)
{
char buff[128]={0};
int n=read(fd,buff,127);//n是读到的字符数
if(n==0)
{
break;
}
printf("n=%d,buff=%s\n",n,buff);
}
close(fd);
exit(0);
}
管道写端关闭,读端会返回0
管道读端关闭,写端也会被关闭,会向写端发送终止信号
1.必须被两个进程同时打开,必须是一读一写,否则会被阻塞
2.打开管道open
3.写入数据write,管道文件存放在内存中,在磁盘上大小为0 管道数据如果为满会阻塞住
4.读管道 read 管道数据如果为空会阻塞住
5.关闭管道 close
无名管道
无名管道主要应用于父子进程间的通信
#include <unistd.h>
/*
pipe()成功返回 0,失败返回-1
fds[0]是管道读端的描述符 相当于文件的头指针
fds[1]是管道写端的描述符 相当于文件的尾指针
*/
int pipe(int fds[2]);
main文件,父子进程创建管道
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
int main()
{
int fd[2];
pipe(fd);//fd[0]读 fd[1] 写
pid_t pid=fork();
assert(pid!=-1);
if(pid==0)
{
close(fd[1]);
while(1)
{
char buff[128]={0};
if(read(fd[0],buff,127)==0)
{
break;
}
else
{
printf("child read:%s\n",buff);
}
}
close(fd[0]);
}
else
{
close(fd[0]);
while(1)
{
char buff[128]={0};
fgets(buff,128,stdin);
if(strncmp(buff,"end",3)==0)
{
break;
}
else
{
write(fd[1],buff,strlen(buff));
}
}
close(fd[1]);
}
exit(0);
}
管道的实现:
1.有名和无名的区别:
有名可以在任意两个进程间通信,无名只能用在父子进程
2.写入管道的数据在哪:
内存
3.管道通信的方式是全双工还是半双工:
半双工
通过dup2函数,更改子进程的输出方式
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>
int main()//更改子进程的输出方式,父进程将子进程的输出打入file.txt的文件中,或者打到屏幕上
{
int fd[2];
if(pipe(fd)==-1)//创建无名管道文件
{
exit(0);
}
pid_t pid=fork();
if(pid==-1)
{
exit(0);
}
if(pid==0)
{
dup2(fd[1],1);//替换标准输出 输出到fd[1]中,覆盖掉1
dup2(fd[1],2);//替换标准错误输出
execl("/usr/bin/ps","ps","-f",(char*)0);
printf("exec err");
exit(0);
}
char buff[1024]={0};
close(fd[1]);
int n= read(fd[0],buff,1023);
//printf("ps输出%s\n",buff);
int fdw=open("file.txt",O_WRONLY|O_CREAT,0600);
write(fdw,buff,strlen(buff));
close(fd[0]);
exit(0);
}