Неблокирующий код в Unix
Как дать вход неблокирующему коду в unix? Код выглядит следующим образом:
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
void set_fl(int fd, int flags);
char buf[10];
int main()
{
int noread;
set_fl(STDIN_FILENO, O_NONBLOCK); //code for nonblocking
set_fl(0, O_NONBLOCK); //code for nonblocking
noread = read(0, buf, sizeof(buf));
printf("INPUT: %s\n", buf);
return 0;
}
void set_fl(int fd, int flags)
{
int val;
if ((val = fcntl(fd, F_GETFL, 0)) < 0)
printf("ERROR: %s\n", "fcntl F_GETFL error");
val |= flags; //changes the bit
if (fcntl(fd, F_SETFL, val) < 0)
printf("ERROR: %s\n", "fcntl F_SETFL error");
}
1 ответ
Вы можете использовать select(), чтобы определить, когда STDIN_FILENO имеет больше байтов для чтения, например так:
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
void set_fl(int fd, int flags);
char fullBuf[1024] = ""; // initialized to an empty string, so we can strncat() to it below
int main()
{
set_fl(STDIN_FILENO, O_NONBLOCK); //code for nonblocking
while(1)
{
fd_set inFDs;
FD_SET(STDIN_FILENO, &inFDs);
int maxFD = STDIN_FILENO; /* set this to the maximum of all fd's in the inFDs set */
if (select(maxFD+1, &inFDs, NULL, NULL, NULL) >= 0) /* select() won't return the user has entered a line of text */
{
char buf[128];
memset(buf, 0, sizeof(buf));
int noread = read(0, buf, sizeof(buf));
if (noread < 0)
{
printf("Error reading from stdin!\n");
break;
}
printf("read %i bytes\n", noread);
strncat(fullBuf, buf, sizeof(fullBuf)-strlen(fullBuf)-1);
if ((strchr(buf, '\n'))||(strchr(buf, '\r'))) break; /** We'll stop gathering input after one line */
}
}
printf("INPUT: %s\n", fullBuf);
return 0;
}
void set_fl(int fd, int flags)
{
int val;
if ((val = fcntl(fd, F_GETFL, 0)) < 0)
printf("ERROR: %s\n", "fcntl F_GETFL error");
val |= flags; //changes the bit
if (fcntl(fd, F_SETFL, val) < 0)
printf("ERROR: %s\n", "fcntl F_SETFL error");
}
Обратите внимание, что это сложнее, чем простое использование блокирующего чтения, но выполнение этого способа имеет преимущество в том, что вы можете передать указатель на не-NULL временную структуру в качестве последнего аргумента select() для реализации тайм-аута.