一个例子掌握FIFO通信

先来看下Makefile:

NONBLOCK_WRITER = nb.w
BLOCK_WRITER    =  b.w
NONBLOCK_READER = nb.r
BLOCK_READER    =  b.r

all: writer reader

writer:
	cc w.c -o $(NONBLOCK_WRITER) -DNONBLOCK
	cc w.c -o $(BLOCK_WRITER)

reader:
	cc r.c -o $(NONBLOCK_READER) -DNONBLOCK
	cc r.c -o $(BLOCK_READER) 

clean:
	rm -f $(NONBLOCK_WRITER) $(BLOCK_WRITER) $(NONBLOCK_READER) $(BLOCK_READER)


分别将读者进程和写者进程编译成阻塞版本和非阻塞版本。

将公共部分写到一个头文件里:

/* file name: fifotest.h
 * cmd: make
 * author: yilonglucky#gmail.com
 * description: fifo header file
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define FIFO_PATH "/tmp/w.fifo"
#define BUF_LEN (4096*2)


再来看下读者进程的代码:

/* file name: r.c
 * cmd: make
 * author: yilonglucky#gmail.com
 * description: fifo reader
 */
#include "fifotest.h"

int main(int argc, char *argv[])
{
    char buf[BUF_LEN];
    int fd;
    int r_size;
    int real_rnum;

    if(2 != argc)
    {
        printf("Usage: %s read_len\n", argv[0]);
        exit(0);
    }    
    r_size = atoi(argv[1]);
    printf("requred real read %d bytes\n", r_size);


#ifdef NONBLOCK
    fd = open(FIFO_PATH, O_RDONLY|O_NONBLOCK, 0);
#else
    fd = open(FIFO_PATH, O_RDONLY, 0);
#endif

    if(-1 == fd)
    {
        perror(FIFO_PATH);
        exit(2);
    }

    do
    {
        memset(buf, 0, sizeof(buf));
        real_rnum = read(fd, buf, r_size);
        if(-1 == real_rnum)
        {
            if(EAGAIN == errno)
            {
                perror("no data so try later");
            }
        }
        else
        {
            printf("real read %d bytes\n", real_rnum);
        }

        sleep(1);

    }while(1);    /* read once while 0 */

    close(fd);
    unlink(FIFO_PATH);

    return 0;
}

最后是写者进程的代码:

/* file name: w.c
 * cmd: make
 * author: yilonglucky#gmail.com
 * description: fifo writer
 */
#include "fifotest.h"

int main(int argc, char *argv[])
{
    char buf[BUF_LEN];
    int fd;
    int w_size;
    int real_wnum;

    printf("PIPE_BUF = %d\n", PIPE_BUF);
    if(2 != argc)
    {
        printf("Usage: %s write_len\n", argv[0]);
        exit(0);
    }    
    w_size = atoi(argv[1]);
    printf("requred real write %d bytes\n", w_size);

#if 1 /* you can test ENOENT if 0*/
    if((mkfifo(FIFO_PATH, O_CREAT|O_EXCL) < 0) && (EEXIST != errno))
    {
        printf("%s no exist and create failed\n", FIFO_PATH);
    }
#endif

#ifdef NONBLOCK
    fd = open(FIFO_PATH, O_WRONLY|O_NONBLOCK, 0);
#else
    fd = open(FIFO_PATH, O_WRONLY, 0);
#endif

    if(-1 == fd)
    {
        if(ENXIO == errno)
        {
            perror("no reading process");
            exit(6);
        }
        else    /* ENOENT no access to the fifo */
        {
            perror(FIFO_PATH);
            exit(2);
        }
    }

    sleep(10);    /* sleep for nonblock reader's EAGAIN */

    memset(buf, 0xf, sizeof(buf));
    real_wnum = write(fd, buf, w_size);
    if(-1 == real_wnum)
    {
        if(EAGAIN == errno)
        {
            /* who can tell me how to be here */
            printf("write to fifo error: try later\n");
        }
    }
    else
    {
        printf("real write num is %d\n", real_wnum);
    }

    close(fd);
    return 0;
}


你可能感兴趣的:(fifo,管道,命名管道,进程间通信,ipc)