Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ふつうのLinuxプログラミング-プロセスとハードウェア

sksat
June 09, 2020

 ふつうのLinuxプログラミング-プロセスとハードウェア

研究会の輪講でやったやつ.多少がんばった&評価も高めだったし使いまわせそうなので上げておく.

sksat

June 09, 2020
Tweet

More Decks by sksat

Other Decks in Programming

Transcript

  1. #11
    プロセスと
    ハードウェア
    B2 sksat

    View Slide

  2. おさらい:デジタルデータの表現
    ・ビット(bit):情報の最小単位
    ・0/1, yes/no, ON/OFF, +/-, N/S
    ・2進数の1桁
    ・バイト(byte):8bit
    ・電子計算機ではデータをだいたい
    1〜数バイト単位で処理
    ※実は1byte != 8bit.まあほとんどは8bitだが...(明示的に8bitだと言う場合はオクテット)

    View Slide

  3. コンピュータの構造(迫真)
    :thinking_think:
    ホンマか?

    View Slide

  4. 皆さんのお手元のThinkPad X230

    View Slide

  5. バラバラ事件
    これを
    こうして こうじゃ

    View Slide

  6. マザーボード
    HDD
    メモリ
    CPU
    ファン

    View Slide

  7. メモリ
    ・データをたくさん置いておける
    (1,2,4,8,16,32,64...GB)
    ・1次記憶・主記憶
    ・揮発性:電源切るとデータが消える
    ・アドレス(番地)を指定してデータを読み書き
    ・byteごと
    data

    0x0000
    0x0001
    0x0002
    0x0003
    0x0004
    0xffff
    0xfffe
    0xfffd
    0xfffc
    0xfffb

    View Slide

  8. メモリの読み書き
    0xaf
    0xbe
    0xad
    0xde

    0x0000
    0x0001
    0x0002
    0x0003
    0x0004
    0xffff
    0xfffe
    0xfffd
    0xfffc
    0xfffb
    CPU
    \addr=0x002のデータが1byteホシイ/
    0xab
    \addr=0xfffeに0xabを入れたい/
    0xad
    0xab

    View Slide

  9. バス
    ・メモリ読み込み
    ・CPU:アドレス→アドレスバス
    ・メモリ:memory[addr] -> データバス
    ・メモリ書き込み
    ・CPU:アドレス→アドレスバス
      書くデータ→データバス
    ・メモリ:memory[addr]

    View Slide

  10. レジスタ
    ・CPUの中にも記憶領域がある
    ・レジスタは小さい(8〜64bit)
    ・メモリよりはるかに高速
    ・メモリが作業机ならレジスタは手とか
    ・用途によって色々ある
    x86のレジスタ

    View Slide

  11. HDD/SSD
    ・2次記憶装置
    ・不揮発性:電源切ってもデータが残る!
    ・OS/プログラムはここに保存
    ・起動したらメモリに読み出してから動作
    ・容量がデカい:数百GB〜数TB
    ・ブロックデバイス:「ブロック
    (512byteとか)」ごとに読み書き

    View Slide

  12. 記憶装置
    記憶容量: 2次記憶(HDD/SSD) >>> 1次記憶(メモリ) >>>>>>> レジスタ
    ・ぜんぶ2次記憶でいいじゃん
    アクセス速度:レジスタ >>>>>>> 
    1次記憶 >>>> 2次記憶
    ・それだと遅すぎる!!!!!
    ・レジスタはCPUの内部なので超高速
    容量当たりの価格: レジスタ >>> 
    1次記憶 >>> 2次記憶
    ・でも2次記憶装置は安い
    ・2次記憶でもHDDは低速安価大容量,SSDは高速高価低容量(比較的)

    View Slide

  13. メモリのアクセス速度
    ・メモリ:数十〜数百サイクル
    ・昔はCPUの動作速度が大したことなかったのでなんとかなった
    ・今:CPU「俺の”速さ”についてこられるかな?」
    ・int a = 1 + 2; ← a, 1, 2がレジスタかメモリ上かで数十〜数百倍速度が変わってしまう!?
    ・コンパイラの最適化でできる限りレジスタが使われるようになってる
    ・めでたしめでたし・・・とはいかない
    ・思い出すシリーズ:レジスタはクソ小さい
    ・じゃあどうすんねん

    View Slide

  14. キャッシュメモリ
    ・レジスタとメモリの中間の存在
    ・もちろんメモリより低容量高価格だが高速
    ・レジスタとメモリの間に挟む
    レジスタ
    キャッシュメモリ
    メモリ
    3次キャッシュ
    2次キャッシュ
    ・最近は2, 3, 4次キャッシュなんてものも

    View Slide

  15. キャッシュメモリのしくみ
    ・発想:アクセスしそうなデータがいいかんじに
    キャッシュに載っているとうれしい!
    メモリ
    キャッシュメモリ
    addr=0x01, data=0xbe
    addr=0x03, data=0xde
    addr=0x05, data=0xba
    addr=0x09, data=0x1f
    0x00: 0xef
    0x01: 0xbe
    0x02: 0xad
    0x03: 0xde
    0x04: 0xbe
    0x05: 0xba
    0x06: 0xfe
    0x07: 0xca
    0x08: 0x8b
    0x09: 0x1f
    0x0a: 0x00
    addr=0x0a, data=0x00

    View Slide

  16. キャッシュメモリのしくみ(2)
    ・「アクセスしそうなデータ」とは?
    ・時間的局所性:同じアドレスに何度もアクセスする
    ・空間的局所性:アクセスしたところの近くにアクセスする
    ・方式がいくつかある:ダイレクトマップ,セットアソシアティブ,フルアソシアティブ

    View Slide

  17. デバイスとのやりとり
    ・入出力命令
    ・入力:ちょっとN番のデバイスから値を取ってきて
    ・出力:ちょっとN番のデバイスにこれをセットして
    ・割り込み:デバイス「カンカンカンカン!!!入力!!!!おきてー!!!!!」
    ・MMIO

    View Slide

  18. MMIO
    ・Memory Mapped I/O
    ・メモリとデバイスが繋がっている
    (!?)
    ・マイコンだとよくある
    ・PCだとVRAM(Video RAM)
    ・「(x=10, y=20)を紫に」とかを入出力命令でやってたら遅すぎる
    ・メモリの一部の領域がディスプレイと接続
    VRAM
    0xA0000
    0xAFFFF

    View Slide

  19. 「プログラム」の正体
    ・プログラムもデータ(バイナリ)
    ・CPUへの命令の集まり
    ・「機械語」

    View Slide

  20. 機械語
    ・CPUはバカ
    ・int a = 1 + 2; ← こんなの難しすぎてわからん
    ・面接官「あなたは何ができるんですか?」
    ・CPU「計算がとても速くできるくらいです
    ...」
    ・思い出すシリーズ:電子計算機
    ・機械語:CPUが理解できる「言葉」
    ・いくつか[要出典]の命令

    View Slide

  21. 機械語の種類
    ・算術命令:add, sub, mul, divなど
    ・add eax, 0x05:EAXレジスタの値に5を足す
    ・論理演算命令:and, or, not, xorなど
    ・ビットシフト
    ・メモリの読み書き
    ・入出力命令
    ・ジャンプ命令:実行位置を変更

    View Slide

  22. プログラムの実行
    ・電源投入
    ・2次記憶→メモリ
    ・実行開始!
    ・どうやって?

    View Slide

  23. プログラム実行のしくみ
    add r0, 5
    sub r1, [0x20]
    inc r1
    add r0, r1
    jmp -2
    実行中
    PC: 0x01
    r0: 0x05
    r1: 0x00
    memory[0x20] = 0x03
    メモリ

    View Slide

  24. プログラム実行のしくみ
    add r0, 5
    sub r1, [0x20]
    inc r1
    add r0, r1
    jmp -2
    実行中
    PC: 0x02
    r0: 0x02
    r1: 0x00
    memory[0x20] = 0x03
    メモリ

    View Slide

  25. プログラム実行のしくみ
    add r0, 5
    sub r1, [0x20]
    inc r1
    add r0, r1
    jmp -2
    実行中
    PC: 0x03
    r0: 0x02
    r1: 0x01
    memory[0x20] = 0x03
    メモリ

    View Slide

  26. プログラム実行のしくみ
    add r0, 5
    sub r1, [0x20]
    inc r1
    add r0, r1
    jmp -2
    実行中
    PC: 0x04
    r0: 0x03
    r1: 0x01
    memory[0x20] = 0x03
    メモリ

    View Slide

  27. プログラム実行のしくみ
    add r0, 5
    sub r1, [0x20]
    inc r1
    add r0, r1
    jmp -2
    実行中
    PC: 0x02
    r0: 0x03
    r1: 0x01
    memory[0x20] = 0x03
    メモリ

    View Slide

  28. プログラム実行のしくみ
    add r0, 5
    sub r1, [0x20]
    inc r1
    add r0, r1
    jmp -2
    実行中
    PC: 0x03
    r0: 0x03
    r1: 0x02
    memory[0x20] = 0x03
    メモリ

    View Slide

  29. プログラムカウンタ
    ・「次に実行する命令」や「今実行している命令」の
    アドレスを指すレジスタ
    ・ジャンプ命令:プログラムカウンタの値を変える命令
    絶対ジャンプ:アドレスを指定してジャンプする
    相対ジャンプ:「N個前/後の命令」にジャンプする
    ・前にジャンプ → 繰り返し処理を実現
    ・条件ジャンプ命令:「比較結果が0だったらジャンプ」
    ・条件分岐の実現(条件分岐命令とも)

    View Slide

  30. 様々なコンピュータアーキテクチャ
    ・コンピュータの基本的な構造は大体同じ
    ・スマホもバラせばCPU・バス・メモリ・ディスク・外部装置
    ・PCの/bin/bashをスマホにコピーしたら動くか? 
    → 動かない
    ・何故か?
    ・CPUの種類が違う
    ・PCはx86,スマホはarm
    ・機械語の種類・フォーマットが全然違う

    View Slide

  31. RISCとCISC
    ・アーキテクチャ設計の2つの思想
    ・RISC:命令が固定長
    ・CISC:命令が可変長

    View Slide

  32. 代表的なアーキテクチャ(ISA)
    ・x86:CISC.皆さんのお手元のPCに多分入ってる.Core 〜とかRyzen 〜とか.
    ・Arm:RISC(などと主張しており).スマホに入ってる.マイコンの
    Cortex-M*とかもある.
    ・RISC-V:RISC.UCB発のオープンなアーキテクチャ.最近はマイコンも出てきた.
    ・MIPS:RISC.今はもう...
    ・PowerPC:RISC.昔のAppleが使ってた.なんかPerseveranceに入ってるらしい.
    ・SPARC:RISC. .京はSPARC64.
    ・SuperH:RISC.日立製作所.組み込み向け.日本の人工衛星には結構入ってるらしい.
    ・PDP-11:おぢさんがすきなやつ

    View Slide

  33. 64bitアーキテクチャ
    ・「これは16bitアーキテクチャ,こっちは32bitアーキテクチャ」とか言ったりする
    ・32bitアーキテクチャは汎用レジスタ・メモリアドレスのサイズが
    32bit
    ・0xffffffff ≒ 4 * 1024 * 1024 * 1024
    ・表現できるのが約4GB(4GiB) ・今は32/64bitアーキテクチャが主流

    View Slide

  34. マルチタスク

    View Slide

  35. ところで

    View Slide

  36. 選ばれたのは,Ryzen™でした
    ・最近3600から3700Xに
    ・個人でも8C16TのCPUが安価に手に入る時代...
    ・すりっぱほしい

    View Slide

  37. しかし実際は
    ・プロセス数>>>>CPUコア数
    ・無理があろうと思われます

    View Slide

  38. 同時に動いているとでも?それは残像だ
    ・「時分割」処理
    ・短い時間で区切って実行タスクを切り替える
    ・適度に高速に切り替えられれば人間からは同時に動いているように見える
    ・TSS:Time Shareing System
    CPU1
    時間→


















































    View Slide

  39. スケジューリング
    ・プロセスには優先度がある
    ・音の再生とかは優先度高め
    ・niceコマンドで設定できる
    ・プロセスの動作をいいかんじに管理しないといけない
    ・スケジューラ(ディスパッチャ)
    ・スケジューラの設計で性能が全然変わってくる

    View Slide

  40. プロセスのメモリ
    ・諸々のアドレス(開始アドレスとか)がまちまちだとダルい
    ・関数呼び出し,アドレスを指定したジャンプ
    (絶対ジャンプ)がやりにくい
    ・事前にアドレスを覚えておく or 相対ジャンプでなんとかする
    (位置独立コード)
    ・他プロセスとの競合
    ・そんなんやってらんねえ!!!!
    ・じゃあどうするか? → 仮想メモリ

    View Slide

  41. 仮想メモリ
    ・プロセスから見える仮想的なメモリ空間
    ・プロセスからは0x00〜の広大なメモリが全部自分のものとして扱える
    ・どうやって?
    ・アドレス変換:仮想のアドレス 
    → 実際のアドレス(物理アドレス)
    ・実際の読み書きは物理アドレスで行われる
    ・実際にプロセスからアクセスできるか
    (存在しているか,権限があるか
    )は別の話

    View Slide

  42. 物理アドレス・論理アドレス
    ・プロセスは幻想に浸ったままアドレスを指定してメモリを読み書きできる
    物理アドレス:実際のアドレス
    論理アドレス:幻想のアドレス
    ・物理アドレス ⇔ 論理アドレス が自動的に行われる
    ・MMU:Memory Management Unit
    ※x86の場合物理アドレス →リニアアドレス→論理アドレス
    プロセス
    俺はアドレス0x00にアクセスしている ...
    addr=0x00 MMU addr=0x1000
    メモリ
    ふふふ...こっちがアドレスを
    書き換えてるとも知らずに
    ...

    View Slide

  43. 仮想メモリの種類
    ・セグメンテーション:今はほとんど使われない
    ・「〜から〜までのメモリ空間」みたいなのを設定
    ・ページング
    ・メモリを「ページ」という単位で切り分ける
    ・それぞれのページを仮想メモリ空間の一部に対応させる
    ・昔はバンク切り替えとかもあった
    (仮想記憶とは呼ばない)

    View Slide

  44. ページング
    ・1ページは4KBとか
    ・メモリをページ毎に切る
    ・論理アドレス空間内に割り当て
    ・対応するページが存在する必要は無い
    ・必要になってから物理ページを確保して対応させてもいい
    (デマンドページング)
    ・対応するページが物理メモリ上にある必要は
    無い

    View Slide

  45. ページングと2次記憶
    ・メモリにアクセス→存在しない!?→ページイン
    存在しない!?:ページフォルト
    ・メモリがいっぱい or 今これいらねえな→2次記憶に突っ込む
    2次記憶に突っ込む:ページアウト
    ・うまいことやると高速化できる
    ・やることはキャッシュの時と同じ
    ・ただしこっちの制御はOS
    2次記憶
    メモリ
    ページ
    ページ
    ページ
    ページ
    ページイン
    ページアウト

    View Slide

  46. メモリマップトファイル
    ・”ド”の表記も多いけど”ト”の方が正しいとかなんとか
    (まあ元の発音からしてそう
    )
    ・ファイルをメモリ領域のように扱える
    ・ファイルは使ってたらそりゃメモリの中にあるやろがい
    ・ファイルをプロセスのメモリ空間の中に(仮想的に)割り当てる
    ・*addr = ‘A’; とかできる

    View Slide

  47. 共有メモリ
    ・メモリを他のプロセスと共有できると 
    → たのしい!!!!!!
    ・同じページ(群)を復数のプロセスのメモリ空間内に割り当てる
    ・巨大なデータを復数プロセスで扱いたいときとか
    ・アクセス競合には気をつけよう!
    プロセス
    プロセス
    メモリ

    View Slide

  48. アドレス空間の構造
    ・text:プログラムそのもの.機械語
    ・data:文字列,明示的に初期化される変数
    (グローバル変数や関数内の
    static変数)
    ・bss:初期化の必要が無い変数.
    ELFなどではサイズ情報だけ(ロード時に確保される)
    ・heap:動的に確保する領域
    ・stack:関数呼び出しで積まれていくデータの領域.関数の引数やローカル変数.

    View Slide

  49. プロセスのメモリ確保
    ・text, data:そのままメモリに載せればいい
    ・bss:サイズが確定している→ロード時にそれだけ確保してやればいい
    ・stack:仮想アドレスのめちゃくちゃ後ろから始めれば使い切ることないやろ
    (鼻ホジ)
    ・heap:システムコール呼ぶしかねえ

    View Slide

  50. 動的なメモリ確保
    ・システムコール:brk/sbrk
    ・mmapを使うことも
    ・メモリを確保してプロセスの仮想メモリ空間内に割り当てる
    ・やったね!
    ・でも遅い(システムコールは大体遅い
    )

    View Slide

  51. malloc()
    ・libc(C言語の標準ライブラリ)の関数
    ・malloc()で確保,free()で開放
    ・内部でbrk/sbrk/mmapを呼んで大きめのメモリ領域を確保
    ・細かい領域の割り当ては
    malloc()が行う
    ・高速!ヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノ
    ・色々なアルゴリズム・実装がある
    (性能がめちゃくちゃ変わってくる
    )

    View Slide

  52. いろいろなmalloc
    ・glibc malloc: ふつうこれ
    ・K&R malloc: いにしえ
    ・dlmalloc: 移植性が高い(自作OSでお世話になる)
    ・jemalloc: FreeBSDのlibc,マルチコア環境での性能,
    Facebook
    ・tcmalloc: Google
    ・mimalloc: Microsoft

    View Slide

  53. プログラムができるまで

    View Slide

  54. プログラムができるまで
    コンピュータ黎明期:機械語を書けばええ(パンチカード,コアロープメモリ,
    ...)
    いま:int main(int argc, char **argv){ printf(“hello, world!”); return 0; }
    ・ソースコード(人間が理解できるもの) → 機械語
    ・コンパイル型言語:コンパイラで事前に機械語にしておく
    ・インタプリタ型言語:インタプリタが解釈しながら実行
    ・C/C++はコンパイル型言語
    ・C/C++コンパイラ:gcc, clang, icc, aocc, ...

    View Slide

  55. プリプロセス
    ・#から始まるアレを処理する
    アレ:プリプロセッサディレクティブ マクロとも
    ・基本的に単純な(ソースコードの)書き換え
    ・#define -> 値に書き換えられる
    ・#include -> ファイルの中身がそのまま展開される
    ・gcc -E a.c / cpp a.c でプリプロセスだけできる
    ・定数/関数の定義 ← 毎回同じものを定義するのはめんどい
    → ヘッダとしてまとめて,プリプロセス時にそのまま展開してくれればいい
    → #include Linux「えっ,マクロで関数が作れるのか.使いまくったろ」 
    C++「templateだいすき!ヘッダに実装を書くプラよ〜」
    ctags「ア゜」 C++20「C++の最新の妹です.兄が迷惑をおかけしました.
    moduleです.STLはまだです.」

    View Slide

  56. コンパイル
    ・匠の手によりC言語のソースコードをアセンブリに変換
    ・匠:コンパイラ
    ・アセンブリ言語:機械語と
    1対1対応
    BEFORE AFTER

    View Slide

  57. アセンブル
    ・アセンブリ言語のソースコードをバイナリ
    (機械語列)に変換
    ・変換するプログラム:アセンブラ
    ・バイナリフォーマット:ELF,COFF,a.out
    ・ベタなバイナリは扱いにくい
    これはディスアセンブルだけど
    ...

    View Slide

  58. リンク
    ・ELFとか:機械語列以外のデータがいろいろ付いてる
    ・大抵ソースコードのファイルは複数
    ・後でくっつけないといけない
    ・「のりしろ」に相当するデータ
    ・リンク:「のりしろ」を見てファイルをくっつける
    ・リンク前のELFなどのファイル(.o)をオブジェクト・ファイルとよぶ

    View Slide

  59. ライブラリのリンク
    ・みんなよく使う便利関数とかをライブラリとして切り出しておく
    ・あとからリンクする→かんたんに過去の資産が使えてべんり!

    View Slide

  60. ダイナミック(動的)リンク
    ・ライブラリをリンクするとファイルサイズが大きくなる
    (それはそう)
    ・めちゃくちゃ色々なプログラムが使うライブラリ
    ・同じライブラリの分だけストレージが膨れ上がっていく
    ・無駄すぎる
    ・ライブラリは1つだけ入れておいて実行時にリンクしてしまえばいいのでは!?
    (天才)
    ・リンクローダ/ローダ

    View Slide

  61. どっちのリンク使えばええねん
    ・大体動的リンクでいい
    ・libcだって動的リンク
    ・Golang「せやろか」

    View Slide

  62. ダイナミックロード
    ・ダイナミックリンクのようなことをプロセスが自分でやる
    ・API:dlopen
    ・インタプリタとか

    View Slide

  63. プログラムができるまで:まとめ
    C







    セン
    ブリ






    Cコンパイラ アセンブラ オ

    ジェ
    クト
    ファ


    リンカ
    コンパイル
    元のCソースコード






    アセンブル
    C







    セン
    ブリ






    Cコンパイラ アセンブラ オ

    ジェ
    クト
    ファ


    コンパイル アセンブル
    静的ライブラリ
    リンク










    ローダ
    動的リンク








    動的ライブラリ
    これはメモリ上

    View Slide

  64. プログラムができるまで:まとめ
    C







    セン
    ブリ






    Cコンパイラ アセンブラ オ

    ジェ
    クト
    ファ


    リンカ
    コンパイル
    元のCソースコード






    アセンブル
    C







    セン
    ブリ






    Cコンパイラ アセンブラ オ

    ジェ
    クト
    ファ


    コンパイル アセンブル
    静的ライブラリ
    リンク










    ローダ
    動的リンク








    動的ライブラリ
    これはメモリ上
    広義での「コンパイル」

    View Slide

  65. まとめ
    ・コンピュータはCPU・バス・メモリ・2次記憶・外部装置!w   GPU...?知らない子ですね
    ...
    ・記憶装置:レジスタ,キャッシュ,メモリ,
    SSD,HDD,...
    ・プログラム = 機械語の塊
    ・コンピュータアーキテクチャには色々ある:
    x86,arm,RISC-V,PowerPC,MIPS,...
    ・TSS:高速に処理を切り替えてマルチタスクを実現
    ・仮想メモリ:アドレス変換で仮想的なプロセス専用のメモリを扱える
    ・メモリ確保のAPI:システムコールで大きく確保,内部は
    malloc/freeで管理
    ・ソースコード→アセンブリ→オブジェクトファイル→実行形式ファイル
    ・どうしてこの内容を1章にしてしまったんですかねぇ
    ...

    View Slide