C中带有管道的非阻塞I/O

先决条件: 管道()系统调用 当管道中发生I/O阻塞()时? 考虑两个过程,一个过程是实时收集数据(读取数据),另一个是绘制数据(写入数据)的过程。这两个过程由一根管道连接,管道 数据采集 进程为数据打印进程提供数据。两个过程的数据采集速度不同。 管道中的默认行为是,如果伙伴进程较慢,管道的写入端和读取端将表现出阻塞行为。这很糟糕,因为数据采集过程可能会等待绘图过程(写入数据)。因此,在数据采集过程中,阻塞管道中的读取调用,程序挂起。如果我们不想发生这种情况,我们必须在读取结束调用之前关闭写入结束进程。 用简单的语言,

null
  • read调用获取的数据量与它请求的数据量或管道拥有的数据量相同,以较小者为准
  • 如果管道是空的
    • 如果没有进程的写端打开,管道上的读取将返回EOF(返回值0)
    • 如果某个进程将管道打开以进行写入,则read将阻塞以等待新数据

带管道的非阻塞I/O

有时,让I/O不阻塞是很方便的,也就是说,我们不希望读调用阻塞一个,以防另一个输入。解决方案是给定的函数:

  To specify non-blocking option:       #include<fcntl.h>        int fd;        fcntl(fd, F_SETFL, O_NONBLOCK); 
  • fd: 文件描述符
  • F_SETFL: 将文件状态标志设置为arg指定的值。此处的文件访问模式仅用于 O_非块 旗帜
  • O_NONBLOCK: 用于非阻塞选项。
  • 0: 成功回报
  • -1: 返回错误,设置错误否

此函数成功运行后,将返回读/写调用 -1 如果管道 空/满 并将errno设置为 伊根 示例:Child每隔3秒向父级写入“hello”,父级每秒执行非阻塞读取。

图片[1]-C中带有管道的非阻塞I/O-yiteyi-C++库

C

// C program to illustrate
// non I/O blocking calls
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h> // library for fcntl function
#define MSGSIZE 6
char * msg1 =“hello”;
char * msg2 =“bye !!”;
int main()
{
int p[2], i;
// error checking for pipe
if (pipe(p) < 0)
exit (1);
// error checking for fcntl
if (fcntl(p[0], F_SETFL, O_NONBLOCK) < 0)
exit (2);
// continued
switch (fork()) {
// error
case -1:
exit (3);
// 0 for child process
case 0:
child_write(p);
break ;
default :
parent_read(p);
break ;
}
return 0;
}
void parent_read( int p[])
{
int nread;
char buf[MSGSIZE];
// write link
close(p[1]);
while (1) {
// read call if return -1 then pipe is
// empty because of fcntl
nread = read(p[0], buf, MSGSIZE);
switch (nread) {
case -1:
// case -1 means pipe is empty and errono
// set EAGAIN
if ( errno == EAGAIN) {
printf (“(pipe empty)”);
sleep(1);
break ;
}
else {
perror (“read”);
exit (4);
}
// case 0 means all bytes are read and EOF(end of conv.)
case 0:
printf (“End of conversation”);
// read link
close(p[0]);
exit (0);
default :
// text read
// by default return no. of bytes
// which read call read at that time
printf (“MSG = % s”, buf);
}
}
}
void child_write( int p[])
{
int i;
// read link
close(p[0]);
// write 3 times "hello" in 3 second interval
for (i = 0; i < 3; i++) {
write(p[1], msg1, MSGSIZE);
sleep(3);
}
// write "bye" one times
write(p[1], msg2, MSGSIZE);
// here after write all bytes then write end
// doesn't close so read end block but
// because of fcntl block doesn't happen..
exit (0);
}


输出:

(pipe empty)MSG=hello(pipe empty)(pipe empty)(pipe empty)MSG=hello(pipe empty)(pipe empty)(pipe empty)MSG=hello(pipe empty)(pipe empty)(pipe empty)MSG=bye!!End of conversation

原子写入管道

原子意味着没有任何其他进程观察到其部分完成。如果写入的数据大小不大于 管道(4096字节) 这意味着数据传输似乎是一个瞬时单位,这意味着系统中没有任何其他东西可以观察到数据传输部分完成的状态。原子I/O可能不会立即开始(它可能需要等待缓冲区空间或数据),但一旦开始,它就会立即完成。 数据写入多达 管道(4096字节) 它们是原子的。读取或写入大量数据可能不是原子的;例如,来自共享描述符的其他进程的输出数据可以散布。还有一次 烟斗 已写入字符,将阻止进一步写入,直到读取部分字符 例子: 进程1同时发送一条100字节的消息,进程2发送一条100字节的消息,不保证订单,但管道将接收所有一条消息,然后再接收所有其他消息。 在较大写入的非原子写入中,没有这样的保证,数据可能会混淆,如下所示:

图片[2]-C中带有管道的非阻塞I/O-yiteyi-C++库

管道容量

  • 管道可以容纳有限的字节数。
  • 写入填充管道并在管道已满时阻塞
    • 它们会一直阻塞,直到另一个进程在管道的另一端读取足够的数据,并在所有要写入的数据传输完毕后返回
  • 管道的容量至少为512字节,通常更大(取决于系统)

C

// C program to illustrate
// finding capacity of pipe
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int count = 0;
// SIGALRM signal handler
void alrm_action( int signo)
{
printf ( "Write blocked after %d characters" , count);
exit (0);
}
int main()
{
int p[2];
char c = 'x' ;
// SIGALRM signal
signal (SIGALRM, alrm_action);
// pipe error check
if (pipe(p) == -1)
exit (1);
while (1) {
alarm(5);
// write 'x' at one time when capacity full
// write() block and after 5 second alarm
write(p[1], &c, 1);
// send signal and alrm_action handler execute.
++count;
alarm(0);
}
}


输出:

Write blocked after 65536 characters //output depend on the system so output may change in different system

在这里,在while循环中,第一个5秒的报警设置在 写() call只写一个字符 “x” 在管道里。和 计数 变量用于计数管道中的字符写入。strong> 警报(0) 表示取消设置的报警 5. 第二管道容量满一段时间后,write()调用被阻塞,程序不执行下一条指令,5秒后设置报警铃声并发送信号 西格尔姆 .之后 阿尔拉姆_行动 处理程序执行并打印管道可以写入的最大字符数。 本文由 卡丹·帕特尔 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享