即使 struct termios c_cc[VMIN]=1,两个线程和终端也不会阻塞

问题描述

我有两个线程(thrd_t):一个主线程处理事件 和一个使用 fgetwc 等待终端输入的子线程。

    #include <threads.h> // mtx_t,mtx_lock,mtx_unlock
    #include <wchar.h> // fgetwc,fgetwc_unlocked
    FILE* f = (FILE*) p2;
    mtx_t* m = (mtx_t*) p1;
    volatile sig_atomic_t* i = (volatile sig_atomic_t*) p0;
    mtx_lock(m);
    volatile wint_t c = fgetwc(f);
    if (c != WEOF) {
        ungetwc(c,f);
        copy_integer(p0,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
    }
    mtx_unlock(m);
    while (*i != *FALSE_BOOLEAN_STATE_CYBOI_MODEL);

由于我想读取ansi转义码序列(三个字符), 终端不得在每个字符后阻塞,因此 在主线程中使用 t.c_cc[VMIN]=0 设置为非阻塞。 检测到序列后,我将终端重置为阻塞 使用 t.c_cc[VMIN]=1,以便子线程在 fgetwc 处阻塞 直到检测到下一个输入。

    mtx_t* m = (mtx_t*) p3;
    int* i = (int*) p2;
    // The loop break flag.
    int b = *FALSE_BOOLEAN_STATE_CYBOI_MODEL;
    // The escape character flag.
    int esc = *FALSE_BOOLEAN_STATE_CYBOI_MODEL;
    int aec = *FALSE_BOOLEAN_STATE_CYBOI_MODEL;
    // The input character.
    wint_t c = WEOF;
    mtx_lock(m);
    // Set unblocking mode in terminal.
    edit_service(p4,(void*) FALSE_BOOLEAN_STATE_CYBOI_MODEL,(void*) TERMINAL_CYBOI_CHANNEL);
    while (*TRUE_BOOLEAN_STATE_CYBOI_MODEL) {
        if (b != *FALSE_BOOLEAN_STATE_CYBOI_MODEL) {
            break;
        }
        read_unix_terminal_character(p0,p1,(void*) &b,(void*) &esc,(void*) &aec,(void*) &c);
    }
    // Set blocking mode in terminal. VMIN = 1
    edit_service(p4,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL,(void*) TERMINAL_CYBOI_CHANNEL);
    // Reset interrupt request in input/output entry.
    copy_integer(i,(void*) FALSE_BOOLEAN_STATE_CYBOI_MODEL);
    mtx_unlock(m);

问题:有时,fgetwc 会阻塞,有时不会。 当读入一个字符序列(三个字符)时, 阅读循环留在第三个字符处 子线程块很好。 当读取单个字符时,它的结尾会被检测到 跟随WEOF,但子线程不再阻塞, 即使t.c_cc[VMIN]=1

    wint_t* c = (wint_t*) p5;
    int* aec = (int*) p4;
    int* esc = (int*) p3;
    FILE* f = (FILE*) p1;
    *c = fgetwc(f);
    if (*c != WEOF) {
        if (*aec == *TRUE_BOOLEAN_STATE_CYBOI_MODEL) {
            // The character sequence ESC[ was received before.
            // This is the beginning of an ansi escape code sequence.
            // Reset ansi escape code flag.
            copy_integer(p4,(void*) FALSE_BOOLEAN_STATE_CYBOI_MODEL);
            // Append source character to destination item.
            // This is the actual ansi escape code.
            modify_item(p0,p5,(void*) WIDE_CHaraCTER_TEXT_STATE_CYBOI_TYPE,(void*) PRIMITIVE_STATE_CYBOI_MODEL_COUNT,*NULL_POINTER_STATE_CYBOI_MODEL,(void*) VALUE_PRIMITIVE_STATE_CYBOI_NAME,(void*) APPEND_MODIFY_LOGIC_CYBOI_FORMAT);
            // Set loop break flag.
            // All values have been received,so that the loop can be left Now.
            copy_integer(p2,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
        } else if (*esc == *TRUE_BOOLEAN_STATE_CYBOI_MODEL) {
            // The escape character ESC was received before.
            // This might be the beginning of an ansi escape code.
            // Reset escape character flag.
            copy_integer(p3,(void*) FALSE_BOOLEAN_STATE_CYBOI_MODEL);
            if (*c == *((wint_t*) LEFT_SQUARE_BRACKET_UNICODE_CHaraCTER_CODE_MODEL)) {
                // The escape character ESC received before
                // is followed by an opening square bracket [.
                // This is the beginning of an ansi escape code.
                // Set ansi escape code flag.
                copy_integer(p4,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
                // Append source character to destination item.
                modify_item(p0,(void*) APPEND_MODIFY_LOGIC_CYBOI_FORMAT);
            } else {
                // The escape character ESC received before
                // is followed by another,second character
                // which is NOT an opening square bracket.
                // This is NOT going to be an ansi escape code sequence.
                // Unread this character so that it may be
                // processed once more later on.
                ungetwc(*c,f);
                // Set loop break flag.
                copy_integer(p2,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
            }
        } else if (*c == *((wint_t*) ESCAPE_UNICODE_CHaraCTER_CODE_MODEL)) {
            // The escape character ESC was received.
            // This might be the beginning of an ansi escape code.
            // Set escape character flag.
            copy_integer(p3,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
            // copy source character to destination character array.
            modify_item(p0,(void*) APPEND_MODIFY_LOGIC_CYBOI_FORMAT);
        } else {
            // No special characters have been found.
            // So this is a normal source character
            // that is just copied to the destination.
            // copy source character to destination character array.
            modify_item(p0,(void*) APPEND_MODIFY_LOGIC_CYBOI_FORMAT);
            // CAUTION! Do NOT set loop break flag here.
            // More than just one character might have to be
            // received in a sequence,e.g. an ansi escape code.
            // In this case,only a WEOF will break the loop.
        }
    } else {
        // Set loop break flag.
        copy_integer(p2,(void*) TRUE_BOOLEAN_STATE_CYBOI_MODEL);
    }

termios c_cc[VMIN] 值是否可能被缓存而不是从共享内存中读取?

在此处查找项目和所有源代码https://savannah.nongnu.org/svn/?group=cybop

可能相关: Does making reference variable volatile,make all its field volatile too in java? “...对象不是变量。...所有线程看到相同的引用, 并不是因为它们的内部内容观察到相同的值。”

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)