一:什么是有名管道
不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。就好像把管道的fd[0]和fd[1]变成了两个文件来操作。
二:创建有名管道
有名管道的创建
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * pathname, mode_t mode)
函数的第一个参数是路径名,第二个参数与打开普通文件的open()函数中的mode参数相同。如果mkfifo的第一个参数是一个已经存在的路径名时,会返回EEXIST错误,所以一般典型的调用代码首先会检查是否返回该错误,如果确实返回该错误,那么只要调用打开FIFO的函数就可以了。一般文件的I/O函数都可以用于FIFO,如close、read、write等等 。
Python和C类似,看懂了C的函数,python自然就会了,就是熟悉一下流程而已。
三:C代码如下
头文件:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAXLINE 512
#define ERR_EXIT(sz) \
do{ \
perror(sz); \
exit(EXIT_FAILURE); \
}while(0)
const char* write_fifo = "write_fifo";
const char* read_fifo = "read_fifo";
服务器端:
#include "unp.h"
int main()
{
int res;
if(access(read_fifo, F_OK) < 0){ //检测是否存在
if( (res = mkfifo(write_fifo, O_CREAT|O_EXCL|0755)) < 0) //创建写fifo,0755为执行权限
ERR_EXIT("mkfifo err.");
}
int write_fd;
if( (write_fd = open(write_fifo, O_WRONLY)) < 0){
unlink(write_fifo); //如果失败,删除
ERR_EXIT("open write_fifo err.");
}
int read_fd;
while( (read_fd = open(read_fifo, O_RDONLY)) < 0) //等待客户端创建读fifo
sleep(1);
printf("client connect.\n");
char sendbuff[MAXLINE];
char recvbuff[MAXLINE];
for(; ;){
printf("client:>");
ssize_t ret;
if( (ret = read(read_fd, recvbuff, MAXLINE)) < 0)
ERR_EXIT("read err.");
printf("%s\n", recvbuff);
printf("server:>");
scanf("%s", sendbuff);
write(write_fd, sendbuff, strlen(sendbuff)+1);
}
unlink(write_fifo);
return 0;
}
客户端:
#include "unp.h"
int main()
{
int res;
if( (res = mkfifo(read_fifo, O_CREAT|O_EXCL|0755)) < 0)
ERR_EXIT("mkfifo err.");
int read_fd;
if( (read_fd = open(write_fifo, O_RDONLY)) < 0)
ERR_EXIT("open err.");
int write_fd;
if( (write_fd = open(read_fifo, O_WRONLY)) < 0){
unlink(read_fifo);
ERR_EXIT("open write_fifo err.");
}
char sendbuff[MAXLINE];
char recvbuff[MAXLINE];
ssize_t ret;
for(; ;){
printf("client:>");
scanf("%s", sendbuff);
if( (ret = write(write_fd, sendbuff, strlen(sendbuff)+1)) < 0)
ERR_EXIT("write err.");
printf("server:>");
read(read_fd, recvbuff, MAXLINE);
printf("%s\n", recvbuff);
}
unlink(read_fifo);
return 0;
}
四:Python代码如下
服务器端:
import os
name_write = 'write_fifo'
name_read = 'read_fifo'
def main():
if os.access(name_write, os.F_OK) == False:
os.mkfifo(name_write)
write_fd = os.open(name_write, os.O_WRONLY)
read_fd = os.open(name_read, os.O_RDONLY)
while True:
out_msg = raw_input('server:>')
os.write(write_fd, out_msg)
in_msg = os.read(read_fd, 100)
print 'client:>' + in_msg
os.close(write_fd)
if __name__ == '__main__':
main()
客户端:
import os
name_read = 'write_fifo'
name_write = 'read_fifo'
def main():
if(os.access(name_write, os.F_OK) == False):
os.mkfifo(name_write)
read_fd = os.open(name_read, os.O_RDONLY)
write_fd = os.open(name_write, os.O_WRONLY)
while True:
in_msg = os.read(read_fd, 100)
print 'server:>' + in_msg
out_msg = raw_input('client:>')
os.write(write_fd, out_msg)
os.close(read_fd)
if __name__ == '__main__':
main()
五:结果截图如下