qt 使用select监听串口时主线程被阻塞

在QT中,另起一个线程读串口,使用select监听的,可是为什么主线程也被阻塞了呢?
代码如下:

thread.h

 #ifndef DISTANCE_SERIAL_PORT_H
#define DISTANCE_SERIAL_PORT_H

#include <QtCore/QThread>

class Distance_serial_port : public QThread
{
    Q_OBJECT
public:
    explicit Distance_serial_port(QObject *parent = 0);
    void run();
    void run_once();
    void setTermios(struct termios * pNewtio, int uBaudRate);
    void gps_uart_init(int ttyFd,struct termios *oldtio,struct termios *newtio);

};

#endif // DISTANCE_SERIAL_PORT_H

thread.cpp

 #include "distance_serial_port.h"
#include <sys/time.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <iostream>
#include <termios.h>

#define BUF_LENGTH 6
#define DEV_NAME "/dev/tty"

Distance_serial_port::Distance_serial_port(QObject *parent) :
    QThread()
{}
class CLASS_JULI{
   public:
    CLASS_JULI(int f = -1):fd(f){ }
      ~CLASS_JULI()
      {
        close(fd);
      }
      int fd;
};
CLASS_JULI dis_port_fds;
void Distance_serial_port::run(){

    while(1)
    {
       try{
          run_once();
       }
        catch(...){
          std::cerr<<"distance serial port  run throw exception!"<<std::endl;
       }

       sleep(1);
    }
}
void Distance_serial_port::run_once()
{
    int ret = 0,i;
    unsigned char buf_read[BUF_LENGTH];
    fd_set readfd;
    struct timeval timeout;
    struct termios oldtio, newtio;
    dis_port_fds.fd= open(DEV_NAME,O_RDONLY | O_NONBLOCK);

    if ((dis_port_fds.fd = open(DEV_NAME, O_RDONLY |  O_NONBLOCK)) <= 0) {
           std::cout<<" open "<<DEV_NAME<<" faurel!\n"<<std::endl;
           return ;
    }
    else
    {
        std::cout<<" open "<<DEV_NAME<<" faurel!\n"<<std::endl;
    }
    gps_uart_init(dis_port_fds.fd,&oldtio,&newtio);
    assert(dis_port_fds.fd>0);
    while(1)
    {
        timeout.tv_sec=1;
        timeout.tv_usec=0;
        FD_ZERO(&readfd);
        FD_SET(dis_port_fds.fd,&readfd);
        ///监控函数
        ret=select(dis_port_fds.fd+1,&readfd,NULL,NULL,&timeout);

        if(ret == -1) //错误情况
        {
            std::cout<<"error"<<std::endl ;
        }
        else if(ret>0) //返回值大于0 有数据到来
        {

            if(FD_ISSET(dis_port_fds.fd,&readfd))
            {
                i=read(dis_port_fds.fd,buf_read,BUF_LENGTH);
                std::cout<<"----------------------------------------"<<std::endl;
                int m = 0;
                for(m = 0; m < BUF_LENGTH ; m++)
                {
                    std::cout<<buf_read[m]<<" "<<std::endl;
                }

                if(buf_read[0] == 'D')
                {
                    char _buf = buf_read[1];
                     //QBitArray ba(8);
                    if( (_buf&0x80) == 1 )
                    {

                    }
                    else
                    {

                    }
                }
                break;
            }
            else //超时情况
            {
                std::cout<<"time out"<<std::endl;
                continue;
            }
        }
        else
        {
        }

    }

}

void Distance_serial_port::setTermios(struct termios * pNewtio, int uBaudRate)
{
    /*
     *clear struct for new port settings
     */
    bzero(pNewtio, sizeof(struct termios));
    //8N1
    pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;
    pNewtio->c_iflag = IGNPAR;
    pNewtio->c_oflag = 0;
    pNewtio->c_lflag = 0; //non ICANON
}

/*
 *设置串口的波特率9600,并刷新使其立即生效
 */
void Distance_serial_port::gps_uart_init(int ttyFd,struct termios *oldtio,struct termios *newtio)
{
        tcgetattr(ttyFd, oldtio); /* save current serial port settings */
        setTermios(newtio, B115200);
        tcflush(ttyFd, TCIFLUSH);
        tcsetattr(ttyFd, TCSANOW, newtio);
}

调用方法

 dis_serial_prot = new Distance_serial_port();
    dis_serial_prot->run();

为什么呢?难道在QT中不能使用select?

3个回答

晕,你写的类继承了QThread,创建对象后,run函数不是你调用的,是线程启动后自动调用的,你应调用start函数启动线程。你现在的代码写好了线程,但根本没用上多线程

opt.c_cc[VMIN] = 0 //最小时间设置为0
136 opt.c_cc[VTIME] = 1;//最小字节设置为1

llx2007
凌云志轩 回复凌云志轩: 2.TIME和MIN值 这两个值只用于非标准模式,两者结合共同控制对输入的读取方式,还能控制在一个程序试图与一个终端关联的文件描述符时将发生的情况 MIN = 0, TIME = 0时:read立即返回,如果有待处理的字符,它们就会被返回,如果没有,read调用返回0,且不读取任何字符 MIN = 0, TIME > 0时:有字符处理或经过TIME个0.1秒后返回 MIN > 0, TIME = 0时:read一直等待,直到有MIN个字符可以读取,返回值是字符的数量.到达文件尾时返回0 MIN > 0, TIME > 0时:read调用时,它会等待接收一个字符.在接收到第一个字符及其后续的每个字符后,启用一个字符间隔定时器.当有MIN个字符可读或两字符间的时间间隔超进TIME个0.1秒时,read返回 通过设置MIN和TIME值,我们可以逐个字符地对输入进行处理
接近 2 年之前 回复
llx2007
凌云志轩 额,写反了,应该是opt.c_cc[VTIME] = 0 //最小时间设置为0 ; opt.c_cc[VMIN] = 1;//最小字节设置为1
接近 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!