我在使用select,FD_ISSET,讀取等從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:
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;
}
當USB電纜被拔掉,select()的解除阻塞,這意味着輸入是可用的,FD_ISSET返回true。在serialPortRead中,read()將返回零字節。然後它返回到select(),它再次解除阻塞,說明輸入可用,依此類推。因此,你得到一個無限循環的select(),FD_ISSET返回true,fd永遠不會被清除,讀取返回0等等。我怎樣才能解決這個問題?我期望的行爲是,當沒有真正需要閱讀的內容時,select不會錯誤地解鎖?
注:當選擇放開它返回一個正數
你確定選擇返回手段'輸入可用'嗎? afaik它也可能意味着'有錯誤',這正是這種情況。 – stijn
當讀取返回0時,沒有更多需要閱讀的內容,因此您必須將fd從您選擇的集合中取出。發生錯誤時,您有機會將錯誤傳遞給您;一旦你被告知錯誤,你必須關閉fd並停止選擇它,而不是試圖繼續選擇和閱讀。 –
我想我所希望的行爲不僅僅是它的工作方式。當應用程序啓動時,它會查看插入的USB設備並將其打開以供輸入。除非偶然拔掉插頭,否則配置不應改變。我希望它不做任何事情。然後,當電纜再次插入時,可以在沒有中斷的情況下接收輸入。 – Jim