创建有名管道,如果管道存在则直接使用
//创建有名管道,如果管道存在则直接使用
int n = mkfifo("./myfifo",0664);
if( n < 0 && errno!=EEXIST)
{
perror("mkfifo");
return -1;
}
负责管道写数据线程
void *thread_fun_write(void *p)
{
char *buf = "12345";
int fd;
fd = open("./myfifo",O_WRONLY);
if(fd == -1)
{
printf("write fifo open fail....\n");
exit(-1);
return;
}
while(1)
{
write( fd, buf, strlen(buf)+1 );
puts("write ok");
sleep(5);
}
close(fd);
}
负责读取管道内容的线程,如果管道内没有数据,阻塞等待读取数据。
void *thread_fun_read(void *p)
{
int fd;
fd = open("./myfifo", O_RDONLY );
if(fd == -1)
{
printf("read fifo open fail...\n");
exit(-1);
return;
}
char buf[100] = {0};
int num;//保存读数据大小
while(1)
{
num = read( fd, buf, 100 );
puts("read ok:");
puts(buf);
}
close(fd);
}
完整代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
void *thread_fun_write(void *p)
{
char *buf = "12345";
int fd;
fd = open("./myfifo",O_WRONLY);
if(fd == -1)
{
printf("write fifo open fail....\n");
exit(-1);
return;
}
while(1)
{
write( fd, buf, strlen(buf)+1 );
puts("write ok");
sleep(5);
}
close(fd);
}
void *thread_fun_read(void *p)
{
int fd;
fd = open("./myfifo", O_RDONLY );
if(fd == -1)
{
printf("read fifo open fail...\n");
exit(-1);
return;
}
char buf[100] = {0};
int num;//保存读取数据的大小
while(1)
{
num = read( fd, buf, 100 );
puts("read ok:");
puts(buf);
}
close(fd);
}
int main()
{
//创建有名管道,如果管道存在则直接使用
int n = mkfifo("./myfifo",0664);
if( n < 0 && errno!=EEXIST)
{
perror("mkfifo");
return -1;
}
//创建线程
pthread_t writeId,readId;
pthread_create( &writeId, NULL, thread_fun_write, NULL );
pthread_create( &readId, NULL, thread_fun_read, NULL);
pthread_join(writeId,NULL);
pthread_join(readId,NULL);
while(1);
return 0;
}
若想实现写进程阻塞,读进程非阻塞。只需将读进程中管道打开方式改为
fd=open("./myfifo",O_RDONLY | O_NONBLOCK);
先运行写进程(被阻塞),再运行读进程,程序一切正常。先运行读进程,程序直接崩掉(Segmentation fault (core dumped))。
此外,用户还可能想着,我在读取的时候,使用阻塞的方式的话,会一直卡着;使用非阻塞的方式,则会没完没了的调用while(1)占用了CPU还不干活。
有没有在阻塞的情况下再提供超时的机制呀?比如,我尝试等待5s,如果在这5s内,管道中有数据,则我就读取,如果么有,我就进入下一次循环,继续等待5s。而这等待过程中不占用CPU。
有!但是完全不占用CPU是不可能的。
首先,我们不能使用while(1)这种方式,这货不释放CPU,没完没了的去尝试从管道中拿数据;
其次,我们也不能使用sleep(0.5)或者类似的等待机制(比如衰退式的睡眠时间等),这会造成另外一个问题,睡眠时释放了CPU,但是如果在睡眠过程中管道里有数据了,这种方式只能在睡眠结束后去拿数据,可能黄花菜都凉了;
最后,操作系统提供了select系统调用,可使用它来完成超时机制的设置,但是这个是与文件绑定的,具体地是和fd绑定的。在select调用过程中,如果指定的fd发生了事件(具体什么事件,去看看select的介绍),则select会返回大于0的数值,此时就可以执行之后的代码;如果在等待过程中没有产生事件,则返回小于0的数值,那就可以进入下一次循环,而不用执行后续操作。通过这种在读管道之前加入超时的方式,变相地实现了带超时机制的读数据。但是在这种情况下,读管道是否为堵塞其实都没有意义了,因为无论是设置成堵塞还是非堵塞,前面的select都会执行,也就是都会堵塞。