命名管道是一种特殊类型的文件(FIFO),可以完成两个不相关之间的通信。它在文件系统中以文件名的方式存在,但行为却和一般的管道相似。
一.创建FIFO
在程序中,可以使用两个不同的函数调用创建:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename, mode_t mode);
int mknod(const char *filename, mode_t mode | S_IFIFO, (dev_t) 0);
二.打开FIFO
可以直接用open函数打开:
int open( const char * pathname, int flags);
参数flags有四种组合方式:
O_RDONLY:open调用一直阻塞,直到有一个进程以写方式打开一个FIFO
O_RDONLY | O_NONBLOCK:立即调用并返回,如果没有其他进程以写方式打开一个FIFO,就返回0
O_WRONLY:open调用一直阻塞,直到有一个进程读写方式打开一个FIFO
O_WRONLY | O_NONBLOCK:立即调用并返回,如果没有其他进程以读方式打开一个FIFO,就返回0
在这里没有O_RDWR模式,困为管道是单向传输数据的,如果需要双向传输,常用的方法是打开两个管道;还有一种是在一个方向的传输结束后关闭该管道,然后再打开进行另一个方向的传输,这种方法用得少。
三.读写操作
打开管道时使用O_NONBLOCK全影响到对它的write,read调用
对一个空的、阻塞的FIFO的read调用将待,直到有数据可以读时才继续执行,与此相反,对一个空的,非阻塞的FIFO进行read调用会立即返回0。
对一个阻塞的FIFO进行write调用将待,直到数据可以被写入才继续执行。如果FIFO不能接收所有数据(通常是在非阻塞模式),它将以下规则执行:
如果请求写入的数据小于等于FIFO_BUF字节,调用失败,数据不能写入。
如果请求写入的数据大于FIFO_BUF,将写入部分数据,返回实际写入的字节数,返回值也可能是0
(为什么要这么设置)
FIFO_BUF是命名管道的长度,这个常量在limits.h中定义,linux和多数unix系统中是4096字节,某些系统中是512字节。
系统规定:一个以阻塞方式打开的命名管道中,如果写入的数据小于FIFO_BUF字节,那么或者全部写入,或者一个字节都不写。这种设置保证了每人个写操作都是原子化的,在多个进程写同一个FIFO文件时可以确保来自各进程的数据不会交错。
四.例子:
两个本来不相关的程序creater.c和consumer.c,它们打开同一个命名管道,creater.c向管道中写入数据,后者从中读出。
creater.c:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "fifo"
#define BUFFER_SIZE PIPE_BUF
int main()
{
int pipe_fd;
int res;
int open_mode = O_WRONLY;
int bytes_send;
char buffer[BUFFER_SIZE + 1] = "access(判断是否具有存取文件的权限)相关函数 stat,open,chmod,chown,setuid,setgid";
if( -1 == access(FIFO_NAME, F_OK)) //判断FIFO_NAME文件是否存在
{
res = mkfifo(FIFO_NAME, 0777); //不存在则创建
if(0 != res)
{
fprintf(stderr, "Could not create fifo %s \n", FIFO_NAME);
exit(EXIT_FAILURE);
}
}
pipe_fd = open(FIFO_NAME, open_mode); //打开FIFO文件
printf("Process %d result %d \n", getpid(), pipe_fd);
if( -1 != pipe_fd)
{
res = write(pipe_fd, buffer, BUFFER_SIZE); //向FIFO文件写入数据
printf("res: %d \n", res);
bytes_send += res;
close(pipe_fd);
}
else
{
exit(EXIT_FAILURE);
}
printf("Process %d finished\n\n", getpid());
exit(EXIT_SUCCESS);
}
consumer.c:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "fifo"
#define BUFFER_SIZE PIPE_BUF
int main()
{
int pipe_fd;
int res;
int open_mode = O_RDONLY;
int bytes_read;
char buffer[BUFFER_SIZE + 1];
memset(buffer, 0, sizeof(buffer));
printf("Process %d opening FIFO_NAME O_RDONLY", getpid());
pipe_fd = open(FIFO_NAME, open_mode); //打开FIFO文件
printf("Process %d result %d \n", getpid(), pipe_fd);
if(-1 != pipe_fd)
{
do
{
res = read(pipe_fd, buffer, BUFFER_SIZE); //从管道中读取数据
printf("%s", buffer);
memset(buffer, 0, sizeof(buffer));
bytes_read += res;
}while(res > 0);
printf("\n");
close(pipe_fd);
}
else
{
exit(EXIT_FAILURE);
}
printf("Process %d finished, %d bytes read\n\n", getpid(), bytes_read);
exit(EXIT_SUCCESS);
}
一.创建FIFO
在程序中,可以使用两个不同的函数调用创建:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename, mode_t mode);
int mknod(const char *filename, mode_t mode | S_IFIFO, (dev_t) 0);
二.打开FIFO
可以直接用open函数打开:
int open( const char * pathname, int flags);
参数flags有四种组合方式:
O_RDONLY:open调用一直阻塞,直到有一个进程以写方式打开一个FIFO
O_RDONLY | O_NONBLOCK:立即调用并返回,如果没有其他进程以写方式打开一个FIFO,就返回0
O_WRONLY:open调用一直阻塞,直到有一个进程读写方式打开一个FIFO
O_WRONLY | O_NONBLOCK:立即调用并返回,如果没有其他进程以读方式打开一个FIFO,就返回0
在这里没有O_RDWR模式,困为管道是单向传输数据的,如果需要双向传输,常用的方法是打开两个管道;还有一种是在一个方向的传输结束后关闭该管道,然后再打开进行另一个方向的传输,这种方法用得少。
三.读写操作
打开管道时使用O_NONBLOCK全影响到对它的write,read调用
对一个空的、阻塞的FIFO的read调用将待,直到有数据可以读时才继续执行,与此相反,对一个空的,非阻塞的FIFO进行read调用会立即返回0。
对一个阻塞的FIFO进行write调用将待,直到数据可以被写入才继续执行。如果FIFO不能接收所有数据(通常是在非阻塞模式),它将以下规则执行:
如果请求写入的数据小于等于FIFO_BUF字节,调用失败,数据不能写入。
如果请求写入的数据大于FIFO_BUF,将写入部分数据,返回实际写入的字节数,返回值也可能是0
(为什么要这么设置)
FIFO_BUF是命名管道的长度,这个常量在limits.h中定义,linux和多数unix系统中是4096字节,某些系统中是512字节。
系统规定:一个以阻塞方式打开的命名管道中,如果写入的数据小于FIFO_BUF字节,那么或者全部写入,或者一个字节都不写。这种设置保证了每人个写操作都是原子化的,在多个进程写同一个FIFO文件时可以确保来自各进程的数据不会交错。
四.例子:
两个本来不相关的程序creater.c和consumer.c,它们打开同一个命名管道,creater.c向管道中写入数据,后者从中读出。
creater.c:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "fifo"
#define BUFFER_SIZE PIPE_BUF
int main()
{
int pipe_fd;
int res;
int open_mode = O_WRONLY;
int bytes_send;
char buffer[BUFFER_SIZE + 1] = "access(判断是否具有存取文件的权限)相关函数 stat,open,chmod,chown,setuid,setgid";
if( -1 == access(FIFO_NAME, F_OK)) //判断FIFO_NAME文件是否存在
{
res = mkfifo(FIFO_NAME, 0777); //不存在则创建
if(0 != res)
{
fprintf(stderr, "Could not create fifo %s \n", FIFO_NAME);
exit(EXIT_FAILURE);
}
}
pipe_fd = open(FIFO_NAME, open_mode); //打开FIFO文件
printf("Process %d result %d \n", getpid(), pipe_fd);
if( -1 != pipe_fd)
{
res = write(pipe_fd, buffer, BUFFER_SIZE); //向FIFO文件写入数据
printf("res: %d \n", res);
bytes_send += res;
close(pipe_fd);
}
else
{
exit(EXIT_FAILURE);
}
printf("Process %d finished\n\n", getpid());
exit(EXIT_SUCCESS);
}
consumer.c:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "fifo"
#define BUFFER_SIZE PIPE_BUF
int main()
{
int pipe_fd;
int res;
int open_mode = O_RDONLY;
int bytes_read;
char buffer[BUFFER_SIZE + 1];
memset(buffer, 0, sizeof(buffer));
printf("Process %d opening FIFO_NAME O_RDONLY", getpid());
pipe_fd = open(FIFO_NAME, open_mode); //打开FIFO文件
printf("Process %d result %d \n", getpid(), pipe_fd);
if(-1 != pipe_fd)
{
do
{
res = read(pipe_fd, buffer, BUFFER_SIZE); //从管道中读取数据
printf("%s", buffer);
memset(buffer, 0, sizeof(buffer));
bytes_read += res;
}while(res > 0);
printf("\n");
close(pipe_fd);
}
else
{
exit(EXIT_FAILURE);
}
printf("Process %d finished, %d bytes read\n\n", getpid(), bytes_read);
exit(EXIT_SUCCESS);
}