MST

星途 面试题库

面试题:C语言中Linux非阻塞I/O常见错误类型及处理

在Linux环境下使用C语言进行非阻塞I/O操作时,经常会遇到哪些错误?请列举至少三种,并说明如何使用`errno`进行相应的错误处理。
33.8万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

以下是在Linux环境下使用C语言进行非阻塞I/O操作时可能遇到的错误及基于errno的错误处理:

  1. EAGAINEWOULDBLOCK
    • 含义:资源暂时不可用,例如在非阻塞模式下读取套接字,而此时没有数据可读。
    • 处理方式:在循环中等待一段时间后重试操作。示例代码如下:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#define BUFFER_SIZE 1024

int main() {
    int fd = open("test.txt", O_RDONLY | O_NONBLOCK);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    char buffer[BUFFER_SIZE];
    ssize_t bytesRead = read(fd, buffer, BUFFER_SIZE);
    if (bytesRead == -1) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            // 等待一段时间后重试
            sleep(1); 
            bytesRead = read(fd, buffer, BUFFER_SIZE);
            if (bytesRead == -1) {
                perror("read after retry");
                close(fd);
                return 1;
            }
        } else {
            perror("read");
            close(fd);
            return 1;
        }
    }

    close(fd);
    return 0;
}
  1. EBADF
    • 含义:文件描述符无效。可能是因为文件描述符没有被正确打开,或者已经被关闭。
    • 处理方式:检查文件描述符的获取过程,确保在使用前正确打开且未被意外关闭。例如:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main() {
    int fd = -1; // 无效的文件描述符
    ssize_t bytesRead = read(fd, NULL, 0);
    if (bytesRead == -1) {
        if (errno == EBADF) {
            printf("文件描述符无效,可能未正确打开或已关闭\n");
        } else {
            perror("read");
        }
    }
    return 0;
}
  1. EINTR
    • 含义:系统调用被信号中断。例如在非阻塞I/O操作过程中,程序收到一个信号,导致操作中断。
    • 处理方式:可以选择重新执行被中断的系统调用。示例如下:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#define BUFFER_SIZE 1024

int main() {
    int fd = open("test.txt", O_RDONLY | O_NONBLOCK);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    char buffer[BUFFER_SIZE];
    ssize_t bytesRead;
    do {
        bytesRead = read(fd, buffer, BUFFER_SIZE);
    } while (bytesRead == -1 && errno == EINTR);

    if (bytesRead == -1) {
        perror("read");
        close(fd);
        return 1;
    }

    close(fd);
    return 0;
}
  1. ENOTSOCK
    • 含义:如果对非套接字的文件描述符执行了期望套接字的操作(如在非阻塞模式下对普通文件描述符进行类似套接字的I/O控制操作),会出现此错误。
    • 处理方式:检查操作对象是否为正确的套接字描述符,确保操作与文件描述符类型匹配。示例:
#include <stdio.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main() {
    int fd = open("test.txt", O_RDONLY);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1) {
        perror("fcntl F_GETFL");
        close(fd);
        return 1;
    }

    // 尝试将普通文件描述符设置为非阻塞,这会导致ENOTSOCK错误
    int newFlags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    if (newFlags == -1) {
        if (errno == ENOTSOCK) {
            printf("该操作不适用于非套接字文件描述符\n");
        } else {
            perror("fcntl F_SETFL");
        }
    }

    close(fd);
    return 0;
}