相同点:
1. 都是先进先出
不同点:
1. 管道可以以只读方式打开,但不能以只写方式打开;因为管道是不存储数据的
如何用Linux系统中的fifo来实现队列:
消费者a.php:$fp = fopen("/dev/shm/fifo1","w+");
while(!feof($fp)) {
echo fgets($fp);
sleep(4);
}
生产者b.php:$fp = fopen("/dev/shm/fifo1","w+");
$pid = posix_getpid();
while(1) {
$str = $pid."_".time()."n";
fwrite($fp,$str);
echo $str;
sleep(2);
}
注意:
1. 不管是生产者还是消费者都要以读写的方式打开;否则:
生产者如果以只写方式打开,会因为没有消费者而在打开时阻塞;
消费者如果以只读方式打开,消费完就退出了,不会阻塞,达不到随时服务的效果。
2. 因为文件总是有4096字节的IO Block,所以管道里可以阻塞4096字节的数据;就是说,如果消费者进程仅仅是打开了fifo,但是没有读取,这时生产者可以写入最多4096字节的数据(这个4096和生产者进程的buffer无关,是文件本身的一个属性,不知道怎么修改),和写入进程的多少没有关系,一旦阻塞了4096字节的数据,任何欲写入(可能还没写一个字节呢)的进程都会被阻塞或直接返回失败。
3. 注意下面情况:
1) A进程打开某fifo1,开始循环读取
2) 删除fifo1, 这时A进程是不知道的,并且不会发生错误
3) B进程创建同样的fifo1,开始写fifo1, 这时A进程是读取不到B进程写入的数据的,必须重新打开 解决办法: 还没有呢
4. 如果消费者进程没有启动,则生产者进程写入多少丢弃多少
5. 如果有一个消费者进程,多个生产者进程,则任何一个生产者进程退出,消费者进程都将读到一个文件结束符,所以这种情况不能在读取到文件结束符时退出,而是读到文件结束符时丢弃,继续读取(没有数据时会阻塞的)。
6. 如果不小心将fifo创建成了一般文件,则后果就难以预测了。
7. 如果想以非阻塞的方式来读取一个fifo中的数据,则需要:
a. 以读写的方式打开(注意要有写权限才行哦)
b. 对打开的流做nonblock的设置,php里面的语法为: stream_set_blocking($fp, 0);
我需要一个队列:
1. 没有网络开销和磁盘IO的开销,只需要内存就可以
2. 允许在数据处理太慢时丢失旧数据,因为对我来说,过期的数据是没有意义的
3.