いとうです。何度もすみません。

From: Koh-ichi Ito <k...@kkdlabs.jp>
Subject: [FreeBSD-users-jp 94048] Re: umodem で PICC18F2550 にアクセスすると不安定
Date: Mon, 12 Nov 2012 19:38:44 +0900

>> デバイスドライバを書く側から見たら、いつデータが来るか
>> わからないときは「100回以上回しても平気」なほうの構造
>> にするか、センサ側がデータ送出指令を待つようにすべきだ
>> と思いますが、運がよければ、最初のプログラム構造でも、
>> sleep() を close() の後に移動すると(完全ではないにして
>> も)改善されるかもしれないですね。
>> 
>> 平林 浩一
> 
> 実は本番の(というほど大げさな話じゃないんですけど :-)プログラムは Perl
> じゃなくって C で書いているんですが、ともかく close()の後ろに sleep()を
> 入れると改善されることはわかりましたので、がんばってみます。

C のコードでは、close()の後ろに sleep()を入れてみても現象は変わらず、
read()の前の select()がタイムアウトし、そのまま再実行すると、select()が
タイムアウトすらせず返ってこなくなります。^C を打鍵するとプロンプトは返っ
てきます。

長くて恐縮ですが試したコードを載せます。PAUSE の値は1でダメだったので5
にしてみましたが、やはりダメでした。

#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>

#define PAUSE   5

main()
{
        int     i,
                fd;
        size_t  rlen,
                tlen;
        ssize_t n;
        char    *tmesg,
                rmesg[16];
        fd_set  fds;
        struct termios  tios;
        struct timeval  timeout;

        for (i = 0; ; i++) {
                printf("i = %d\n", i);
                if ( (fd = open("/dev/ttyU0", O_RDWR | O_NONBLOCK) ) < 0) {
                        err(1, "open()");
                }
                if (ioctl(fd, TIOCEXCL) < 0) {
                        err(1, "ioctl(TIOCEXCL)");
                }
                if (tcflush(fd, TCOFLUSH) < 0) {
                        err(1, "tcflush(TCOFLUSH)");
                }
                if (tcflush(fd, TCIFLUSH) < 0) {
                        err(1, "tcflush(TCIFLUSH)");
                }
                if (tcgetattr(fd, &tios) < 0) {
                        err(1, "tcgetattr()");
                }
                tios.c_cflag |= (CREAD | CLOCAL);
                tios.c_iflag |= IXANY;
                tios.c_iflag &= ~(ISTRIP | ICRNL | INLCR | IXON | IXOFF
                        | IMAXBEL);
                tios.c_lflag |= ICANON;
                tios.c_lflag &= ~(ECHO | ECHONL);
                tios.c_oflag &= ~OPOST;
                if (tcsetattr(fd, TCSADRAIN, &tios) < 0) {
                        err(1, "tcsetattr()");
                }
                FD_ZERO(&fds);
                FD_SET(fd, &fds);
                timeout.tv_sec = 1;
                timeout.tv_usec = 0;
                tmesg = "BARH\r\n";
                tlen = strlen(tmesg);
                if ( (n = select(fd + 1, NULL, &fds, NULL, &timeout) ) < 0) {
                        err(1, "select() for write()");
                } else if (n == 0) {
                        fprintf(stderr, "select() for write() timeout.\n");
                        close(fd);
                        sleep(PAUSE);
                        exit(1);
                }
                if (write(fd, tmesg, tlen) < 0) {
                        err(1, "write()");
                }
                FD_ZERO(&fds);
                FD_SET(fd, &fds);
                if ( (n = select(fd + 1, &fds, NULL, NULL, &timeout) ) < 0) {
                        err(1, "select() for read()");
                } else if (n == 0) {
                        fprintf(stderr, "select() for read() timeout.\n");
                        close(fd);
                        sleep(PAUSE);
                        exit(1);
                }
                bzero(rmesg, 16);
                if ( (n = read(fd, rmesg, 15) ) < 0) {
                        err(1, "read()");
                        close(fd);
                        sleep(PAUSE);
                        exit(1);
                }
                printf("rmesg: %s\n", rmesg);
                close(fd);
                sleep(PAUSE);
        }
}

-----
kkdlabs.jp, featuring Koh-ichi Ito as just another DNS freak in town.

メールによる返信