创建FIFO
FIFO为半双工通信,具有读写端,只能单向传输。一旦创建,读写端就无法更改。
管道创建:int mkfifo(const char *pathname, mode_t mode);
参数:
pathname 全局路径,对所有进程可见(这也是非血缘关系进程间通信的基础);
mode 文件权限;
返回值:
0 成功;-1 失败
创建管道的实质就是在内核开辟一个buffer,并且在读端和写端都同时打开的情况下,两端才能通过buffer进行数据交互。由写端往buffer写入数据,读端从buffer读出数据并处理。
工作模式
阻塞模式:管道为空,读端读数据默认阻塞;管道数据满,写端写数据默认阻塞;
非阻塞模式:管道为空,读端读数据返回失败;管道数据满,写端写数据返回失败;
Linux man手册给的建议是最好以阻塞的方式打开读端,以非阻塞的方式打开写端:
查看man手册,man 7 pipe,里面有这么一段话:
Pipe capacity
A pipe has a limited capacity. If the pipe is full, then a write(2) will block or fail, depending on whether the O_NONBLOCK flag is set (see below). Different implementations have different limits for the pipe capacity.
Applications should not rely on a particular capacity: an application should be designed so that a reading process consumes data as soon as it is available, so that a writing process does not remain blocked.
Talk is cheap, show you the code
fifo_read.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#define TEST_PATH "./1.txt"
int main()
{
int rc = -1;
if(access(TEST_PATH, F_OK))
{
rc = mkfifo(TEST_PATH, 0666);
if(rc < 0)
{
printf("create fifo[%s] error!", TEST_PATH);
return 1;
}
}
int fd = open(TEST_PATH, O_RDONLY);//只读方式打开写端
if(fd < 0)
{
printf("open fifo:%s error!\n",TEST_PATH);
return 1;
}
char rcv_buf[256] = {0};
while(1)
{
memset(rcv_buf, 0x00, sizeof(rcv_buf));
rc = read(fd, rcv_buf, sizeof(rcv_buf));
if(rc > 0)
{
printf("Read: %s\n", rcv_buf);
if(strncmp("quit",rcv_buf, 4) == 0)
{
break;
}
}
}
close(fd);
return 0;
}
fifo_write.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#define TEST_PATH "./1.txt"
int main()
{
int rc = 0;
if(access(TEST_PATH, F_OK))
{
rc = mkfifo(TEST_PATH, 0666);
if(rc < 0)
{
printf("create fifo[%s] error!", TEST_PATH);
return 1;
}
}
int fd = open(TEST_PATH, O_WRONLY|O_NONBLOCK);//写端以非阻塞方式打开
if(fd < 0)
{
perror("open");
exit(1);
}
int count = 0;
char send_buf[32] = {0};
while(1)
{
snprintf(send_buf, sizeof(send_buf), "Hello world %d", count++);
rc = write(fd, send_buf, sizeof(send_buf));
if(rc > 0)
{
printf("Write: %s\n", send_buf);
}
if(count == 10)
{
memset(send_buf, 0x00, sizeof(send_buf));
strncpy(send_buf, "quit", 4);
write(fd, send_buf, sizeof(send_buf));
break;
}
sleep(2);
}
close(fd);
return 0;
}
输出如下
写端
读端