IPC under Linux-FIFO(2)

23 8 月, 2010 by edsionte Leave a reply »

下面我们来详细说明有名管道的读写规则。

3.有名管道读取规则

(1)如果进程A事先写打开FIFO,但却不进行写操作(FIFO中为空),那么进程B对其进行读操作时候将会阻塞,或者直接返回-1(当设置了非阻塞标志时)。
我们继续以《LinuxC编程实战》一书中的例子(P252)为原型,对procwrite.c函数稍作改动即可,具体代码如下。

	printf("Now the writer will sleep 5s..\n");
	sleep(5);
	printf("Now the writer wake up and will write to FIFO..\n");
	write(fd,buf,strlen(buf)+1);
	printf("writer will leave!\n");
	close(fd);

我们可以发现,procwrite进程运行后,发生了阻塞,这一点可用上文的打开规则来解释。当在另一个终端运行procread进程后,此时的procwrite正常运行。由于我们让procwrite进程睡眠5s,所以当前管道缓冲区是空的,我们可以在另一终端发现procread进程发生了阻塞。但当procwrite睡眠结束,继续运行时,procread进程可正确读出管道内数据。

如果你理解了规则1,那么我们继续来了解两种读操作阻塞的情况。

(2)当FIFO中有数据时,但是正在被进程A所读取,如果B进程此时也欲读FIFO,B进程将阻塞;如果FIFO中无数据,那么读进程也将阻塞(规则1所述)。想要解除阻塞只要在管道内写入数据即可,不管写入多少数据,也不管读进程请求读多少数据。

我们继续以上述例子为原型,但是需要两个读进程。首先procwrite进程先进行第一次写,然后睡眠20s,接着进行第二次写操作,这是为了解除因读操作而阻塞的进程。

        //procwrite.c部分代码
	printf("Now the writer will write data to FIFO..\n");
	write(fd,buf,strlen(buf)+1);
	printf("writer will leave!\n");
	sleep(20);
	strcpy(buf,"The write write another data now");
	write(fd,buf,strlen(buf)+1);
	close(fd);
	exit(0);

在procread.c程序中,我们让此进程一次性只读取一个字符。

int n=20;
while(n--)
{
read(fd,buf,1);
buf[strlen(buf)]='\0';
printf("Read content:%s\n",buf);
sleep(2);
}
close(fd);
unlink(FIFO_NAME);
exit(0);

在procread2.c程序中,我们让此进程一次性读完管道内所有数据。

printf("I will read data from FIFO..\n");
read(fd,buf,BUF_SIZE);
printf("Read content:%s\n",buf);
close(fd);
exit(0);

我们首先运行procwrite,然后立马运行procread,可以看到其每次只输出一个字符;接着我们运行procread2,可以看到这个进程一次性读完了管道内剩余的所有数据,而此时再看运行procread的那个终端,可知procread进程发生了阻塞,不过再稍等片刻,可发现它有接着输出字符,这是因为procwrite进程第二次的写操作解除了procread进程的阻塞。

这里只是为大家做一个简单的演示,我们可以在理解上述规则的基础上编写其他程序去验证。

4.有名管道的写规则

如果打开FIFO时,没有加非阻塞标志,那么写操作遵循以下的规则:

(1)如果写入数据的字节数不大于PIPE_BUF(注意,从内核2.6.11开始,其值为65536),Linux将保证写操作的原子性。当管道内的剩余缓冲区大于要写入的数据字节数时,那么将一次性写完数据;否则,进程进入睡眠状态,直至管道内的缓冲区可以容纳要写入的数据为止。

(2)如果写入的数据字节数不大于PIPE_BUF,那么Linux将不保证写操作的原子性。管道内一有空闲的缓冲区,写进程就去写数据,直至所有数据都被写完为止。

如果打开FIFO的时候加入了阻塞标志,那么写操作遵循一下规则:

(1)如果要写入数据的字节数大于PIPE_BUF,那么linux将不会保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。

(2)如果要写入的数据的字节数不大于PIPE_BUF,那么linux将保证写入的原子性。如果当前FIFO空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写。

Advertisement

15 comments

  1. alenChou说道:

    有名管道的读写默认的是阻塞的。嘿嘿。你的例子改的很好,我当时讲的时候只是说,都没用到好的例子。

    [回复一下]

    edsionte 回复:

    你回来了?

    [回复一下]

  2. alenChou说道:

    哦,上面提到的例子是读规则阻塞验证的那个例子。

    [回复一下]

    edsionte 回复:

    写的验证程序,我还在调试。。

    [回复一下]

  3. alenChou说道:

    这个回复怎么才能通过邮件通知我呢?

    [回复一下]

    edsionte 回复:

    我给你回复邮件没同志你吗?

    [回复一下]

    alenChou 回复:

    没有,从来没有过。都是我路过这里的时候才看到。的

    [回复一下]

    edsionte 回复:

    。。。。。。。。。。。我晕。我可以邮件收到别人给我的回复。。
    不过你在你那给我回复我也是收不到的。以前也收不到吗。

    [回复一下]

    alenchou 回复:

    一直收不到,一直是路过看到你的回复。。

    [回复一下]

    edsionte 回复:

    我昏。。也许wordpress没有这个功能。。。。。。。。

    [回复一下]

    edsionte 回复:

    @alenchou, 这下ok?

    [回复一下]

    alenChou 回复:

    @edsionte, 这下OK了,怎么处理的。

    [回复一下]

    edsionte 回复:

    @alenChou, 你在后台搜索Wordpress Thread Comment就ok了

  4. alenChou说道:

    是安装这个评论插件吗?

    [回复一下]

    edsionte 回复:

    @alenChou, 对。。。你试试。。

    [回复一下]

发表回复

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key