ttyUSB0
USB経由でコンピュータに情報を送信するデバイスがあります。Arch Linux は、 という名前のファイルを作成してこのデバイスをセットアップします/dev/
。私は を使用してGTKterm
、この着信情報を受信して、エミュレートされたターミナル ウィンドウに表示しています。
私の質問は、 がGTKterm
このttyUSB0
ファイルに対して読み取り/書き込みを行うのは正確にはどのように行うのか、また、同様の機能を実装する方法をどこから学習すればよいのかということです。つまり、最も基本的な形式では、 に文字を書き込むにはどうすればよいのかttyUSB0
、または、対照的に、バイトを受け取ってファイルに書き込むにはどうすればよいのかということです。
答え1
TTY は、他のファイルと同じように使用できるファイルです。言語の標準的なファイル オープン ツールを使用して開き、読み書きすることができます。TTY には「通常の」ファイルとは異なる特別な動作がありますが、基本は同じです。最後にいくつかの特別なケースについて説明しますが、まずは実験してみましょう。
通常のターミナルから直接実行できる興味深い機能の 1 つ。実行するtty
と、次のような行が出力されます。
/dev/pts/2
これは、端末が実行されている TTY デバイスです。その端末に何かを書き込むことができます。
$ echo Hello > /dev/pts/2
Hello
$
そこから読むこともできます:
$ read X < /dev/pts/2
hello
$ echo $X
hello
$
(read X
は sh の「標準入力から 1 行を変数 X に読み込む」コマンドです。< は、読み取りコマンドの標準入力として /dev/pts/2 を使用するためのものです。最初の「hello」は私が入力したもので、2 番目は出力されたものです)。
screen
またはを使用して別のシェルを開くとxterm
、そのシェルで run を実行して元の端末にテキストを表示できますecho spooky > /dev/pts/2
。他のコマンドについても同様です。これはすべて、シェルが TTY であることを認識せずにファイルを開くだけです。
以下は、まさにあなたが尋ねたとおりのことを実行し、/dev/pts/3 に 1 文字を書き込み、そこから 1 バイトを読み取る非常に単純な C プログラムです。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
char byte;
int fd = open("/dev/pts/3", O_RDWR);
write(fd, "X", 1);
ssize_t size = read(fd, &byte, 1);
printf("Read byte %c\n", byte);
return 0;
}
シェルまたはターミナル エミュレーターに接続された実際の TTY デバイスでは興味深い動作が行われますが、何かが返されるはずです。
端末にアクセスするには、端末を使用する権限が必要です。これらは、 で表示されls -l
、 で設定される標準的なファイル権限ですchmod
。ファイルを開いて読み取るには読み取り権限が必要で、ファイルに書き込むには書き込み権限が必要です。端末をバックアップする TTY はあなたが所有しますが、他のユーザーの TTY は所有しません。また、USB デバイスの TTY は、設定に応じて所有される場合とされない場合があります。権限は、通常と同じ方法で変更できます。
これを使ってプログラムを書く場合、特別なことをする必要はありません。例を見れば、しない必要なのは、データを相手側で読み取るために毎回ファイルを閉じることだけです。TTYファイルはパイプラインのように動作し、データが入ってくると両方向にデータを送ります。TTYにテキストを書き込むとすぐに表示され、その後読み取るときには何も待っていませんでした。ない通常のファイルに書き込む場合と同様に、データはディスク上に保存され、すぐに反対側に渡されるか、誰かが読み取るまでメモリ内に保存されます。
使用したい場合があります選択する機能を使用すると、デバイスが何かを言うのを待っている間に他の作業を行うことができますが、データが届くのを待つだけでよい場合は、ブロッキング読み取りを使用して OS に処理を任せることができます。
覚えておくべきことの1つは、カーネルのバッファサイズには制限があり、一度に大量のデータを書き込むと意図せずブロックされてしまう可能性があるということです。それが問題になる可能性がある場合は、非ブロッキングIOいずれにしopen("/dev/...", O_RDWR | O_NONBLOCK)
ても原理は同じです。