gpt4 book ai didi

c++ - 使用 select 多路复用未命名管道和其他文件描述符

转载 作者:太空宇宙 更新时间:2023-11-04 10:10:18 24 4
gpt4 key购买 nike

我正在尝试将一个未命名的管道与其他一些文件描述符进行多路复用。问题是管道文件描述符总是出现在 select 的结果中。换句话说,事件循环无限次地从管道读取。这是我想做的事情和实际发生的事情的比喻。

#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>


using namespace std;
int main(){
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()
FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);
int fdmax; // maximum file descriptor number
int pfd[2];
if(pipe(pfd)!=0) {cout<<"Unable to create a pipe.\n",exit(1);};

FD_SET(0, &master);
FD_SET(pfd[0],&master);

fdmax=pfd[0];

if(fork()){//Parent


for (;;){
read_fds = master; // copy it
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);
}
for(int i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) {
int n;
char buff[200];

if (i==pfd[0]){
close(pfd[1]);
n=read(pfd[0],buff,sizeof(buff));
buff[n]=0;
cout<<"Read from pipe:"<<buff<<endl;
}else if(i==0){
n=read(0,buff,sizeof(buff));
buff[n]=0;
cout<<"Read from std:"<<buff<<endl;
}
}
}

}
}else{//Child
usleep(50000);
char buff[200]="This is a simple sample.";
close(pfd[0]);
write(pfd[1],buff,sizeof(buff));
close(pfd[1]);
exit(0);
}
}

最佳答案

首先,read() 调用可以读取少于最后一个参数中指定的字节数,ant id 不会自动附加零字节终止符,因此您的接收代码可以轻松访问未初始化的buff[] 及其之后的内存(如果没有零字节)。您需要在调用 read 时检查返回值,并且只使用来自缓冲区的这么多字节。

然后,当 readfds 集合中的任何文件描述符不会阻塞后续读取时,select 调用返回。其中包括文件结束条件。当 fork 进程关闭其 fd 时,您的情况可能会发生这种情况。参见 this SO question也是。

会不会是你遇到问题的原因?在调用 read 时检查返回值让您清楚这一点,因为当且仅当 fd 到达文件末尾时 read 返回零。

最后一个细节——仅在 readfds 中返回 pfd[0] 后关闭 pfd[1] 没有多大意义.您应该在 fork 之后立即关闭它,这样只有当您在父进程中不需要它时,它才会在子进程中保持打开状态。

关于c++ - 使用 select 多路复用未命名管道和其他文件描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49458275/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com