select, FD_ISSET, read 등을 사용하여 ttyUSB 포트에서 읽는 일부 Linux C 코드에 문제가 있습니다. 모뎀에서 FTDI 직렬 직렬 USB 케이블을 입력으로 사용합니다. 문제는 USB 케이블이 뽑혀있을 때 선택 해제를 해제하는 것입니다. 그것을 막을 수있는 방법이 있습니까?왜 USB 케이블이 연결되지 않았습니까?
count = 0;
while (g_running) {
FD_ZERO(&readFdSet);
maxfd = 0;
numTransPorts = 0;
logger(DEBUG, "Begin g_running loop - %d", count);
for (i = 0; i < MAX_CONFIG_PORTS; i++) {
if (configPorts[i].commType == 1 && configPorts[i].pttyHost != NULL) {
FD_SET(configPorts[i].pttyHost->fd, &readFdSet);
logger(DEBUG, "FD_SET - fd=%d, index=%d", configPorts[i].pttyHost->fd, i);
if (configPorts[i].pttyHost->fd >= maxfd) {
maxfd = configPorts[i].pttyHost->fd;
}
numTransPorts++;
}
}
maxfd++; // add one because select check a range to n-1 file descriptors
if (maxfd != 0) { // indicates no ports are available
logger(DEBUG, "Calling select() with %d ports and maxfd of %d", numTransPorts, maxfd);
logger(INFO, "Waiting for input ...");
select(maxfd, &readFdSet, NULL, NULL, NULL); // blocking until one available
if(result == -1){
logger(INFO, "select() error. errno: %d", errno);
} else if (result > 0){
for (i = 0; i < MAX_CONFIG_PORTS; i++) {
if (FD_ISSET(configPorts[i].pttyHost->fd, &readFdSet)) { // input is available
logger(INFO, "Input on port %s", configPorts[i].pttyHost->serialPath);
result = serialPortRead(buffer, configPorts[i].pttyHost->fd);
if (result <= 0) {
// there was an error due to the file descriptor. It
// probably indicates that the tty ports are no longer available
}
}
}
} else {
logger (INFO, "select() returns 0");
}
}
count++;
}
serialPortRead : USB 케이블 연결이 해제되면
int serialPortRead(char *buf, int serialHandle) {
//char ch;
char *ptr;
int res = 0;
int bytesRead = 0;
int i;
logger(TRACE, "TRACE: serialPortRead() with fd = %d", serialHandle);
ptr = buf;
// try 3 times
for (i = 0; i < 3; i++) {
while ((res = read(serialHandle, ptr, 1)) > 0) { // read 1 byte at a time
if (*ptr == 0x0d) { //there is 0x0d as a terminate byte from ECR
break;
}
ptr += res;
}
if (res < 0 && errno == EAGAIN) {
continue;
} else {
break;
}
}
*ptr = 0x00; // set 0x00 as a terminate byte
// pthread_mutex_unlock(&g_serial_trans_mutex);
if (res < 0) {
// if res is -1, there is an error
bytesRead = -1;
logger(DEBUG, "serialPortRead error. errno = %d", errno);
} else {
bytesRead = (int) (ptr - buf);
logger(DEBUG, "serialPortRead %d bytes", bytesRead);
}
return bytesRead;
}
는, 선택() 차단을 해제, 입력을 의미하는 것은 FD_ISSET가 true를 반환 할 수 있습니다. serialPortRead의 read()는 읽은 0 바이트를 반환합니다. 그런 다음 입력을 사용할 수 있음을 다시 차단 해제하는 select()로 돌아갑니다. 따라서 select(), FD_ISSET이 true를 반환하고 fd가 지워지지 않고 read가 0을 반환하는 등의 무한 루프가 발생합니다. 이 문제를 어떻게 해결할 수 있습니까? 예상 할 수있는 동작은 실제로 읽을 내용이 없을 때 select가 잘못 차단되지 않는다는 것입니다.
참고 : 선택을 해제한다 때 읽을 수있는 정보가 있기 때문에
선택 반환은 '입력 가능'이라는 의미입니까? afaik 그것은 또한 '오류가 있습니다'를 의미 할 수 있습니다. 정확하게 여기에있는 경우입니다. – stijn
read가 0을 반환 할 때, 더 읽을 것이 아무것도 없기 때문에, 당신은 당신이 선택하고있는 세트에서 fd를 가져와야합니다. 오류가 발생하면 오류가 사용자에게 전달 될 수 있습니다. 오류에 대한 정보를 얻은 후에는 fd를 닫고 선택 및 읽기를 계속하기보다는 선택을 중지해야합니다. –
내가 바라는 행동은 그것이 작동하는 방식이 아니라는 것입니다. 앱이 시작되면 USB 장치가 꽂혀 있고 입력을 위해 열립니다. 우연히 플러그를 뽑지 않으면 구성이 변경되어서는 안됩니다. 나는 단지 아무 것도하지 않기를 바랄뿐입니다. 그런 다음 케이블을 다시 꽂으면 방해받지 않고 입력을받을 수 있습니다. – Jim