创建FIFO
FIFO为半双工通信,具有读写端,只能单向传输。一旦创建,读写端就无法更改。
管道创建:int mkfifo(const char *pathname, mode_t mode);
参数:
pathname 全局路径,对所有进程可见(这也是非血缘关系进程间通信的基础);
mode 文件权限;
返回值:
0 成功;-1 失败
创建管道的实质就是在内核开辟一个buffer,并且在读端和写端都同时打开的情况下,两端才能通过buffer进行数据交互。由写端往buffer写入数据,读端从buffer读出数据并处理。
当FIFO读端和写端都关闭时,内核会释放这块缓冲区,但文件系统中的“pathname”对应的文件会一直存在,除非手动删除。
进程通过FIFO数据交互时,文件系统只是给进程提供一个访问FIFO的入口(即pathname),数据实际保存在内核缓冲区,并非保存在文件系统中。
工作模式
阻塞模式:管道为空,读端读数据默认阻塞;管道数据满,写端写数据默认阻塞;
非阻塞模式:管道为空,读端读数据返回失败;管道数据满,写端写数据返回失败;
非阻塞模式下,如果写端以O_WRONLY模式开启FIFO,会报如下错误,必须等读端开启后才能开启:
open: No such device or address
注意事项:读端关闭后,写端继续往fifo发送数据,会产SIGPIPE信号。如果写端没有捕获该信号或者没有对该信号设置为SIG_IGN(忽略),那么写端进程将终止。
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);
sleep(1);//加延迟目的是防止读端读不到最后一条quit数据
write(fd, send_buf, sizeof(send_buf));
break;
}
sleep(1);
}
close(fd);
return 0;
}
输出如下
写端

读端

667

被折叠的 条评论
为什么被折叠?



