本文介绍了如何避免从读取功能阻塞?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从 cygwin 命令中心的 USB 端口写入和读取数据.我已经设法在设备连接时写入和读取数据,但我想要一种方法来检测其他设备是否不存在或无法发回任何数据.我当前的测试代码如下所示(我尝试了很多不同的东西,但似乎没有任何效果).

I am trying to write and read data from an USB port in a cygwin command central. I have managed to write and read data when the device is connected but I want a way to detect if the other device isn't present or is unable ta send back any data. My current test code is shown below(I have tried a bunch of different things but nothing seemed to work).

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <stdio.h>
#include "USB_com.h"
#include "unistd.h"
void main()
{
  int fd, value, bytes_read, bytes_written, nbytes, i, j;
  char buffR[20];
  char buffS[20];
  fd = USB_init("/dev/com1");
  printf("enter a message (write exit to terminate the session): ");
  fgets(buffS, 19, stdin);
  while (strncmp("exit", buffS, 4) != 0)
  {
    bytes_written = write(fd, buffS, 19);
    sleep(1);
    bytes_read = read(fd, buffR, 19);
    printf("string recieved : %s\n", buffR);
    memset(buffS, '\0', 19);
    printf("enter a message (write exit to terminate the session): ");
    fgets(buffS, 19, stdin);
  }
  USB_cleanup(fd);
}

我的 USB_init.c 用于从 USB 设备写入和读取如下所示.

And my USB_init.c for writing and reading from the USB device is shown below.

#include "USB_init.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>


/* baudrate settings are defined in <asm/termbits.h>, which is
 * included by <termios.h> */
#ifndef BAUDRATE
#define BAUDRATE B9600
#endif

#define _POSIX_SOURCE 1     /* POSIX compliant source */

static int fd, c, res;
static struct termios oldtio, newtio;
static char *device;

int USB_init(char *modemdevice)
{
    /* 
     * Open modem device for reading and writing and not as controlling tty
     * because we don't want to get killed if linenoise sends CTRL-C.
     **/
    device = modemdevice;
    //fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY);
    fd = open (device, O_RDWR | O_NOCTTY );
    if (fd < 0)
      {
      perror (device);
      exit(-1);
      }

    tcgetattr (fd, &oldtio);    /* save current serial port settings */
    bzero (&newtio, sizeof (newtio));   /* clear struct for new port settings */

    /* 
     *BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
     *CRTSCTS : output hardware flow control (only used if the cable has
     *all necessary lines. )
     *CS8     : 8n1 (8bit,no parity,1 stopbit)
     *CLOCAL  : local connection, no modem contol
     *CREAD   : enable receiving characters
     **/
    newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;

    /*
     *IGNPAR  : ignore bytes with parity errors
     *ICRNL   : map CR to NL (otherwise a CR input on the other computer
     *          will not terminate input)
     *          otherwise make device raw (no other input processing)
     **/
    newtio.c_iflag = IGNPAR | ICRNL;

    /*
     * Map NL to CR NL in output.
     *                  */
#if 0
    newtio.c_oflag = ONLCR;
#else
    newtio.c_oflag = 0;
#endif


    /*
     * ICANON  : enable canonical input
     *           disable all echo functionality, and don't send signals to calling program
     **/
#if 1
    newtio.c_lflag = ICANON;
#else
    newtio.c_lflag = 0;
#endif

    /* 
     * initialize all control characters 
     * default values can be found in /usr/include/termios.h, and are given
     * in the comments, but we don't need them here
     *                                       */
    newtio.c_cc[VINTR] = 0; /* Ctrl-c */
    newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */
    newtio.c_cc[VERASE] = 0;    /* del */
    newtio.c_cc[VKILL] = 0; /* @ */
    newtio.c_cc[VEOF] = 4;  /* Ctrl-d */
    newtio.c_cc[VTIME] = 0; /* inter-character timer unused*/
    newtio.c_cc[VMIN] = 1;  /* blocking read until 1 character arrives*/
    newtio.c_cc[VSWTC] = 0; /* '\0' */
    newtio.c_cc[VSTART] = 0;    /* Ctrl-q */
    newtio.c_cc[VSTOP] = 0; /* Ctrl-s */
    newtio.c_cc[VSUSP] = 0; /* Ctrl-z */
    newtio.c_cc[VEOL] = 0;  /* '\0' */
    newtio.c_cc[VREPRINT] = 0;  /* Ctrl-r */
    newtio.c_cc[VDISCARD] = 0;  /* Ctrl-u */
    newtio.c_cc[VWERASE] = 0;   /* Ctrl-w */
    newtio.c_cc[VLNEXT] = 0;    /* Ctrl-v */
    newtio.c_cc[VEOL2] = 0; /* '\0' */

    /* 
     * now clean the modem line and activate the settings for the port
     **/
    tcflush (fd, TCIFLUSH);
    tcsetattr (fd, TCSANOW, &newtio);

    /*
     * terminal settings done, return file descriptor
     **/

    return fd;
}

void USB_cleanup(int ifd){
    if(ifd != fd) {
        fprintf(stderr, "WARNING! file descriptor != the one returned by serial_init()\n");
    }
    /* restore the old port settings */
    tcsetattr (ifd, TCSANOW, &oldtio);
}

有人能告诉我如何做类似 read(fd,buffR,19) 的事情,但如果我没有收到任何数据并打印类似的东西,在一段时间后中止它printf("没有与设备接触")?

Can someone tell me how I can do something like read(fd,buffR,19) but abort it after some time if I haven't recieved any data and print something likeprintf("no contact with the device")?

我非常感谢您提供有关如何解决此问题的任何建议!

I am extremely thankful for any suggestions on how to solve this!

推荐答案

处理连续剧时,您有两个选择:要么使用 select/poll 超时,要么使用 termios 配置端口.

When working with serials, you have two options: either use select/poll with timeout, or configure the port using termios.

对于selectpoll,方法是先等待描述符上的事件,然后读取 成功的结果.这种方法的优点是它也适用于网络套接字和其他一些描述符类型:

For select and poll, the approach is first wait for event on descriptor and read after successful result. Pro of this method is that it works also with network sockets and some other descriptor types:

int fd = ...
fd_set fds;
stuct timeval timeout;

timeout.tv_sec = 10; /* timeout in secs */
timeout.tv_usec = 0;
FD_ZERO(&fds)
FD_SET(fd, &fds)
if (select(fd, fds, NULL, NULL, &timeout) > 0)
  read(...)
else ... timeout

poll 示例与上面的非常相似.

The poll example is very similar to above.

但是,在使用任何类型的串行设备时,还有另一种方法可以使读取正确超时.您需要使用 VMINVTIME 属性:

But, when working with any kind of serial devices, there is another way of making read to time out correctly. You need to use VMIN and VTIME attributes:

newtio.c_cc[VTIME] = timeout; /* timeout in 1/10 of second  1==100ms, 10==1sec*/
newtio.c_cc[VMIN] = 0;

就是这样.

这篇关于如何避免从读取功能阻塞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 14:19