管道与FIFO的区别,就在于 unnamed 和 named 的区别:
#include
int pipe (int fd[2]);
/* Return value: if success, return 0; if error, return -1 */
int fd[2],顾名思义,file descriptors,是两个文件描述符fd[0]和fd[1];
#include "apue.h"
#include
#define DEF_PAGER "/bin/more"
int
main(int argc, char *argv[])
{
int n;
int fd[2];
pid_t pid;
char *pager, *argv0;
char line[MAXLINE];
FILE *fp;
if(argc != 2)
err_quit("usage: a.out ");
if((fp = fopen(argv[1], "r")) == NULL)
err_sys("can't open %s", argv[1]);
/* create a pipe */
if(pipe(fd) < 0)
err_sys("pipe error");
/* fork */
if((pid = fork()) < 0)
err_sys("fork error");
else if(pid > 0) {
close(fd[0]); /* parent process close read end */
/* parent read argv[1] and write to pipe */
while (fgets(line, MAXLINE, fp) != NULL) {
n = strlen(line);
if(write(fd[1], line, n) != n)
err_sys("write error to pipe");
}
if(ferror(fp))
err_sys("fgets error");
close(fd[1]); /* close write end of pipe for reader */
/* wait until the child process terminate, if not wait, system will not release
the resources associated with the child, and the child of course will become a "zombie". */
if(waitpid(pid, NULL, 0) < 0)
err_sys("waitpid error");
exit(0);
} else {
close(fd[1]); /* child process close write end */
/* duplicate the read end to STDIN_FILENO */
if(fd[0] != STDIN_FILENO)
{
/* duplicate from the old fd to new fd */
if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
err_sys("dup2 error to stdin");
close(fd[0]); /* we don't need this after dup2 */
}
/* From this section, we can see how to use the "environ" to call the page program. */
/* get arguments for execl() */
if((pager = getenv("PAGER")) == NULL)
pager = DEF_PAGER;
if((argv0 = strrchr(pager, '/')) != NULL)
argv0++; /* step past rightmost slash */
else
argv0 = pager; /* no slash in pager */
if(execl(pager, argv0, (char *)0) < 0)
err_sys("execl error for %s", pager);
}
exit(0);
}
程序很长,但无论怎样应该好好看看。
#include
FILE *popen(const char *cmdstring, const char *type);
/* Returns: file pointer if OK, NULL on error */
int pclose(FILE *fp);
/* Returns: termination status of cmdstring, or −1 on error */
(1)popen函数
/* This is a filter program that transform upper characters to the lowers */
#include "apue.h"
#include
int
main(void)
{
int c;
while((c = getchar()) != EOF)
{
if(isupper(c))
c = tolower(c);
if(putchar(c) == EOF)
err_sys("output error");
if(c == '\n')
fflush(stdout);
}
exit(0);
}
/* This is the program that calls popen */
#include "apue.h"
#include
int
main(void)
{
char line[MAXLINE];
FILE *fpin;
/* call popen function to create a pipe and execute filter program */
if((fpin = popen("./filter", "r")) == NULL)
err_sys("popen error");
for(; ;)
{
fputs("prompt> ", stdout);
fflush(stdout);
if(fgets(line, MAXLINE, fpin) == NULL) /* read from pipe */
break;
if(fputs(line, stdout) == EOF)
err_sys("fputs error to pipe");
}
/* close the pipe */
if(pclose(fpin) == -1)
err_sys("pclose error");
putchar('\n');
exit(0);
}
程序运行时,将输入的大写转换为小写,遇到EOF(ctrl+D)时结束。
#include "apue.h"
int
main(void)
{
int n, int1, int2;
char line[MAXLINE];
while ((n = read(STDIN_FILENO, line, MAXLINE)) > 0) /* read from STDIN_FILENO */
{
line[n] = 0; /* note: null terminate */
if(sscanf(line, "%d%d", &int1, &int2) == 2) /* read int1, int2 from line[MAXLINE] */
{
sprintf(line, "%d\n", int1 + int2); /* write sum of int1 and int2 to line[MAXLINE] */
n = strlen(line);
if(write(STDOUT_FILENO, line, n) != n) /* write line[MAXLINE] to STDOUT_FILENO */
err_sys("write error");
} else {
if(write(STDOUT_FILENO, "invalid args\n", 13) != 13)
err_sys("write error");
}
}
}
上面的程序中,read后的line[n]=0需要注意,其余4种读写的方式了解一下;
/* fifo.h */
#include
#include
#include /* FIFO is a type of file; this header includes mkfifo function */
#include
#include
//#include
#define FIFO1 "/tmp/fifo.1"
#define FIFO2 "/tmp/fifo.2"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
/* server.c */
#include "fifo.h"
void server(int readfd, int writefd)
{
/* ... */
}
int
main(void)
{
int readfd, writefd;
/* create two FIFOs; OK if they already exist */
if((mkfifo(FIFO1, FILE_MODE) < 0) && (errno != EEXIST))
{
printf("can't create %s\n", FIFO1);
exit(1);
}
if((mkfifo(FIFO2, FILE_MODE) < 0) && (errno != EEXIST))
{
unlink(FIFO1);
printf("can't create %s\n", FIFO2);
exit(1);
}
/* we don't handle the errors in the following. */
if((readfd = open(FIFO1, O_RDONLY, 0)) < 0)
{
perror("open FIFO1 failed");
unlink(FIFO1);
exit(1);
}
if((writefd = open(FIFO2, O_WRONLY, 0)) < 0)
{
perror("open FIFO2 failed");
unlink(FIFO2);
exit(1);
}
server(readfd, writefd);
exit(0);
}
/* client.c */
#include "fifo.h"
void client(int readfd, int writefd)
{
/* ... */
}
int
main(int argc, char *argv[])
{
int readfd, writefd;
/* not handle errors in the following. */
writefd = open(FIFO1, O_WRONLY, 0);
readfd = open(FIFO2, O_RDONLY, 0);
client(readfd, writefd);
close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);
exit(0);
}
以上程序为简洁起见,没有进行充分的错误检查(尤其是client.c),这里需要注意以下几点:
mkfifo fifo1
prog3 < fifo1 &
prog1 < infile | tee fifo1 | prog2