Неблокирующий код в 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() для реализации тайм-аута.

Другие вопросы по тегам