Lubuntuでは、Konsoleの文字エンコーディングをUTF-16に設定しました(KonsoleがUTF-16リトルエンディアンを使用するのかUTF-16ビッグエンディアンを使用しているのかわかりません)。
その後、実行ウィンドウで次のコマンドを実行しました。
その後、キーボードの「a」ボタン(Lubuntuで選択したキーボードレイアウトは英語です)を押しました。これにより、バイト61 00
(KonsoleがUTF-16リトルエンディアンを使用している場合)が次に送信されると思いました。ライン規律、しかもライン規律このバイトは順番に Konsole にエコーされ、Konsole は文字 "a" を表示します。しかし、私は次のような結果を得ます。
「a」ボタンをもう一度押すと、次のような結果が表示されます。
「a」ボタンをもう一度押すと、次のような結果が表示されます。
「a」ボタンをもう一度押すと、次のような結果が表示されます。
単に「aaaa」という文字が表示されるのではなく、これらの奇妙な文字が表示されるのはなぜですか?
編集する:
Konsoleに表示される文字は次のとおりです。
覚醒`覚醒>覚醒`覚醒
答え1
xxd -p
これは無関係であることをさらに強調します。いいえ言うそれ出力。カーネル側のラインバッファリングのため、入力も見えないため、出力も生成されません。価値のあるものはacat
またはasleep 100000
または他のものかもしれません。私たちは方法について話していますコア(ラインルール)エコー入力。
UTF-8に戻ってEnterを押すと、xxd -p
出力は次のようになりますfffe6100fffe6100
。エンディアンはほとんど確認されていませんが(またはアーキテクチャの基本エンディアン)、各文字の前にBOMがあることは驚くべきことです。 Konsoleの開発者はこれについて正しく考えていないようです。彼らは利用可能なすべての入力ブロックに対してターゲット文字セットとしてUTF-16(BEまたはLEが指定されていない)を使用して盲目的にiconvを呼び出し、iconvをそこに入れました。
konsoleを使用して、リンクされたstrace
ファイル記述子に対してどのようなことを行うかを見てみましょう/dev/ptmx
。
write(..., "\377\376a\0", 4) = 4
[...]
read(..., "\377\376a^@", 5) = 5
NULバイト(0x00)はリテラル^@
、0x5eの後に0x40として返されます。
(0x61)と一緒にa
U + 5e61が提供され、これは正確に最初に表示されるグリフです。また、1バイトずつ差が生じる。つまり、次の下位バイトが上位バイトとして解釈され、その逆も同様です。
バイトの場合、カーネルが0x00
エコーされる方法を破りました。他のバイトについては、他の操作も実行します。たとえば、bytes 0x03
(^C
)は通常フォアグラウンドプロセスに送信された割り込みをトリガし、0x15
(^U
)はこれまでに入力したデータを消去し、0x0a
(0x0d
または改行)アプリケーションにデータをフラッシュします。これらのバイトはすべてUTF-16文字表現に正当に表示される可能性があり、実際に入力したときにこれが発生したくありません。
弟子ラインでUTF-16を使用するには、カーネルはそれに対する明示的なサポートを提供しなければならず、このエンコーディングが使用されていることを知らなければなりませんstty utf16
(私の知る限り、これは実装されていません(幸いなことに、開発者リソースは完全に無駄になります)。カーネルはASCII互換エンコーディングを期待していますが、UTF-16はそうではありません。
UTF-16がttyライン用のカーネルに実装されていても、生態系全体は非常に脆弱です。エンドポイントは複数のソースから同時にデータを受け取ることができ、すべてのデータプロデューサーとすべての送信者(SSHなど)が常にペアごとのバイト結合を維持するという保証はありません。上記のようにバイトが失われると、残りは使用できません。
これで、Konsole開発者がそれを正しく考慮していないことがより確実になりました。私の考えでは、UTF-16が提供するエンコードリストから削除するか、少なくとも警告を表示する必要があると思います。提出しましたKonsoleのバグ 395171。