繁体   English   中英

使用select复用未命名管道和其他文件描述符

[英]multiplexing unnamed pipe and other file descriptors using select

我正在尝试将未命名的管道与其他一些文件描述符进行复用。 问题在于管道文件描述符始终出现在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调用将返回。 其中包括文件结束条件。 在您的情况下,当分叉进程关闭其fd时,可能会发生这种情况。 也看到这个问题

可能是您遇到问题的原因吗? 调用read时检查返回值使您很清楚,因为如果fd到达文件末尾,则read仅返回零。

最后一个细节–仅在readfds返回pfd[0]之后关闭pfd[1]并没有多大意义。 您应该在派生之后立即将其关闭,因此只有在父进程中没有使用它时,它才在子进程中保持打开状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM