Не могу установить дескриптор файла в режим блокировки - PullRequest
0 голосов
/ 26 сентября 2019

Я пытаюсь написать самый короткий код, чтобы иметь дескриптор файла блокировки.

Я установил первый: O_NONBLOCK
Второй: ICANON, [VMIN], [VTIME] для моего файлового дескриптора ...

Какие еще опции мне нужно установить, чтобы получить файл блокировкидескриптор?

(sample.txt пуст и открыт () в другом режиме ничего не меняет)


#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;
}

1 Ответ

0 голосов
/ 26 сентября 2019

Ваш код изменяет только части неинициализированной переменной 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" в текущем каталоге, который вряд ли будет терминалом.В этом случае вызовы tcgetattr и tcsetattr вернут -1 и установят errno в ENOTTY.

...