【问题标题】:Nonblocking code in UnixUnix 中的非阻塞代码
【发布时间】:2015-04-28 04:31:52
【问题描述】:

如何在 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");
}

【问题讨论】:

  • 你的问题是?

标签: c linux system


【解决方案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 timeval 结构的指针作为 select() 的最后一个参数传递,以实现超时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    • 1970-01-01
    • 2016-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    相关资源
    最近更新 更多