Android C Select() 性能

问题描述 投票:0回答:1

我用C语言开发了一个串口程序,程序收到相应命令时会发送按键代码。我通过 adb 运行我的程序,它运行完美。但是,如果我使用init.rc来运行我的程序,则无法完全接收uart数据。我怀疑手动执行和init.rc自动调用

select()
函数的运行性能有所不同。我的程序需要在启动时自动执行,所以我必须解决这个问题。

这是我的代码。

main.c

#include "ts_uart_common.h"

int ts_uart_main()
{
    int             i = 0;
    fd_set          readFds;
    int             retval;
    struct timeval  respTime;
    struct timeval setTime;
    struct timespec ts;
    struct tm tm1;
    unsigned char   output_buf[bufsize];
    int             j, error = 0, dev_kb = 0, counter = 0;
    time_t          t1;
    pthread_t       socket_thread, send_thread, watchdog_thread;
    struct timeval  last_receive_time, diff_time;

    /*
     * to handle ctrl +c 
     */
    if( signal(SIGINT, signalHandler) == SIG_ERR) {
        printf("ERROR : Failed to register signal handler\n");
        exit(1);
    }

    if( pthread_create( &socket_thread , NULL ,  socket_receive_handler, (void*) 0) < 0) {
        printf("pthread error\n");
        exit(1);
    }

    timeout = read_ints(TIMEOUT_FILE);
    printf("timeout = %d ms\n", timeout / 1000);

    pthread_mutex_init (&params.mutex , NULL);
    pthread_cond_init (&params.done, NULL);

    size = 0;
    memset(output_buf, 0, bufsize);

    ut.baudrate = 115200;
    ut.flow_cntrl = 0;
    ut.max_delay = 0;
    ut.random_enable = 0;

    ut.fd = open(UART_DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);

    if (ut.fd == -1) {
        exit(1);
    }
    else {
        fcntl(ut.fd, F_SETFL, 0);
    }

    dev_kb = open(DEVICEKEYBOARD, O_RDWR);
    if(dev_kb < 0){
        exit(1);
    }

    printf("Open_port successful, existing port baud=%d\n", getbaud(ut.fd));
    gettimeofday(&last_send_time, NULL);

    tcgetattr(ut.fd, &oldtio);
    initport(ut.fd, ut.baudrate, ut.flow_cntrl);
    while (1) {
        FD_ZERO(&readFds);
        FD_SET(ut.fd, &readFds);
        respTime.tv_sec = 0;
        respTime.tv_usec = timeout;

        retval = select(FD_SETSIZE, &readFds, NULL, NULL, &respTime);

        if (retval == 0) {
            //determine send heartbeat signal or not
            struct timeval now_time, result;
            gettimeofday(&now_time, NULL);
            timeval_subtract(&result, &now_time, &last_send_time);

            if(result.tv_sec > 5) {
                int r = pthread_create( &watchdog_thread , NULL ,  send_watchdog , (void*) NULL);
                gettimeofday(&last_send_time, NULL);
            }
            continue;
        }
        else if (retval == ERROR) {
            printf("select: error :: %d\n", retval);
        }

        if (FD_ISSET(ut.fd, &readFds) != 0) {
            //calculated from the previous command is received
            struct timeval now_time, result;
            gettimeofday(&now_time, NULL);
            timeval_subtract(&result, &now_time, &last_receive_time);
            printf("\n------Start------\n");
            printf("Get Command!!! Diff = %08ld, timeout = %d\n", result.tv_usec, (result.tv_usec > timeout));
            if(result.tv_usec > timeout) {
                //clear the data if the time is over than timeout
                printf("==> Timeout, clean data!!\n");
                size = 0;
                memset(output_buf, 0, bufsize);
            }

            size = readport(&ut.fd, output_buf);
            if (ERROR == size){
                printf("Read Port failed\n");
                close_port();
            }
        }

        //determine whether the instruction to be executed
        for(i = 0; i < size; i++) {
            if(i + 1 < size) {
                if(output_buf[i] == 85 && (output_buf[i + 1] == 128 || output_buf[i + 1] == 130)) {
                    printf("==> Found command!\n");
                    break;
                }
            }
        }
        printf("Length = %d\n", size);

        //we want to run a command
        if(output_buf[i] == 85){
            if(output_buf[i + 1] == 128) {
                //KeyPress command
                if(output_buf[i + 2] == 1) {
                    printf("==>Detect Enter\n");
                    uart_sendevent_keyboard(dev_kb, 1, 28, 1);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);
                    uart_sendevent_keyboard(dev_kb, 1, 28, 0);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0); 
                }
                else if(output_buf[i + 2] == 2) {
                    printf("==>Detect BACK\n");
                    uart_sendevent_keyboard(dev_kb, 1, 158, 1);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);
                    uart_sendevent_keyboard(dev_kb, 1, 158, 0);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);
                }
                else if(output_buf[i + 2] == 3) {
                    printf("==>Detect UP\n");
                    uart_sendevent_keyboard(dev_kb, 1, 103, 1);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);
                    uart_sendevent_keyboard(dev_kb, 1, 103, 0);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);
                }
                else if(output_buf[i + 2] == 4) {
                    printf("==>Detect DOWN\n");
                    uart_sendevent_keyboard(dev_kb, 1, 108, 1);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);
                    uart_sendevent_keyboard(dev_kb, 1, 108, 0);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);                   
                }
                else if(output_buf[i + 2] == 5) {
                    printf("==>Detect LEFT\n");
                    uart_sendevent_keyboard(dev_kb, 1, 105, 1);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);
                    uart_sendevent_keyboard(dev_kb, 1, 105, 0);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0); 
                }
                else if(output_buf[i + 2] == 6) {
                    printf("==>Detect RIGHT\n");
                    uart_sendevent_keyboard(dev_kb, 1, 106, 1);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0);
                    uart_sendevent_keyboard(dev_kb, 1, 106, 0);
                    uart_sendevent_keyboard(dev_kb, 0, 0, 0); 
                }
            }
        }

        //record time
        gettimeofday(&last_receive_time, NULL);

        //if we get commands from uart, send it to the socket
        pthread_create( &send_thread , NULL ,  socket_send_handler , (void*) output_buf);
    }
    FD_CLR(ut.fd, &readFds);

    close_port();

    return 0;
}

void *socket_receive_handler() {
    int len_inet, i;
    struct sockaddr_in adr_clnt;
    unsigned char socket_buf[bufsize], socket_buf_show[bufsize];
    struct sockaddr_in my_addr;
    pthread_t write_thread;
    my_addr.sin_family = AF_INET;
    my_addr.sin_port=htons(10000);
    my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    bzero(&(my_addr.sin_zero), 8);   
    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
        perror("socket");
        exit(1);
    }
    if(bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind error");
        exit(1);
    }

    while(1){
        len_inet = sizeof adr_clnt;
        memset(socket_buf, 0, bufsize);
        udp_receive = recvfrom(sockfd,            // Socket
                         socket_buf,        // Receiving buffer
                         sizeof socket_buf, // Max recv buf size
                         0,            // Flags: no options
                         (struct sockaddr *)&adr_clnt, // Addr
                        &len_inet);  // Addr len, in & out
        if ( udp_receive < 0 ){
            perror("recv");
            exit(1);
        }
        else {
            //write to uart
            strncpy(socket_buf_show, socket_buf, udp_receive);
            pthread_create( &write_thread , NULL , send_uart, (void*) socket_buf_show);

            //print it
            printf("UDP Socket Receive: ");
            for(i = 0; i < udp_receive; i++) {
                printf("0x%x", socket_buf_show[i]);
                if(i != udp_receive - 1) {
                    printf(", ");
                }
            }
            printf("\n");
        }
    }
}

void *socket_send_handler(void* arg) {
    struct sockaddr_in addrDest;
    addrDest.sin_family = AF_INET;
    addrDest.sin_port = htons(10001);
    addrDest.sin_addr.s_addr = inet_addr("127.0.0.1");

    unsigned char *array = (unsigned char*) arg;
    int result = sendto(sockfd, array, size, 0,  (struct sockaddr*)&addrDest, sizeof addrDest);
    printf("Send UDP bytes: %d\n", result);
    printf("------END------\n\n");
    return 0;
}

void *send_uart(void* arg) {
    unsigned char *array = (unsigned char*) arg;
    int new_timeout = array[2];

    //if we get commands from app, send it to the uart
    writeport(&ut.fd, array, udp_receive);
    return 0;
}

void *send_watchdog(void* arg){
    unsigned char command[3] = {0x55, 0xFF, 0x00};
    writeport(&ut.fd, command, 3);
    printf("==>Send heart beat Complete\n");
    return 0;
}



ts_uart_common.c

#include "ts_uart_common.h"

int writeport(int *fd, unsigned char *chars,int len) {
    int lock_result = -1;

    /* Lock.  */
    do{
        lock_result = pthread_mutex_lock(&params.mutex);
    }while(lock_result != 0);

    /* Work.  */
    int n = write(*fd, chars,len);

    /* Unlock and signal completion.  */
    pthread_mutex_unlock(&params.mutex);
    pthread_cond_signal (&params.done);

    if (n < 0) {
        fputs("write failed!\n", stderr);
        return 0;
    }
    return n;
}

int readport(int *fd, unsigned char *result) {
    int iIn=0;
    iIn = read(*fd, result, bufsize);
    tcflush(*fd, TCIFLUSH);
    if (iIn < 0) {
        if (errno == EAGAIN) {
                //printf("SERIAL EAGAIN ERROR\n");
                return 0;
        } else {
              //printf("SERIAL read error %d %s\n", errno, strerror(errno));
                return 0;
        }
    }
        return iIn;
}


int getbaud(int fd) {
        struct termios termAttr;
        int Speed = -1;
        speed_t baudRate;
        tcgetattr(fd, &termAttr);
        /* Get the input speed.                              */
        baudRate = cfgetispeed(&termAttr);
    switch (baudRate) {
            case B300:    Speed = 300; break;
            case B600:    Speed = 600; break;
            case B1200:   Speed = 1200; break;
            case B1800:   Speed = 1800; break;
            case B2400:   Speed = 2400; break;
            case B4800:   Speed = 4800; break;
            case B9600:   Speed = 9600; break;
            case B19200:  Speed = 19200; break;
            case B38400:  Speed = 38400; break;
            case B115200: Speed = 115200; break;
            case B230400: Speed = 230400; break;
            case B460800: Speed = 460800; break;
            case B500000: Speed = 500000; break;
            case B576000: Speed = 576000; break;
            case B921600: Speed = 921600; break;
            case B1000000:Speed = 1000000; break;
            case B1152000:Speed = 1152000; break;
            case B1500000:Speed = 1500000; break;
            case B2000000:Speed = 2000000; break;
            case B2500000:Speed = 2500000; break;
            case B3000000:Speed = 3000000; break;
            case B3500000:Speed = 3500000; break;
    }
    return Speed;
}

int initport(int fd,long baudrate,int flow_ctrl) 
{
    struct termios options;
        memset(&options, 0 , sizeof(options));
        if(ERROR == tcgetattr(fd, &options)) {
                perror("tcgetattr: ");
                return ERROR;
        }

    switch (baudrate) {
        case 300:   cfsetispeed(&options,B300); 
                cfsetospeed(&options,B300);
                options.c_cflag |= B300 | CBAUD;
                break;
        case 600:   cfsetispeed(&options,B600);
                cfsetospeed(&options,B600);
                options.c_cflag |= B600 | CBAUD;
                break;
        case 1200:  cfsetispeed(&options,B1200);
                cfsetospeed(&options,B1200);
                options.c_cflag |= B1200 | CBAUD;
                break;
        case 1800:  cfsetispeed(&options,B1800);
                cfsetospeed(&options,B1800);
                options.c_cflag |= B1800 | CBAUD;
                break;
        case 2400:  cfsetispeed(&options,B2400);
                cfsetospeed(&options,B2400);
                options.c_cflag |= B2400 | CBAUD;
                break;
        case 4800:  cfsetispeed(&options,B4800);
                cfsetospeed(&options,B4800);
                options.c_cflag |= B4800 | CBAUD;
                break;
        case 9600:  
        default:    cfsetispeed(&options,B9600);
                cfsetospeed(&options,B9600);
                options.c_cflag |= B9600 | CBAUD;
                break;
        case 19200: cfsetispeed(&options,B19200);
                cfsetospeed(&options,B19200);
                options.c_cflag |= B19200 | CBAUD;
                break;
        case 38400: cfsetispeed(&options,B38400);
                cfsetospeed(&options,B38400);
                options.c_cflag |= B38400 | CBAUD;
                break;
        case 115200:    cfsetispeed(&options,B115200);
                cfsetospeed(&options,B115200);
                options.c_cflag |= B115200 | CBAUDEX;
                break;
        case 230400:    cfsetispeed(&options,B230400);
                cfsetospeed(&options,B230400);
                options.c_cflag |= B230400 | CBAUDEX;
                break;
        case 460800:    cfsetispeed(&options,B460800);
                cfsetospeed(&options,B460800);
                options.c_cflag |= B460800 | CBAUDEX;
                break;
        case 500000:    cfsetispeed(&options,B500000);
                cfsetospeed(&options,B500000);
                options.c_cflag |= B500000 | CBAUDEX;
                break;
        case 576000:    cfsetispeed(&options,B576000);
                cfsetospeed(&options,B576000);
                options.c_cflag |= B576000 | CBAUDEX;
                break;
        case 921600:    cfsetispeed(&options,B921600);
                cfsetospeed(&options,B921600);
                options.c_cflag |= B921600 | CBAUDEX;
                break;
        case 1000000:   cfsetispeed(&options,B1000000);
                cfsetospeed(&options,B1000000);
                options.c_cflag |= B1000000 | CBAUDEX;
                break;
        case 1152000:   cfsetispeed(&options,B1152000);
                cfsetospeed(&options,B1152000);
                options.c_cflag |= B1152000 | CBAUDEX;
                break;
        case 1500000:   cfsetispeed(&options,B1500000);
                cfsetospeed(&options,B1500000);
                options.c_cflag |= B1500000 | CBAUDEX;
                break;
        case 2000000:   cfsetispeed(&options,B2000000);
                cfsetospeed(&options,B2000000);
                options.c_cflag |= B2000000 | CBAUDEX;
                break;
        case 2500000:   cfsetispeed(&options,B2500000);
                cfsetospeed(&options,B2500000);
                options.c_cflag |= B2500000 | CBAUDEX;
                break;
        case 3000000:   cfsetispeed(&options,B3000000);
                cfsetospeed(&options,B3000000);
                options.c_cflag |= B3000000 | CBAUDEX;
                break;
        case 3500000:   cfsetispeed(&options,B3500000);
                cfsetospeed(&options,B3500000);
                options.c_cflag |= B3500000 | CBAUDEX;
                break;
    }

    /* Enable or Disable Hardware flow control. */
    if(!flow_ctrl) {
        options.c_cflag &= ~CRTSCTS;
        //printf("Flow control disabled \n");
    }
    else {
        options.c_cflag |= CRTSCTS;
        //printf("Flow control enabled \n");
    }

        /* No Parity, 8N1. */
        options.c_cflag &= ~PARENB; // No parity bit
        options.c_cflag &= ~CSTOPB; // 1 stop bit
        options.c_cflag &= ~CSIZE;  // character size 8
        options.c_cflag |=  CS8 ;

        /* Hardware Control Options - Set local mode and Enable receiver to receive characters */
        options.c_cflag     |= (CLOCAL | CREAD );

        /* Terminal Control options */
        /* - Disable signals. Disable canonical input processing. Disable echo. */
        options.c_lflag     &= ~(ICANON | IEXTEN | ECHO | ISIG); /* Line options - Raw input */

        options.c_iflag     &= ~(ICRNL | INPCK | ISTRIP | BRKINT | IXON | IXOFF | IXANY);
        /* Output processing - Disable post processing of output. */
        options.c_oflag     &= ~OPOST;      /* Output options - Raw output */
        /* Control Characters - Min. no. of characters */
        options.c_cc[VMIN]  = 0;
        /* Character/Packet timeouts. */
        options.c_cc[VTIME] = 3;

    if(ERROR == tcflush(fd,TCOFLUSH) ) {
                  //printf("tcflush failed");
                  return ERROR;
        }

    if(ERROR == tcsetattr(fd, TCSANOW, &options))  {
                //printf("Error: Couldn't configure Serial port " );
                return ERROR;
        }

/*
    //printf("\n\n");
    system("stty -F /dev/ttyS0 -a");
    //printf("\n\n"); 
*/
    return SUCCESS;
}


void signalHandler()
{
    //printf("\n Closing device %s\n",UART_DEV_NAME);
    close_port();
}

void close_port()
{
    /* Destroy all synchronization primitives.  */    
    pthread_mutex_destroy (&params.mutex);
    pthread_cond_destroy (&params.done);

    tcsetattr(ut.fd, TCSANOW, &oldtio);
    if(tx_rx == 'r')
        close(fd2);
    else
     close(fd1);

    close(ut.fd);
    exit(1);
}

int uart_sendevent_keyboard(int dev_kb, int type, int code, int value) {
    int i;
    int fd;
    int ret;
    int version;
    struct input_event event;

    if (ioctl(dev_kb, EVIOCGVERSION, &version)) {
        return 1;
    }
    memset(&event, 0, sizeof(event));
    event.type = type;
    event.code = code;
    event.value = value;
    ret = write(dev_kb, &event, sizeof(event));
    if(ret < sizeof(event)) {
        return -1;
    }

    return 0;
}

 int timeval_subtract (struct timeval * result, struct timeval * x, struct timeval * y) {
   /* Perform the carry for the later subtraction by updating y. */
   if (x->tv_usec < y->tv_usec) {
     int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
     y->tv_usec -= 1000000 * nsec;
     y->tv_sec += nsec;
   }
   if (x->tv_usec - y->tv_usec > 1000000) {
     int nsec = (x->tv_usec - y->tv_usec) / 1000000;
     y->tv_usec += 1000000 * nsec;
     y->tv_sec -= nsec;
   }

   /* Compute the time remaining to wait.
      tv_usec is certainly positive. */
   result->tv_sec = x->tv_sec - y->tv_sec;
   result->tv_usec = x->tv_usec - y->tv_usec;

   /* Return 1 if result is negative. */
   return x->tv_sec < y->tv_sec;
 }

 int read_ints (const char* file_name) {
     int i = 50;
     if( access( file_name, F_OK ) == 0 ) {
       FILE* file = fopen (file_name, "r");
       fscanf (file, "%d", &i);    
       while (!feof (file)) {
         fscanf (file, "%d", &i);      
       }
       fclose (file);
    }

    return i * 1000;  
}

 void write_ints (const char* file_name, int value) {
    FILE* file = fopen (file_name, "w+");
    fprintf(file, "%d", value);
    fclose (file);
}
android c posix-select
1个回答
0
投票

我解决了这个问题。

在main.c中添加usleep(10 * 10000);。

while (1) {
    FD_ZERO(&readFds);
    FD_SET(ut.fd, &readFds);
    respTime.tv_sec = 0;
    respTime.tv_usec = timeout;

    retval = select(FD_SETSIZE, &readFds, NULL, NULL, &respTime);

    if (retval == 0) {
        //determine send heartbeat signal or not
        struct timeval now_time, result;
        gettimeofday(&now_time, NULL);
        timeval_subtract(&result, &now_time, &last_send_time);

        if(result.tv_sec > 5) {
            int r = pthread_create( &watchdog_thread , NULL ,  send_watchdog , (void*) NULL);
            gettimeofday(&last_send_time, NULL);
        }
        continue;
    }
    else if (retval == ERROR) {
        printf("select: error :: %d\n", retval);
    }
    usleep(10 * 10000);

    ...
    ...
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.