几个术语
- 二义性:当我们往一个管道里面写端写数据的时候,比如写一个hello的时候,当我们写到he的时候,读端就已经开始读取数据了,所以这是不对的,这就是二义性
- 临界资源:多个流可以访问的一个共同的存储资源
- 临界区:访问临界资源的代码叫做临界区
- 互斥:任一时候只能有一个进程利用临界资源访问临界区,并且是以原子性访问
- 原子性:要么访问,要么没有访问,不存在正在访问的情况
- 饥饿问题:一个进程因为级别低,在某些场景之下要求访问某一资源的时候一直访问不了,这就出现了饥饿问题
- 同步:按照某一顺序访问临界资源
命名管道
命名管道的概念
匿名管道(pipe)的一个不足之处就是,匿名管道只能用于具有血缘关系的进程之间的通信,但是进程间通信的时候有很多时候都不是具有血缘关系的,这个时候就需要其他的一些通信方式,然后就有了命名管道。 命名管道通过一个路径将各个进程相连,只要一个进程能够访问某一个路径就能够访问这个管道了
命名管道的创建和读写
在shell下面我们可以使用mknod和mkfifo来创建管道
这里我们经常使用的是mkfifo,所以只是简单的介绍一个mkfifo,另一个就不做详细的介绍了
我们在shell下可以使用mkfifo myfifo.pipe来创建一个命名管道,然后在记住他的路径,在使用的时候,我们可以直接通过open来打开一个管道进行读写的 操作
下面的是程序中使用的mkfifo函数,先看接口原型
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename, mode_t mode);
解释一些返回值和参数,创建成功返回0,失败返回-1。
参数中const char *filename,就是一个路径加上文件名的形式,mode_t mode是我们创建的这个管道的操作权限,我们可以是设置为0666 | S_IFIFO,如下的使用方式,其中的S_IFIFO是一个固定的操作命名管道的一种方式,这里先不用管
我们在函数中可以按照如下的使用
if(fifo("./pipe",0666 | S_IFIFO) < 0)
{
printf("fifo error");
return 1;
}
下面我们通过一个简单的程序实现一个写端,一个读端的操作,这个时候我们可以打开两个终端,分别运行下面的程序,就会实现进程间通信,一个写,一个读
写 端
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define _PATH_ "/home/xiaoxu/code/fifo/log.pipe"
int main()
{
umask(0);
if(mkfifo(_PATH_,0666|S_IFIFO) < 0 )
{
printf("fifo error\n");
return 1;
}
int fd = open(_PATH_,O_WRONLY);
if(fd <= 0)
{
printf("open error\n");
return 1;
}
else
{
char buf[100];
memset(buf,'\0',sizeof(buf));
while(1)
{
scanf("%s",&buf);
int wr = write(fd,buf,sizeof(buf));
if(wr <= 0)
{
printf("write error\n");
break;
}
}
}
close(fd);
return 0;
}
读端
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define _PATH_ "/home/xiaoxu/code/fifo/log.pipe"
int main()
{
int fd = open(_PATH_,O_RDONLY); //只读方式打开一个管道
if(fd < 0) //打开管道失败
{
printf("read error\n");
return 1;
}
else //打开管道成功
{
char buf[100];
memset(buf,'\0',sizeof(buf));
while(1)
{
int red = read(fd,buf,sizeof(buf)); //把管道里面的内容读取到buf中,所以上面应该加上memset这个函数,对buf进行初始化
if(red <= 0) //
{
printf("read error\n");
break;
}
printf("%s\n",buf);
}
close(fd);
}
return 0;
}