平林さん すっかりお世話になっています。
From: Kouichi Hirabayashi <k...@mogami.com> Subject: [FreeBSD-users-jp 94051] Re: umodem で PICC18F2550 にアクセスすると不安定 Date: Wed, 14 Nov 2012 09:14:58 +0900 > 2回分まとめますが、まず、前回の疑問 > >> 「いつデータがくるかわからない」という状況ではない > > は、よくあるパターンだと思って、私が相手のデバイスのマニ > ュアルを読まずに、perl のコーディングだけ見て書いてしまっ > たのが原因です。 最初の説明が至らず失礼しました。 > open(), close() はハードウェアを初期化してしまいますから、 > open() で行うたくさんの仕事がハードウェアで全て完了するま > で、接続相手のデバイスと正常なコンタクトができません。ま > た、相手側のデバイスが open() の後、一定時間しないとコマ > ンドを受け付けられる状態にならないケースもあります。 予備知識が足りませんが、雰囲気はわかりました。ご説明ありがとうございま す。 > 次に、今回の C のプログラムのほうは、 > > tios.c_lflag |= ICANON; > > でしたら、 > > tios.c_cc[VEOL] = '\n'; > tios.c_cc[VMIN] = 0; > tios.c_cc[VTIME] = 100; > > とか、デリミタなどの待機終了条件を指定しておかないと、運任 > せになります。 試してみましたが変わりませんでした。 この点、ぼくの理解と食い違いがあるので確認させて下さい。 tios.c_lflag |= ICANON; ですので、Canonical mode に *している* つもりです。その前提で… VEOL は、明示的に設定する前でも \n を行末として1行単位で read()できてい るように見えますが、上述の通り明示的に設定してもダメでした。 VMIN と VTIME は、Canonical mode のときは動作に影響しないと理解していま す。 > あと、相手のデバイスの仕様書を見ると、単純なコマンド・レス > ポンス方式ですから、本来 select() のような入出力多重化機構 > は要らないわけで、素直に \n をデリミタにした canonical 入力 > (ICANON) でタイミングを合わせるのが一番ではないでしょうか? ここなんですけど、まず、open()に O_NONBLOCK を与えないと、open()がブロッ クされ、termios 関係の設定に進むことができなかったので、O_NONBLOCK を追 加しました。知識がないので、こんなもんか、と思って疑問なく O_NONBLOCK を追加したんですが、もしかして、ここが既におかしいでしょうか? O_NONBLOCK を追加すると、今度は read()が Resource temporarily unavailable を起こしてしまうので select()を追加した、という経緯です。 write()の方の select()は、read()に入れるなら write()にも入れた方が無難 かな? という程度で、深くは考えていません。 > つまり、 > > open(); // デリミタ LF の CANONICAL 入力 > sleep(); // 相手側で必要なら > write(); // コマンド出力 > read(); // データ入力 > close(); > > の繰り返しになります。気圧計でしたら、プログラム中でのループ > でなく、cron からの起動になると思いますが。 はい、この点はおっしゃる通りです。 値を取得して RRD に格納するプログラムを書いて、「できた!」と思って15分 ごとに起動するように crontab に仕込んだら、何回か成功した後、失敗して、 ブロックされたプロセスが溜まってしまった、というのが事の次第です。短時 間でループを回しているのは、あくまで加速試験の意味でやっています。 最悪、cron で起動するんじゃなくって15分 sleep()してループするという逃げ も考えてはいるんですが…他にもコマンドラインで起動して、その点の値を一 発取得しておしまい、というプログラムも欲しいとは思っています。 恐れ入りますが、引き続きよろしくお願いします。 ----- kohi@sh$ diff -u test8.c test9.c --- test8.c 2012-11-13 20:31:49.000000000 +0900 +++ test9.c 2012-11-14 21:57:14.000000000 +0900 @@ -43,6 +43,9 @@ if (tcgetattr(fd, &tios) < 0) { err(1, "tcgetattr()"); } + tios.c_cc[VEOL] = '\n'; + tios.c_cc[VMIN] = 0; + tios.c_cc[VTIME] = 100; tios.c_cflag |= (CREAD | CLOCAL); tios.c_iflag |= IXANY; tios.c_iflag &= ~(ISTRIP | ICRNL | INLCR | IXON | IXOFF ----- kkdlabs.jp, featuring Koh-ichi Ito as just another DNS freak in town.