管道与队列

相同点

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.

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据