Daily Grind

システム開発関連の忘備録です

システム情報の取得

[システム情報]

1.「スタートメニュー」→「すべてのプログラム」→「アクセサリ」→
「システムツール」メニューにある「システム情報」を選択します。
2.「システム情報」のツールにおいて、「システムの概要」を選択し、
「ファイル」→「エクスポート」を選択します。
3. 任意のファイル名で保存したファイルを採取します。

[環境変数の情報]

現象が発生したPCにおいて、コマンドプロンプトで以下のコマンドを実行した後、
envval.txtを採取します。
set > envvar.txt

[イベントログ]

現象が発生したPCにおいて、イベントビューアを使用して、コンテキストメニューから
「ログ ファイルの名前を付けて保存」を選択することで以下のイベントログをテキストで
採取します。
・アプリケーション
・システム

ARPについて

本来、ARPパケットは、通信先したい宛先のIPアドレスに対する
MAC(物理)アドレスを求める目的で、ARPリクエストやARPリプライが送受信
されますが、(※RFC-827を参照のこと http://tools.ietf.org/html/rfc826)

その後、このARPをそれ以外の目的でも利用されるようになり
以下のようなARPが存在しています。

(※RFC-5227を参照のこと http://tools.ietf.org/html/rfc5227)

Gratuitous ARP(GARP)

GARPは、自身のIPアドレスと同じIPアドレスの機器が存在しないか確認するため
SenderIPとTargetIPに自身の機器と同じIPアドレスを指定した
ブロードキャストARPリクエストとなります。

Probe ARP

Probe ARPは、GARPから派生したARPで、SenderIPは、何も指定しない(0.0.0.0)で
GARP同様にブロードキャストARPリクエストを送信するARPになります。

通信先の機器に探索にGARPを用いた場合、通信先の機器の機器で
IPアドレス重複が検出されてしまい、最悪の場合、そのIPアドレスが利用できなく
なってしまいます。

そこで登場したのが"Probe ARP"です。

Probe ARPの場合、SenderIPが0.0.0.0のため、既にIPアドレスが割り当てられている
機器については、IPアドレス重複は発生しません。

Colasoft Packet Builder

フリーウェアで提供されている Colasoft Packet Builder が強力です。
http://www.colasoft.com/jp/packet_builder/?top=prover&sig...Colasoft Packet Builder- Colasoft


パケットの順序変えたり、パケット間の時間調整したり、ロストさせたり、
コピーしたり、別のパケット挿入したり、さらにさらにパケット内を
Wireshark並みに表示して書き換えができます。

Check SUM値などは自動計算してくれます。

ためしに、HTTPヘッダに1つ追加(INSキーであけて、TEST: ABCと書いて、
バイト列側で 0D 0A とタイプ)したら、ちゃんとヘッダも追加できました。

ただ、このままWiresharkで見たら、パケットが正しく表示されない。
IPフレームの Length は自動で変更してくれないようです。
TEST: ABC[CR][LF] 分の+11してみたら、見事表示できました。

GCCのマクロ

色々なところに、文献あると思いますが、とりあえず以下。
https://www.ibm.com/developerworks/jp/linux/library/l-gcc-hacks/


GCC の中に、ビルトインでマクロが用意されています。
基本的に、カーネルで使用する記述になっていますが、GCCのマクロですので
ユーザ空間でも使用可能なものもあります。

その中で、性能改善に有効なもの(ドライバで良く使用)を紹介します。

・分岐予測のヒント

#define likely(x)	__builtin_expect(!!(x), 1)
#define unlikely(x)	__builtin_expect(!!(x), 0)

※ ユーザモードのコンパイルでは、上記マクロは未定義なので
自分で定義する必要があります。

// 使い方 1
// 以下の例の場合、コンパイラは、likely判定を先に行うアセンブラ命令
// 出力します。 優先する予測情報をコンパイラに与えます。
// 処理として、良く走るところを 優先として登録します
if ( likely( a == 1 ) ) {
printt(" ok ");
} else {
print(" ng ");
}
// 使い方 2
// よくある エラー判定には、unlikely を 設定すると 正常に処理された
// ret == 0 が先に 判定されて、性能改善になります
ret = ioctl();
if ( unlikely( ret != 0 )) {
printf(" NG");
return(ret);
}

うるう秒について

うるう秒

たとえば、日本時間 2012 年 7 月 1 日 9:00 にうるう秒が挿入されている。
「08:59:59」の次の時刻に「08:59:60」が入る。

 +―――――――――+―――――――――-+――――――――――――――――――――+
 | 日本標準時 JST  | NTPDを使っている | NTPを使っていない           |
 | 2012/07/01    | (STEPモード   +――――――――――-+――――――――+
 |         | デフォルト)[※1] | TZDATA更新済み[※2] | 未対策[※3]  |
 +―――――――――+―――――――――-+――――――――――-+――――――――+
 | 08:59:59     | 08:59:59     | 08:59:59      | 08:59:59    |
 +―――――――――+―――――――――-+――――――――――-+――――――――+
 | 08:59:60     | 08:59:59     | 08:59:60      | 09:00:00    |
 +―――――――――+―――――――――-+――――――――――-+――――――――+
 | 09:00:00     | 09:00:00     | 09:00:00      | 09:00:01    |
 +―――――――――+―――――――――-+――――――――――-+――――――――+

[※1]:ntpdが有効な場合、標準のstepモード(大体これで運用されている)

  ・うるう秒 08:59:60 (JST)挿入時、08:59:59 を繰り返す(時間遡行)
  ・ntpd に ‘-x’ オプション(slewモード)を有効にすると、うるう秒を挿入せず、ゆっくり時間補正する
   しかし、ntp-4.2.2p1-9 以下の ntpd では、-x オプションをつけても時間が遡行する
  ・kernelが古い場合は、クラッシュする可能性がある
    ○問題のあったバージョン
    ・v2.6.22 以降のkernel
      ※v2.6.22 以前のkernelは問題なし
    ○対応されたkernel(以降のkernelであれば問題なし)
     ・SLES11 SP1 x86_64 kernel >= 2.6.32.59-0.7.1
     ・SLES11 SP2 x86_64 kernel >= 3.0.38-0.5.1
     ・SLES11 SP1 i386 kernel >= 2.6.32.59-0.7.1
     ・SLES11 SP2 i386 kernel >= 3.0.38-0.5.1
     ・RHEL4 | kernel-2.6.9-89.EL (RHSA-2009:1024-1) 以上
     ・RHEL5 | kernel-2.6.18-164.el5 (RHSA-2009:1243-3) 以上

STEPモード

   STEPモードでは不連続に一度に時刻を調整するため、時刻がずれている場合は
   すぐに正しい時刻に調整されていきますが、時間の逆行が発生する可能性が
   あります。これによりソフトウェアに不具合が起きることがあります。

SLEWモード

   SLEWモードは、時間を逆行させることはせず、最大でも0.5msずつ徐々に
   時間をずらしていきます。時刻がずれている場合には正しい時刻に調整する
   にの膨大な時間がかかります。
   例えば10秒ずれていると、これを調整するのに20000秒必要になります。

[※2]:TZDATA更新済みの場合(2015年のうるう秒を含んだtzdataパッケージにアップデート、かつ、うるう秒を含んだタイムゾーンを指定している場合

  ・ntp を動かさなくても、08:59:60 がカウントされる
  ・ただし、08:59:60 秒をカウントしても、許容されうる環境のみ推奨

[※3]:ntpdを入れていない場合

  ・世間から「1秒」時刻が進む

 ※参考URL
  http://hiroki.jp/leap-second-2015
  http://pocketstudio.jp/log3/2012/06/23/leaptime_2012/

コアダンプ設定

1.コアダンプ設定

■[Linux] coreファイルについて
 http://qiita.com/suzutsuki0220/items/aa84d7e2e8f37e867f3d
 
 システム起動時に起動するプロセスで、常にcoreファイルを出力するようにしたい場合
 
 initスクリプト(/etc/init.d/XXXX)で /etc/rc.d/init.d/functions を読み込む前に以下の行を追加する

   DAEMON_COREFILE_LIMIT=unlimited

 ※ /etc/rc.d/init.d/functions の中で DAEMON_COREFILE_LIMIT の値でulimitを実行するようになっている。
 functionsのスクリプトが無い環境の場合は、initスクリプトの中でulimitコマンドを実行するようにしてください


■ulimitの設定をOS再起動後も各デーモンに反映させる
 http://tsunokawa.hatenablog.com/entry/20130515/p1

 CentOS6系
   /etc/sysconfig/init

2.デーモン側でコアダンプさせる方法

 1のやり方とは別方法になるが、デーモン側でコアダンプさせる方法もある。

#include <sys/resource.h>
#include <sys/prctl.h>

struct rlimit	lmtbuff;

ret = getrlimit(RLIMIT_CORE, &lmtbuff);

if (!ret) {
	syslog(LOG_INFO, 
		"INFO! [debug] rlimit max=[%lu] cur=[%lu].",
		lmtbuff.rlim_max,
		lmtbuff.rlim_cur);

	if ((lmtbuff.rlim_max != RLIM_INFINITY)	|| 
		(lmtbuff.rlim_cur != RLIM_INFINITY)) {

		ret = setrlimit(RLIMIT_CORE, &lmtbuff);

		if (ret){
			syslog(LOG_INFO,
			"INFO! [debug] setrlimit failure. (%s)",
			strerror(errno));
		}
	}
}
else {
	syslog(LOG_INFO,
		"INFO! [debug] getrlimit failure. (%s)",
		strerror(errno));
}

ret = prctl(PR_SET_DUMPABLE, 1);

if (ret){
		syslog(LOG_INFO, 
		"INFO! [debug] prctl failure. (%s)", 
		strerror(errno));
}