饮水思源 - 主题文章阅读  [讨论区: C]
本主题共有 13 篇文章,分 1 页, 当前显示第 1 页 [返回讨论区]
[回复本文][原帖] 发信人: WaterElement(UnChanged), 信区: C
标  题: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月09日23:29:51 星期二)

请问对于标准输入流可以设置不带缓冲吗?比如以下程序
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
        FILE *fp = fdopen(STDIN_FILENO, "r");
        setvbuf(fp, NULL, _IONBF, 0);
        char buffer[20];
        buffer[0] = 0;
        fgets(buffer, 20, fp);
        printf("buffer is:%s", buffer);
        return 0;
}

似乎还是需要在命令行输入后按回车才会让fgets返回,不带缓冲究竟体现在哪里?

--

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 122.84.224.179]

[回复本文][原帖] 发信人: przhu(仙贝), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月10日10:39:30 星期三)

according to the manual, only output stream is related.

你要做的还是通过 ncurses 库实现。

【 在 WaterElement 的大作中提到: 】
: 请问对于标准输入流可以设置不带缓冲吗?比如以下程序
: #include <stdio.h>
: #include <unistd.h>
: int main(int argc, char *argv[]) {
:         FILE *fp = fdopen(STDIN_FILENO, "r");
:         setvbuf(fp, NULL, _IONBF, 0);
:         char buffer[20];
:         buffer[0] = 0;
:         fgets(buffer, 20, fp);
:         printf("buffer is:%s", buffer);
:         return 0;
: }
: 似乎还是需要在命令行输入后按回车才会让fgets返回,不带缓冲究竟体现在哪里?

--
Yours, Sincerely
    PrZhu
※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 219.228.118.130]

[回复本文][原帖] 发信人: Gorkon(Torlek), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月10日12:30:27 星期三)

如果不行就用系统catch key board event(windows)
要并行处理,必须多线程
【 在 WaterElement 的大作中提到: 】
: 请问对于标准输入流可以设置不带缓冲吗?比如以下程序
: #include <stdio.h>
: #include <unistd.h>
: int main(int argc, char *argv[]) {
:         FILE *fp = fdopen(STDIN_FILENO, "r");
:         setvbuf(fp, NULL, _IONBF, 0);
:         char buffer[20];
:         buffer[0] = 0;
:         fgets(buffer, 20, fp);
:         printf("buffer is:%s", buffer);
:         return 0;
: }
: 似乎还是需要在命令行输入后按回车才会让fgets返回,不带缓冲究竟体现在哪里?

--
'You' and your best friend are at the same school. Your friend gradually get addict to his awakened god power, who was the last son of the Gods. He killed innocents and you are in his way. In order to protect a girl from his murder, you were thrown into the world of liberated gods and learned the truth of yourself. With the help of new friends, you sealed your old friend. And stopped the ambition of acient God Monarchy.
※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 58.246.14.242]

[回复本文][原帖] 发信人: WaterElement(UnChanged), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月10日14:48:46 星期三)

没有,只是看书看到标准库缓存这部分,不太清楚fgets的具体实现
【 在 przhu 的大作中提到: 】
: according to the manual, only output stream is related.
: 你要做的还是通过 ncurses 库实现。
: 【 在 WaterElement 的大作中提到: 】
: : 请问对于标准输入流可以设置不带缓冲吗?比如以下程序
: : #include <stdio.h>
: : #include <unistd.h>
: : int main(int argc, char *argv[]) {
: :         FILE *fp = fdopen(STDIN_FILENO, "r");
: :         setvbuf(fp, NULL, _IONBF, 0);
: :         char buffer[20];
: :         buffer[0] = 0;
: :         fgets(buffer, 20, fp);
: :         printf("buffer is:%s", buffer);
: :         return 0;
: : }
: : 似乎还是需要在命令行输入后按回车才会让fgets返回,不带缓冲究竟体现在哪里?

--

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 64.104.125.224]

[回复本文][原帖] 发信人: fcfarseer(fc), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月10日15:17:06 星期三), 转信

這和緩存無關,是控制檯的實現方式的問題。

再講細節一點,這裏有很多個程序和設備。以下按 linux 的情況講:
1. 終端模擬器窗口(比如xterm)收到鍵盤事件
2. 終端模擬器(xterm)把鍵盤事件發給虛擬終端 pty1
3. pty1 檢查目前的輸入狀態,把鍵盤事件轉換成 stdin 的輸入,發給你的程序
4. 你的程序的 c 庫從 stdin 讀入一個輸入,處理

標準庫說的輸入緩存是在 4 的這一步進行的。
而行輸入是在 3 的這一步被緩存起來的。

終端pty有多種狀態,一般控制檯程序所在的狀態叫「回顯行緩存」狀態,這個狀態的
意思是:
1. 所有普通字符的按鍵,會回顯到屏幕上,同時記錄在行緩存區裏。
2. 處理退格(BackSpace),刪除(Delete)按鍵爲刪掉字符,左右按鍵移動光標。
3. 收到回車的時候把整個一行的內容發給stdin。
參考: http://en.wikipedia.org/wiki/Cooked_mode

同時在Linux/Unix下可以發特殊控制符號給pty讓它進入「raw」狀態,這種狀態下按鍵
不會被回顯,顯示什麼內容都靠你程序自己控制。
如果你想得到每一個按鍵事件需要用raw狀態,這需要自己控制回顯自己處理緩衝,
簡單點的方法是用 readline 這樣的庫(基本就是「回顯行緩存」的高級擴展,支持了
Home/End,支持歷史)或者 ncurses 這樣的庫(在raw狀態下實現了一個簡單的窗口/
事件處理框架)。
參考: http://en.wikipedia.org/wiki/POSIX_terminal_interface#History

除此之外, Ctrl-C 轉換到 SIGINT , Ctrl-D 轉換到 EOF 這種也是在 3 這一步做的。

以及,有些終端模擬器提供的 Ctrl-Shift-C 表示複製這種是在 2 這一步做的。

以上是 Linux/unix 的方式。 Windows的情況大體類似,只是細節上有很多地方不一樣:
1. 窗口事件的接收者是創建 cmd 窗口的 Win32 子系統。
2. Win32子系統接收到事件之後,傳遞給位於 命令行子系統 的 cmd 程序
3. cmd 程序再傳遞給你的程序。
Windows上同樣有類似行緩存模式和raw模式的區別,只不過實現細節不太一樣。

【 在 WaterElement (UnChanged) 的大作中提到: 】
: 没有,只是看书看到标准库缓存这部分,不太清楚fgets的具体实现
: 【 在 przhu 的大作中提到: 】
: : according to the manual, only output stream is related.
: : 你要做的还是通过 ncurses 库实现。


--
computerは神様だと信じていて
だからVIMの上でずっと指が舞って
自ら恋愛相手を作り出して

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 133.1.236.59]

[回复本文][原帖] 发信人: WaterElement(UnChanged), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月10日21:53:54 星期三)

感谢FC的详尽解答。

用strace查看了下,设置标准输入没有缓存的话读每个字符都会调用一次read系统调用,
比如输入abc:
read(0, abc
"a", 1)                         = 1
read(0, "b", 1)                         = 1
read(0, "c", 1)                         = 1
read(0, "\n", 1)                        = 1

如果有缓存的话就只调用一次了read系统调用了:
read(0, abc
"abc\n", 1024)                  = 4

【 在 fcfarseer 的大作中提到: 】
: 這和緩存無關,是控制檯的實現方式的問題。
: 再講細節一點,這裏有很多個程序和設備。以下按 linux 的情況講:
: 1. 終端模擬器窗口(比如xterm)收到鍵盤事件
: 2. 終端模擬器(xterm)把鍵盤事件發給虛擬終端 pty1
: 3. pty1 檢查目前的輸入狀態,把鍵盤事件轉換成 stdin 的輸入,發給你的程序
: 4. 你的程序的 c 庫從 stdin 讀入一個輸入,處理
: 標準庫說的輸入緩存是在 4 的這一步進行的。
: 而行輸入是在 3 的這一步被緩存起來的。
: 終端pty有多種狀態,一般控制檯程序所在的狀態叫「回顯行緩存」狀態,這個狀態的
: 意思是:
: 1. 所有普通字符的按鍵,會回顯到屏幕上,同時記錄在行緩存區裏。
: 2. 處理退格(BackSpace),刪除(Delete)按鍵爲刪掉字符,左右按鍵移動光標。
: 3. 收到回車的時候把整個一行的內容發給stdin。
: 參考: http://en.wikipedia.org/wiki/Cooked_mode
: 同時在Linux/Unix下可以發特殊控制符號給pty讓它進入「raw」狀態,這種狀態下按鍵
: 不會被回顯,顯示什麼內容都靠你程序自己控制。
: 如果你想得到每一個按鍵事件需要用raw狀態,這需要自己控制回顯自己處理緩衝,
: 簡單點的方法是用 readline 這樣的庫(基本就是「回顯行緩存」的高級擴展,支持了
: Home/End,支持歷史)或者 ncurses 這樣的庫(在raw狀態下實現了一個簡單的窗口/
: 事件處理框架)。
: (以下引言省略...)

--

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 122.84.218.154]

[回复本文][原帖] 发信人: fcfarseer(fc), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月11日15:02:17 星期四), 转信

沒錯,這個是你的進程內C庫做的緩存,tty屬於字符設備所以是一個一個字符塞給你的
程序的。

如果想感受一下 raw mode 可以試試下面這段程序(沒有檢測錯誤返回值)

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

static int ttyfd = STDIN_FILENO;
static struct termios orig_termios;

/* reset tty - useful also for restoring the terminal when this process
   wishes to temporarily relinquish the tty
*/
int tty_reset(void){
    /* flush and reset */
    if (tcsetattr(ttyfd,TCSAFLUSH,&orig_termios) < 0) return -1;
    return 0;
}


/* put terminal in raw mode - see termio(7I) for modes */
void tty_raw(void)
{
    struct termios raw;

    raw = orig_termios;  /* copy original and then modify below */

    /* input modes - clear indicated ones giving: no break, no CR to NL,
       no parity check, no strip char, no start/stop output (sic) control */
    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);

    /* output modes - clear giving: no post processing such as NL to CR+NL */
    raw.c_oflag &= ~(OPOST);

    /* control modes - set 8 bit chars */
    raw.c_cflag |= (CS8);

    /* local modes - clear giving: echoing off, canonical off (no erase with
       backspace, ^U,...),  no extended functions, no signal chars (^Z,^C) */
    raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);

    /* control chars - set return condition: min number of bytes and timer */
    raw.c_cc[VMIN] = 5; raw.c_cc[VTIME] = 8; /* after 5 bytes or .8 seconds
                                                after first byte seen      */
    raw.c_cc[VMIN] = 0; raw.c_cc[VTIME] = 0; /* immediate - anything       */
    raw.c_cc[VMIN] = 2; raw.c_cc[VTIME] = 0; /* after two bytes, no timer  */
    raw.c_cc[VMIN] = 0; raw.c_cc[VTIME] = 8; /* after a byte or .8 seconds */

    /* put terminal in raw mode after flushing */
    tcsetattr(ttyfd,TCSAFLUSH,&raw);
}


int main(int argc, char *argv[]) {
    atexit(tty_reset);
    tty_raw();
    FILE *fp = fdopen(ttyfd, "r");
    setvbuf(fp, NULL, _IONBF, 0);
    char buffer[20];
    buffer[0] = 0;
    fgets(buffer, 20, fp);
    printf("buffer is:%s", buffer);
    return 0;
}


【 在 WaterElement (UnChanged) 的大作中提到: 】
: 感谢FC的详尽解答。
: 用strace查看了下,设置标准输入没有缓存的话读每个字符都会调用一次read系统调用,
: 比如输入abc:
: read(0, abc
: "a", 1)                         = 1
: read(0, "b", 1)                         = 1
: read(0, "c", 1)                         = 1
: read(0, "\n", 1)                        = 1
: 如果有缓存的话就只调用一次了read系统调用了:
: read(0, abc
: .................(以下省略)

--
computerは神様だと信じていて
だからVIMの上でずっと指が舞って
自ら恋愛相手を作り出して

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 133.1.236.59]

[回复本文][原帖] 发信人: vander(大青蛙), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月12日08:52:20 星期五)

学习了!

进一步想请教一下fc大神。如果我在Linux上做终端上的字符编程,是否除了用ncurses库
之外,也可以不用该库而直接与终端打交道,就是你所说的直接在raw模式?
另外,终端类型vt100和linux的差别在哪里?为什么Kevin Boone的KBox配置手册里面说必
须把终端类型设成linux,而且要加上terminfo文件,才能让终端上的vim正常工作?term
info文件又是干什么的?
【 在 fcfarseer 的大作中提到: 】
: 這和緩存無關,是控制檯的實現方式的問題。
: 再講細節一點,這裏有很多個程序和設備。以下按 linux 的情況講:
: 1. 終端模擬器窗口(比如xterm)收到鍵盤事件
: 2. 終端模擬器(xterm)把鍵盤事件發給虛擬終端 pty1
: 3. pty1 檢查目前的輸入狀態,把鍵盤事件轉換成 stdin 的輸入,發給你的程序
: 4. 你的程序的 c 庫從 stdin 讀入一個輸入,處理
: 標準庫說的輸入緩存是在 4 的這一步進行的。
: 而行輸入是在 3 的這一步被緩存起來的。
: 終端pty有多種狀態,一般控制檯程序所在的狀態叫「回顯行緩存」狀態,這個狀態的
: 意思是:
: 1. 所有普通字符的按鍵,會回顯到屏幕上,同時記錄在行緩存區裏。
: 2. 處理退格(BackSpace),刪除(Delete)按鍵爲刪掉字符,左右按鍵移動光標。
: 3. 收到回車的時候把整個一行的內容發給stdin。
: 參考: http://en.wikipedia.org/wiki/Cooked_mode
: 同時在Linux/Unix下可以發特殊控制符號給pty讓它進入「raw」狀態,這種狀態下按鍵
: 不會被回顯,顯示什麼內容都靠你程序自己控制。
: 如果你想得到每一個按鍵事件需要用raw狀態,這需要自己控制回顯自己處理緩衝,
: 簡單點的方法是用 readline 這樣的庫(基本就是「回顯行緩存」的高級擴展,支持了
: Home/End,支持歷史)或者 ncurses 這樣的庫(在raw狀態下實現了一個簡單的窗口/
: 事件處理框架)。
: (以下引言省略...)

--
我是大青蛙。别人就叫我范德蛙。
※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 210.14.75.228] ※ 修改:·vander 于 2014年12月12日08:55:18 修改本文·[FROM: 210.14.75.228]

[回复本文][原帖] 发信人: fcfarseer(fc), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月12日14:16:25 星期五), 转信

嗯理論上可以不用 ncurses 庫直接在 raw 模式操縱終端。

這裏稍微聊一下terminfo/termcap的歷史,詳細的歷史和吐槽參考Unix hater's 
Handbook第6章 Terminal Insanity。
首先一個真正意義上的終端就是一個輸入設備(通常是鍵盤)加上一個輸出設備(打印
機或者顯示器)。很顯然不同的終端的能力不同,比如如果輸出設備是打印機的話,顯
示出來的字符就不能刪掉了(但是能覆蓋),而且輸出了一行之後就不能回到那一行了
。再比如顯示器終端有的支持粗體和下劃線,有的支持顏色,而有的什麼都不支持。
早期Unix工作在電傳打字機(TeleTYpe)終端上,後來Unix被port到越來越多的機器上
,然後越來越多類型的終端會被連到Unix上,很可能同一臺Unix主機連了多個不同類型
的終端。由於是不同廠商提供的不同的終端,能力各有不同,自然控制他們工作的方式
也是不一樣的。所有終端都支持回顯行編輯模式,所以一般的面向行的程序還比較好寫
,但是那時候要撰寫支持所有終端的「全屏」程序就非常痛苦,這種情況就像現在瀏覽
器沒有統一標準下寫HTML要測試各種瀏覽器兼容性一樣。
通常的做法是1. 使用最小功能子集 2. 假設終端是某個特殊設備,不管別的設備。水源
的代碼源頭 Firebird2000 就是那樣的一個程序,只支持固定大小的vt102終端。

這時有一個劃時代意義的程序出現了,就是 vi,試圖要做到「全屏可視化編輯」。這在
現在看起來很簡單,但是在當時基本是天方夜譚。
vi 的做法是提出一層抽象,記錄它所需要的所有終端操作,然後有一個終端類型數據庫
,把那些操作映射到終端類型的具體指令上。當然並不是所有操作在所有終端類型上都
支持,所以會有一堆 fallback,比如要「強調」某段文字,在彩色終端上可能 
fallback 到紅色,在黑白終端上可能 fallback 到粗體。
vi 一出現大家都覺得好頂讚,然後想要寫更多類似 vi 這樣的全屏程序。然後 vi 的作
者就把終端抽象的這部分數據庫放出來形成一個單獨的項目,叫 termcap (Terminal
 Capibility),對應的描述終端的數據庫就是 termcap 格式。然後 termcap 只是一個
數據庫(所以無狀態)還不夠方便易用,所以後來又有人用 termcap 實現了 curses 。

再後來大家用 curses/termcap 的時候漸漸發現這個數據庫有一點不足:它是爲 vi 設
計的,所以只實現了 vi 需要的那部分終端能力。然後對它改進的努力就形成了新的 
terminfo 數據庫和 pcurses 和後來的 ncurses 。 然後 VIM 出現了自然也用 
terminfo 實現這部分終端操作。

然後麼就是 X 出現了, xterm 出現了,大家都用顯示器了,然後 xterm 爲了兼容各種
老程序加入了各種老終端的模擬模式。不過因爲最普及的終端是 vt100 所以 xterm 默
認是工作在兼容 vt100 的模式下。然後接下來各種新程序(偷懶不用*curses的那些)
都以 xterm/vt100 的方式寫。

嗯到此爲止是 Unix 世界的黑歷史。
知道這段歷史的話就可以明白爲什麼需要 TERM 變量配合 terminfo 數據庫纔能用一些 
Unix 下的全屏程序了。類比一下的話這就是現代瀏覽器的 user-agent。

然後話題回到 Linux 。 大家知道 Linux 早期代碼不是一個 OS, 而是 Linus 大神想
在他的嶄新蹭亮的 386-PC 上遠程登錄他學校的 Unix 主機,接收郵件和逛水源(咳咳
)。於是 Linux 最早的那部分代碼並不是一個通用 OS 而只是一個 bootloader 加一個
終端模擬器。所以現在 Linux 內核裏還留有他當年實現的終端模擬器的部分代碼,而這
個終端模擬器的終端類型就是 linux 啦。然後他當時是爲了逛水源嘛所以 linux 終端
基本上是 vt102 的一個接近完整子集。

說到這裏脈絡大概應該清晰了, xterm終端類型基本模擬 vt100,linux終端類型基本模
擬 vt102。這兩個的區別其實很細微,都是同一個廠商的兩代產品嘛。有差別的地方差
不多就是 Home/End/PageUp/PageDown/Delete 這些不在 ASCII控制字符表裏的按鍵的映
射關係不同。
嗯這也就解釋了爲什麼在linux環境的圖形界面的終端裏 telnet 上水源的話,上面這些
按鍵會錯亂…… 如果設置終端類型是 linux/vt102 的話就不會亂了。在 linux 的 
TTY 裏 telnet 也不會亂的樣子。

寫到這裏纔發現貌似有點長…… 總之可以參考 Unix Hater's Handbook 裏的相關歷史
評論和吐槽,那一段非常有意思。
 
【 在 vander (大青蛙) 的大作中提到: 】
: 学习了!
: 进一步想请教一下fc大神。如果我在Linux上做终端上的字符编程,是否除了用ncurses库
: 之外,也可以不用该库而直接与终端打交道,就是你所说的直接在raw模式?
: 另外,终端类型vt100和linux的差别在哪里?为什么Kevin Boone的KBox配置手册里面说必
: 须把终端类型设成linux,而且要加上terminfo文件,才能让终端上的vim正常工作?term
: info文件又是干什么的?
: 【 在 fcfarseer 的大作中提到: 】
: : 這和緩存無關,是控制檯的實現方式的問題。
: : 再講細節一點,這裏有很多個程序和設備。以下按 linux 的情況講:
: : 1. 終端模擬器窗口(比如xterm)收到鍵盤事件
: .................(以下省略)

--
computerは神様だと信じていて
だからVIMの上でずっと指が舞って
自ら恋愛相手を作り出して

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 133.1.236.59] ※ 修改:·fcfarseer 于 2014年12月12日14:51:43 修改内容·[FROM: 133.1.236.59]

[回复本文][原帖] 发信人: amuluo(阿姆罗), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月12日14:42:28 星期五), 转信

哇~原来故事是这样的。
【 在 fcfarseer (fc) 的大作中提到: 】
: 嗯理論上可以不用 ncurses 庫直接在 raw 模式操縱終端。
: 這裏稍微聊一下terminfo/termcap的歷史,詳細的歷史和吐槽參考Unix hater's 
: Handbook第6章 Terminal Insanity。
: 首先一個真正意義上的終端就是一個輸入設備(通常是鍵盤)加上一個輸出設備(打印
: 機或者顯示器)。很顯然不同的終端的能力不同,比如如果輸入設備是打印機的話,顯
: 示出來的字符就不能刪掉了(但是能覆蓋),而且輸出了一行之後就不能回到那一行了
: 。再比如顯示器終端有的支持粗體和下劃線,有的支持顏色,而有的什麼都不支持。
: 早期Unix工作在電傳打字機(Teletype)終端上,後來Unix被port到越來越多的機器上
: ,然後越來越多類型的終端會被連到Unix上,很可能同一臺Unix主機連了多個不同類型
: 的終端。由於是不同廠商提供的不同的終端,能力各有不同,自然控制他們工作的方式
: .................(以下省略)

--
太阳:水瓶座 10°17' 第3宫            月亮:水瓶座 26°04' 第4宫
水星:水瓶座 22°39' 第3宫            金星:射手座 24°02' 第2宫
火星:白羊座 15°30' 第5宫            木星:双鱼座 23°05' 第4宫
土星:射手座 18°20' 第2宫            天王星:射手座 25°12' 第2宫
海王星:摩羯座 06°45' 第2宫          冥王星:天蝎座 09°48' 第12宫
上升:天蝎座 17°34'                   天顶:狮子座 23°30'

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 120.90.6.98]

[回复本文][原帖] 发信人: przhu(仙贝), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月12日15:00:09 星期五)


【 在 amuluo 的大作中提到: 】
: 哇~原来故事是这样的。
: 【 在 fcfarseer (fc) 的大作中提到: 】
: : 嗯理論上可以不用 ncurses 庫直接在 raw 模式操縱終端。
: : 這裏稍微聊一下terminfo/termcap的歷史,詳細的歷史和吐槽參考Unix hater's 
: : Handbook第6章 Terminal Insanity。
: : 首先一個真正意義上的終端就是一個輸入設備(通常是鍵盤)加上一個輸出設備(..
: : 機或者顯示器)。很顯然不同的終端的能力不同,比如如果輸入設備是打印機的話..
~~~打字机 不是打印机= = 

: : 示出來的字符就不能刪掉了(但是能覆蓋),而且輸出了一行之後就不能回到那一..
: : 。再比如顯示器終端有的支持粗體和下劃線,有的支持顏色,而有的什麼都不支持。
: : 早期Unix工作在電傳打字機(Teletype)終端上,後來Unix被port到越來越多的機..
: : ,然後越來越多類型的終端會被連到Unix上,很可能同一臺Unix主機連了多個不同..
: : 的終端。由於是不同廠商提供的不同的終端,能力各有不同,自然控制他們工作的..
: : .................(以下省略)

--
Yours, Sincerely
    PrZhu
※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 219.228.118.130]

[回复本文][原帖] 发信人: fcfarseer(fc), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月12日15:04:26 星期五), 转信

手滑…… 其實我想說的是輸出設備…… 然後有些是  teletype 有些是 teleprinter
嘛,其實差別不大……
【 在 przhu (仙贝) 的大作中提到: 】
: 【 在 amuluo 的大作中提到: 】
: : 哇~原来故事是这样的。
: ~~~打字机 不是打印机= = 


--
computerは神様だと信じていて
だからVIMの上でずっと指が舞って
自ら恋愛相手を作り出して

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 133.1.236.59]

[回复本文][原帖] 发信人: vander(大青蛙), 信区: C
标  题: Re: 可以设置不带缓冲的标准输入流吗?
发信站: 饮水思源 (2014年12月15日12:11:55 星期一)

太精彩了,特别是Linus上水源这段历史好有趣。感谢fc大神,收藏了!
【 在 fcfarseer 的大作中提到: 】
: 嗯理論上可以不用 ncurses 庫直接在 raw 模式操縱終端。
: 這裏稍微聊一下terminfo/termcap的歷史,詳細的歷史和吐槽參考Unix hater's 
: Handbook第6章 Terminal Insanity。
: 首先一個真正意義上的終端就是一個輸入設備(通常是鍵盤)加上一個輸出設備(打印
: 機或者顯示器)。很顯然不同的終端的能力不同,比如如果輸出設備是打印機的話,顯
: 示出來的字符就不能刪掉了(但是能覆蓋),而且輸出了一行之後就不能回到那一行了
: 。再比如顯示器終端有的支持粗體和下劃線,有的支持顏色,而有的什麼都不支持。
: 早期Unix工作在電傳打字機(TeleTYpe)終端上,後來Unix被port到越來越多的機器上
: ,然後越來越多類型的終端會被連到Unix上,很可能同一臺Unix主機連了多個不同類型
: 的終端。由於是不同廠商提供的不同的終端,能力各有不同,自然控制他們工作的方式
: 也是不一樣的。所有終端都支持回顯行編輯模式,所以一般的面向行的程序還比較好寫
: ,但是那時候要撰寫支持所有終端的「全屏」程序就非常痛苦,這種情況就像現在瀏覽
: 器沒有統一標準下寫HTML要測試各種瀏覽器兼容性一樣。
: 通常的做法是1. 使用最小功能子集 2. 假設終端是某個特殊設備,不管別的設備。..
: 的代碼源頭 Firebird2000 就是那樣的一個程序,只支持固定大小的vt102終端。
: 這時有一個劃時代意義的程序出現了,就是 vi,試圖要做到「全屏可視化編輯」。..
: 現在看起來很簡單,但是在當時基本是天方夜譚。
: vi 的做法是提出一層抽象,記錄它所需要的所有終端操作,然後有一個終端類型數..
: ,把那些操作映射到終端類型的具體指令上。當然並不是所有操作在所有終端類型上都
: 支持,所以會有一堆 fallback,比如要「強調」某段文字,在彩色終端上可能 
: (以下引言省略...)

--
我是大青蛙。别人就叫我范德蛙。
※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 210.14.75.228]

本主题共有 13 篇文章,分 1 页, 当前显示第 1 页 [返回讨论区]

[返回上一页][本讨论区(一般模式)]