首页 文章

linux串口:读取被阻塞模式

提问于
浏览
0

我的目标是为串行端口设置2个线程:一个用于读取,一个用于写入 .

我的例子是大量引用[one](//引用how to open, read, and write from serial port in C),但我在代码中添加了pthread:

//refer to https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
    //refer to https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>

    #include <unistd.h>
    #include <fcntl.h>
    #include <termios.h>

    #include <pthread.h>    /* POSIX Threads */

    #define MAX_STR_LEN                         256

    /*
     * The values for speed are 
     * B115200, B230400, B9600, B19200, B38400, B57600, B1200, B2400, B4800, etc
     * 
     *  The values for parity are 0 (meaning no parity), 
     * PARENB|PARODD (enable parity and use odd), 
     * PARENB (enable parity and use even), 
     * PARENB|PARODD|CMSPAR (mark parity), 
     * and PARENB|CMSPAR (space parity).
     * */


    int SetInterfaceAttribs(int fd, int speed, int parity)
    {
            struct termios tty;
            memset (&tty, 0, sizeof tty);
            if (tcgetattr (fd, &tty) != 0) /* save current serial port settings */
            {
                printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
                return -1;
            }

            cfsetospeed (&tty, speed);
            cfsetispeed (&tty, speed);

            tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
            // disable IGNBRK for mismatched speed tests; otherwise receive break
            // as \000 chars
            tty.c_iflag &= ~IGNBRK;         // disable break processing
            tty.c_lflag = 0;                // no signaling chars, no echo,
                                            // no canonical processing
            tty.c_oflag = 0;                // no remapping, no delays
            tty.c_cc[VMIN]  = 0;            // read doesn't block
            tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

            tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

            tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                            // enable reading
            tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
            tty.c_cflag |= parity;
            tty.c_cflag &= ~CSTOPB;
            tty.c_cflag &= ~CRTSCTS;

            if (tcsetattr (fd, TCSANOW, &tty) != 0)
            {
                    printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
                    return -1;
            }
            return 0;
    }/*set_interface_attribs*/


    void SetBlocking(int fd, int should_block)
    {
            struct termios tty;
            memset (&tty, 0, sizeof tty);
            if (tcgetattr(fd, &tty) != 0)
            {
                    printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
                    return;
            }

            tty.c_cc[VMIN]  = should_block ? 1 : 0;
            tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

            if (tcsetattr (fd, TCSANOW, &tty) != 0)
                     printf("__LINE__ = %d, error %s\n", __LINE__, strerror(errno));
    }/*SetBlocking*/


    void *sendThread(void *parameters)
    {
        char sendBuff[MAX_STR_LEN];

        memset(&sendBuff[0], 0, MAX_STR_LEN);
        snprintf(&sendBuff[0], MAX_STR_LEN, "hello!");

        int fd;

        fd = *((int*)parameters);

        while(1)
        {
            write(fd, &sendBuff[0], strlen(&sendBuff[0]) ); 

            // sleep enough to transmit the length plus receive 25:  
            // approx 100 uS per char transmit
            usleep((strlen(&sendBuff[0]) + 25) * 100);             
        }/*while*/

        pthread_exit(0); 
    }/*sendThread */


    void *readThread(void *parameters)
    {
        char readBuff[MAX_STR_LEN];


        int fd;

        fd = *((int*)parameters);

        while(1)
        {
            ssize_t len;

            memset(&readBuff[0], 0, MAX_STR_LEN);

            len = read(fd, &readBuff[0], MAX_STR_LEN); 

            if (len == -1)
            { 
                switch(errno) 
                {
                    case EAGAIN:
                    printf("__FUNCTION__ = %s, __LINE__ = %d\n", __FUNCTION__, __LINE__);
                    usleep(5*1000); 
                    continue;
                    break;

                    default:
                    printf("__FUNCTION__ = %s, __LINE__ = %d\n", __FUNCTION__, __LINE__);
                        pthread_exit(0); 
                    break;      
                }
            }
            // sleep enough to transmit the length plus receive 25:  
            // approx 100 uS per char transmit
            usleep((len + 25) * 100);
            printf("len = %d\n", (int)len);

            int i;

            for(i = 0; i< len; i++)
                printf("%c(%d %#x)\t", readBuff[i], readBuff[i], readBuff[i]);

            printf("\n");               
        }/*while*/

        pthread_exit(0); 
    }/*readThread */


    int main(int argc, char *argv[])
    {
        int fd, c, res;
        struct termios oldtio,newtio;
        char buf[MAX_STR_LEN];
        int k;
        char deviceName[MAX_STR_LEN];

        memset(&deviceName[0], 0, MAX_STR_LEN);
        snprintf(&deviceName[0], MAX_STR_LEN, "/dev/ttyUSB0");

        k = 1;
        while(argc > k)
        {   
            if(0 == strncmp(argv[k], "-d", MAX_STR_LEN))
            {
                    if(k + 1 < argc)
                    {
                        snprintf(&deviceName[0], MAX_STR_LEN, "%s", argv[k + 1]);
                    }
                    else
                    {
                        printf("error : -d should be follow a device!\n");      
                        return 0;
                    }/*if */
            }
            k++;    
        }/*while k*/

        printf("__FUNCTION__ = %s, __LINE__ = %d\n", __FUNCTION__, __LINE__);


        fd = open(&deviceName[0], O_RDWR | O_NOCTTY |O_NONBLOCK| O_NDELAY); 
        if(0 > fd) 
        {
            perror(&deviceName[0]); 
            exit(-1); 
        }/*if */


        SetInterfaceAttribs(fd, B115200, 0); /* set speed to 115,200 bps, 8n1 (no parity)*/
        SetBlocking(fd, 1); 

        pthread_t readThread_t, sendThread_t;  /* thread variables */

        pthread_create(&sendThread_t, NULL, (void *)sendThread, (void *)&fd);
        pthread_create(&readThread_t, NULL, (void *)readThread, (void *)&fd);

        pthread_join(sendThread_t, NULL);
        pthread_join(readThread_t, NULL);

        close(fd);


        return 0;
    }/*main*/

发送数据线程运行良好 .

但读取数据线程:我无法将其设置为阻塞,读取函数立即返回,即使读取数据长度为零 .

我该如何修改代码以阻止读取功能?

1 回答

  • 1

    fd = open(&deviceName [0],O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);

    尝试从公开呼叫中删除O_NONBLOCK和O_NDELAY . 或者,即使您特别希望它阻止,您是否有特殊原因?

相关问题