使用epoll()命令从文件描述符中读取数据

Use epoll() command to read data from a file descriptor

本文关键字:描述 读取 数据 文件 epoll 命令 使用      更新时间:2023-10-16

我有一个">/dev/ttyS0"的打开文件描述符,用于从RS232设备读取数据。我正在尝试使用epoll实例从文件描述符进行并发读取,因为我在从文件描述符读取数据时遇到错误(资源暂时不可用(。我有用epoll编写的示例代码来完成这项工作,但它并没有按预期运行。程序在epoll_wait((调用处无限等待。

请帮助我验证我编写代码的方式
fdRS232/dev/ttyS0的打开文件描述符

int DeviceRS232::readDecoderData(unsigned char *dataBuffer, size_t bufferSize)
{
    unsigned char recvBuffer[251];
    unsigned char *ptrChar;
    int nBytes, portStatus;
    int inputBufSize = 0;
    // Use epoll for read and write event handling
    int fdEpoll, returnStatus;
    struct epoll_event rwEpollEvent;
    struct epoll_event *prwEpollEvent;
    fdEpoll = epoll_create1(0);
    if(fdEpoll == -1)
    {
        std::cout << "Error: " << strerror(errno);
        return 0;
    }
    rwEpollEvent.data.fd = fdRS232;
    rwEpollEvent.events = EPOLLIN | EPOLLET;
    returnStatus = epoll_ctl(fdEpoll, EPOLL_CTL_ADD, fdRS232, &rwEpollEvent);
    if(returnStatus == -1)
    {
        std::cout << "Error: " << strerror(errno);
        return 0;
    }
    prwEpollEvent = (epoll_event *)calloc(MAX_EVENTS, sizeof(rwEpollEvent));
    while(true)
    {
        std::cout << "test1" << std::endl;
        int nfd;
        nfd = epoll_wait(fdEpoll, prwEpollEvent, MAX_EVENTS, -1);
        std::cout << "ndf: " << nfd << std::endl;
        for(int x=0; x<nfd; x++)
        {
            std::cout << "test-for" << std::endl;
            if(prwEpollEvent[x].events & EPOLLERR ||
               prwEpollEvent[x].events & EPOLLHUP ||
               !(prwEpollEvent[x].events & EPOLLIN))
            {
                std::cout << "test2" << std::endl;
                std::cout << "epoll error: " << strerror(errno);
                close(prwEpollEvent[x].data.fd);
                continue;
            }
            else
            {
                std::cout << "test3" << std::endl;
                ChangeCTS(fdRS232, 0);
                ChangeRTS(fdRS232, 0);
                while(inputBufSize <= 0)
                {
                    ioctl(fdRS232, FIONREAD, &inputBufSize);
                    usleep(1);
                }

                if(inputBufSize > 0)
                {
                    int decodePacketLen = 0;
                    //unsigned char
                    memset(recvBuffer, 0x00, sizeof(recvBuffer));
                    nBytes = 0;
                    usleep(100000);
                    while(nBytes < ((int)recvBuffer[0] + 2))
                    {
                        int index = 0;
                        int recvDataLen = 0;
                        if(nBytes != 0)
                            index = nBytes - 1;
                        recvDataLen = read(fdRS232, &recvBuffer[index], 251);
                        if(recvDataLen < 0)
                        {
                            std::cout << "[INFO@DeviceRS232::receiveDecodedData]File read error: " << strerror(errno) << std::endl;
                            //sleep(1);
                        }
                        nBytes += recvDataLen;
                        if(nBytes == ((int)recvBuffer[0] + 2))
                            break;
                    }
                    if(recvBuffer[1] == DECODE_DATA)
                        sendCommandToDecoder(OPCODE_ACK);
                    std::cout << "[INFO @ DeviceRS232::receiveDecodedData]Data Lenght (without CheckSum) : " << (int)recvBuffer[0] << std::endl;
                    for(int i=0; i<nBytes; i++)
                    {
                        std::cout << "recvBuffer[" << i << "]: ";
                        printf("%xn", recvBuffer[i]);
                    }
                    std::cout << "-----------------------------------" << std::endl;
                    //ChangeRTS(fdRS232, 1);
                    //ChangeCTS(fdRS232, 1);
                    //sleep(1);
                }
            }
        }
    }
    free(prwEpollEvent);
    //strcpy((char *)dataBuffer, (char *)recvBuffer);
    memcpy((char *)dataBuffer, recvBuffer, sizeof(recvBuffer)/sizeof(recvBuffer[0]));
    inputBufSize = 0;
    return nBytes;
}

程序在epoll_wait((调用处无限等待。

这可能是由于使用了EPOLLET。参见man epoll电平触发和边缘触发

调用者最终可能会等待一些已经存在的数据在输入缓冲器内。

只需使用

    rwEpollEvent.events = EPOLLIN;

相反。