syslog
syslog.confをはじめていじってみた。
最初の作品。
/etc/syslog.conf
*.info /var/log/0317Log
priorityがLOG_INFO以上(=LOG_DEBUG以外)を、/var/log/0317Log に出力するという設定ファイル
左側の、*.info 部分を セレクターフィールド
右側をアクションフィールドと呼ぶらしい(manpageより。。)
セレクターフィールドは、
hoge.hoge のように、ピリオドでふたつに区切られる。
左側にfacility
右側にpriority を記述する。
今回の設定ファイルでは、 facilityは*としており、すべてのfacilityについて、の、info プライオリティ以上について、アクションを行う を意味している。
※単に、facilityが良くわかんなかっただけ(^^;
で、この設定ファイルをsyslogデーモンに読み直させる必要があるんだけど、
これまたやりかたがよくわからなかったから、
ps -ef | grep syslog*
で、syslogdのPIDをみっけて、
kill その番号
で、いっかい切ってから、また、/sbin/syslogdで再起動したら、なんとかうまくいってた。。。
syslog.conf
*.info /hoge/hoge
を、のみとすることで、info未満のpriority、すなわち、LOG_DEBUGは、syslogされないわけだけど、
syslog(LOG_DEBUG,"***");
自体が呼ばれないというわけではない。
int main(void){ unsigned int i = 0; syslog(LOG_ERR,"ERR"); for(i=0;i<1000000;i++){ // syslog(LOG_DEBUG,"DEBUG"); syslog(LOG_ERR,"ERR"); } return 0; }
の実行結果が、
debian36:/home/play/0317# time ./a.out real 0m10.244s user 0m3.376s sys 0m6.864s
int main(void){ unsigned int i = 0; syslog(LOG_ERR,"ERR"); for(i=0;i<1000000;i++){ syslog(LOG_DEBUG,"DEBUG"); syslog(LOG_ERR,"ERR"); } return 0; }
の実行結果が、
debian36:/home/play/0317# time ./a.out real 0m25.071s user 0m7.544s sys 0m14.113s
なわけで、開発の進行度合によって、syslog.conf書き換えれば、ログ出力変え放題だぜぃ、
#ifdef DEBUG
なんていらないぜぃ
っていうのは、なし、、、っぽい。
なし、、、っぽい。
なし、、、なんだよね?
いくら出力されないからって、むだなsyslogをぽんぽん書いてたら、
処理的に重くなっちゃうんだよね?
そんなオモッタラシイコードを、製品に乗っけちゃうのはナシだよね・・・?
Makefile
/cygdrive/c/Users/play/0315/Makefile
all : make -C ./sub
/cygdrive/c/Users/play/0315 ディレクトリにおいて、
$ make -s /cygdrive/c/Users/play/0315/sub/ /cygdrive/c/Users/play/0315/
っちゅーこっちゃ。
`pwd` は、そこでコマンドを実際に実行するから、現在の作業ディレクトリ(sub)を示す
$(PWD)は、環境変数を表すだけで(Make内でのディレクトリ移動ではこの環境変数は
変わらない!?)、make が呼ばれたルートディレクトリをずっと示し続ける。
Makefile を書くときは注意です。
$(PWD)で、そのMakefileが置いてあるディレクトリを見ると思って clean とかやってたら、makeが最初に呼ばれたディレクトリのファイルをいつの間にか消しているみたいな・・・・(^^;
Makefile
make all
って打ったときに、
まずは、make clean して、ビルドしなおす、
のように、「あれをして、これをしてから、これをする」みたいにMakefileを書きたいとき。
たとえば、こんな風にMakefileを書くと、
all: 1 2 3 test.c gcc -o test test.c 1: echo '1' 2: echo '2' 3: echo '3'
$ make all echo '1' 1 echo '2' 2 echo '3' 3 gcc -o test test.c
のように実行できます。
Makeターゲット all は、1, 2, 3, test.c それぞれの”ファイル”に依存しており、
ファイル1は存在せず、make 1 が実行され、
echo '1' が実行される。
同じように、ファイル2は存在せず、 make 2 が実行され、
echo '2' が実行され・・・・
.PHONYとやらをしっかり使ったほうがいいのだろうけど、
とりあえず、 make all って打つだけで、あれやこれをしたいって時に!
スタブ
単体テストをしよう!
まずは、下位モジュール(他のモジュールに依存しないモジュール)を単体テスト。
で、それを使うモジュールを単体テスト。
で、それを使うモジュールを単体テスト。。。
のように、なんとなく考えてしまってたけど、これって単体テストではなくて、結合テスト(ボトムアップテスト)になってしまうんですね。
テスト済みの下位モジュールは、スタブのように扱えると思っていたのだけれど・・・
他のモジュールを組み込むことで、テストの結果に対して、本来のテストターゲット以外の要因が関わる可能性があります。
それは、テストの信頼性、テストの行いやすさを小さくしてしまいます。
スタブって、完成していないモジュールを代替する目的のみに用いるイメージを抱いていたけれど、
もし完成していたとしても、ピュアな単体テストを実行するために必要なものなんですね。
完成しているのにー
最終的には、その完成しているやつと一緒にシステムになるのにー
なんで、わざわざスタブをつくらなあかんのやー
って感じだけど、真の単体テストのために、スタブを作ります!!
ライブラリの依存関係
main.cがlibtest1.aに依存し、
libtest1.aがlibtest2.aに依存している場合のビルドは、
gcc main.c -ltest1 -ltest2
依存先を後ろにつけます。
では、ライブラリが双方向(相互)に依存している場合はどうするのか?
これまた、
gcc main.c -ltest1 -ltest2
でもいけるし、
gcc main.c -ltest2 -ltest1
でもいけちゃう。
「依存先は後」の法則(?)に忠実に、
gcc main.c -ltest1 -ltest2 -ltest1
とする必要はない(もちろんこれでも通る)。
この場合だと、
gcc main.c -ltest2 -ltest1
はリンクエラーで、
gcc main.c -ltest1 -ltest2
ならOK.
とりあえず、依存矢印の順にライブラリを指定していけばいいのかな。。。
リンク(リンカ)の仕組みをまったくしらないから、すっきりしない。
ちょっとずつ勉強していきたい〜
まぁ、ペイントでUMLを書くと意外に楽しいってことが分かっただけでも(^^;
■
http://itpro.nikkeibp.co.jp/article/COLUMN/20060313/232340/
「かつて自動車はエンジンで動いていたが,今動かしているのはソフトウェアだ」
これらのソフトウェアを実際に意識することはあまりないが(意識するときは,故障が起こった場合など,ろくでもないことが多い),経済産業省の調査ではメーカーが開発する機器のほぼ94%が組み込みシステムを搭載している。
自動車を動かしているのは、ソフトウェア
だが、
そのソフトウェアの存在はほとんど意識されない。
さらに、そのソフトウェアに求められる機能・納期・コスト等の要求は厳しくなるばかり。
http://d.hatena.ne.jp/fromdusktildawn/20080302/1204438490
仕事の経験が少ない人ほど、単に好きな仕事をすれば幸福感を味わえるという幻想に捕らわれている傾向にあると思う。
しかし、十数年も仕事をしてみて分かったことは、どうやら「やりがい」というものは、
自分を幸せにすることよりも、他人を幸せにすることで得られるものだということだ。
ソフトウェアを組み込みエンジニアは、自分の開発作業によって、製品を使う消費者が幸せになってくれるだろうと妄想を巡らすが、実際に消費者は、上記記事にあるように、「ソフトウェアの存在を意識していない」。
恩を押し付けているか?
外部からエンジニアの開発作業に対する「感謝」が得られないのであれば、
自発的に、「感謝」の存在を妄想するしかないのだろうか。。。
POSIX メッセージキュー リベンジ編
前回:http://d.hatena.ne.jp/debian36/20080220/1203510497
ちょっと前に挑戦して、うまくいかなかったPOSIX メッセージキューを用いたIPCプログラミング。
いろいろ試した結果、前回の ERRNO 90 (ELOOP) の原因は、
mq_receive 時のバッファサイズ指定ミスのようでした。
SysVのMsgQだと、メッセージキューそのものの属性がどうであろうと、
そのときに(msgrcvコール時に)取得するメッセージ以上のサイズをmsgrcv()のlength引数に渡せばよかったのですが、
POSIXのMsgQの場合、実際に格納されているメッセージのサイズがどうであろうと、対象となるメッセージキューに格納されうる最大のサイズを mq_receive() のlen 引数に渡さなければいけないようです。
そのため、mq_receive()する前に、
mq_getattr()を用いて、メッセージキューの属性として定義されている メッセージキューが保持できるメッセージの最大サイズ を取得しておく必要があります。
そのサイズをもとに、メッセージ受け取り用バッファ分のメモリを獲得し、
mq_receiveをコールします。
defs.h
#define QPATH "/msgQ" typedef struct{ char str[100]; }MSG;
enq.c
#include#include #include #include #include "defs.h" int main(void){ mqd_t qid; MSG obj = {"Hello POSIX MsgQ!"}; int ret; mq_unlink(QPATH); qid = mq_open(QPATH, O_RDWR|O_CREAT, S_IRWXU|S_IRWXO, NULL); printf("qid : %d\n",qid); ret = mq_send(qid, &obj, sizeof(MSG), 0); printf("ret : %d\n",ret); return 0; }
deq.c
#include#include #include #include #include #include "./defs.h" #include int main(void){ mqd_t qid; int ret; void* buf; struct mq_attr attr; qid = mq_open(QPATH, O_RDWR); printf("qid : %d\n",qid); mq_getattr(qid, &attr); printf("msgsize : %d\n",attr.mq_msgsize); buf = malloc(attr.mq_msgsize); ret = mq_receive(qid, buf, attr.mq_msgsize, NULL); printf("ret : %d\n",ret); printf("errno : %d\n",errno); printf("Received Message : %s\n",((MSG*)buf)->str); return 0; }
実行結果
debian36 # ./enq qid : 3 ret : 0 debian36 # ./deq qid : 3 msgsize : 8192 ret : 100 errno : 0 Received Message : Hello POSIX MsgQ!