对于有名管道FIFO,它是半双工的。类似于管道但是又不同于管道。它是一个单向数据流。更为重要的是,每个FIFO有一个路径名与之关联,从而允许无亲缘关系的进程访问同一个FIFO。
管道只能用于有一个共同祖先进程的各个进程之间。
FIFO由mkfifo函数创建。
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char *pathname,mode_t mode);
使用两个FIFO代替管道来编写客户―服务器的例子
#include<sys/stat.h>
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<fcntl.h>
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"
#define FILE_MODE S_IFIFO|0666
#define MAXLINE 2000
void client(int ,int ),server(int,int);
int main(int arg,char **argvc)
{
int readfd,writefd;
pid_t childpid;
unlink(FIFO1);
unlink(FIFO2);
/*create two FIFO2;OK if they already exist*/
if(mkfifo(FIFO1,FILE_MODE)<0)
{
printf("can't create %s\n",FIFO1);
exit(1);
}
if(mkfifo(FIFO2,FILE_MODE)<0)
{
unlink(FIFO1);
printf("cant't create %s\n",FIFO2);
exit(1);
}
/*child*/
if((childpid = fork())==0)
{
readfd = open(FIFO1,O_RDONLY,0);
writefd = open(FIFO2,O_WRONLY,0);
server(readfd,writefd);
exit(0);
}
/*parent*/
writefd = open(FIFO1,O_WRONLY,0);
readfd= open(FIFO2,O_RDONLY,0);
client(readfd,writefd);
waitpid(childpid,NULL,0);
close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);
exit(0);
}
void server(int readfd,int writefd)
{
int fd;
ssize_t n;
char buff[MAXLINE+1];
/*read pathname from IPC channel*/
if((n = read(readfd,buff,MAXLINE))==0)
{
printf("It's an error,please exit");
exit(1);
}
buff[n]='\0'; /*null terminate pathname*/
if((fd = open(buff,O_RDONLY))<0)
{
/*error must tell client*/
snprintf(buff + n,sizeof(buff) - n, ":can't open,%s\n",strerror(errno));
n = strlen(buff);
write(writefd,buff,n);
}
else
{
/*open succeed:copy file to IPC channel*/
while((n = read(fd,buff,MAXLINE))>0)
{
write(writefd,buff,n);
close(fd);
}
}
}
void client(int readfd,int writefd)
{
size_t len;
ssize_t n;
char buff[MAXLINE];
/*read pathname*/
fgets(buff,MAXLINE,stdin);
len = strlen(buff);/*fgets() guarantees null byte at end*/
if(buff[len-1]=='\n')
len--; /*delete newline from fgets()*/
/*write pathname to IPC channel*/
write(writefd,buff,len);
/*read from IPC,write to standard output*/
while((n = read(readfd,buff,MAXLINE))>0)
write(STDOUT_FILENO,buff,n);
}
(1)在这个函数中要注意前面两个宏定义#define FIFO1 “/tmp/fifo.1”
#define FIFO2 "/tmp/fifo.2"
如果tmp前面少了/ 的话在程序运行过程中就不会找到tmp,运行完can't create fifo.1就会结束。
(2)还有在程序中使用的一些 宏定义的标识符
如:O_RDONLY、O_WRONLY都包含在头文件 #include<fcntl.h>中
STDOUT_FILENO等文件描述符包含在#include<unistd.h>中;在unix系统调用中,标准输入描述字用stdin,标准输出用stdout,标准出错用stderr表示,但在一些调用函数,引用了STDIN_FILENO表示标准输入才,同样,标准出入用STDOUT_FILENO,标准出错用STDERR_FILENO.
他们的区别:
stdin等是FILE *类型,属于标准I/O,在<stdio.h>。
STDIN_FILENO等是文件描述符,是非负整数,一般定义为0, 1, 2,属于没有buffer的I/O,直接调用系统调用,在<unistd.h>。
size_t 包含在头文件 #include<stdlib.h>
mkfifo()包含在头文件#include<sys/stat.h>
#define FILE_MODE S_IFIFO|0666 指名创建一个有名管道且权限为0666.