linux fcntl — сброс флага

Как сбросить уже установленный флаг с помощью fcntl?

Например, Я могу установить сокет в неблокирующий режим, используя

fcntl(sockfd, F_SETFL, flags | O_NONBLOCK)

Теперь я хочу снять флаг O_NONBLOCK.

Я попробовал fcntl(sockfd, F_SETFL, флаги | ~O_NONBLOCK). Это дало мне ошибку EINVAL


person chappar    schedule 23.12.2008    source источник
comment
Попробуйте flags & ~O_NONBLOCK. т. е. &, а не |.   -  person Chris Jester-Young    schedule 23.12.2008
comment
Да, ты прав. Скопируйте, вставьте проблему. :-). При кодировании нужно думать.   -  person chappar    schedule 23.12.2008


Ответы (4)


int oldfl;
oldfl = fcntl(sockfd, F_GETFL);
if (oldfl == -1) {
    /* handle error */
}
fcntl(sockfd, F_SETFL, oldfl & ~O_NONBLOCK);

Не проверено, но надеюсь, что это поможет. :-)

person Chris Jester-Young    schedule 23.12.2008
comment
Конечно. Прочтите и мой комментарий к вашему вопросу. А именно, если у вас не было опечатки в вашем редактировании, вы должны использовать & для очистки флагов, а не |. - person Chris Jester-Young; 23.12.2008
comment
Даниил, спасибо, что указали на это. Иногда я думаю, что изобилие бесполезной проверки ошибок, подобной этой, отпугивает новых программистов от важной проверки ошибок там, где это действительно необходимо. - person R.. GitHub STOP HELPING ICE; 25.05.2011
comment
@DanielTrebbien: неправильно. Только безошибочное значение не является отрицательным. fcntl(fd, F_GETFL) может завершиться ошибкой, т. е. он может вернуть -1, например, неверный fd может привести к EBADF. - person jfs; 31.07.2014
comment
@J.F.Sebastian: Ой, моя ошибка. Ты прав. Фактически, спецификация говорит, что в противном случае должно быть возвращено -1 и errno указывает на ошибку. и приводит пример: flags = fcntl(fd, F_GETFD); if (flags == -1) /* Handle error */; Крис, надеюсь, ты не против, но я восстановил твой исходный код. - person Daniel Trebbien; 31.07.2014

val = fcntl(fd, F_GETFL, 0);
flags = O_NONBLOCK;
val &= ~flags;
fcntl(fd,F_SETFL,val);

Если вы сделаете это, уже установленный O_NONBLOCK будет отключен. здесь flags содержит флаги, которые вы хотите снять. После завершения операции И (&) вам снова нужно установить флаг, используя значение в val. Я надеюсь, что это поможет вам.

person sat    schedule 07.10.2011

Следующий код снимет флаг, например, флаг O_NONBLOCK:

if ((flags = fcntl(fileno(sockfd), F_GETFL, 0)) < 0) {
    perror("error on F_GETFL");
}
else {
    flags &= ~O_NONBLOCK;
    if (fcntl(fileno(sockfd), F_SETFL, flags) < 0) {
        perror("error on F_SETFL");
    }
    else {
        /* O_NONBLOCK set without errors. continue from here */
        }
}

С Уважением

person Miguel Rentes    schedule 22.03.2012

Пробовал сбросить все флаги:

fcntl(sockfd, F_SETFL, 0);

Также ИЛИ флаги с ~O_NONBLOCK бесполезны, вам нужно И это, так как вы хотите сбросить бит (ы) O_NONBLOCK.

person codelogic    schedule 23.12.2008
comment
Сбрасывать все флаги немного излишне, если вы просто хотите снять неблокирующий флаг. :-) - person Chris Jester-Young; 23.12.2008