无法将文件描述符设置为阻塞模式

标签 c linux file-descriptor termios

我正在尝试编写具有阻塞文件描述符的最短代码。

我先设置:O_NONBLOCK
第二个:ICANON,[VMIN],[VTIME] 作为我的文件描述符...

我还需要设置哪些选项才能拥有阻塞文件描述符?

(sample.txt 是空的 & 不同模式的 open() 不会发生任何事情)


#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>


void set_blocking(int fd, int blocking) {

    int flags = fcntl(fd, F_GETFL, 0);

    if (blocking)
        flags &= ~O_NONBLOCK;
    else
        flags |= O_NONBLOCK;

    fcntl(fd, F_SETFL, flags);

    return;
}

int main(){

        int fd;
        char buff[100];
        struct termios options;

        options.c_lflag &= ~ICANON;

        options.c_cc[VMIN] = 2;
        options.c_cc[VTIME] = 0;

        fd = open("sample.txt",O_RDWR);

        tcsetattr(fd, TCSANOW, &options);

        set_blocking(fd,1);

        read(fd,buff,2);

        printf("%s\n",buff);

        return 0;
}

最佳答案

您的代码仅修改了未初始化的 struct termios options 变量的一部分。当您的代码调用 tcsetattr 时,大部分 options 变量将被设置为随机位,因此 tcsetattr 可能返回错误或应用终端的虚假设置。

由于您的代码仅显式修改某些终端设置,因此初始化 options 变量的最佳方法是调用 tcgetattr 将旧设置读入其中:

    ret = tcgetattr(fd, &options);
    if (ret < 0) {
        perror("tcgetattr");
        exit(1);
    }

    options.c_lflag &= ~ICANON;

    options.c_cc[VMIN] = 2;
    options.c_cc[VTIME] = 0;

    ret = tcsetattr(fd, TCSANOW, &options);
    if (ret < 0) {
        perror("tcsetattr");
        exit(1);
    }

上面的代码示例假定文件描述符fd 链接到终端,因此isatty(fd) 返回1。当fd 链接到一个普通文件。

在您发布的代码中,fd 链接到当前目录中名为“sample.txt”的文件,该文件不太可能是终端。在这种情况下,tcgetattrtcsetattr 调用将返回 -1 并将 errno 设置为 ENOTTY.

关于无法将文件描述符设置为阻塞模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58118569/

相关文章:

c - 指向 const 静态数组的指针

复制到 C 中的 Null 位置并传递无效数据时崩溃

java - 如何在大文本文件的开头插入文本?

java - 生命周期测试中高负载下的 JVM 卡住

c - OpenMP 最小值数组

linux - SocketCAN中canfd_frame中的 `flags`字段是什么?

linux - 我可以使用 Visual Studio 开发 Mono 应用程序吗?

linux - 文件描述符执行 IO 是否需要处理器周期?

linux - 为什么 mplayer 在循环时退出 Bash?

c - 迭代C中未初始化的数组