FC2ブログ

2009年08月 の記事一覧

夏休み残り4日

今週は夏休みで実家に戻ってきている。
エンジン不調 because of バイオガソリン なVTZ250で、日曜の早朝に帰ってきた。

なぜお盆でなく今週かと言うと、引っ越し先を探すため。お盆は不動産屋さんも閉まりまくっているので、部屋を見ることができなかったりする。なので、お盆より後ろで夏休みを取ることにして、月曜に探してきた。

結論:東京は高い
   今住んでいるところは素晴らしい

ある程度田舎の方が自分には合っていると思った。
で、神奈川県内に引っ越そうと思っている。まだ確定じゃないけど。


引っ越しが決まれば、ここ4年連続で引っ越しをしていることになる。アホみたいだな・・・。来年は引っ越さないで済むように願おう。


今月ももう終わりか。何かあっという間だったな。
来週から残り4日間の勤務日をこなせば、会社に行かなくてよくなる。
が、現時点では全く実感がないなぁ。これから無事に生活していけるのか、かなーり不安だが、まぁ、何とかなるっしょ。とプラス思考で乗り切ることにした。人生そんなもんさ。
スポンサーサイト



pthread_cond_timedwaitを使ってみる(2)

pthread_cond_timedwaitの検索をして来る人が多いので、もう少し頑張って説明してみることにした。
と言っても、自分も完全に分かっているわけではないので、まぁ参考程度にということで。これでバグが生まれてても責任は持てないので。

ソース自体は前回とあまり変わっていない。
前回のソースが分かりにくくなっていた原因の1つ、スレッドを二重構造にすることをやめてみた。これだけで大分みやすくなったかと思う。

main()から直接スレッドを起動し、スレッドからのcond_signalもmainで直接受信するようになっている。

超おおまかな動作はこんな感じ。自分で書くのもアレだが、超分かりにくいのでソース見た方がいい。


main()からスレッドを起動し、mainでは起動スレッド数が0になるまでwhileでループ。
ちなみに、whileに入る前にmutex_lockしている。子スレッドではmutex_lockして起動スレッド数を減ずる処理を入れているため、このままではmainがwhileループにいる限り永遠に起動スレッド数を減ずることができない。

そこでcond_timedwaitが出てくる。
BSDのpthread_cond_timedwaitのmanによると、

The pthread_cond_timedwait() function atomically blocks the current thread waiting on the condition variable specified by cond and unblocks the mutex specified by mutex.

だそうだ。書いてあるとおり、mutexはunblockしてくれる。こういったことをふまえて、pthread_mutex_lock/pthread_mutex_unlock, pthread_cond_signal/pthread_cond_timedwait(cond_wait)をうまいこと組み合わせていく。

1つだけ注意を書いておくと、pthread_cond_signalはmutex_lockした状態で投げよう。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>


//----------
// 定数
//----------
#define THR_NUM     10       // スレッドの数
#define TIMEOUT     5        // タイムアウト(秒)


//----------
// プロトタイプ宣言
//----------
void *mainThread(void *arg);
void *childThread(void *arg);


//----------
// グローバル変数
//----------
int giThrNum = 0;        // 起動しているスレッドの数
pthread_mutex_t gMutexThrNum;  // mutex変数
pthread_cond_t gCondThrNum;   // 条件変数


//----------
// メイン
//----------
int main(int argc, char *argv[])
{
  int iCnt = 0;        // カウンタ
  int iFbRet = 0;       // 呼び出し関数戻り値
  pthread_t tId[THR_NUM];   // スレッドID
  struct timespec timeout;  // タイムアウト
  void *pRet;         // スレッド戻り値

  // mutex初期化
  pthread_mutex_init(&gMutexThrNum, NULL);
  // 条件変数初期化
  pthread_cond_init(&gCondThrNum, NULL);

  for (iCnt = 0; iCnt < THR_NUM; iCnt++)
  {
    // スレッド(childThread)起動
    iFbRet = pthread_create(&tId[iCnt], NULL, childThread, (void *)iCnt);
    printf("[main] pthread_create #%d: %d\n", iCnt, iFbRet);

    // 起動スレッド数をインクリメント
    pthread_mutex_lock(&gMutexThrNum);
    giThrNum++;
    pthread_mutex_unlock(&gMutexThrNum);
  }

  pthread_mutex_lock(&gMutexThrNum);
  // 起動スレッド数がゼロになるまで待つ
  //  mutex_lockしているので、この条件判定の間にgiThrNumの数が変わることはない
  while (giThrNum > 0)
  {
    // このwhile文の中では、pthread_cond_timedwaitしている間だけ
    // gMutexThrNumがunlockされる
    // なので、この間だけが子スレッドでgiThrNumを更新可能

    printf("[main] In while() before cond_timedwait\n");
    timeout.tv_sec = time(NULL) + TIMEOUT;
    timeout.tv_nsec = 0;
    // pthread_cond_timedwaitは内部でmutex_unlockしているので
    // mutex_lockした状態で用いてOK
    iFbRet = pthread_cond_timedwait(&gCondThrNum, &gMutexThrNum, &timeout);
    switch (iFbRet)
    {
    case ETIMEDOUT:     // タイムアウト
      printf("[main] pthread_cond_timedwait() timed out.\n");
      // スレッドの実行をキャンセル
      for (iCnt = 0; iCnt < THR_NUM; iCnt++)
      {
        // すでに実行終了しているものもあるが、エラーを無視してcancel
        pthread_cancel(tId[iCnt]);
      }
      return(-1);
    case EINVAL:      // timeoutの値がおかしかったりすると、EINVALが返る
      printf("[main] pthread_cond_timedwait() returned EINVAL.\n");
      // スレッドの実行をキャンセル
      for (iCnt = 0; iCnt < THR_NUM; iCnt++)
      {
        pthread_cancel(tId[iCnt]);
      }
      return(-2);
    default:
      break;
    }
  }
  pthread_mutex_unlock(&gMutexThrNum);
  printf("[main] After while() for cond_timedwait\n");

  // メモリリークしないようにpthared_joinしておく
  //  最初からdetachableでスレッド生成しろよな・・・
  //  どうせ戻り値使ってないんだから・・・>自分
  for (iCnt = 0; iCnt < THR_NUM; iCnt++)
  {
    pthread_join(tId[iCnt], &pRet);
  }

  return(0);
}


//----------
// 子スレッド
//----------
void *childThread(void *arg)
{
  int iCnt = 0;        // カウンタ

  printf("\t[childThread:%X] %d begin\n", (unsigned int)pthread_self(), (int)arg);

  // 適当な時間待つ
  srandom(time(NULL));
  iCnt = random() >> 7;    // 長すぎるとtimeoutしてしまうので、7bit右シフト
  for ( ; iCnt > 0; iCnt--)
  {
    // NOP
  }
  
  printf("\t[childThread:%X] %d end\n", (unsigned int)pthread_self(), (int)arg);

  // スレッド終了前にスレッド起動数を減じて、signalを送る
  pthread_mutex_lock(&gMutexThrNum);
  giThrNum--;
  pthread_cond_signal(&gCondThrNum);
  pthread_mutex_unlock(&gMutexThrNum);

  // mutex_unlockしたらすぐに終了すること
  pthread_exit(NULL);
}



まぁ、読めばわかるべ。
って説明してないじゃん・・・。


今回の例のように複数からsignalを受けることは多いかと思う。うまいことmutex_lock/unlockを駆使しよう。

VTZ250の燃費

忙しくてあんまり乗っていないVTZ250だが、今週末帰省するので給油してきた。

VTZ250は燃料メータが付いていない。なので、走行距離で給油のタイミングを判断する。 そして、買ってからまだ150kmくらいしか乗っていないため、買った直後に入れた1回が唯一の給油。

なので、今回から燃費を算出することにしよう。

前回メータをクリアし忘れたので、積算距離から逆算。前回は23,739kmで、今回は23,900kmで給油した。入れた量は5.77L。夏だし満タンは避けたいのだが、帰省で90km乗ることになるので問題ないと判断。なので、入れた量は乗った距離で使用した分ということになる。

ということは、
 (23900-23739)/5.77=27.9km/L
ということになる。

嘘くせぇ・・・。いくらなんでも走りすぎじゃねぇか?
確かにあんまり回さないで走ってるけど、それにしても走りすぎだろ。別に実家との道で高速には乗らないし、信号待ちはたくさんある。

まぁ、もう何回か計算すると精度が上がるだろう。


初回の給油で入れられてしまったバイオガソリンが少し薄まったはずだ。
バイオガソリンのせいでものすごく調子が悪い状態(エンジンが超かかりにくい、アイドリングが不安定、エンジンが暖まっていてもアイドリング中にエンストするときがある、など)だったのだが、これで少し改善してくれることを祈ろう。

会社辞めます

何か、「いまさら」って感じのネタだが。

来月いっぱいで会社を辞めることにした。
まぁ、ご存じの方も多いかと。

で、博士課程へ進学することにした。
って言っても、試験はこれから。
まぁ、何とかなるっしょ。

今日は退職願を提出した。人生初。面白くも何ともないけど、無事受理されましたとさ。
結構前から話しはしてあったし、決意は固めているという意思表示はしっかりしていたので、円満退職ということになるのかな。


別に会社が嫌になったとか、仕事がつまらないとか、そういうわけではないけど、
やっぱり自分の手がけた研究があまり進まないのは何か嫌なんだよねぇ。
独自に調べたりはしていたけど、仕事が忙しくなると離れてしまう。
その繰り返しでしっかりしたサーベイというのは出来ていない。

結局、どっちつかずはダメなんだろうな~ってこと。
当たり前か。

会社の嫌なところが無いとは言わない。
一番嫌なのは、好きなだけ時間を使えないということ。
労働基準法というものがあるし、ヒューマンリソースの投入量で給料が決まっていく体系だから残業できないのも仕方のないことだ。
けど、はまったことはとことんやりたいよね~っていうのが正直なところで、それが出来ないのは何か理不尽だ。まぁ、サービス残業をふんだんに使って対応したこともなくはないが。

色々と思うところはあるし、色々悩んだりもしたけど、結論は標記の通りというわけだ。


将来への不安がないとは言わないし、この先どうなるかなんて分からないけど、まぁ何とか生きていこう。

とりあえず、残りの勤務日(残り6日間の予定)はしっかりやりますかね。

スイッチング電源を作ろう(9)

【第9回】
 製作


※この連載を初めてご覧になる方は、まずこちらをご一読下さい
※前回の記事はこちら


随分時間が空いてしまったが、製作の様子を軽く紹介することにしよう。


■部品の配置と配線

前回書いたように、ユニバーサル基板を用いて製作する。まずはレイアウトに従って部品を配置していく。

なんのことはない。ただ部品を半田付けしていけばいい。
道具と部品を準備。

20090815 Switching Regulator, originally uploaded by pman0214.


【続きを読む】

初めてのエンジンオイル交換

夏になったことだし、エンジンオイルを交換することにした。

土日の度に天気が悪かったり、家事に負われたりして時間がなくなり、あんまり乗ってないのだが、まぁ、乗らなくてもエンジンオイルは酸化するし、来週帰省するときに乗っていくつもりなので変えようかなっと。

てなわけで、Castrolの10W-40を購入。40にしたのは夏だから。HONDA純正君でもいいんだが、たまたま10W-30しか置いてなかったので却下。

で、ドレンボルトを見てみると、あれまぁ、17mmのレンチが必要。
8x10, 12x14しか持ってないので、KTCの17x19を買ってきた。
しかし、ここにも罠が。近所の金物屋にあるのでいいやと思いきや、お盆休みだよーんって貼り紙が。他の店もそうだろうと思って、諦めてライコランドまで行ってきた。

まずはエンジンをかけてしばらく暖気運転する。2, 3分。冬ならもう少しかけた方がいいかも。アイドリングが規定になったらやめればいいらしいけど、そこはまぁ感覚的にOKかな~ってところまでで。ちなみに、やりすぎるとオイルがあっちっちになって火傷しちゃうかもしれないのでご注意を。

で、ドレンボルトを外すと、すごい勢いでオイルが出てきた。
どこにこんなに入ってるんだろうと思うくらい多い。そりゃまぁエンジンは二気筒だしたくさん入っとるか。
ポタポタ垂れるのが全然止まらなかったので、5分くらい放置。無事全部出た。

あとはドレンボルトをキレイにして、元通りに締める。締め付け強度が分からなくならないように外す前にマジックで印を付けておいたので、そこまで締める。

そして買ってきたオイルを入れる。簡単だ。
オイル交換時は1.8Lと書いてあったから、とりあえず、1.5Lくらいまでは何も考えずにガンガン入れる。で、オイル量をチェックする窓を見ながら少しずつ足していく。

まずは規定量をちょっとオーバーするくらいに入れる。
で、エンジン始動。しばらく暖気運転すると(夏だし2, 3分で十分)、オイルがまわって見た目は少なくなる。で、エンジン停止。

再びオイル量チェックの窓を見ると少なくなっているはず。なのでオイルをつぎ足す。今度は入れすぎないように規定量までにしよう。

これを何回か繰り返して規定量になれば完了。

注意!
エンジン停止後はしばらく待ってから窓を見る。
これにやられた。しばらく待たないとオイルは少なく見える。なので少し入れすぎてしまった。仕方がないので少し抜いた。

まぁまだ多少多いけど、やばいレベルではないのでよしということにした。


え?写真?汚い手でカメラを持ちたくないので撮影しなかった。
そのうち撮るかも。オイルを抜くまではほとんど手が汚れないし。

しかし、自分でいぢれるってのは楽しいね。

とりで利根川大花火

今年は家から手賀沼の花火が見られると思いきや、なんと不況の影響で花火自体が中止になってしまった。

無念。なので近所で花火をやらないか探したら、取手市が利根川で花火をやるのを発見。
で、それが今日だった。


20090808 Toride Fireworks, originally uploaded by pman0214.


コンデジで花火をキレイに取るのは割と難しい。
特に、自分の使っているカメラはレリーズタイムラグが非常に大きい上、フォーカスに時間がかかる。一瞬で終わってしまう花火の撮影には全く向いていないカメラだな。

まぁ、何とかマニュアルモードを駆使して撮影してきた。
煙とかも意外と拾っちゃうんだな。夜景はうまく撮れないと思ってたけど、思ったよりは性能がいいようだ。


20090808 Toride Fireworks, originally uploaded by pman0214.


ちなみに、一番キレイだと思った花火の写真はない。
なぜって、そりゃあ自分が見てたからに決まってる。だって、撮影してたら見られないし。


20090808 Toride Fireworks, originally uploaded by pman0214.


ともあれ、1:30以上に及ぶ花火をずっと見てた。
やっぱ一人で見るもんだな。

とりあえず、人はすごかった。ありえないくらい路駐が多くあり、シートとか用意して見てる人もいた。そこまでするか・・・。

そして、何よりもうざかったのが車。畑の中の道で見ていたのだが、まだ終わらないうちに(混まないうちに)帰ろうという魂胆なのか、人が見てるところでヘッドライトを煌々と点けて移動してくる。当たり前だが、周辺の人々もみんなウザがってた。だいたい、あんな位置まで車で行くなんてどうかと思う。

車から降りないで見ている人とかいたけど、あの音とかがいいんじゃないかね。冷房がそんなに好きなのか?
とりあえず、何も遮るものがないから風が割とあって寒かった。しかし、蚊にさされまくった・・・。


まぁ、何はともあれ、大満足だ。引っ越したくなくなってきたけど、そうもいかんだろうな・・・。さすがに遠いし。
無念・・・

Windows版Safariの罠

別に罠ってほどでもないんだけど。

会社で都合によりWindows版のSafariを使う機会ができた。
は、いいんだが、インストールしたらメニューがない。おいおい。
と思ったら、右の方にあった謎のボタンからメニューの表示に成功した。

さて、次はショートカット。メニューを選べないんだけど・・・。
昔の記憶をたぐり、Alt+Fとかではなく、F10を押してみた。おぉ。メニューが選べた。

え?でも、(F)とかがないから、矢印キーを使ってメニューを選ばないといけないの?
そりゃないだろ、Appleさんよぉ。

仕方がないので英語化してみる。設定にそれっぽいのがないので、きっとMacと同じだろうと思ってインストールディレクトリを覗いてみると、English.lprojフォルダとかがある。
なので、English.lproj以外を全部削除。
ところが、この.lproj、色々なフォルダに点在している。フレームワークとかってことか?
まぁともかく、全部なくす。English.lprojじゃなくてen.lprojなんてところもあるけど、そこはKYってことで。


で、Safariを起動すると無事に英語化に成功。Bookmark(B)とかなってるから、Alt+Bってしたら選択できた。要するに日本語版がクソだってことだな。


とはいえ、Top Sitesとか重すぎだろ。これは使い物にならない。
WindowsSafariは使うもんじゃないということがよく分かった。

Hyper EstraierでWeb検索

どんな会社でもあるでしょ。

全然整理されてないのに、情報が集約されてしまっているWebサーバが。

え?ない?
まぁ、ないに越したことはないよ。

でも、あった場合は困る。
何が困るって、そこの情報を見て何かしろという指示が飛ぶわけだけど、その情報とやらを発見できない。

なに?検索すればいい?
だから、その検索機能がないんだよ。


というわけで、非常に不便な思いをしているわけだが、文句を言っても対応されないらしいのでHyper Estraierでcrawlingして検索サイトを作ってしまうことにした。

幸いなことに、自分のいるプロジェクトで使っている割と高スペックなdebianマシンがある。ここにはapacheをはじめ、数々のアプリが入っているので、ここの上に構築することにした。

以下、メモがないので記憶によるもの。

1. hyper estraierをインストール
aptでおk。

sudo aptitude install hyperestraier


2. crawl用dir作成

sudo mkdir -p /var/estraier/casket
cd !$
sudo estwaver init .


3. crawl用_conf編集

sudo vi _conf

何を変えるかが問題だ。seedとlanguageは絶対直さないと。logfileは/var/log/estraier.logとかにしとけばいいだろ。proxy使ってる場合はproxy関連も設定必須。
あとはテキトーに。maxdepthやseeddepth(?)なんかを適宜設定して、strategyも変更する必要あり?
今回のように、イントラネット内のページに限定するのであれば、allowrxをうまいこと設定してやる。
詳細はこの辺でも見てくれということで。

4. crawlする

sudo estwaver crawl -revcont .


5. _indexをコピーする

cd ..
sudo cp -r casket/_index .


6. 検索ページを準備する

cd /usr/lib/cgi-bin
sudo ln -s /var/lib/estraier/estseek.cgi estseek.cgi
sudo ln -s /usr/share/hyperestraier/estseek.conf estseek.conf
sudo ln -s /usr/share/hyperestraier/estseek.help estseek.help
sudo ln -s /usr/share/hyperestraier/estseek.tmpl estseek.tmpl
sudo ln -s /usr/share/hyperestraier/estseek.top estseek.top


estseek.confを開いて、indexnameを変更する。

indexname: /var/estraier/_index


今回のようにWebを直接crawlingした場合は、replaceは不要なのでコメントアウトしておく。

7. estseek.cgiにアクセスしてみる
http://サーバ/cgi-bin/estseek.cgiに接続して検索してみる。ダメなら色々と見直せばいいんでないか?apacheのログとかもhelpになるかも。

8. cronから呼び出してcrawlする
面倒なので省略。crawlとコピーのコマンドだけ書いて/etc/cron.dailyとかに放り込めばいいだけだし。

9. logrotateとかしてみちゃう
logが激しいことになるから、logrotateとかで定期的に削除されるようにする方がいいかもね。/etc/logrotate.d配下にテキトーな設定ファイルを作ればいい。


てなわけで、記憶だけで書いてると間違っている可能性もあるわけだが、こんな感じで検索システムができたわけだ。

ていうか、こんなに簡単に入るんなら、同じシステムを情報集約してるWebサーバに入れてくれればいいと思うんだが。
そうすればhttpでアクセスしないで済むし、こちらとしてはありがたいのだが。

怠慢もいいかげんにして欲しいものだ。