平林さん

すっかりお世話になっています。

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.

メールによる返信