割り込みメモ
割り込み
入出力処理中のプロセスは、割り込みによって入出力完了が通知されるまで実行権を手放します。
割り込み
- ハードウェア割り込み
- タイマー割り込み(タイマーコントローラが一定周期で割り込みを発生させる)
- 外部装置から
- プロセッサ間割り込み
- NMI割り込み
- ソフトウェア割り込み
- intn命令
- ハードウェア割り込み
- 例外 (CPUの動作自体によって引き起こされる事象)
- フォルト
- セグメントやページの保護機能
- トラップ
- INTO,INT3命令
- アボート
- 処理を継続できないようなエラー発生した時
- フォルト
割り込み、例外、それぞれにハンドラが設定してある。 通常の割り込みはマスクすることによってCPUが割り込みを受け取れないようにすることができる。
ハードウェア割り込みハンドラの起動
- 外部装置
- 割り込みコントローラに対して割り込み要求
↓
- 割り込みコントローラ
- そのデバイスからの割り込みが禁止されていな ければ、CPUに対して割り込み要求を行います
↓
- CPU
- 処理中断。割り込みエントリ関数do_IRQ()呼び出し
↓
- do_IRQ()
応答性の確保
応答性を必要とするものはハードウェア割り込みハンドラで実行 必要の無いものは後でまとめてソフト割り込みで実行
ハードウェア割り込み
- デバイスドライバへの通知手段として利用。目的のデバイスドライバが用意している割り込みハンドラを呼び出す。
- ドライバ読み込み時に、割り込み処理テーブルの各割り込み種別(IRQ)にドライバのハンドラを登録している
- 一つのIRQのエントリに複数の割り込みハンドラを登録できる
- マスク負荷割り込み(NMI)は必ず割り込むことができる。
ソフト割り込み
- ソフトウェア割り込みとは異なる
- ソフト割り込みは、ハードウェア割り込み処理が要因となり発生します。ソフト割り込みハンドラは、ハードウェア割り込みハンドラで行った処理を引き継ぎ、動作します。
- ハードウェア割り込みと連携、効率的に動作する。
- ハードウェア割り込みを禁止しない
- ソフトウェア割り込みとは別枠
- do_softir()
割り込みは素早くやる必要あり。よってソフト割り込みが利用される。 ソフトウェア割り込みでは普通にスケジューリングされる?
時計メモ2
時計
- 世界標準時1970年1月1日0時からの経過時間をxtime変数に記録することで時計を実現しています
- Linuxカーネル起動時にハードウェアカレンダの値で初期化された後は、一定周期に動 作するグローバルタイマー割り込みハンドラ(do_timer関数)で時刻が進められます。
- 1970年1月1日0時からの経過時刻(秒数)で表現している。
- 時間の経過はタイマー割り込みで通知。タイマー割り込みごとに少しずつ進めている。
- dateコマンドを実行すると(timeシステムコール、gettimeofdayシステムコールを呼び出すと)、 Linux内部時計の時刻を得ることができます。
役割
時間の管理と時限処理
ハードウェアのカレンダ
- 本質的にLinuxとは無関係の世界で独自に時刻を刻んでいます。Linuxカーネルは、起動時にハードウェアのカレンダをLinux内部時計(xtime変数)に反映させます。そのあとは、原則Linux内部 時計とハードウェアのカレンダの同期は行いません。 シャットダウン時などにシステムクロックとハードウェアクロックを同期させているみたい。
xtime変数
世界標準時1970年1月1日0時からの経過時間をxtime変数に記録
jiffies
- Linuxカーネル起動時を0とする時刻です。これはLinuxカーネル起動後に発生したタイマー割り込みの回数を数えることにより実現しています
- Linux内部の時限処理のベースとしてのみ利用されています
- 通常時にはこの値は変更できません。jiffiesの値はタイマー割り込みハンドラ(dojimer関数)のみが変更可 能で、唯一、マシン再起動によってリセットされます。
3つの時計
グローバルな時計処理割り込み(グローバルタイマー割り込み) ハードウェア割り込み
- システムの時刻を進めることが目的
- システム上のいずれかのCPUに対して割り込みが発生する
- グローバルタイマー割り込み → do_timer()
CPUローカルな時計処理(ローカルタイマー割り込み) 八一ドウェア割り込み
- smp_locaLtimer_interrupt()がハンドラ → run_timer_softirq() ソフト割り込みハンドラ
- タイマーリストを監視するみたい
do_timer() ハードウェア割り込みのハンドラ
- システム起動後に発生したタイマー割り込みの回数を記録するjiffies変数にl
- clac_load(ticks)ロードアベレージ(システム負荷)を計算
グローバルタイマー割り込みの遅延
高負荷時に、グローバルタイマー割り込みハンドラが期待どおりに動作せず、複数のタイマー割り込みに対し、1回だけグローバルタイマー割り込みハンドラが動作する可能性があります。そのまま普通にタイマー割り込みハンドラ(do-timer関数を実行すると、時刻が遅れることになります。アーキテクチャ依存ですが、この遅れを検出し、正常な時刻に設定し直す機能が実装されています。
タイマーリスト
- Linuxも伝統的なUNIXと同様に、登録した一定時間後にコールバックされるハンドラを登録するための、汎用の仕組みを備えています。
- とくにネットワークプロトコル 処理やデバイスドライバ処理におけるタイムアウト処理、再実行処理に数多く利用
- Linuxカーネルでは、実行してほしい時刻を指定して、ハンドラを登録します。ここでは説明のために、実 行してほしい時刻のことを起動時刻と呼ぶことにします。起動時刻を指定してタイマーリストにハンドラを登 録しておくと、ローカルタイマーソフト割り込みハンドラがこの起動時刻を監視し、指定した時刻が来たとき に登録したハンドラを呼び出してくれます
まとめ
グローバルもローカルもタイマー割り込みはハードウェア割り込み
Linuxの時計
概要
時計メモ
メモ
ノート: デフォルトでは systemd はハードウェアクロックに UTC を使用します。
用語
ハードウェアクロックまたはリアルタイムクロック(RTC)
- マザーボードが持つ内部時計であり、BIOS クロックやCMOS クロックとも呼ばれます。マザーボード上の IC に実装
- CentOSではデフォルトではハードウェアクロックをUTCを標準時を参照しているように考えてシステムクロックを設定するみたい。
- LINUXが起動する時に一度だけ参照。
- また、RTCはさほど精度が高くないこともあり、定期的にインターネット上のNTPサーバーから現在時刻を取得しRTCに書き込むということも行われます。最近のWindowsではデフォルトでマイクロソフトのNTPサーバーを参照しています。
- MacやLinuxでは、RTCからUTC(協定世界時)を設定しておきOS側でタイムゾーンや夏時間の時差を足し引きしてローカルタイムを表示しているようです。
システムクロック
- 一般的に、UTC を使う OS は起動時に CMOS (ハードウェアクロック) の時間を UTC 時間 (GMT, Greenwich time) だと認識して、あなたのタイムゾーンによってその時間を調整してシステム時刻を設定します。
- OSは起動されるとハードウェア クロックの時刻情報を読み出し、基準時刻からの経過秒数の形式に編集してOSが管理するメモリ内にシステム クロックとして格納します。
- システムクロックの更新はタイマー割り込み毎に加算され、基準時刻からの経過秒数で現在の時間を運用(時計の進行)する。
NTPの必要性
- ログの時間の整合性をあわせるなどなど、ネットワーク内の複数のシステムで同じ時間に合わせる必要があるのでNTPを利用する。
- 時間が正確
- /etc/ntp.conf でntpサーバを設定。ntpdを起動させる。
- 即時に合わせる場合、nttdate ntpサーバで合わせることができる。
まとめ
工場でマザーボード作成。現在の時間設定される。以後動き続ける。
↓
届く
↓
Linuxサーバ設定、起動
↓
起動時にRTCを参照。 LinuxではRTCをUTCをとして認識、そこからlinuxのタイムゾーンにあった時間に変換(システム クロックの設定)
↓ 運用
システムで時間を統一する必要ntpの導入(システムクロックの値はntpdから取得)
↓
問題
- RTCはずれる。「ハードウェア クロックはあまり正確ではない」と言われているくらいらしい
- RTCがずれたままだど再起動する度にずれた時間が設定される。(ntpdで修正されるも即時ではない場合、時間がかかる)
↓
システムクロックとRTCを同期する。 デフォルトでタイミングは再起動やシャットダウン
これでRTCとシステムクロック同期するのでずれない。 また、NTPで各サーバーの時間も同期。NTP使うので時間は正確。
参考
メモリメモ
コピーオンライトがあるのでスレッドよりもプロセスが重いなんてことはない。昔の話。
# cat /proc/meminfo MemTotal: 1020096 kB MemFree: 71060 kB Buffers: 45848 kB Cached: 762244 kB SwapCached: 5980 kB Active: 183652 kB Inactive: 668244 kB Active(anon): 13576 kB Inactive(anon): 30580 kB Active(file): 170076 kB Inactive(file): 637664 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 5079036 kB SwapFree: 5054380 kB Dirty: 248 kB Writeback: 0 kB AnonPages: 38924 kB Mapped: 12704 kB Shmem: 308 kB Slab: 76584 kB SReclaimable: 22564 kB SUnreclaim: 54020 kB KernelStack: 1600 kB PageTables: 2288 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 5589084 kB Committed_AS: 157228 kB VmallocTotal: 34359738367 kB VmallocUsed: 8340 kB VmallocChunk: 34359717896 kB HardwareCorrupted: 0 kB AnonHugePages: 2048 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 8180 kB DirectMap2M: 1040384 kB
物理メモリの配分
64ビットではLowメモリとHighメモリの区別もなくなる 全てのメモリ領域がカーネルが利用できるLowメモリ領域として認識される ユーザーメモリとカーネルメモリ
ユーザメモリの分類
Anonymous (anon)
プログラムの実行中に動的に確保したメモリ。mallocとか。
File-backed(file)
ディスクキャッシュなど、ディスク上にもある種類ものと対応がある。
active
最近利用
inactive
長時間利用されていない
4種類のLRUリスト(Least Recently Used)
- anon(active)
- anon(inactive)
- file(active)
- file(inactive)
プラス
- 原理的に開放できないもの Unevictableリスト
移動する
- メモリの状況によって移動する。
- anon(active) ←→ anon(inactive)
- file(active) ←→ file(inactive)
カーネルメモリの分類
- そもそも仮想空間ない。物理に直接
- そもそもカーネルでは2つのメモリ管理
- データの形式によって事前に2つの方式でまとめて確保している
- Buddyシステム(Buddyアロケータ)
- 4Kb以上
- Slabアロケータ
- 4KB以下
- Buddyシステム(Buddyアロケータ)
- vmalloc()
strace
概要
straceの使い方についてのメモ
スレッド
$ strace -p 3887 Process 3887 attached futex(0x7fc579e0b9d0, FUTEX_WAIT, 3889, NULL^CProcess 3887 detached
上記コマンドを打ったところ、プロセスはちゃんと働いているはずなのにここで止まってしまった。 そのプロセスからforkしたプロセスも対象にいれないといけませんでした。
$ strace -f -p 3887
これでドバーとシステムコールが表示される。
オプション
$ strace -ttT -ff -o ~/strace-log -p 3887
- tt: 行頭にタイムスタンプをマイクロ秒単位で出力
- T: 行末にシステムコール内での所要時間を出力
- ffとo:この2つを組み合わせることで
strace-log.スレッドID
毎にstraceのログを出力してくれる
$ strace -ttT -fc -p 3887 % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 38.39 0.206970 10893 19 epoll_wait 36.90 0.198972 1442 138 46 futex 21.14 0.113984 18997 6 4 restart_syscall 3.13 0.016853 624 27 mmap 0.35 0.001882 1 2746 clock_gettime 0.05 0.000292 4 82 unlink 0.03 0.000164 4 44 munmap 0.00 0.000022 0 293 write 0.00 0.000013 0 1011 6 lstat 0.00 0.000000 0 15 read 0.00 0.000000 0 32 open 0.00 0.000000 0 34 close 0.00 0.000000 0 115 stat 0.00 0.000000 0 166 fstat 0.00 0.000000 0 4 mprotect 0.00 0.000000 0 1 rt_sigprocmask 0.00 0.000000 0 44 sched_yield 0.00 0.000000 0 1 madvise 0.00 0.000000 0 469 gettimeofday ------ ----------- ----------- --------- --------- ---------------- 100.00 0.539152 5247 56 total
cで統計表示。便利。
SystemTap Man
systemtapを動かすには
- 実行しているカーネルの kernel-devel
- 実行しているカーネルの kernel-debuginfo
- 実行しているカーネルの kernel-debuginfo-common
- gcc
- systemtap
kernel-debuginfo
とkernel-debuginfo-common
debuginfo-install kernel
でお目当てのバージョンをインストールする。
$ debuginfo-install kernel --skip-broken ============================================================================================================================================== Package Arch Version Repository Size ============================================================================================================================================== Installing: kernel-debuginfo x86_64 2.6.32-642.15.1.el6 base-debuginfo 282 M Updating: yum-plugin-auto-update-debug-info noarch 1.1.30-40.el6 base 27 k Installing for dependencies: kernel-debuginfo-common-x86_64 x86_64 2.6.32-642.15.1.el6 base-debuginfo 46 M Skipped (dependency problems): kernel-debuginfo x86_64 2.6.32-642.6.2.el6 base-debuginfo 282 M kernel-debuginfo x86_64 2.6.32-642.11.1.el6 base-debuginfo 282 M kernel-debuginfo x86_64 2.6.32-642.13.1.el6 base-debuginfo 282 M kernel-debuginfo x86_64 2.6.32-642.13.2.el6 base-debuginfo 282 M Transaction Summary ============================================================================================================================================== Install 2 Package(s) Upgrade 1 Package(s)
Version、 2.6.32-642.15.1.el6
OK
これで残りもインストールできたらsystemTapが使える。実際に使えた。が、インストールした翌日に再び実行してみると下記の様なエラーがでるようになった。
emantic error: missing x86_64 kernel/module debuginfo [man warning::debuginfo] under '/lib/modules/2.6.32-642.15.1.el6.x86_64/build'
よくよく調べるとyum-cronが走り。centos.plusたるものにアップデートされてた。
Packages Altered: Updated kernel-debuginfo-2.6.32-642.15.1.el6.x86_64 @base-debuginfo Update 2.6.32-642.15.1.el6.centos.plus.x86_64 @base-debuginfo Updated kernel-debuginfo-common-x86_64-2.6.32-642.15.1.el6.x86_64 @base-debuginfo Update 2.6.32-642.15.1.el6.centos.plus.x86_64 @base-debuginfo
yum install kernel-debuginfo
だと、centos.plusのやつが入るみたい。
入れ直し必要。