wait.c

はい、いつものように、突然のよくわからないものです。

でもこれが結構大事で、
wait.c内に、ファイルディスクリプタを指定時間監視し、入力または出力があったら1を返し、指定時間経過してもなければ0を返す、
そんなwait関数を作っております。
ファイルディスクリプタという事は、もちろん0(標準入力)や、1(標準出力)にも使えますし、
特に使いやすいのがTCP接続なんかでのソケットの監視です。
ファイルディスクリプタと同様にして、そのソケットに入力があるかどうか、指定時間監視できる、
つまりタイムアウトなんかに使えます。
wait.cで使っているのは、select関数です。
ファイルディスクリプタを指定時間監視して、即時読み込み、書き込み可能であれば、その可能なディスクリプタの個数を返します。
manで見るとわかると思いますが、なかなか分けのわからない仕組みをしています。

やることは、
① fd_setというファイルディスクリプタのリストを宣言
② FD_ZEROでそのリストを初期化
③ FD_SETでそのリストにファイルディスクリプタを追加
④ select関数を、うまく使う。
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
・nfds…fd_setに含まれてるファイルディスクリプタの最大値+1(なぜこれを入れるのか謎)
・readfds, writefds, exceptfds…該当するところにfd_setのアドレスをいれる。なければNULL
・timeout…timevalのアドレスを入れる。
timevalは、
struct timeval {
               long    tv_sec;         /* 秒 */
               long    tv_usec;        /* マイクロ秒 */
           };
となっているので、うまく宣言すればOKです。

というわけで、wait.cは下のような感じになりました。
#ifndef _WAIT
#define _WAIT

#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

int wait(int fd, int time_ms, int RorW){
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(fd, &fds);
   struct timeval tv = {time_ms / 1000, (time_ms % 1000) * 1000};
   if(RorW == 0) return select(fd + 1, &fds, NULL, NULL, &tv);
   else return select(fd + 1, NULL, &fds, NULL, &tv);
}

#endif