文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>fifo 一例

fifo 一例

时间:2006-04-30  来源:iry

  命名管道一般简称为FIFO。FIFO在UNIX/Linux中用的比较多。FIFO的具体内容就不说了。
值得一提的是,在两个进程分别用只读和只写的方式打开FIFO的情况下,
如果只写打开FIFO的进程先退出,或者先关闭FIFO;
则只读打开FIFO的进程的read函数将读到0字节;这个时候只读进程也应该关闭FIFO。
如果不关闭FIFO,则select将一直报告有读描述符准备好,造成极大CPU资源浪费。
eg。有两个进程,进程receiver用来接收某个fifo的数据,进程sender用来向某个fifo发送数据。 #define BUFSIZE 128
#define FIFO "fifo"
program receiver: #include ... int main(int argc, char *argv)
{
    int fd;
    char buff[BUFSIZE];
    fd_set readfds;
    struct timeval tv;
    int value;
    fd = open(FIFO, O_RDONLY | O_NONBLOCK)
    if (fd < 0)
    {
        perror("open fifo");
        return -1;
    }
    else
    {
        printf("open fifo success\n");
    }
    value = fcntl(fd, F_GETFL);
    if (value < 0)
    {
       close(fd);
       return -1;
    }
    value &= (~O_NONBLOCK);
    if (fcntl(fd, F_SETFL, value) < 0)
    {
        close(fd);
        return -1;
    }
    while (1)
    {
        tv.tv_sec = 3;
        tv.tv_usec = 0;
        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);
        value = select(fd+1, &readfds, NULL, NULL, &tv);
        if (value > 0)
        {
            printf("%d fds are ready.\n", i);
            if (FD_ISSET(fd, &readfds))
            {
                printf("FIFO is ready for read.\n");
                memset(buff, 0, BUFSIZE);
                read(fd, buff, BUFSIZE-1);
                printf("received stirng: %s\n", buff);
            }
        }
        else if (value == 0)
        {
            printf("timeout, No file descriptor ready.\n");
        }
        else
        {
            printf("have error occured, exit program!!!\n");
            close(fd);
            return -1;
        }
    }
    close(fd);
    return 0;
}

program sender:
#include ... int main(int argc, char *argv[])
{
    int fd;
    char buff[BUFSIZE];
    int len;
    fd = open(FIFO, O_WRONLY);
    if (fd < 0)
    {
        perror("open fifo");
        reutrn -1;
    }
    else
    {
        printf("open fifo success!\n");
    }
    memset(buff, 0, BUFSIZE);
    strncpy(buff, "123456789", BUFSIZE-1);
    if (write(fd, buff, strlen(buff)) != strlen(buff))
    { 
        perror(write);
        close(fd);
        return -1;
    }
    else
    {
        printf("write success!\n");
    }
    close(fd);
    return 0;
}
  编译这两个程序,不管先启动哪个程序,sender都能得到正确的结果.但receiver却不能正确的运行.
  结果如下:
sender:
open fifo success!
write success!
receiver:
open fifo success!
1 fds are ready.
FIFO is ready for read.
received string:123456789
1 fds are ready.
FIFO is ready for read.
received stirng:
1 fds are ready.
FIFO is ready for read.
received stirng:
......
在屏幕上不停的循环显示 "1 fds are ready.  FIFO is ready for read.  received stirng:"
为什么会出现这种情况呢? 是因为当FIFO的write端关闭后,会通知read端;这样在read端就会变得可以读,但并没有任何数据;
这样的目的就是通知读端关闭.所以我们只要简单的关闭FIFO描述符就可以了.
  但是,receiver程序的目的是打开某个FIFO,并一直等待其它程序的数据,如果我们关闭了的话程序也就推出了.
  所以我们要做的是应该是重新打开.
receiver程序新版如下: program receiver: #include ... int open_fifo(void)
{
    int fd;
    int value;
    fd = open(FIFO, O_RDONLY | O_NONBLOCK)
    if (fd < 0)
    {
        perror("open fifo");
        return -1;
    }
    else
    {
        printf("open fifo success\n");
    }
    value = fcntl(fd, F_GETFL);
    if (value < 0)
    {
        close(fd);
        return -1;
    }
    value &= (~O_NONBLOCK);
    if (fcntl(fd, F_SETFL, value) < 0)
    {
        close(fd);
        return -1;
    }
 
    return fd;
}
  int main(int argc, char *argv)
{
    int fd;
    char buff[BUFSIZE];
    fd_set readfds;
    struct timeval tv;
    if((fd = open_fifo()) == -1)
    {
        return -1;
    }
    while (1)
    {
        tv.tv_sec = 3;
        tv.tv_usec = 0;
        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);
        value = select(fd+1, &readfds, NULL, NULL, &tv);
        if (value > 0)
        {
            printf("%d fds are ready.\n", i);
            if (FD_ISSET(fd, &readfds))
            {
                printf("FIFO is ready for read.\n");
                memset(buff, 0, BUFSIZE);
                if (read(fd, buff, BUFSIZE-1) <= 0)
                {
                    printf("error or notify close fifo. reopen it.\n");
                    close(fd);
                    if((fd = open_fifo()) == -1)
                    {
                        return -1;
                    }
                }
                else
                {
                     printf("received stirng: %s\n", buff);
                }
            }
        }
        else if (value == 0)
        {
            printf("timeout, No file descriptor ready.\n");
        }
        else
        {
            printf("have error occured, exit program!!!\n");
            close(fd);
            return -1;
        }
    }
    close(fd);
    return 0;
}
程序修改成这样,就不存在上面的问题了.
相关阅读 更多 +
排行榜 更多 +
浴血混战官方下载

浴血混战官方下载

飞行射击 下载
检票员模拟器免广告下载

检票员模拟器免广告下载

模拟经营 下载
最终前哨最终版手机版下载

最终前哨最终版手机版下载

休闲益智 下载