2010-05-24
NHK白熱教室 - 第4回「この土地は誰のもの?」ノート
そろそろ、ノート取らないと全然内容が理解できなくなってきそうなので、メモを取り始めました。が、メモを取ってもやっぱし分からないところは分からない。実際、納得できない主張や理論については全て疑問形の文としてメモしていたのですが、いざ自分の取ったメモを読み返してみると、疑問文が多すぎるw。真面目に理解しようとしたら、ちゃんとReading Listも読まないとマズいですね。本業の方のReading Listも溜まっているので、そこまで読む気には中々なれませんが。。。
参考:
第4回「この土地は誰のもの?」, NHK白熱教室
Lecture 7: 土地略奪に正義はあるか
===============================
ジョン・ロック
ーリバタリアンの味方
ーー例え民主的に選ばれた政府であっても、犯せない権利がある
ーーーe.g. 生命/自由/財産に対する自然権
ー財産権
ーー政治以前のものである=自然権である
ーーー政府が存在する前から存在するもの
ー法律が出来る前の状態/法律が出来る前の状態を考えるー>自然状態(=自由な状態)
ーー人間は自由で平等ー>階層は存在しない。王や農民などはダメ
ーーただし、自由≠好き勝手
ーー自然状態でも法律が存在する。ー>自然法
ー自然法によって制約される行動とは?
ーー自然権を手放したり、取り上げたりすること
ーーーe.g. 生命/財産の権利
ーー自分を奴隷にすることもできない??? -> 完全なリバタリアンではない。
2つの答え:
ー1. 生命/財産は自分のものではない。神の創造物???
ーー神なんているの?信じていない人はどうするの?
ーー自由≠好き勝手でないと説いた。矛盾してない???
ーーー不可譲。e.g. 航空券は譲渡できない。
ーーー誰かのものではない。
ーーーcf. アメリカ独立宣言
ーーー不可譲の権利:自然状態から持っている権利。
ーー財産の場合は?
ーーー政府が無くても私有財産が存在するのか?
ーーーその人の中では存在している???
ーー私有財産についてはリバタリアンの考え方と同じだが、他は違う。
エイズの薬の特許の話:
ー医薬に関しては、特許を尊重しなければ、色々な人が助かる?
ー作り出すための研究開発のコスト/モチベーションは?
ーこのとき、私有財産権はどうなる???
ネイティブアメリカンの話:
ーアメリカの入植者がネイティブアメリカンから略奪した行為の正当化である?
ーー証拠はない。また、統治時は戦争状態だから、状況が違う。双方の同意が無い。
ーーロックの理論によれば、ネイティブアメリカンは既に土地を占有していた。ただし、主張はしていなかった。
政府のあり方:
ー私的所有権は絶対化される。政府もその権利を犯せない。
ーしかし権利が絶対化されることは政府によって定義される。
ー2. ???
ーー???
ーー???
Lecture 8: 社会に入る「同意」
============================
同意なしで私有財産権を持つことは可能か?
ー例外:他者のために、充分なリソースがある場合に限り、ロックの理論は適用される。
ー同意とは?
ーーe.g. くじ引きに同意/殺害に対する同意
ーー正当な政府の基礎は同意にある?
同位に基づいて設立された政府には、何ができるのか?
ー復習:自然状態とは?
ーーなぜ政府など作ったのか?
ーー自然状態の不都合な点
ーーーe.g. 誰もが自然法を実行できる/誰もが執行者である
ーーーーe.g. 泥棒を勝手に処罰できる
ーー人は、自分が判事になると我を忘れる?
ーーー行き過ぎた侵略/行き過ぎた処罰->いずれは、不可譲の権利を享受出来なくなる。
ーー人は、戦いを仕掛けてくる人を処罰出来るー>力と暴力の世界
ーー人は、故にそういった世界から離れたくなる。ー>同意
ーー他の皆に同意をする。
ーーー他の皆:協定や社会契約に参加したい全ての人々
ーーーマジョリティが決めたことに、皆従う。
ーーーvs. 自然権との兼ね合い。
ーーーー疑問:多数はどれほどの力を持てるのか?
少数派に課税することはなぜダメと思われるのか?
ー自然権を侵害することになるから
社会に入る理由=自然権を守りたいから?
ー所有権は””コミュニティの法”によって制定される。
ー所有権は政府が定義するもの?
ー多数派の同意で決まる?
ー財産権も含まれる?
ー財産を恣意的に取り上げることは違法。
ーしかし、何を持って財産とみなすか/財産を取り上げたとみなすか?
ーーそれは、政府が定義していいの?
ーー定義して良いのならば、同意の果たすやることは大きいー>大きな政府が必要?
社会に参加することに同意したのか?
ー祖先が社会に参加することに同意した?
ー同意はサインではない?暗黙的に同意が有効である?
ー捕まらなければ税を払わない?
徴兵制や生命に対する権利:
ー不可譲の権利は持っているが、放棄する権利は持っていない
ー同意する際に権利を放棄することが出来ないから、政府は制限できない。
ーーもし放棄がゆるされないのならば、なぜ徴兵制のような生命を脅かすことを強制出きるのか?
ー人の権利を恣意的に犯すのはダメだが、法律を通して無作為に選ぶのは良いのか?
ーー恣意的でなければ、例えば、人の生命の権利を犯すことは許されるのか?
ロックは想像上の世界について理論を展開させていたわけではない。
ー当時の現実世界の現状を見て、理論を展開させたかもしれない。
ーー???
次回:
ー同意は、どのような働きをもたらすのか?
ー同意の限界とは?
まとめ:
ー多数派が権利を侵害することは許されない?
ー政府は法律という形で課税?
2009-11-22
Mini Reference for Git
This is a memo for Git commands.
*** config ***
- set user name and contact info
git config --global user.name "User Name"
git config --global user.email "name@domain.com"
- display current settings
git config --list
- turn on coloring mode
git config --global color.ui "auto"
- set an alias for a command
git config --global alias.<alias-name> "<native-command-name>"
*** mode ***
- Git with GUI
git gui
- display whole history using GUI
gitk
- display diff using GUI
git mergetool
*** command ***
- initialize and reinitialize .git
git init
- add git repository
git add <filename>
git add -i (Interact Mode)
git add -p (Patch Mode in Interact Mode)
- commit with a message
git commit -m "message"
git commit -C HEAD -a --amend (Amend previous commit by using same log message)
- revert commits
git revert -n <commit ID>
-> Do revert in time order to avoid waste troubles.
- reset change log by changing files
git reset --hard HEAD
- see the working tree from Git
git status
- change working branch
git checkout <destinated branch>
git checkout -b <new branch> <existing branch> (checkout with making new branch)
- make a branch
git branch <new branch> <based branch>
git branch <new branch> <based tag-name>
git branch -a (show all branches)
git branch -d <delete branch>
git branch -m ("mv" command for branches)
git branch -M ("mv" command for branches in rewriting mode)
- merge a branch
git checkout <master branch>
-> git merge <slave branch>
-> git merge --squash <slave branch> (Compressed Commit)
-> git cherry-pick <commit ID> (Cherry Pick)
-> git cherry-pick -n <commit ID> (put a commit into staging area)
--> Do not put "-m" option when committing because it already has a message.
- track back to previous situation
git reset --hard HEAD^ (Maybe you need to replace with "\^")
- put a tag on the current revision of branch
git tag <tag-name> <branch-name>
- fetch a change of branch and put it in front of another branch
git rebase <branch-name>
git rebase -i <commit ID> (It helps to change committing order)
- make a archive for release
git archive --format=tar --prefix=<dir-name> <tag-name> | gzip > <archive-name>.tar.gz
git archive --format=zip --prefix=<dir-name> <tag-name> | <zip-name>.zip
- read user manual
git help <command>
- see commit logs
git log
git log -<num> (Show some of logs in time order)
git log --pretty=oneline (Show each commit in 1 line)
git log -p (Display all differences between revisions)
git log <commit ID>
git log --since="<num> hours"
git log --before="today" | ="2009-11-22" | "yesterday"
git log <older commit ID>..<later commit ID>
git log <older commit ID>..HEAD{^} (from some commit to latest)
-> Windows may need double quotations.
git log HEAD~<num>..HEAD
git log -C -C -p (Display detailed info in each commit)
- display differences between corresponded files if existing
git diff
git diff --cached (Differences between Not Commited and Current files)
git diff HEAD (Display all differences in current branch)
git diff <commit ID>
git diff --stat <tag> (Display stats info between resources)
- Display who writes which codes
git blame <filename>
git blame -L <start>,<end> <filename>
git blame -L <start>,+|-<num> <filename>
git blame -M <filename> (look for same lines in a file)
git blame -C -C copy.txt (look for same lines between files)
- "mv" in Git
git mv <filename> <new filename>
*** others/memo ***
- Git cannot trace empty folders because they have no contents.
-> To avoid this, most people create a ".<filename>" file with meta contents.
- Git does not have to use "cp" command because it already copies when tracking.
- To ignore buffer files, add "a pattern name" into .git/info/exclude or .gitignore
2009-02-20
2008-10-07
Database Design: Intro, ER model
データベース設計の授業の予習をしまくってXMLをマスターすれば、情報検索のアプリケーションに100%役に立つことを発見。しかも課題も資料も回答ももろもろ全部先に提示してくれるとか、さすがIBMの研究員ともなるとレベルが違うわw。個人的には、このスタイルの授業が割にあってるなぁ。
----- note -----
・成績評価について
中間レポート 40%
→11月ごろ、課題をだす。
期末テスト 60%
→資料持ち込み負荷
目標:データベースの設計が出きるようになる。
教科書は使わない。
→http://www.fukudat.com/
参考書:
Ullman, Widom, "A First Cource in Database Systems," Prentice Hall.
北川, "データベースシステム" 昭晃堂
福田, 森本, 徳山, "データマイニング”
・今日の授業内容
1. データベース入門
2. ERモデル
-------------------------
「1st PPT:データベースの概要」
・What's Database?
→データを蓄えておくところ
→めもりは?
→データを永続的に蓄えておくところ
→HD, CD, Tapeは?
・Definition
データベースとは、
「複数の応用目的絵の共有を意図して、組織的活永続的に格納された大量のデータ群」
keyword:多目的、共有
→入れ物
ーDataBase Management System
「データベースを作成、管理するための機能を提供する仕組み」
→器
ーこれらは混同されて、単に「データベース」とよばれることが多い。
・データベースの役割
例:amazon
データ=本、顧客、仕掛け注文、注文履歴、売れ筋、顧客の嗜好などの情報
大量:中規模の書店でも、少なくとも数偽がギガバイトの情報を管理しなければならない
→メモリには大きすぎる。Cppでやろうとすると、メモリ管理が大変。
永続性:
→途中でなくなっては困る。サーバーシステムでも時々は電源をきらなくてはいけないことがある。ライフタイムが長いから。
複数のアクセスが競合する可能性がある。
マルチユーザ:
→ex:売上集計、注文など
・マルチユーザの例
二人が同時で買い物する時を考える。
重要なこと:どうやって排他制御をプログラムで実現するのか?
・何故データベースを使うのか?
scheme = definition of data
→変更の伝搬・影響が起こらないようにできる
各層の間のマッピングが再構成できれば、他のアプリケーションは安定的に動かすことが出来る。
下からくる場合もある。physical dataから
→マッピングが再構成が出来れば
現在の主流:relational database
conceptual scheme:概念スキーマ
・Logical data independence
・physical data independence
これらを実現するのが、データベースの役割。
・DBMSはsoftware system
→ハードウェアで実現しようとするのは駆逐された。
しばしば、application server, middlewareと一緒に用いられる。
・DBMSのoutline(実装の例)
ユーザが2種類:一般ユーザ、データベース管理者
M:データの定義
U:問い合わせ、更新
strage = hard disc
これをどうやって作れば良いのか、が本当はやりたいこと。
しかし、授業では時間が足りないので、ある程度のテンプレートを使うことにする。
よって、データベース管理システム設計ではなく、データベース設計。
・Required things
-ACID property
Atomic Consistent(一貫性がある) Isolation Durable←データベースに求められる特性
-database schema
-relational database
-query processing
-physical data structure
3-tier schema(3層スキーマ)
-external schema
-conceputal schema
-
・教養としてしっておくこと
-Relational Data Model
E.F. Codd(1923-2003)
San Jose, Almaden laboratory
概念:すべてのデータをrelationで表現する->すべてのデータは表で表現できる。→relation=表, テーブル(visible)
プログラムとデータの独立
データ構造を知らなくても問い合わせがかける
relationというのは、Tableのこと
モデル図のオブジェクト間にある線のこと(だけ)ではない。
詳しくは「relational data model」の回で説明する。
-Relational Completeness 関係完備性 (完全>完備)
関係論理という宣言的な体系を使って表現できる異と、関係台数という手続的な体系を使って表現で切ることが同じであることを証明した。
→relational databaseで表現出来ないことはない。出来なければスキルが足りないか、スペックが足らないかなどが原因。
Ex.IMS 階層型DB
関係論理には十分な表現力が(なんとなく)しんじることができるので、関係台数にも十分な表現があることが分かる。
→SQLでは書けないことがある。
関係データベースの問い合わせ言語、SQLも関係完備。
-Normal Forms 正規化の理論
究極の正規形である第5正規形を発見した。
projection-join normal formともいう
他の正規形(1NF, 2NF, 3NF, BCNF, 4NF)の一般化になっている
→relational databaseで出きること、出来ないことを明確化した。
逆に言えば、正規形でないリレーションは、異常(anomaly)を起こす。
更新異常
削除異常
挿入異常
・データベース業界について
シェアウェア:
oracle
IBM DB2, Informix
Microsoft SQL Server, Access
Sybase
Hitachi HiRDB
フリーウェア:
MySQL - Private companyが作った
サービスを有償で売っている。
PostgreSQL
Apache Derby
SQLite Ipod関係がよく使っている
・データベース業界、学会
国際学会
ACM SIGMOD(実践的なデータベース/PODS(データベースの原理)
SIGMODは日本からはほとんど通らない。
SIG=special interest group
ジャーナル国内(ある程度の結論でも載る:研究者の業績)
ACM TODS
IEEE TKDE
VLDB Journal
国内
情報処理学会 DBS研究会
電子情報通信学会 DEkennkyuukai
ACM SIGMOD 日本支部
日本データベース学会
文献検索
DBLP
「2nd PPT:データモデリング」
データモデルの3要素
1. データ構造を記述するための規約
2. データ構造に対する操作
3. データが満たす制約を記述するための規約
・データモデルの種類
関係データモデル
タプルの集合
現在の主流
ネットワークモデル
・実世界のデータモデリング
→作るための道具
real world -> conceptual design -> conceptual model(entity-relational model) -> logical design -> logical model
・ERモデルとは
実世界の事象をモデル化する。
データベース設計の概念的な概略を描くことが出来る。
設計図はER図と呼ばれる絵(一種の文法のようなもの)
・Entitiyとは
実体:もの。こと。
実体集合:似通った実体の集まり
→学生は同じ?違う?
→何を重要だと思うかによる
↑これがモデリング。この概念はOOPの前身となった。
属性:実体の特性
・ER図
ER図では、各実体集合は短形で表わせる
書き方;
○:名前、製造元
□:酒←注目しているもの
・関連
実体集合を関連図蹴る
◇:関連付ける塩っ太守烏合を表す短径と線で結ばれる
Ex.売る、行き着け、好き
2008-08-09
Strategy, SoC memo C1(1)
Basic TOEFLが昨日ようやく終わりました。途中から何人かUSAに帰ったので、結果、最終日の受講生の状況がハーレム状態だったのが唯一の良い思い出です。一方で、まわりの受講生が全員高校生とはいえ、皆帰国子女だったので、readingの早さとかlisteningの把握力とか負けまくりだったのはつらい思い出 orz。ま、最後のテストではぼちぼちいい点数取れたので、よしということで。
今回、さらっとTOEFL iBTの概要を学んだだけだけど、やっぱstrategyは大事だね。readingとか、ITPの問題だったけど、普通に正答率2倍になったわ。Listeningも同じく、とりあえず正答率が5割を越えた。ただ、iBTのstrategyは本当にさらっとやっただけで、まだ勉強していないところもいっぱいあるらしい。実際、今までやってたのはR/Lだけだしね。
と、そんなこんなで、明日からはiBTのR/L standardとBasic Writingの授業開始です。今まで最年長だったけど、今度は社会人クラスなので最年少になるらしい。といっても特に変わらないと思うけど(帰国子女がいなくなる分、全体的にはレベルダウンするのかな)。まぁ、とにかく、ぼちぼち頑張ります。
----- SoC C1 (1) NOTE(途中) -----
レポート課題:C1章(2)No1 演習1,2 PP.69
1. プロセスモデルのOSとスレッドモデルのOSの特徴を説明せよ。
2. 4種類のOSの動作モデルと特徴を述べよ。
----- noteのまとめ -----
[C1章 組み込みソフトウェアの基礎(1)]
概要:組み込みシステムの特徴、ハードウェアの基礎知識、組み込みシステムとは何か、車を用いた事例
・Introduction
一般的にコンピュータ関連産業をIT産業と呼ばれているが、経済産業省では明確にIT産業とET産業に区別している。
IT:Information Technology
-> インターネット系情報サービス
Ex. 銀行のオンラインシステム、座席予約システム
ET: Embedded Technology
-> ある目的に専用化されたシステム。具体的には、汎用コンピュータ以外のコンピュータシステム。
Ex. i-Pod, 家電, 携帯(ただし,iアプリは汎用コンピュータ)
注:ロードして実行するプログラムは、組み込みソフトウェアではない!
Ex. java program, PDA
→このようなソフトウェアは、アプリケーションソフトウェアという方が適している。
しかし、言葉は生きているので、現在の定義がこの先も常に変わらないとは限らない。
→定義として覚えるのではなくイメージとして覚えた方が効率的。
・ET産業と特徴
- 厳しいリソースの制約
- 高い信頼性
→PCとは違った信頼性
cf. 回収経路が違う。
つまり、組み込みシステムに対するユーザの期待度が高い。
cf. windows XPがフリーズしても、ユーザには暗黙の諦めがある。
cf. i-Podがフリーズしたら、ユーザはクレームをつける。
・原因は何か?
ユーザはモノを使うとき、思い描いた動作するためにはどのように操作すればいいのか、という予測を行いモノを扱う。
この予測が期待値を左右する。よって、
-ET系は期待値が高い。
-PCに対しての諦め。
という差異が起こる。
Ex:リアルタイム性
→ある操作に対して、その操作が完了するまでどの程度時間がかかるか、という予測。
開発者は、この予測を正確に把握する必要がある。ただし、早ければよいということではない!
・では、組み込みシステムにはどのような厳しい要求があるのか?
1. 重大な欠陥にたいする賠償→めちゃくちゃ損害が大きい
Ex: Panasonicが10年前に行った欠陥ストーブの回収
2. 開発サイクルの短縮
6ヶ月未満が4割、1年〜6ヶ月が4割。
→8割の組み込みシステムは、1年未満のサイクルで製造されている。
→技術者はドMなので、やりがいを感じる(?)→デスマーチ(?)
大抵は、半期モデルとかで、6ヶ月単位でサイクルすることが大きい。
というか、実際にはこれ以上生産サイクルは縮まらない。しかし、ソフトウェアのソースコードの行数は年々増加している。
→そろそろ限界に達するので、何かしらの現象が起こる(?)
Q. 技術者に余裕をもたらすために、生産サイクルの単位をもっとゆとりを持たせられないのか?
A. ユーザがそれを求める限り、企業倫理的に無理。
結論:このような状況下で開発を成功させるのは無謀。実際にほとんどのプロジェクトが"成功"といえる水準に至っていない。
仮対策:以下に効率的なエンジニアリング手法を取り入れるかが重要。
ex. 過去の資産を活用、開発工程の管理
・組み込みソフトウェアの、HW的な違い
1. Sencorがある
2. Actuatorがある
3. I/Oが違う
Sencor:温度、変位、音、磁気、化学量、光度などに反応して電気信号に変換する素子
Actuator:センサの逆。電気信号を物理的、科学的変化に変換。
Ex:電磁ソレノイド、motor
・具体的な制御例(Case:直流Motor)
電力up→pulse幅down→早く回転する
電力down→pulse幅up→遅く回転する
motorだけとっても、制御の仕方は他にも、AC(Alternating Current)・stepping・sorvo・linerなどがある。
・他HW知識
Analog量とDegital量, Sampling Freq, AD transformation
→全部実験でやった奴。
・data圧縮
1. 可逆圧縮
→ZIP,LZH, GIF, PNG
2. 不可逆圧縮(圧縮率高い)
→MPEG, JPEG, AAC
→このため、動画では圧縮をする度に品質は落ちていく。(が、人間が感知できるほど気になる量ではないらしい。)
圧縮例:
1. Run Length
事例:動画圧縮
背景はあまり変わらないことが多いので、差分データのみ(動くモノのみ)を変化させるようにすれば、割と効率的に動く。
逆に言えば、桜が落ちるシーンや、潮の満ち引きがある海では、背景が頻繁に変わるので、あまり効果は期待できない。
・組み込みシステムで扱うOS(基本的にCAやOS、programing Cで勉強したこと)
内容:MPU内部における割り込みの動作、外部割り込みと内部割り込み、Big EndianとLittle Endian、←の性能比較、
MPUとデバイスとデバイスとでEndianが異なる場合の配線、キャッシュ(の動作)、周辺デバイス、レジスタ、RTOSを動作させるために必要なI/Oデバイス
(以下、上述の内容のうち、自分が知らなかったところだけを補足)
- NMI(Non Mashable Interrupt):停電等が起こってもいつでも割り込みで切るような仕組み
- BigEndian: 上位バイトから出力
- LittleEndian: 下位バイトから出力
→読み込みの時はBig Endianの方がよい。
- ではなぜLittle Endianが主流なのか?
→Little Endianは当初、計算機気のためではなく、電卓のために設計されたから。
→このため、現代でもその名残りとしてLittle Endian方式が主流となってしまった。
・BEとLEの利点
LE:数値の桁数が分からなくても解析できる
BE:メモリの内容が直感的にわかる。(人間の文字を読む順序と同じ)
→デバック時や、memory dumpで内容を把握するときに便利。
→LEの場合は、変換関数を通した後でレジスタの内容を出力する必要がある。
・なぜBEが良いと言われているのか?
→自然界のあらゆる現象は、すべてBig Endianと同じだから。
またLEの場合、ハードでバイトスワップしなくてはいけない。
→つまり、Busごとをごっそりswapする。
このような考えは、通常、IT産業では扱わない。
・キャッシュ
- write through: 書き込み時に、キャッシュメモリと実際のメモリに対して書き込みを行う
- write back: 書き込み時に、キャッシュメモリだけを書き換えて、実際のメモリに対しては書き込みを行わない(メモリはちょっと遠い位置にあるので)
使用例:ある程度write backでメモリを無視おき、write throughで今までの内容を一気に書き込む。
demerit:メモリに書くべき内容がかかれない危険性がある。
キャッシュは、当たれば早いが外れると極端に遅くなる。
→99.999%時間内に動作しても0.0001%間に合わない、では許されない。
→組み込みシステムでは、キャッシュを入れることにより、逆に遅くなることも有り得る。
2008-07-30
memo3
----- OS Report No.1 -----
問題1 オペレーティングシステムがアプリケーションプログラムに対して提供するインターフェースの重要性を2つ述べよ。
一つ目の重要性は、プログラマがハードウェアのことをあまり意識しなくてもプログラミングできるようにすることである。これにより、プログラマがプログラミングするための手間を大幅に削減することが出来る。
二つ目の重要性は、アプリケーションソフトの互換性を保障することである。具体的には、命令体系が同じであるようなマイクロプロセッサやOSを搭載したコ ンピュータ同士では、アプリケーションソフトを改変しなくては同じ動作をさせることである。具体的な具現化の方法としては、C言語の#defineを利用 して、OS毎に実行するソースコードを変更させることで具現化できる。これにより、プログラマが、プログラムを移植する際に被る手間を削減することが出来る。
問題2 各自が聞いたことがあるOSの名前を4つ述べ、その特徴を説明せよ。
OSASK:OSの実行効率向上を追求したOS。実行効率を上げるため、低級言語を用いてプログラムされているところも比較的多い。
Ubunto:Wubi というインストーラを使うことで、UbuntoのファイルシステムをWindowsと同じものにすることが出来、パーティション等の作業を行わなくても、 簡単にWindowsとUbuntoのデュアルブートを実現できるようになるOS。インストールやアンインストールもWindows側から行うことが出来 る。
Knoppix:CDやDVDから起動することが出来る。また、ハードウェアを自動で認識してくれるので、例えば、Knoppixから他OSで生成したファイルにアクセスすることができる。
Windows:OS市場で最も高いシェア率を持つOS。新旧の互換性に優れている。
Macintosh:ハードウェア設計とOS開発を同時に手がけていて、ハードとソフトとの統一感に優れている。
問題3 もし、OSが使用できなかった場合、ユーザプログラマが記述する必要があるプログラムはどのように変わってくるのか200字程度で説明せよ。
OSが使用できない場合は、OSが提供するAPIを使用することができないので、CPUの提供する機能以外は使用することができない。具体的には、外部 ハードウェアを扱うことができなくなり、マウス操作を感知する関数や、キーボードからの入力を感知する関数、また、画面に文字を出力する関数などが使えな くなる。加えて、OSの提供するABIも使えなくなるため、例え命令体系が似ているマイクロプロセッサであったとしても、プログラムを移植することができなくなる。
問題4 C言語を実行する場合にスタックはどのように使用されるのか?特に、Cの関数を呼び出すときにスタックがどのように使用されるかに関して説明せよ。
スタックは、現在レジスタに格納されている値を、FIFOなどの方式を用いて一時的に非難させるために用いられる。具体的な使用例を挙げると、C言語のプ ログラムを実行して、関数を呼ぶ処理が行われるとき、その関数が呼ばれる直前のレジスタをスタックに非難させ、関数を実行し終えた後に、スタックに入って いる非難させた値をレジスタに戻してあげることになる。こうすることで、どのような関数を呼び出したとしても、使う予定のレジスタが書き換えられるというような危険性がなくなる。
問題5 キャッシュメモリと命令パイプラインに関してそれぞれ100字程度で説明せよ。
キャッ シュメモリ:記憶装置の一つで、メインメモリとレジスタとのアクセス速度の格差を緩和させるためのメモリである。レジスタほどCPUに近くはないがメイン メモリほど離れているわけではない。このため、アクセス速度は、レジスタ>キャッシュ>メインメモリとなり、記憶容量はメインメモリ> キャッシュ>レジスタという順になっている。
命令パイプライン:CPUの処理速度を高速化する方法で、LOAD命令やSTORE命令に必要なphaseを固定長にすることで、CPUが行う様々な命令を並列的に処理することができる。現在、ほとんどのCPUがこの方法を用いて命令を実行している。
問題6 コンテキストスイッチとプロセススケジューリングに関してそれぞれ100字程度で説明せよ。
コ ンテキストスイッチ:CPUの状態を保存・復元させて、複数のプロセスを1つのCPUに割り当てること。マルチタスクOSのように、複数のプロセスが存在 するときには、複数のプロセスを同時進行しているかのように見せる必要がある。しかしながら、CPUは限られた数しかないため、1つのCPUで各プロセス を同時に扱うことができない。このため、CPUの状態を保存・復元させ、各プロセスを少しずつ処理していくことで、ユーザに対してあたかも複数のプロセス を同時進行しているかのように見せることができる。
プロセススケジューリング:CPUに効率よくプロセスを割り当てること。どのようなと きにコンテキストスイッチを使い、次にどのプロセスをCPUに割り当てるのかによって、システム全体にスループットや、リアルタイム性に変化が生じる。具 体的にいえば、ネットからの膨大な量のパケットを高速に処理しなくてはいけない場合、パケットの取りこぼしを避けるため、CPUに他のプロセスを割り当て ることが困難になる。
問題7 プログラムを実行する上で、プログラムカウンタとスタックポインタの役割を100字程度で説明せよ。
プログラムカウンタ:CPU内部にあるレジスタの一つで、次に実行する命令のアドレスが入っている。1つの命令が終わると、固定された値を現在のプログラムカウンタに加算する。このとき、プログラムカウンタの指すアドレスが次に実行する命令のアドレスとなる。
スタックポインタ:CPU内部にあるレジスタの一つで、スタックポインタに格納されている値は、今扱っているスタックのトップの場所を指している。例えば、 プログラムから違うプログラムを呼び出すとき、プログラムカウンタの値をスタックポインタに詰め込むことで、呼び出されたプログラムから元いた番地に戻ることが出来る。
問題8 プログラムを実行するときに、どのようにメモリ空間が利用されるかを100字程度で説明せよ。図を使用してもかまわない。
プログラムを実行するとき、メモリ空間からそのプログラムの実行に必要なメモリ容量を確保する必要がある。このとき、メモリ空間上でフラグメンテーションが 起こっていた場合は、「連続して空いているメモリ空間≧確保したいメモリ容量」の場所をメモリ空間の中から探し出す。条件にあう場所を発見したら、その場所を使ってプログラムの実行を行う。
問題9 ユーザ空間とカーネル空間の2つのメモリ空間が存在する理由を100字程度で説明せよ。
カーネル空間とユーザ空間を分けることで、ユーザ空間を使ってカーネル空間の内容を書き換えられないようにすることが出来る。これにより、悪意をもってカーネルを破壊しようとするプログラムから、カーネル空間におかれている内容を守ることが出来る。
問題10 10年後のコンピュータがどうなっていると思われるか各自の意見を述べよ。また、そのコンピュータは20年後のコンピュータとはどう違うと予測するか?
ムーアの法則から、10年後にはマシンのスペックが少なくとも約7倍向上することが予想される。加えて、様々なモノに組み込み系の技術が使われ、色々なモノが電子化されていくと考えている。
20年後には、電流ではなく光を使ったCPUが使われ、CPUの処理速度は今よりも格段に向上すると考える。加えて、様々なモノに組み込まれるOSが規格化され、組み込み系ソフトの入っているモノ同士の通信が容易になると思う。
---------C言語の復習とOS概要---------
問題1 オペレーティングシステムがアプリケーションプログラムに対して提供するインターフェースの重要性を2つ述べよ。
一つ目の重要性は、プログラマがハードウェアのことをあまり意識しなくてもプログラミングできるようにすることである。これにより、プログラマがプログラミングするための手間を大幅に削減することが出来る。
二つ目の重要性は、アプリケーションソフトの互換性を保障することである。具体的には、命令体系が同じであるようなマイクロプロセッサやOSを搭載したコ ンピュータ同士では、アプリケーションソフトを改変しなくては同じ動作をさせることである。具体的な具現化の方法としては、C言語の#defineを利用 して、OS毎に実行するソースコードを変更させることで具現化できる。これにより、プログラマが、プログラムを移植する際に被る手間を削減することが出来る。
問題2 各自が聞いたことがあるOSの名前を4つ述べ、その特徴を説明せよ。
OSASK:OSの実行効率向上を追求したOS。実行効率を上げるため、低級言語を用いてプログラムされているところも比較的多い。
Ubunto:Wubi というインストーラを使うことで、UbuntoのファイルシステムをWindowsと同じものにすることが出来、パーティション等の作業を行わなくても、 簡単にWindowsとUbuntoのデュアルブートを実現できるようになるOS。インストールやアンインストールもWindows側から行うことが出来 る。
Knoppix:CDやDVDから起動することが出来る。また、ハードウェアを自動で認識してくれるので、例えば、Knoppixから他OSで生成したファイルにアクセスすることができる。
Windows:OS市場で最も高いシェア率を持つOS。新旧の互換性に優れている。
Macintosh:ハードウェア設計とOS開発を同時に手がけていて、ハードとソフトとの統一感に優れている。
問題3 もし、OSが使用できなかった場合、ユーザプログラマが記述する必要があるプログラムはどのように変わってくるのか200字程度で説明せよ。
OSが使用できない場合は、OSが提供するAPIを使用することができないので、CPUの提供する機能以外は使用することができない。具体的には、外部 ハードウェアを扱うことができなくなり、マウス操作を感知する関数や、キーボードからの入力を感知する関数、また、画面に文字を出力する関数などが使えな くなる。加えて、OSの提供するABIも使えなくなるため、例え命令体系が似ているマイクロプロセッサであったとしても、プログラムを移植することができなくなる。
問題4 C言語を実行する場合にスタックはどのように使用されるのか?特に、Cの関数を呼び出すときにスタックがどのように使用されるかに関して説明せよ。
スタックは、現在レジスタに格納されている値を、FIFOなどの方式を用いて一時的に非難させるために用いられる。具体的な使用例を挙げると、C言語のプ ログラムを実行して、関数を呼ぶ処理が行われるとき、その関数が呼ばれる直前のレジスタをスタックに非難させ、関数を実行し終えた後に、スタックに入って いる非難させた値をレジスタに戻してあげることになる。こうすることで、どのような関数を呼び出したとしても、使う予定のレジスタが書き換えられるというような危険性がなくなる。
問題5 キャッシュメモリと命令パイプラインに関してそれぞれ100字程度で説明せよ。
キャッ シュメモリ:記憶装置の一つで、メインメモリとレジスタとのアクセス速度の格差を緩和させるためのメモリである。レジスタほどCPUに近くはないがメイン メモリほど離れているわけではない。このため、アクセス速度は、レジスタ>キャッシュ>メインメモリとなり、記憶容量はメインメモリ> キャッシュ>レジスタという順になっている。
命令パイプライン:CPUの処理速度を高速化する方法で、LOAD命令やSTORE命令に必要なphaseを固定長にすることで、CPUが行う様々な命令を並列的に処理することができる。現在、ほとんどのCPUがこの方法を用いて命令を実行している。
問題6 コンテキストスイッチとプロセススケジューリングに関してそれぞれ100字程度で説明せよ。
コ ンテキストスイッチ:CPUの状態を保存・復元させて、複数のプロセスを1つのCPUに割り当てること。マルチタスクOSのように、複数のプロセスが存在 するときには、複数のプロセスを同時進行しているかのように見せる必要がある。しかしながら、CPUは限られた数しかないため、1つのCPUで各プロセス を同時に扱うことができない。このため、CPUの状態を保存・復元させ、各プロセスを少しずつ処理していくことで、ユーザに対してあたかも複数のプロセス を同時進行しているかのように見せることができる。
プロセススケジューリング:CPUに効率よくプロセスを割り当てること。どのようなと きにコンテキストスイッチを使い、次にどのプロセスをCPUに割り当てるのかによって、システム全体にスループットや、リアルタイム性に変化が生じる。具 体的にいえば、ネットからの膨大な量のパケットを高速に処理しなくてはいけない場合、パケットの取りこぼしを避けるため、CPUに他のプロセスを割り当て ることが困難になる。
問題7 プログラムを実行する上で、プログラムカウンタとスタックポインタの役割を100字程度で説明せよ。
プログラムカウンタ:CPU内部にあるレジスタの一つで、次に実行する命令のアドレスが入っている。1つの命令が終わると、固定された値を現在のプログラムカウンタに加算する。このとき、プログラムカウンタの指すアドレスが次に実行する命令のアドレスとなる。
スタックポインタ:CPU内部にあるレジスタの一つで、スタックポインタに格納されている値は、今扱っているスタックのトップの場所を指している。例えば、 プログラムから違うプログラムを呼び出すとき、プログラムカウンタの値をスタックポインタに詰め込むことで、呼び出されたプログラムから元いた番地に戻ることが出来る。
問題8 プログラムを実行するときに、どのようにメモリ空間が利用されるかを100字程度で説明せよ。図を使用してもかまわない。
プログラムを実行するとき、メモリ空間からそのプログラムの実行に必要なメモリ容量を確保する必要がある。このとき、メモリ空間上でフラグメンテーションが 起こっていた場合は、「連続して空いているメモリ空間≧確保したいメモリ容量」の場所をメモリ空間の中から探し出す。条件にあう場所を発見したら、その場所を使ってプログラムの実行を行う。
問題9 ユーザ空間とカーネル空間の2つのメモリ空間が存在する理由を100字程度で説明せよ。
カーネル空間とユーザ空間を分けることで、ユーザ空間を使ってカーネル空間の内容を書き換えられないようにすることが出来る。これにより、悪意をもってカーネルを破壊しようとするプログラムから、カーネル空間におかれている内容を守ることが出来る。
問題10 10年後のコンピュータがどうなっていると思われるか各自の意見を述べよ。また、そのコンピュータは20年後のコンピュータとはどう違うと予測するか?
ムーアの法則から、10年後にはマシンのスペックが少なくとも約7倍向上することが予想される。加えて、様々なモノに組み込み系の技術が使われ、色々なモノが電子化されていくと考えている。
20年後には、電流ではなく光を使ったCPUが使われ、CPUの処理速度は今よりも格段に向上すると考える。加えて、様々なモノに組み込まれるOSが規格化され、組み込み系ソフトの入っているモノ同士の通信が容易になると思う。
---------C言語の復習とOS概要---------
システムコール = OSを呼び出すための関数
普通は、OSのデータ構造にはアクセスできない。
システムコールを介してのみ、アクセス可能。
Index
・カーネルの中身
・C言語の復習
-header, structについて
C言語とは
OSを作るのに適切な言語。
低水準programming
assembly言語はCPU毎にソースコードが違う
→移植するときは全部変更しなくてはいけない。
C言語の場合、大抵使いまわせる。
→移植するときの楽。
C言語には予約語が一杯ある。
→JAVAに似ているが、CLASSの概念はない。
C言語は分割しても一括してもどちらでも大丈夫。
→どの関数をどのファイルに置くかを考える必要がある。
Structure
-宣言部
-main関数
-そのほかの関数
C言語を使うときは、型のbyte数を把握する必要がある。
JAVAの"NEW"に近いallocateをするためには、
sizeof(型)をやって自分でbyte数を確保する必要がある。
・auto(自動変数)
関数内部の変数とか。
関数から出たら、解放する。
・static(静的変数)
呼び出すかどうかに関わらず、いつでも存在する。
EX:staticで大きい配列はダメ
・Register(レジスタ変数)
register上に置くので、早くなるかもしれない。
現在は、compilerが勝手にやってくれるので、
使っても無視されることがしばしばある。
・exterm(外部参照変数)
プログラムの外に変数を書く。
グローバル変数 = static変数
main()内はauto変数
関数内の変数をstaticにすると、以前使ったときの
結果が残っている。
int foo(void)
int main()
引数の数は自分で数える。
GNU gccは良いが、他のコンパイラには
引数をカウントしないものもある。
→clashしてdownする可能性がある。
・prototype宣言
int foo(int);
compilerがcheckしてくれる。
Ex:型のミス
void foo(void);
int x = foo;
---------------------------------
・C言語のsequence
C sourve(*.c)
↓
↓ preprocessor
↓
preprocessor後のsource(*.i)
↓
↓ C compiler
↓
Object file
↓ linker
↓←←←←←←library
↓
実行ファイル
・header
#include "queue.h"
↓
preprocessorがlibraryの中にある"queue.h"を
ソースファイル内に展開する。
・マクロ展開
#define MAX 10
MAXを10に置き換える
#define putchar(x) fputc(x, stdout)
xは引数としてマクロ展開する。
用途:何行も使うものをまとめるときに使う。
「何故methodにしないのか」
methodの呼び出しのために、サイクルカウント値を消費してしまい、
動作が遅くなるから。
OSでは、致命的。C言語では重要な部分。
→overflowはなるべく少なくする。
・他の記号
#include"hoge.h"
#if DEBUG == TRUE
print("value = %d\n", val);
→hoge.hが
#define DEBUG TRUEならば
print文がマクロ展開される。
→#include"hoge.h"の文があるかどうかで
実行の有無がわかる。
↓
debugに便利!
・gcc -DTEST ~~~
オプションの-DTESTがあれば
#ifdef TEST以下の文が展開
そうでなければ
#else以下の文が展開される。
用途:
#ifdef LINUX #else WINDOWS
Linux用とwindows用にわけてマクロ展開させることが可能。
・#incledeファイルの場所
→/usr/include/
or
/usr/include/sys/
and
/usr/include/linux/
・include fileのpathを指定したいとき
gcc -I/usr/local/hoge.h
・ifdef~else~endif
#ifdef MAIN
/* MAIN が #define してあったらここの部分がコンパイルされる。#define されていなかったらここの部分は無視される */
#else
/* MAIN が #define されていなかったらここの部分がコンパイルされる。#define してあったらここの部分は無視される */
#endif
・Compilerとlink
実行ファイルの中身
hm -g a.out | grep't'
00001c64 T __darmin_~~~
00001d44 T _main
0000166c T start
プログラムが実行させるときは、まず最初にstartを探す!
startの位置をprogram counterに設定する。
※start -> _mainまでに
色々と初期化している。
mainかんすを呼ぶためにlibraryの中で、
色々と初期化されている。
・動的リンク
必要になったときにlibraryを呼ぶ
複数のプログラムから同じlibraryを使う場合、
共有ライブラリにする
*.so (shared object)
・コンパイラの最適化
program -> binaryにする場合
defaultで -O2 optionが入る。
→-O3以上にしても、あまり結果は変わらない。
・library
-lnew 自分が定義したもの?
-L/usr/local/mylibs
↑このdirectoryの中から優先的に探しだしてlinkする。
・libraryを作る場合
gcc -c newlib.c
ar rcs libnew.a newlib.o
で"new"ライブラリにnewlibを追加
nm/usr/lib/libc
・静的リンク
全部取り込む
→programが大きくなりやすい!注意!
・構造体
データ構造のみを定義。
struct tag名{
type member1;
type member2;
};
struct log{
char time[10];
long ch0;
long ch1;
};
↑この場合
1 structure = 10B+4B+4B = 18B
struct log logger1, logger2;
typedef struct{
~~
~~
~~
}LOG;
↓
LOG logger1;
LOG logger2;
→structを宣言しないで済む。
typedefが主流。
・Pointer
※2000番地に10が入っているものとする。
int a;
int *p;
p=2000;
p=&a;
int *p;
int c = *p;
→integer型のpointerに10が入る。
func(&val);
→OSがCで書かれている理由の一つ
→pointer
予断:javaの場合classはcall-by-referenceになる
☆文字列の最後は必ず'0'が入っている。
"abcd"
↓
'a'+'b'+'c'+'d'+'0'
while(*str) str++;
→文字列を読み終わったら0が入る
→偽になる→while文終了
予断:NULL = 0
・配列とポインタ
&array[0] と arrayは同じ意味
++arrayとすると
array[1]から読み込まれる。
↓
データ構造の文だけincrementされるから。
→箱のサイズは気にしなくてもよい。
・character型の場合
char str[] ⇔ char *str
同じ
一般的に、*pには乗算や除算は使わない
structureをコピーするかpointerで指定するかで、
作業効率が大幅に変わってくる。
struct hm_time{
int hour;
int minute;
};
アクセスするには2つの方法がある。
①time.hour or time.minute
②void addtime(struct hm_time *t1, struct hm_time *t2){
t1->hour += t2->hour; ←メンバーアクセスと呼ぶ
t1->minute += t2->minute;
}
・command line
javaとはちょっと違う。
main(int argc, char argc[]){~~~
argc = コマンド(1)+引数の数
argv[] = コマンド及び引数へのポインタ
・pointerの危険性
異常終了or迷子のポインタ
エラーのとき
int *p;
int c = *p;
malloc <- 動的に領域を割り当てる。 malloc(10) = 10byte確保する ↑うまく確保できない場合は0を返すので if文を使ってエラー処理することも可能! ☆確保したものはfree()で解放すること! 解放し忘れると、メモリがドンドン減ってくる!
-----------------------
memo@file system, device driver etc. 2008/06/17
・ファイル名
ファイルを識別するためのString名からID名へ変換する
例:/a/b/c→101020
・ファイル内のポインタ
論理アドレスから物理アドレスへの変換
↑上記の二つをどうやって実現するのか?
・ファイルシステム概要
ファイルの詰め込み方にはいろんな方法がある
例:
Case 1. 頭からファイルを詰め込んでいく方法
→deflagmentationが起こるのであまり使われない。
Case 2. 固定長のブロックに分けてファイルを詰め込んでいく方法、各ブロックは次のブロックを指すポインタを持っている
→しかしsequencialにしかアクセスできない!
Case 3. 自分のファイルがどこに保存されているかを格納しているところがあり、それを参照して、ファイルの格納場所を知る(←これをディレクトリという。)
→これが最も一般的なやり方
cf.ページテーブル
☆directoryをどうやってストレージデバイスにおいていくか、が実現上大きな問題にある。よって、それぞれのファイルとdirectoryをどうやって実現していくか、をこれから説明する。
・Unix file system
API概要(OSが実現するAPI)
fd = open((file,mode)
read/write(fd, buf, size)
…とか色々
・ファイルシステム全体の概要
全体の構造:
スーパーブロック→inode list→ファイルブロック(固定長に分けたブロックのこと)
- 各用語の意味
i-node table: i-nodeを表形式にまとめたもの?
i-node: 各ファイルごとに一対一対応するデータ構造。
スーパーブロック: ファイル全体を管理するデータ構造
i-node list: 全体の数とかを管理する
ファイルへのアクセスはメモリへのアクセスと比べると時間がかかる。
一度オープンしたファイルに関しては一旦メモリ上にコピーされる。
ファイルデータ構造というのは、readすると順番にブロックが呼び出されていく。どこから呼び出されていくかはOSが知っている。
プロセスデータ構造:プロセスごとに存在し、ファイルデータ構造にある内容をファイルディスクリプタ内の情報に変換する?つまり、ファイルディスクリプタの番号はプロセスごとに閉じている。
ストレージは非常に大きい。よって、メモリ上に持っていくことは出来ない。
しかし、一部のファイルに関してはメモリにコピーしていることがある。
ストレージデバイスで、良く使う部分のみがメモリ上にコピーされる。
・i-nodeとブロックの関係
i-node内部構造:
内部構造は固定長で、
"所有者、アクセス権、アクセスタイム、変更時間、10個のエントリ、3個のエントリ"
が含まれている。ファイルシステムは何年も使われて、安全が保障されてから人に使われる。
よって、開発から実用まで10年ぐらいのスパンがある。
10個のエントリ:それぞれが独立に10個のブロックを指している。
3個のエントリ:それぞれが独立に3個の間接ブロック(=中身はエントリ)を指していて、そのブロックはそれぞれまた別なブロックを指している。
一つのブロックには256個のエントリが入る。よって、
10K + 256*1K + 256*256*1K + 256*256*256*1K
よって、ファイルのサイズが大きくなればなるほど深い層までもぐりこまなければならないのでperformanceは低下する。
i-nodeの数だけファイルが作られるので、ファイルの上限はi-nodeの数に制限される。
・Unix filesystem(4)
ファイルデータ構造は、複数のプロセスから共有されることがある。
例:プロセスAがオープンしたファイルデータ構造はプロセスBからも共有される
forkしたときに、現在オープンしたファイルディスクリプタは共有される。
オフセット:現在書き込みしているところの次はどこに書き込むのか、という情報が格納されている。
(ちなみに、Windowsでは、fork関数は使えない)
・スーパーブロック
スーパーブロックはファイルシステム全体を管理するデータ構造。
一番最初に読み込まれる。
スーパーブロックを読み込むことで分かること:
- ブロックサイズをどうするか?4K?1K?
- どのブロックが現在使われているか?
- 新しくブロックを割り当てる場合、空いているところをビットマップから判断し、割り当てる。
- 名前をどうやってi-nodeに変換するか?
- i-nodeが分かったとき、その後どうやってファイルにアクセスするか。
・read/writeとファイルシステムの関係
ファイルをオープンすると、今アクセスしようとしているi-nodeを認識する。
それをi-node tableのコピーする。
ファイルデータ構造にallocationして、プロセスデータ構造からファイルデータ構造に書き込む。
よって、処理の手順は以下のようになる
1. ファイルデータ構造のoffsetを見て、次に読み込む場所を認識。
2. i-nodeテーブルを見て、i-nodeの何バイト目を見るかを決める。
3. [10Kより小さかった場合] ブロックを発見。
[10Kより大きかった場合] 間接ブロックを辿っていく。
rooter i-node
[例] i-node:3,5,7,19,17と書いてあるとする。
頭は"/"から始まる
"/" "usr"=3
. =自分
..=親のディレクトリ
"vmunix" = 10
→ファイルを直接アクセスしている。
ファイルのブロックが順番にアクセスされる。
usr = 3
usrと認識すると i-node 3を見る。
3は"."を指しているので、親のディレクトリに行く。
例:/usr/readmeをopenする
ディスクからi-node tableの必要なブロックを全部呼び出す。
readmeを探し、7が見つかったので、
i-node 7の指すファイルを全部呼び出して、
前から順々にアクセスしていく。
よって、
ファイル名から、
i-nodeの指すファイルを探して、
ファイルをopenする。
・ハードディスクが複数合った場合はどうするのか?
ディレクトリ+ブロックが入っている。
あるハードディスクのあるディレクトリを、他のハードディスクをマウントするようにする。
mount table
mntはディスクテーブルにある。
mntを見つけたら、ディスクBをアクセスし始める。
mnt=mount
ディレクトリ自体は一つのtree構造であることには変わらない。
・物理的なディスクの構造
ハードディスク上にファイルシステムを作る場合を考える。
ディスクは複数ある。
ディスクは同心円の円がたくさん入っていて、そこにデータがたくさん入っている。
その輪の中にデータを入れていく。
それぞれの輪の部分をトラックという。
トラックを固定長に分割した部分をセクタという。
各ディスクのことをシリンダという。
シリンダ->トラック->セクタ
アームで読み込む。アームは前後に動く。
ディスクが回っていて、アームと接触した部分を読み込む。
よって、読み込むまでの時間は、アームのところに読み込みたいセクタまでディスクを回してあげて、完了するまでの時間。
→読み込み時間=アームの前後に動く時間 + セクタを指定した位置に持っていくまでの時間
よって、ハードディスクの読み込みは比較的遅い。
・バッファキャッシュ
キャッシングとプリフェッチ。
prefetch:次に読み込むものが分かっている場合は、事前にフェッチしておくこと。
ファイル全体をメモリにコピーしていくことが多い。
使用例:ファイルは頭から順番にアクセスしていくことが多いことを利用する。
具体例:Unixは次のブロックを指していたら、その次のブロックがアクセスされる場合が多いので、事前にメモリ上に呼び出しておく。
→CPUの処理効率が向上する。
タイムスタンプ:いつアクセスされていたか。
キャッシュの管理アルゴリズムは、タイムスタンプをつけてLRUで管理している。
・ディスクの書き出し
通常、バッファキャッシュで変更する時間間隔は30秒から1分に1回。
これにより、同じバッファブロックに対して何度も何度も書き出すことを制限することが出来る。
30秒に一回変更されているブロックをディスクに書き出す。
ディレクトリやスーパーブロック, i-nodeの変更はすぐにディスクに書き出す。
→システムがファイルへ書き出す前にクラッシュしたとき、ファイルシステム全体が壊れる可能性がある。
→ファイルのデータ構造をいじくるときは、常にファイルシステムの一貫性を保てるようにする。
・ディスクスケジューリング
FIFOスケジューリングは行ったり来たりする。
メカニカルに動く。
アームの動く速度は遅いので、アームの動く量を最小にしたい。
→C-SCANというアルゴリズムがある。
C-SCAN:
1. いくつかのタスクを溜めておいて、ソートする。
2. ディスクへ書き出す時間になったら、頭から尾に向かって順番にアクセスしていく。
3. その後、アームを頭の位置に戻す。
他のもディスクスケジューリングアルゴリズムがある。
今は、もうちょっと頭のいいアルゴリズムも存在する。
☆ハードディスクのアクセスには物理メモリと違って、
トラックがどこにあるかによってアクセス時間が大幅に違う。
自分のアクセスしたいデータがトラックのどこにあるのかを認識して、
最小限のアームの動きでアクセスする必要がある。
・分散ファイルシステム
リモートにあるマシンに対して同じプログラムを使いたいときは
アクセス透過性と位置透過性を考える必要がある。
アクセス透過性:リモートファイルもローカルファイルも同一のAPIを用いてアクセス可能
位置透過性:ファイル名にマシン名が含まれていない。
→どこのマシンにあるかを気にせずアクセスできる!
・NFS
network file systemの略称。しかしnetwork file systemとは滅多に言わない。
☆プログラマーから見て、あたかも普通にディレクトリをアクセスできるかのようにすることが大切!
→OSは、ネットワーク上の複雑な処理をユーザから隠蔽することが大事!
・I/Oの種類
各I/Oの関係↓
プログラム⇔デバイスドライバ⇔デバイス
デバイスの種類はたくさんある!
デバイスドライバが出来るだけ隠蔽してあげることが大切。
・バスの種類
PCI
ISA
SCSI
…たくさん!
・デバイスドライバ
デバイス独自のプロトコルの使用にあわせて作り、出来るだけ簡略化し、隠蔽する。
デバイスドライバ:各デバイスのアクセスプロトコル(デバイスの制御手順)を実装する。
デバイスドライバはデバイスを自動的に発見し、どのようにアクセスするかを自動的に決定する。
cf:USBの挿入
USBを差し込む→OSが認識→if文分岐
1. [デバイスドライバがない場合] デバイスドライバをインストールする。
2. [デバイスドライバがある場合] USBを読み込む
昔は数百行だったが、今は数千行必要になる。
→デバイスドライバを作る人はこれから増えるかもしれない。
☆重要なこと
デバイスとデバイスドライバのやり取りをどうするかを決めること。
・デバイスアクセスの方法
I/Oイベントの通知
- error通知、利用可能データ通知、状態通知
- ポーリング:CPUからデバイスに対して使用可能か調べる?
- 割り込み
・データの転送
デバイスとCPUのデータ転送方法を決定する。
- read/write
- programmable I/O
- DMA(Direct Memory Access): ある程度の長さのデータを一括して転送する
・I/O port
- メモリ空間と異なるI/O空間
- 各デバイスはI/O空間上にポートを割り当てられる
- ポートをアクセスすることによりデバイスとメモリ間のデータ転送が行われる
- I/Oポートをアクセスするための特注名命令が必要
→x86の場合、in, out命令
・Memory mapped I/O
- デバイスの一部をメモリとしてみることが出来る。
- メモリアクセスとして実現されるが、アクセスコストが異なる。
・ポーリング CPUからデバイスに対して以下のことを確認する。
- データの入力が可能となる
- データの出力が可能となる
- 処理の終了
あるデータの書き出すが起きているときには、それが終わるまでは次の書き出しを禁止する。
ポーリングを使って、"毎回毎回処理が終わったかどうか"を聞く。
例:
while(flagPort != READY); // データの書き出しが終わるまでwhile文でループし続ける
mem = dataPort; // データの書き出しが終わったらデータをメモリ領域に移す
dataPort:どっかのレジスタ
注意:イベントの発生などをポーリングで待つことはCPUの無駄遣い
他の処理の合間にポーリングをすることが可能だが、システム全体の構造がクリアではなくなる
よって、ポーリングを使用するときは、結果が分かるまでの時間が短い場合のみ。
例: 20μsならよいが、20nsでは無駄。
・割り込み interrupt
割り込みの流れ
1. (通常の場合) CPU→要求(I/O port, memory)→デバイス
2. (割り込みの場合) CPU← 割り込み ←デバイス
↑ポーリングによるCPUの無駄遣いを防ぐことが出来る
割り込み:
デバイスからCPUに対して何かを呼び出したいとき、
今実行しているプログラムを中断して割り込んだデバイスの処理をさせるときに使う。
・ 割り込みハンドラ
以下のような処理が割り込み処理に当たる
- 新しく入力された
- エラー処理
- デバイスからの通知処理
番号ごとに違う番号を登録する
例:割り込みベクタ↓
IRQ0 = clock handler
IRQ1 = disk handler
IRQ2 = network handler
IRQ3 = trap handler: page fault, system call, bus error etc.
各デバイスはIRQの何番を用いるか知っている。
場合によっては、割り込みベクタを複数のデバイスで共有することが出来る。
→割り込み処理でもらってきた値を評価して、どのデバイスの割り込みかを認識する。
これにより、IRQの数以上のデバイスを管理することが出来る。
・多重割り込み
割り込みが、同時系列に、複数個存在している状態のこと。
Q: 割り込み処理が実行されたときに、違う割り込みが来た場合はどうするのか?
A: 割り込みには優先度が付いている。優先度を見て割り込み処理の順序を判断。
例:(←優先度低)level2, level3, level4,...,level7(優先度高→)
levelの値が高い方が優先して処理する。
デバイスによっては、あまり長い時間放置されると破綻するものもある。
例:network driverは連続的にパケットが送信されるので、データが来たときにすぐ処理しなければならない。
・時間制約によって勝手に割り込んでくる処理がある。
割り込みの数が多いと、今実行されているプログラムは実行できなくなる。
☆未だに解決できていない課題
時間を測定する関数を使った場合、割り込み処理によって正確な値が測定できない。
割り込みハンドラを実行後レジスタを回復する必要がある。
例:
handler(){
save_register();
process_interrupt();
restore_register();
}
割り込みは割り込みようのスタックを用いる。
これにより、スタックがオーバーフローすることを避けている。
・割り込みのオーバーヘッド
割り込み処理のコストは結構大きい。ポーリングより大きいので、ポーリングを使った方が良いときも多い。
例:
web serverはデータが来る毎に割り込みが発生する。
昔は10MB/bpsだったので、そんなにCPUが早くなくても取りこぼさない。
今は10GB/bpsなので、パケット量が圧倒的に増えて、割り込みが毎回発生する。
最悪の場合、web serverが実行できずに割り込み処理しか実行されない。
→原因:割り込みハンドラの呼ばれる頻度が高い。
結果:10GB/bpsぐらいだと、CPUは有意義な計算を行うことが出来ない。 対処例:割り込みハンドラの呼ばれる頻度が高くなったら、ポーリングに切り替える。
・割り込みの禁止 システムコールの処理と割り込みハンドラ間の排他制御
cf.複数のスレッドを実行するときは排他制御する必要がある。
例:readやwriteがデータ構造をいじっているときは割り込みを禁止する。
例:
syscall()
{
割り込み禁止
排他リソースのアクセス
割り込み可能
}
注意:割り込みを禁止している時間はなるべく短くするように心がける。
→割り込み禁止期間が長いと、マウスが動かなかったり、画面が表示されなかったりと、UIに悪影響を及ぼすから。
・Direct Memory Access
各デバイスはメモリから直接データをやり取りする。
bufPort: buffer size
sizePort:送るべきデータのサイズ
cmdPort: WRITEスタート
CPUとは関係なく実行される
・サイクルスティーリングとは?
メモリとCPUを繋ぐバスがある
DMAデバイスはバスを使う。
→バスは共有されている。同時には使えない。
→DMAが動いているときはパイプラインが使えない
結果:DMAはCPU上で動いているプログラムのパフォーマンスを低下させる可能性を持っている。
かつ、CPUとは無関係に動いているので、どのくらい低下するのか予想するのが難しい。
デバイスからDMAを使ってデータを物理メモリの呼び出されたとき、キャッシュの中をクリアする必要がある。
→DMAをたくさん使うとパフォーマンスが低下する。
・物理空間か仮想空間か
デバイスが、MMUを解さずメモリをアクセスする場合に、デバイスにバッファのアドレスを教えるときは物理メモリアドレスを教える必要がある。
CPUから見えるアドレスとデバイスから見えるアドレスは違うので、マッピングする必要がある。
・TLB管理 経緯:ページテーブルによる仮想アドレスと物理アドレスの変換のオーバーヘッドを減少するため、TLBが導入された。
☆割り込みを考えるとTLBもパフォーマンスを低下させる可能性を持っている。
TLBはコンテキストスイッチが起こるたびにクリアする必要がある。
ページテーブルの変更はTLBに影響を及ぼさない。
以下の場合において、TLBをクリアする必要がある。
- I/Oデバイスが新しくマップかアンマップされたとき
- 新しい仮想エリアが新しくマップかアンマップされたとき
- プロセスのコンテキストスイッチが発生したとき
・ユーザから見たI/Oインターフェース
/dev/device0 10 1
↑このファイルをオープンするとメジャー番号(10)とマイナー番号(1)に変換する。
よって、オープンするときは、
fd = open("/dev/device", mode);
close(fd);
read/write(fd, buf, size);
ioctl(fd, cmd, arg);
何でもかんでもI/Oコマンドを定義していくと移植性が低下するので、
I/Oコマンドの定義は最小限にした方が好ましい。
・/proc
特別なデバイス。各プロセスの色んな情報を取り出すことが出来る。
例:
"文字列" 意味
"/proc/1/fd/3" プロセス1のfd3の情報を取る。
"/proc/1/mem" プロセス1のメモリ
"/proc/pci" PCIに関する情報
"/proc/modules" カーネル内にロードされたモジュールの情報
・非同期I/O readシステムコールはデータが来るまで待っている。
signalを使って非同期化する?
例:
{
signal(SIGIO,..&input_handler)..
fcntl(0, F_SETWON,..getpid());
oflag = fcntl(0, F_GETFL);
fcntl(0, f_SETFL, oflag | FASYNC);
}
・付録
PDFの"付録"にデバイスドライバのサンプルソースコードがあるので目を通しておく。
---------ファイルシステムの講義はここまで---------
---------プロセスについての講義-------
2008/06/24
プロセスとは?
・プログラムの実行形
・独立したアドレス空間とPC, SP, レジスタのセット
・現在使用中のNWソケットや読み書き中のファイルなどのI/Oデバイスの利用状況のセット。
・シグナルにより別プロセスにメッセージを送ることが可能
上記中にあるプログラム自体は単純な動作の集合に過ぎない。
単純な動作の集合から、複雑な動作になっている。
・exec族
例: execlでプロセスが変わる。
→execlのあとにプログラムを書いても意味がない。
p = path
execle = 環境変数を指定して呼び出す。
signal
interupt
signal -> required #inlude
sigaction(SICINT, &act, 0);
// just registerd
act.sa_flags = 0;
act.sa_handler = ouch(function);
例:
while(1){
printf("Hello World!\n");
sleep(1);
}
意味:1 printout per sec
脱出方法:
if you press Ctrl+c, the function ouch is called.
----------------------------
(ここらへんから突如日本語入力に不具合 orz)
pipeline: 8 bit
register: 16bit
cache: 32 or 16 it
例: "ls > aaa"
意味:output ls data into aaa
std output change dup2
opposite cat
"cat <> [understand fork and exec]
understand system call getpid, getppid getued, geteuid,...,and so on.
"ps": confirm process information running
UID = indicate who calls process.
each process have unique ID
PID = unique ID of each Process
[Flow of program]
1, "init" is called by OS(root)
-> forced to allocate memory space
almost Linux has this init program
In config file, there are a lot of programs about init.
2, init calls login program (UID = 0)
then user should input ID and password
Ex: yohei has 515 UID
3, seeing inputed ID, shell command is called
this UID is 515
if sshd has bug, root has possibility to be stolen.
※private address has more safety than global IP.
*the programs under init are supporting init program
GID is represented by 16bit integer.
getpid, getppid, getuid, getgid have no parameter.
you can fetch each ID using functions above.
・fork
implement multi process eniviroment.
copy process image when it is called.
file descriptor is also copied.
usage: "pid_t fork(void);"
including sys/types.h and unistd.h is required!
recognize program itself is parent or child
ex
pid_t new_pid;
new_pie = fork(); // stack is already copied,
if(new_pid) == -1){
// error
}else if(new_pid == 0){
// execution as a child process
}else{
// execution as a general process
}
* if fork return -1, it shows error.
* which is occurred earlier depends on then environment.
* this above means debug work is very hard!
copy on right makes cost less
wait call
how do we synchronize child process and parent process?
while shell command is running, is shell sequential?
wait = wait for finishing of whose process.
waitpid = wait for finishing of certain process.
required #include
wait function has 3 parameters.
ex
waitpid(child, &stat_val, 0);
// "child" contains child process ID.
// if child process is not finished yet, wait for finishing child process!
// if you forget to command "&", you get 0 instead of &stat_val, then you hold or system down.
// so, it is difficult to find out where is bug.
// c++ has exception function, but c does not such a exception.
// if using language has the exception function, you should use it!
// if possible, you should not call system call, because it makes bugs lower.
* OS is still a little weak, so you pay careful attention to write arguments!
*
wait: wait for the status of child is available by family
exit: By child, configure status code, and then notice what parent has finished!
-----------------------------------------
kill
kill -kill 1234
you have killed process having PID of 1234
signal; waiting for pressing any of keyboard and something like that.
alarm(5)
signal is occurred per 5 seconds.
act.sa_handler = ding;
clock_t times(struct tms *buf)
examine how much time program spends.
int system(const char *command)
forced to call command.
In homework, you must not use the system command!
putenv, getenv
reconfigure your envinment variables.
inter communication between processes
pipe, socket
pipe
In shell command
ps -Af | grep hoge
you can move result anywhere.
int pipe(int file_descriptor[2]);
[0]; // for reading
[1]; // for writing
return
0: successful
-1; failure
Case1
Parent <----> child
parent --- file_pipes[1] | file_pipes[0] --- child
parent --- file_pipes[0] | file_pipes[1] --- child
some source codes
int file_pipes[2];
if(pipe(file_pipes) == 0){
fork_result = fork()l
...
}
close(file_pipes[1]); = pipe
data_o = read(file_pipes[0], buffer, BUFSIZ); = file_pipes[0] yu child
// reading data put into buffer
you do not have to close pipe, but it has possibility to occur bugs!
so, you should close it ASAP.
let's consider PS -As | grep hoge (== 1 | 0)
grep is fetching data from 2nd parameter to end parameter.
Using dup2,
dup2(1, p[1])
Meaning: fetching pipeline[1]
dup2(0, p[0]);
Meaning: fetching pipeline[0]
kind of "ls > aaa"
cat <>
From System Call
int mkfifo(const char * filename, mode_t mode);
* this pipe is hardly used.
pipe system can be call if only two programs are related to family-child.
・setjump/longjump
#include
jump_buf ma;
// required and should be put in global domain!
longjmp(ma, -1);
// return value is -1
Ex:
key = setjmp(ma)
// key == -1
EX:
func(){
longjmp
}
main(){
sigaction
setjmp
printf("prompt = ")
read(ls, -1)
fork
wait
exec
}
"ls > a"
cat <= a ls|grep - , cntl.c fork| | | sigaction exec| dup2 | pipe | setjmp/longjmp wait| | | /bin /usr/bin ex. ls -l // search files from upper to bottom in directory. if you find out it, execute it,
---------ここまでプロセスについての講義--------
---------ソケットについての講義---------
2008/07/01
・本日の話 = ネットワークに関するシステムコール
- ソケット
- Client/Server型システムの形態
- システムコール
- 標準ライブラリ
・ソケット
※PDF参照
・クライアント・サーバ型(もっとも基本的な型)
UNIXにはもともとスレッドという概念がない。
スレッド使えるようになったのは5年前の話
プロセスをフォークすることは難しい。
cf: "Copy on Write"
→毎回毎回プロセスをフォークするとコストが大きい
→スレッド使ったり別の方式を使ったりする。
・反復サーバ型
サーバがクライアントのリクエストをリプライする。
受け取った順に処理する。
→もし、サーバの待ち時間が長い場合はサーバが無駄に動いてしまう。
→多くのクライアントからのリクエストを処理する時には向いていない。
・並行サーバ型
ファイルの流れ↓
クライアント → サーバー → (フォーク)Chile Process → クライアント
→サーバはリクエストを受け付けて、子プロセスを生成するだけですむ
→ほとんどのサーバはこの形で作られている。
ただし、スレッドに変えてもそんなにオーバーヘッドが減る分けではない。
実際にはもうちょっと複雑な処理をして、オーバーヘッドを減らしている。
・同期通信、非同期通信
- 同期通信
リクエストが帰ってくるまで動かない
ex.失いたくない貴重な情報の時
- 非同期通信
リクエストが帰ってくるかどうかにかかわらず動きつづける。
割り込みのような形でリプライを受け取る。
ex.音楽再生とか
・Unicast, Broadcast, Multicast
- unicast
1 on 1通信
- broadcast
ネットワーク上の全マシンに対して送信
e.g. DHCP
「僕はあなたのアドレスを知らないけど、あなたのIPアドレスが欲しい!」
- multicast
特定のグループへの加入者に対する同報
・ソケット通信の手順(ストリームソケット)
-Client側
socket // ソケットの生成
bind // ソケットへの名前付け
connect
read/write
close
-Server側
socket
bind
listen
accept
read/write
close
・UBPの場合
-Client側
socket // ソケットの生成
bind //ソケットへの名前付け
sendto //データ送信
recvdrom //データ受信
close //ソケットの除去
-Server側
socket
bind
recvfrom
sendto
close //ソケットの除去
・ソケットの生成
-書式
int socket(int domain, int type, int protocol)
int domein:
使用するドメイン種別
int type:ソケットタイプ
UDPを使いたい場合 SOCK_DGRAM
int protocol: 下位プロトコルの指定
0=default
・ソケットの名前付け:bind
取ってきたファイルディスクリプタに対して名前をつける。
int bind(int socketfd, struct sockaddr(自分のアドレスの定義) *my_addr(データスタラクチャの長さ), sockelen_t addrlen)
・バイトオーダーとホストオーダー
BIG-endianとLittle-endianの違い
→各マシンごとに違うフォーマットを使っている場合は、意識して直す必要がある。
→CPUなどのアーキテクチャを使用する必要がある。
簡素化ため、変数変換用の関数が用意されている
- htonl, htons: host->nw
- ntohl, ntohs: nw->host
h to nl
n to hl
・ソケットアドレスの構造体
-port
送り側と受け手側で違うポート番号を使う必要があるので、要注意。
bzero((void *)&server, sizeof(server));
server sin_family = AF_INET;
・IPアドレスの与え方
- バイナリで与える場合(e.g. 0Xac105504)←バイトオーダーで考える必要がある。
- ドット区切り10進表記で与える場合(e.g. 172.16.85.4)
- hostnameで与える場合
gethostbyname ライブラリ関数を使用(後述)
引数にホスト名が入る。
hostentから、アドレスが返ってくる。
IPaddressを知ることができる。いf
・listen:接続受け入れ準備
接続要求を格納するキュー
→いくつ、接続を格納するキューを確保するか、のために使う。
・connect:接続要求発信
- streamsocket使用時における通信路確立
あとで例題
・accept:接続要求許可
int sockfd:
struct sockaddr:相手のアドレス
この関数が返す引数が使うファイルディスクリプタになる。
・read/write:データ送受信
・ストリームソケットが他の通信手順
・無線デバイスドライバのインストール
Linuxのデバイスドライバをダウンロード→インストール
2008-07-18
SE final preparation
---------------------------------------------------------------------------------------------------
テスト予告:
1. 〜について以下の問いに答えなさい(授業の演習)
座席の設計、要求分析、〜図で描け
(例、航空機予約シナリオのユースケース図を書いたらこうなった、では、航空便を登録するのシナリオ(ユースケース記述)はどうなるか書きなさい)
演習14のような感じ
(1)プロセスからシナリオまたは記述
(2)このユースケース(1)に基づいて概要設計した図を描きなさい(1の書き方によって答えが変わる)
2.次の各設問について答えよ(説明、論述)(5問)
ユースケースにおけるアクターとは何か?←簡単だから出ない?
(200字程度)
3.次の用語の違いについて200字程度で答えよ(5問)
出席20点
テスト50点満点
レポートA 15, B 10, C 5
---------------------------------------------------------------------------------------------------
テスト予告:
1. 〜について以下の問いに答えなさい(授業の演習)
座席の設計、要求分析、〜図で描け
(例、航空機予約シナリオのユースケース図を書いたらこうなった、では、航空便を登録するのシナリオ(ユースケース記述)はどうなるか書きなさい)
演習14のような感じ
(1)プロセスからシナリオまたは記述
(2)このユースケース(1)に基づいて概要設計した図を描きなさい(1の書き方によって答えが変わる)
2.次の各設問について答えよ(説明、論述)(5問)
ユースケースにおけるアクターとは何か?←簡単だから出ない?
(200字程度)
3.次の用語の違いについて200字程度で答えよ(5問)
出席20点
テスト50点満点
レポートA 15, B 10, C 5
---------------------------------------------------------------------------------------------------
2008-07-01
socket programming
2008/07/01
本日の話
・ネットワークに関するシステムコール
-ソケット
-Client/Server型システムの携帯
-システムコール
-標準ライブラリ
・ソケット
・基本型:クライアント・サーバ型
UNIXにはもともとスレッドという概念がない。
スレッド使えるようになったのは5年前の話
プロセスをフォークすることは難しい。
cf:コピーオンライト
→毎回毎回プロセスをフォークするとコストが大きい
→スレッド使ったり別の方式を使ったりする。
・反復サーバ型
サーバがクライアントのリクエストをリプライする。
受け取った順に処理する。
→もし、サーバの待ち時間が長い場合はサーバが無駄に動いてしまう。
→多くのクライアントからのリクエストを処理する時には向いていない。
・並行サーバ型
-ファイルの流れ
クライアント→サーバー→(フォーク)CP→クライアント
→サーバはリクエストを受け付けて、子プロセスを生成するだけで住む
→ほとんどのサーバはこの形で作られている。
ただし、スレッドに変えてもそんなにオーバーヘッドが減る分けではない。
実際にはもうちょっと複雑な処理をして、オーバーヘッドを減らしている。
・同期通信、非同期通信
-同期通信
リクエストが帰ってくるまで動かない
ex.失いたくない貴重な情報の時
-非同期通信
リクエストが帰ってくるかどうかにかかわらず動きつづける。
割り込みのような形でリプライを受け取る。
ex.音楽再生とか
・unicast, broadcast, multicast
-unicast
1 on 1通信
-broadcast
ネットワーク上の全マシンに対して送信
e.g. DHCP
「僕はあなたのアドレスを知らないけど、あなたのIPアドレスが欲しい!」
-multicast
特定のグループへの加入者に対する同報
・ソケット通信の手順(ストリームソケット)
-Client
socket ソケットのせいせい
bind ソケットへの名前付け
connect
read/write
close
-Sever
socket
bind
listen
accept
read/write
close
・UBPの場合
-Client
socket ソケットの生成
bind ソケットへの名前付け
sendto データ送信
recvdrom データ受信
close ソケットの除去
-Server
socket
bind
recvfrom
sendto
・ソケットの生成
-書式
int socket(int domain, int type, int protocol)
int domein:
使用するドメイン種別
int type:ソケットタイプ
UDPを使いたい場合 SOCK_DGRAM
int protocol: 下位プロトコルの指定
0=default
・ソケットの名前付け:bind
取ってきたファイルディスクリプタに対して名前をつける。
int bind(int socketfd, struct sockaddr(自分のアドレスの定義) *my_addr(データスタラクチャの長さ), sockelen_t addrlen)
・バイトオーダーとホストオーダー
BIG-endianとLittle-endianの違い
→各マシンごとに違うフォーマットを使っている場合は、意識して直す必要がある。
→CPUなどのアーキテクチャを使用する必要がある。
このため、変数関数が用意されている
- htonl, htons: host->nw
- ntohl, ntohs: nw->host
h to nl
n to hl
・ソケットアドレスの構造体
-port
送り側と受け手側で違うポート番号を使う必要があるので、要注意。
bzero((void *)&server, sizeof(server));
server sin_family = AF_INET;
・IPアドレスの与え方
- バイナリで与える場合(e.g. 0Xac105504)←バイトオーダーで考える必要がある。
- ドット区切り10進表記で与える場合(e.g. 172.16.85.4)
- hostnameで与える場合
gethostbyname ライブラリ関数を使用(後述)
引数にホスト名が入る。
hostentから、アドレスが返ってくる。
IPaddressを知ることができる。いf
・listen:接続受け入れ準備
接続要求を格納するキュー
→いくつ、接続を格納するキューを確保するか、のために使う。
・connect:接続要求発信
- streamsocket使用時における通信路確立
あとで例題
・accept:接続要求許可
int sockfd:
struct sockaddr:相手のアドレス
この関数が返す引数が使うファイルディスクリプタになる。
・read/write:データ送受信
・ストリームソケットが他の通信手順
・無線デバイスドライバのインストール
Linuxのデバイスドライバをダウンロード→インストール
本日の話
・ネットワークに関するシステムコール
-ソケット
-Client/Server型システムの携帯
-システムコール
-標準ライブラリ
・ソケット
・基本型:クライアント・サーバ型
UNIXにはもともとスレッドという概念がない。
スレッド使えるようになったのは5年前の話
プロセスをフォークすることは難しい。
cf:コピーオンライト
→毎回毎回プロセスをフォークするとコストが大きい
→スレッド使ったり別の方式を使ったりする。
・反復サーバ型
サーバがクライアントのリクエストをリプライする。
受け取った順に処理する。
→もし、サーバの待ち時間が長い場合はサーバが無駄に動いてしまう。
→多くのクライアントからのリクエストを処理する時には向いていない。
・並行サーバ型
-ファイルの流れ
クライアント→サーバー→(フォーク)CP→クライアント
→サーバはリクエストを受け付けて、子プロセスを生成するだけで住む
→ほとんどのサーバはこの形で作られている。
ただし、スレッドに変えてもそんなにオーバーヘッドが減る分けではない。
実際にはもうちょっと複雑な処理をして、オーバーヘッドを減らしている。
・同期通信、非同期通信
-同期通信
リクエストが帰ってくるまで動かない
ex.失いたくない貴重な情報の時
-非同期通信
リクエストが帰ってくるかどうかにかかわらず動きつづける。
割り込みのような形でリプライを受け取る。
ex.音楽再生とか
・unicast, broadcast, multicast
-unicast
1 on 1通信
-broadcast
ネットワーク上の全マシンに対して送信
e.g. DHCP
「僕はあなたのアドレスを知らないけど、あなたのIPアドレスが欲しい!」
-multicast
特定のグループへの加入者に対する同報
・ソケット通信の手順(ストリームソケット)
-Client
socket ソケットのせいせい
bind ソケットへの名前付け
connect
read/write
close
-Sever
socket
bind
listen
accept
read/write
close
・UBPの場合
-Client
socket ソケットの生成
bind ソケットへの名前付け
sendto データ送信
recvdrom データ受信
close ソケットの除去
-Server
socket
bind
recvfrom
sendto
・ソケットの生成
-書式
int socket(int domain, int type, int protocol)
int domein:
使用するドメイン種別
int type:ソケットタイプ
UDPを使いたい場合 SOCK_DGRAM
int protocol: 下位プロトコルの指定
0=default
・ソケットの名前付け:bind
取ってきたファイルディスクリプタに対して名前をつける。
int bind(int socketfd, struct sockaddr(自分のアドレスの定義) *my_addr(データスタラクチャの長さ), sockelen_t addrlen)
・バイトオーダーとホストオーダー
BIG-endianとLittle-endianの違い
→各マシンごとに違うフォーマットを使っている場合は、意識して直す必要がある。
→CPUなどのアーキテクチャを使用する必要がある。
このため、変数関数が用意されている
- htonl, htons: host->nw
- ntohl, ntohs: nw->host
h to nl
n to hl
・ソケットアドレスの構造体
-port
送り側と受け手側で違うポート番号を使う必要があるので、要注意。
bzero((void *)&server, sizeof(server));
server sin_family = AF_INET;
・IPアドレスの与え方
- バイナリで与える場合(e.g. 0Xac105504)←バイトオーダーで考える必要がある。
- ドット区切り10進表記で与える場合(e.g. 172.16.85.4)
- hostnameで与える場合
gethostbyname ライブラリ関数を使用(後述)
引数にホスト名が入る。
hostentから、アドレスが返ってくる。
IPaddressを知ることができる。いf
・listen:接続受け入れ準備
接続要求を格納するキュー
→いくつ、接続を格納するキューを確保するか、のために使う。
・connect:接続要求発信
- streamsocket使用時における通信路確立
あとで例題
・accept:接続要求許可
int sockfd:
struct sockaddr:相手のアドレス
この関数が返す引数が使うファイルディスクリプタになる。
・read/write:データ送受信
・ストリームソケットが他の通信手順
・無線デバイスドライバのインストール
Linuxのデバイスドライバをダウンロード→インストール
2008-06-24
Process programming
2008/06/24
プロセスとは?
・プログラムの実行形
・独立したアドレス空間とPC, SP, レジスタのセット
・現在使用中のNWソケットや読み書き中のファイルなどのI/Oデバイスの利用状況のセット。
・シグナルにより別プロセスにメッセージを送ることが可能
↑中のプログラム自体は単純な動作の集合に過ぎない。
単純な動作の集合から、複雑な動作になっている。
------------ exec ----------------
execlでプロセスが変わる。
このため、execlのあとにプログラムを書いても意味がない。
p = path
execle = 環境変数を指定して呼び出す。
signal
interupt
signal
required #inlude
sigaction(SICINT, &act, 0);
// just registerd
act.sa_flags = 0;
important!
act.sa_handler = ouch(function);
while(1){
printf("Hello World!\n");
sleep(1);
// once output per sec
if you press Ctrl+c, the function ouch is called.
----------------------------
(ここから突如日本語が打てなくなった笑)
pipeline is 8 bit
register 16bit
cache 32 or 16 it
"ls > aaa"
output ls data into aaa
std output change dup2
opposite cat
"cat < aaa" exchange 0 of dup2 why dup2 is important? [understand fork and exec] know system call getpid, getppid getued, geteuid,...,and so on. ps command >confirm process information running
UID = process is appeared by who
The Who is the UID
each process have unique ID
PID = unique ID of each process
[flow of program]
1, init is called by OS(root)
forced to allocate memory space
almost Linux has this init program
In config file, there are a lot of programs about init.
2, init calls login program (UID = 0)
then user should input ID and password
ex tatsuo has 515 UID
3, seeing inputed ID, shell command is called
this UID is 515
if sshd has bug, root has possibility to be stolen.
*private address has more safety than global IP.
*the programs under init are supporting init program
GID is represented by 16bit integer.
getpid, getppid, getuid, getgid have no parameter.
you can fetch each ID using functions above.
fork
implement multi process eniviroment.
copy process image when it is called.
file descriptor is also copied.
usage
pid_t fork(void);
including sys/types.h and unistd.h is required!
recognize program itself is parent or child
ex
pid_t new_pid;
new_pie = fork(); // stack is already copied,
if(new_pid) == -1){
// error
}else if(new_pid == 0){
// execution as a child process
}else{
// execution as a general process
}
* if fork return -1, it shows error.
* which is occurred earlier depends on then environment.
* this above means debug work is very hard!
copy on right makes cost less
wait call
how do we synchronize child process and parent process?
while shell command is running, is shell sequential?
wait = wait for finishing of whose process.
waitpid = wait for finishing of certain process.
required #include
wait function has 3 parameters.
ex
waitpid(child, &stat_val, 0);p
// child contains child process.
// if child process is not finished yet, wait for finishing it!
// if you forget to command "&", you get 0 instead of &stat_val, then you hold or system down.
// so, it is difficult to find out where is bug.
// c++ has exception function, but c does not such a exception.
// if using language has the exception function, you should use it!
// if possible, you should not call system call, because it makes bugs lower.
* OS is still a little weak, so you pay careful attention to write arguments!
*
wait: wait for the status of child is available by family
exit: By child, configure status code, and then notice what parent has finished!
-----------------------------------------
kill
kill -kill 1234
you have killed process having PID of 1234
signal; waiting for pressing any of keyboard and something like that.
alarm(5)
signal is occurred per 5 seconds.
act.sa_handler = ding;
clock_t times(struct tms *buf)
examine how much time program spends.
int system(const char *command)
forced to call command.
In homework, you must not use the system command!
putenv, getenv
reconfigure your envinment variables.
inter communication between processes
pipe, socket
pipe
In shell command
ps -Af|grep hoge
you can move result anywhere.
int pipe(int file_descriptor[2]);
[0];for reading
[1];for writing
return
0: successful
-1; failure
Case1
Parent <----> child
parent --- file_pipes[1] | file_pipes[0] --- child
parent --- file_pipes[0] | file_pipes[1] --- child
some source codes
int file_pipes[2];
if(pipe(file_pipes) == 0){
fork_result = fork()l
...
}
close(file_pipes[1]); = pipe
data_o = read(file_pipes[0], buffer, BUFSIZ); = file_pipes[0] yu child
// reading data put into buffer
you do not have to close pipe, but it has possibility to occur bugs!
so, you should close it ASAP.
let's consider PS -As | grep hoge (== 1 | 0)
grep is fetching data from 2nd parameter to end parameter.
Using dup2,
dup2(1, p[1])
// fetching pipeline[1]
dup2(0, p[0]);
// fetching pipeline[0]
kind of
ls > aaa
cat < aaa ex program close(0); dup(p_id[0]); // equals to "dup2(0,p_id[0]);" close(p_fd[0] close(p_fd[1] pipe added name(FIFO) who call pipe system call? you should clarify that who and who inter communicate. From Command Line mkfifo < filename>
From System Call
int mkfifo(const char * filename, mode_t mode);
* this pipe is hardly used.
pipe system can be call if only two programs are related to family-child.
setjump/longjump
#include // required
jump_buf ma; // required and should be put in global
longjmp(ma, -1) // return value is -1
key = setjmp(ma) // key == -1
EX
func()
{
longjmp
}
main(){
sigaction
setjmp
printf("prompt = ")
read(ls, -1)
fork
wait
exec
}
important!
ls > a
cat <= a ls|grep - , cntl.c
fork| | | sigaction
exec| dup2 | pipe | setjmp/longjmp
wait| | |
/bin
/usr/bin
ex. ls -l
search files from upper to bottom in directory.
if you find out it, execute it,
プロセスとは?
・プログラムの実行形
・独立したアドレス空間とPC, SP, レジスタのセット
・現在使用中のNWソケットや読み書き中のファイルなどのI/Oデバイスの利用状況のセット。
・シグナルにより別プロセスにメッセージを送ることが可能
↑中のプログラム自体は単純な動作の集合に過ぎない。
単純な動作の集合から、複雑な動作になっている。
------------ exec ----------------
execlでプロセスが変わる。
このため、execlのあとにプログラムを書いても意味がない。
p = path
execle = 環境変数を指定して呼び出す。
signal
interupt
signal
required #inlude
sigaction(SICINT, &act, 0);
// just registerd
act.sa_flags = 0;
important!
act.sa_handler = ouch(function);
while(1){
printf("Hello World!\n");
sleep(1);
// once output per sec
if you press Ctrl+c, the function ouch is called.
----------------------------
(ここから突如日本語が打てなくなった笑)
pipeline is 8 bit
register 16bit
cache 32 or 16 it
"ls > aaa"
output ls data into aaa
std output change dup2
opposite cat
"cat < aaa" exchange 0 of dup2 why dup2 is important? [understand fork and exec] know system call getpid, getppid getued, geteuid,...,and so on. ps command >confirm process information running
UID = process is appeared by who
The Who is the UID
each process have unique ID
PID = unique ID of each process
[flow of program]
1, init is called by OS(root)
forced to allocate memory space
almost Linux has this init program
In config file, there are a lot of programs about init.
2, init calls login program (UID = 0)
then user should input ID and password
ex tatsuo has 515 UID
3, seeing inputed ID, shell command is called
this UID is 515
if sshd has bug, root has possibility to be stolen.
*private address has more safety than global IP.
*the programs under init are supporting init program
GID is represented by 16bit integer.
getpid, getppid, getuid, getgid have no parameter.
you can fetch each ID using functions above.
fork
implement multi process eniviroment.
copy process image when it is called.
file descriptor is also copied.
usage
pid_t fork(void);
including sys/types.h and unistd.h is required!
recognize program itself is parent or child
ex
pid_t new_pid;
new_pie = fork(); // stack is already copied,
if(new_pid) == -1){
// error
}else if(new_pid == 0){
// execution as a child process
}else{
// execution as a general process
}
* if fork return -1, it shows error.
* which is occurred earlier depends on then environment.
* this above means debug work is very hard!
copy on right makes cost less
wait call
how do we synchronize child process and parent process?
while shell command is running, is shell sequential?
wait = wait for finishing of whose process.
waitpid = wait for finishing of certain process.
required #include
wait function has 3 parameters.
ex
waitpid(child, &stat_val, 0);p
// child contains child process.
// if child process is not finished yet, wait for finishing it!
// if you forget to command "&", you get 0 instead of &stat_val, then you hold or system down.
// so, it is difficult to find out where is bug.
// c++ has exception function, but c does not such a exception.
// if using language has the exception function, you should use it!
// if possible, you should not call system call, because it makes bugs lower.
* OS is still a little weak, so you pay careful attention to write arguments!
*
wait: wait for the status of child is available by family
exit: By child, configure status code, and then notice what parent has finished!
-----------------------------------------
kill
kill -kill 1234
you have killed process having PID of 1234
signal; waiting for pressing any of keyboard and something like that.
alarm(5)
signal is occurred per 5 seconds.
act.sa_handler = ding;
clock_t times(struct tms *buf)
examine how much time program spends.
int system(const char *command)
forced to call command.
In homework, you must not use the system command!
putenv, getenv
reconfigure your envinment variables.
inter communication between processes
pipe, socket
pipe
In shell command
ps -Af|grep hoge
you can move result anywhere.
int pipe(int file_descriptor[2]);
[0];for reading
[1];for writing
return
0: successful
-1; failure
Case1
Parent <----> child
parent --- file_pipes[1] | file_pipes[0] --- child
parent --- file_pipes[0] | file_pipes[1] --- child
some source codes
int file_pipes[2];
if(pipe(file_pipes) == 0){
fork_result = fork()l
...
}
close(file_pipes[1]); = pipe
data_o = read(file_pipes[0], buffer, BUFSIZ); = file_pipes[0] yu child
// reading data put into buffer
you do not have to close pipe, but it has possibility to occur bugs!
so, you should close it ASAP.
let's consider PS -As | grep hoge (== 1 | 0)
grep is fetching data from 2nd parameter to end parameter.
Using dup2,
dup2(1, p[1])
// fetching pipeline[1]
dup2(0, p[0]);
// fetching pipeline[0]
kind of
ls > aaa
cat < aaa ex program close(0); dup(p_id[0]); // equals to "dup2(0,p_id[0]);" close(p_fd[0] close(p_fd[1] pipe added name(FIFO) who call pipe system call? you should clarify that who and who inter communicate. From Command Line mkfifo < filename>
From System Call
int mkfifo(const char * filename, mode_t mode);
* this pipe is hardly used.
pipe system can be call if only two programs are related to family-child.
setjump/longjump
#include
jump_buf ma; // required and should be put in global
longjmp(ma, -1) // return value is -1
key = setjmp(ma) // key == -1
EX
func()
{
longjmp
}
main(){
sigaction
setjmp
printf("prompt = ")
read(ls, -1)
fork
wait
exec
}
important!
ls > a
cat <= a ls|grep - , cntl.c
fork| | | sigaction
exec| dup2 | pipe | setjmp/longjmp
wait| | |
/bin
/usr/bin
ex. ls -l
search files from upper to bottom in directory.
if you find out it, execute it,
2008-06-17
memo@file system, device driver etc.
2008/06/17
・ファイル名
ファイルを識別するためのString名からID名へ変換する
/a/b/c→101020
・ファイル内のポインタ
論理アドレスから物理アドレスへの変換
↑上記の二つをどうやって実現するのか?
・フ
ァイルシステム概要
ファイルの詰め込み方には異論の方法がある
例:
1. 頭からファイルを詰め込んでいく方法
→deflagmentationが起こるのであまり使われない。
2. 固定長のブロックに分けてファイルを詰め込んでいく方法、各ブロックは次のブロックを指すポインタを持っている
→しかしsequencialにしかアクセスできない!
3. 自分のファイルがどこに保存されているかを格納しているところがあり、それを参照して、ファイルの格納場所を知る(←これをディレクトリという。)
→これが最も一般的なやり方
cf.ページテーブル
☆directoryをどうやってストレージデバイスにおいていくか、が実現上大きな問題にある。よって、それぞれのファイルとdirectoryをどうやって実現していくかがこれから説明する。
・Unix file system
API概要(OSが実現するAPI)
fd = open((file,mode)
read/write(fd, buf, size)
…とか色々
・全体の概要
スーパーブロック→inode list→ファイルブロック:固定長に分けたブロック
i-node table:
i-node:各ファイルごとに一対一対応するデータ構造。
スーパーブロック:ファイル全体を管理するデータ構造
i-node list全体の数とかを管理する
ファイルへのアクセスはメモリへのアクセスと比べると時間がかかる。
一度オープンしたファイルに関しては一旦メモリ上にコピーされる。
ファイルデータ構造というのは、readすると順番にブロックが呼び出されていく。どこから呼び出されていくかはOSが知っている。
プロセスデータ構造:プロセスごとに存在し、ファイルデータ構造にある内容をファイルディスクリプタ内の情報に変換する?
つまり、ファイルディスクリプタの番号はプロセスごとに閉じている。
ストレージは非常に大きい。よって、メモリ上に持っていくことは出来ない。
しかし、一部のファイルに関してはメモリにコピーしていることがある。
ストレージデバイスの良く使うごく一部の部分がメモリ上にコピーする。
・i-nodeとブロックの関係
i-node内部構造:内部構造は固定長で、
"所有者、アクセス権、アクセスタイム、変更時間、10個のエントリ、3個のエントリ"
が含まれている
ファイルシステムは何年も使われて、安全が保障されてから人に使われる。
よって、開発から実用まで10年ぐらいのスパンがある。
10個のエントリ:それぞれが独立に10個のブロックを指している。
3個のエントリ:それぞれが独立に3個の間接ブロック(=中身はエントリ)を指していて、そのブロックはそれぞれまた別なブロックを指している。
一つのブロックには256個のエントリが入る。よって、
10K + 256*1K + 256*256*1K + 256*256*256*1K
よって、ファイルのサイズが大きくなればなるほど深い層までもぐりこまなければならないのでperformanceは低下する。
i-nodeの数だけ、ファイルが作られるので、
ファイルの上限はi-nodeの数に制限される。
・Unix filesystem(4)
ファイルデータ構造は、複数のプロセスから共有されることがある。
例:プロセスAがオープンしたファイルデータ構造はプロセスBからも共有される
forkしたときに、現在オープンしたファイルディスクリプタは共有される。
オフセット:現在書き込みしているところの次はどこに書き込むのか、という情報が格納されている。
・スーパーブロック
スーパーブロックはファイルシステム全体を管理するデータ構造。
一番最初に読み込まれる。
-ブロックサイズをどうするか?4K?1K?
-どのブロックが現在使われているか?
新しくブロックを割り当てる場合、空いているところをビットマップから判断し、割り当てる。
名前をどうやってi-nodeに変換するか?
i-nodeが分かったとき、その後どうやってファイルにアクセスするか。
・read/write
ファイルをオープンすると、今アクセスしようとしているi-nodeを認識する。
それをi-node tableのコピーする。
ファイルデータ構造にallocationして、
プロセスデータ構造からファイルデータ構造に書き込む。
ファイルデータ構造のoffsetを見て、i-nodeテーブルを見て、i-nodeの何バイト目を見るかを決める。
10Kより小さかった場合は、ブロックを発見。
10Kより大きかった場合は、間接ブロックを辿っていく
rooter i-node
i-node:3,5,7,19,17と書いてあるとする。
頭は"/"から始まる
"/" "usr"=3
. =自分
..=親のディレクトリ
"vmunix" = 10
→ファイルを直接アクセスしている。
ファイルのブロックが順番にアクセスされる。
usr = 3
usrと認識すると i-node 3を見る。
3は"."を指しているので、親のディレクトリに行く。
例:/usr/readmeをopenする
ディスクからi-node tableの必要なブロックを全部呼び出す。
readmeを探し、7が見つかったので、
i-node 7の指すファイルを全部呼び出して、
前から順々にアクセスしていく。
よって、
ファイル名から、
i-nodeの指すファイルを探して、
ファイルをopenする。
・ハードディスクが複数合った場合はどうするのか?
ディレクトリ+ブロックが入っている。
あるハードディスクのあるディレクトリを、他のハードディスクをマウントするようにする。
mount table
mntはディスクテーブルにある。
mntを見つけたら、ディスクBをアクセスし始める。
mnt=mount
ディレクトリ自体は一つのtree構造であることには変わらない。
・物理的なディスクの構造
ハードディスク上にファイルシステムを作る
ディスクは複数ある。
ディスクは同心円の円がたくさん入っていて、そこにデータがたくさん入っている。
その輪の中にデータを入れていく。
それぞれの輪の部分をトラックという。
トラックを固定長に分割した部分をセクタという。
各ディスクのことをシリンダという。
シリンダ->トラック->セクタ
アームで読み込む。アームは前後に動く。
ディスクが回っていて、アームと接触した部分を読み込む。
よって、読み込むまでの時間は、アームのところに読み込みたいセクタまでディスクを回してあげて、完了するまでの時間。
→読み込み時間はアームの前後に動く時間と、セクタを指定した位置に持っていくまでの時間に左右される。
よって、ハードディスクの読み込みは遅くなる。
・バッファキャッシュ
キャッシングとプロフェッチ。
prefetch:次に読み込むものが分かっている場合は、事前にフェッチしていくこと。
ファイル全体をメモリにコピーしていくことが多い。
使用例:ファイルは頭から順番にアクセスしていくことが多いことを利用する。
具体例:Unixは次のブロックを指していたら、その次のブロックがアクセスされる場合が多いので、事前にメモリ上に呼び出しておく。
タイムスタンプ:いつアクセスされていたか。
キャッシュの管理アルゴリズムは、タイムスタンプをつけてLRUで管理している。
・ディスクの書き出し
バッファキャッシュで変更する場合、30秒から1分待つ。これにより、同じバッファブロックに対して何度も何度も書き出すことを制限することが出来る。
30秒に一回変更されているブロックをディスクに書き出す。
ディレクトリやスーパーブロック, i-nodeの変更はすぐにディスクに書き出す。
→システムがファイルへ書き出す前にクラッシュしたとき、ファイルシステム全体が壊れる可能性がある。
→ファイルのデータ構造をいじくるときは、常にファイルシステムの一貫性を保てるようにする。
・ディスクスケジューリング
FIFOスケジューリングは行ったり来たりする。
メカニカル動く。
アームの動く速度は遅いので、アームの動く量を最小にしたい。
→C-SCANというアルゴリズムがある。
C-SCAN:
いくつかのタスクを溜めておいて、ソートして
頭から尾に向かって順番にアクセスしていく。
その後、アームを頭の位置に戻す。
他のもディスクスケジューリングアルゴリズムがある。
今は、もうちょっと頭のいいアルゴリズムも存在する。
☆ハードディスクのアクセスには物理メモリと違って、
トラックがどこにあるかによってアクセス時間が大幅に違う。
自分のアクセスしたいデータがトラックのどこにあるのかを認識して、
最小限のアームの動きでアクセスする必要がある。
・分散ファイルシステム
リモートにあるマシンに対して同じプログラムを使いたいときは
アクセス透過性と位置透過性を考える必要がある。
アクセス透過性:リモートファイルもローカルファイルも同一のAPIを用いてアクセス可能
位置透過性:ファイル名にマシン名が含まれていない。
→どこのマシンにあるかを気にせずアクセスできる。
・NFS
network file systemの略称。しかしnetwork file systemとは滅多に言わない。
☆プログラマーから見て、あたかも普通にディレクトリをアクセスできるかのようにすることが大切。
→OS空見れば、ネットワーク上の複雑な処理を隠蔽することが大事!
・I/Oの種類
プログラム⇔デバイスドライバ⇔デバイス
デバイスの種類はたくさんある!
デバイスドライバが出来るだけ隠蔽してあげることが大切。
・バスの種類
PCI
ISA
SCSI
…たくさん!
・デバイスドライバ
デバイス独自のプロトコルの使用にあわせて作り、出来るだけ簡略化し、隠蔽する・
デバイスドライバは、各デバイスのアクセスプロトコル(デバイスの制御手順)を実装する。
デバイスドライバはデバイスを自動的に発見し、どのようにアクセスするかを自動的にけっている。
cf:USBの挿入
USBを差し込む→OSが認識→
デバイスドライバがない場合:デバイスドライバをインストールする。
デバイスドライバがある場合:USBを読み込む
昔は数百行だったが、今は数千行必要になる。
→デバイスドライバを作る人はこれから増えるかもしれない。
☆重要なこと
デバイスとデバイスドライバのやり取りをどうするかを決めること。
・デバイスアクセスの方法
I/Oイベントの通知
-error通知、利用可能データ通知、状態通知
-ポーリング:CPUからデバイスに対して使用可能か調べる?
-割り込み
・データの転送
デバイスとCPUのデータ転送方法を決定する。
-read/write
-programmable I/O
-DMA:direct memory access:ある程度の長さのデータを一括して転送する
・I/O port
-メモリ空間と異なるI/O空間
-各デバイスはI/O空間上にポートを割り当てられる
-ポートをアクセスすることによりデバイスとメモリ間のデータ転送が行われる
-I/Oポートをアクセスするための特注名命令が必要
→x86の場合、in, out命令
・Memory mapped I/O
-デバイスの一部をメモリとしてみることが出来る。
-メモリアクセスとして実現されるが、アクセスコストが異なる。
・ポーリング
CPUからデバイスに対して以下のことを確認する。
-データの入力が可能となる
-データの出力が可能となる
-処理の終了
あるデータの書き出すが起きているときには、それが終わるまでは次の書き出しを禁止する。
ポーリングを使って、毎回毎回処理終わったかどうかを聞く。
例:
while(flagPort != READY);
mem = dataPort;
dataPort:どっかのレジスタ
イベントの発生などをポーリングで待つことはCPUの無駄遣い
他の処理の合間にポーリングをすることが可能だが、システム全体の構造がクリアではなくなる
よって、ポーリングを使用するときは、結果が分かるまでの時間が短い場合のみ。
20μsならよいが20nsでは無駄。
・割り込み interrupt
CPU→要求(I/O port, memory)→デバイス
CPU← 割り込み ←デバイス
↑ポーリングによるCPUの無駄遣いを防ぐことが出来る
割り込みは、デバイスからCPUに対して何かを呼び出したいとき、
今実行しているプログラムを中断して割り込んだデバイスの処理をさせるときに使う。
・割り込みハンドラ
以下のような処理が割り込み処理に当たる
-新しく入力された
-エラー処理
-デバイスからの通知処理
番号ごとに違う番号を登録する
例:割り込みベクタ↓
IRQ0 = clock handler
IRQ1 = disk handler
IRQ2 = network handler
IRQ3 = trap handler: page fault, system call, bus error etc.
各デバイスはIRQの何番を用いるか知っている。
場合によっては、割り込みベクタを複数のデバイスで共有することが出来る。
→割り込み処理で貰ってきた値を評価して、どのデバイスの割り込みかを認識する。
・多重割り込み
割り込みが複数個ある。
割り込み処理が実行されたときに、違う割り込みが来た場合はどうするのか?
割り込みには優先度が付いている。
例:level2, level3, level4,...,level7
levelの値が高い方が優先して処理する。
デバイスによっては、あまり長い時間放置されると破綻するものもある。
例:network driverは連続的にパケットが送信されるので、
データが来たときにすぐ処理しなければならない。
・時間制約によって勝手に割り込んでくる処理がある。
割り込みの数が多いと、今実行されているプログラムは実行できなくなる。
☆未だに解決できていない課題
時間を測定する関数を使った場合、割り込み処理によって正確な値が測定できない。
割り込みハンドラを実行後レジスタを回復する必要がある。
例:
handler(){
save_register();
process_interrupt();
restore_register();
}
割り込みは割り込みようのスタックを用いる。
これにより、スタックがオーバーフローすることを避けている。
・割り込みのオーバーヘッド
割り込み処理のコストは結構大きい。ポーリングより大きいので、ポーリングを使った方が良いときも多い。
例:
web serverはデータが来る毎に割り込みが発生する。
昔は10MB/bpsだったので、そんなにCPUが早くなくても取りこぼさない。
今は10GB/bpsなので、パケット量が圧倒的に増えて、割り込みが毎回発生する。
最悪の場合、web serverが実行できずに割り込み処理しか実行されない。
→割り込みハンドラの呼ばれる頻度が高い。
10GB/bpsだと、CPUは有意義な計算を行うことが出来ない。
対処例:割り込みハンドラの呼ばれる頻度が高くなったら、ポーリングに切り替える。
・割り込みの禁止
システムコールの処理と割り込みハンドラ間の排他制御
cf.複数のスレッドを実行するときは排他制御する必要がある。
例:readやwriteがデータ構造をいじっているときは割り込みを禁止する。
例:
syscall()
{
割り込み禁止
排他リソースのアクセス
割り込み可能
}
注意:割り込みを禁止している時間はなるべく短くするように心がける。
・Direct Memory Access
各デバイスはメモリから直接データをやり取りする。
bufPort: buffer size
sizePort:送るべきデータのサイズ
cmdPort: WRITEスタート
CPUとは関係なく実行される
・サイクルスティーリングとは?
メモリとCPUを繋ぐバスがある
DMAデバイスはバスを使う。
→バスは共有されている。同時には使えない。
→DMAが動いているときはパイプラインが使えない
DMAはCPU上で動いているプログラムのパフォーマンスを低下させる可能性を持っている。
かつ、CPUとは無関係に動いているので、どのくらい低下するのか予想するのが難しい。
デバイスからDMAを使ってデータを物理メモリの呼び出されたとき、
キャッシュの中をクリアする必要がある。
→DMAをたくさん使うとパフォーマンスが低下する。
・物理空間か仮想空間か
デバイスがMMUを解さずメモリをアクセスする場合は、デバイスにバッファのアドレスを教えるときは物理メモリアドレスを教える必要がある。
CPUから見えるアドレスとデバイスから見えるアドレスは違うので、マッピングする必要がある。
・TLB管理
ページテーブルによる仮想アドレスと物理アドレスの変換オーバーヘッドを減少するためTLBが導入された。
☆割り込みを考えるとTLBもパフォーマンスを低下させる可能性を持っている。
TLBはコンテキストスイッチが起こるたびにクリアする必要がある。
ページテーブルの変更はTLBに影響を及ぼさない。
TLBの負ラッシュする必要があるときは以下の場合。
-I/Oデバイスが新しくマップかアンマップされたとき
-新しい仮想エリアが新しくマップされたか案マップされたとき
-プロセスのコンテキストスイッチが発生したとき
・ユーザから見たI/Oインターフェース
/dev/device0 10 1
↑このファイルをオープンするとメジャー番号(10)とマイナー番号(1)に変換する。
よって、オープンするときは、
fd = open("/dev/device", mode);
close(fd);
read/write(fd, buf, size);
ioctl(fd, cmd, arg);
何でもかんでもI/Oコマンドを定義していくと移植性が低下するので、I/Oコマンドの定義は最小限にした方が好ましい。
・/proc
特別なデバイス。各プロセスの色んな情報を取り出すことが出来る。
例:
/proc/1/fd/3 プロセス1のfd3の情報を取る。
/proc/1/mem プロセス1のメモリ
/proc/pci PCIに関する情報
/proc/modules カーネル内にロードされたモジュールの情報
・非同期I/O
readシステムコールはデータが来るまで待っている。
signalを使って非同期化する?
例:
{
signal(SIGIO,..&input_handler)..
fcntl(0, F_SETWON,..getpid());
oflag = fcntl(0, F_GETFL);
fcntl(0, f_SETFL, oflag | FASYNC);
}
・付録
PDFの"付録"にデバイスドライバのサンプルソースコードがあるので目を通しておく。
2008-05-12
Computational Intelligence 3
essayはほぼ終了。あとはresumeとcover letter(多分今回は必要ないっぽい)書いて糸冬了かな。さっさと終わらせて、言語処理系と回路理論の課題やって、hardware記述言語の勉強+状態遷移図の復習しよう。あとそろそろJudeとprologのprogrammingも出来るようにならんとな。でもOSが大分遅れ気味なのも痛いなぁ。
orz
反省しなくては。
こんな事態になった原因は、俺の脳内処理能力+課題解決能力が糞なせいに他ならない。いつでもどこでもtoggle switch一つで脳をフル稼働させられる人間になりたいわ。
----- Computational Intelligence note May 12th, 2008 -----
[Computational Inteligence]
・述語とは
あるものがカテゴリへの所属しているとか student(bob)
性質を持っているとか tall(bob)
動作をするとか runs)bob)
関係とか loves(bob,liz)
述語に引数として与えると原始論理式(atomic formula)となる。
・prologと一階述語論理で扱う記号
定数、変数、関数を一階述語論論理で扱う
定数 bob, 0, june, nil
変数は大文字
数学と情報では変数の概念が違う
⇒単一代入変数
一回決まったら、他の値にはならない
k=3としたら、途中でk=6とかにはしない。
逆の振る舞いを"破壊的代入"という
⇒一回与えた変数を書き換えること
関数 s(X),date(dec,31)
ものからものを作る
"一階"とは、遠陬にはものを表す変数しか入らないということ!
⇒変数にはものしか入らないということ!
・記号 vs. 記号の意味
記号は何らかの意味を担っている。
計算機の中で閉じた意味を作ることが出来る
計算機の中といっても計算機の外とも関係がある。
計算機の中のbobというシンボルと
計算機の外のbobという実在する人物は
人間が結び付けている。
結びつけは全て人間が行っている。
記号の意味はプログラマが決める。
論理式が言及している集合のことを、対象領域という。
・記号による知識表現の例
例えば、生死を扱うとき
定数:socrates
述語:Human, mortal
あらゆるものに名前をつけるということは大変なこと
⇒monthは別々でもいいが、dayにいちいち名前をつけることは大変!
5 = s(s(s(s(s(0))))) means 0の次の次の次の次の次の数
rectangle()関数を使えば、
(x0, y0)と(x1,y1)を貰うことで
長方形を作ることが出来る。
⇒関数と考えるよりもデータ構造と考えた方が自然な場合もある。
書いたものが何を表すかというと、ある複素数を表す"つもり"になっている。
prologでは、f()は定数の親戚と考えても構わない。
・解釈
知識には宣言的と手続き的がある。
prolgにはその両方が備わっている。
prologはどうやって与えられた質問に答えているのか?
例えば、
宣言的な顔:兄弟とか足し算の概念を宣言的に定義している。
⇒何回やっても答えが同じでなくてはならない。
⇒証明をする必要がある。
・宣言的な解釈
基本的には論理学の復習
プログラムとは、ruleを書き並べたもの。
個々のruleがandかorでつながっている。
⇒programではandで繋がっている。
とりあえずデータベースみたいなプログラムを考える。
cf.家族関係(2) - 用語の意味の定義
個々のruleはprogrammerは正しいと思って書かれている。
どれか一個が正しいのではなく、全て正しいと思って書かれている。
では、個々のruleはどうなっているのか?
規則(rule) --- 節とかclauseとか言う。
自然言語で言うと条件文に対応している
factとは肯定平叙文!
質問(query) --- も「clause」
一種の疑問文となる。
正確に言うと、否定疑問文に対応。
・では、何が無いのか?2つある。
普通の否定平叙文がない!
ちなみに、≠は否定ではない。≠は違う人だ、と宣言しているだけ。
つまり、肯定的に二つのものが異なると解釈する。
ORでつながった複文もない。
・演習
is_parent_of(pam, bob)
femail(pam)
is_mother_of(X, Y) :- is_parent_of(X, Y), femail(X)
↑全体はandで繋がっていると考えて、書き直すと、
is_parent_of(pam, bob)
∧ femail(pam)
∧ ∀X∀( Yis_mother_of(X, Y) (is_parent_of(X, Y) ∧ femail(X)) )
となる。さらに三行目は、別の書き方をすると
is_mother_of(X, Y) ∨¬is_parent_of(X, Y) ∨ ¬femail(X)
となる。また、↑のことをclauseという。
・ここまでのまとめ
つまり、節とは、原始論理式やその否定をorで繋げたもの。
原子論理式はばらすことが出来ない論理式。
これ以上バラスと、論理式ではなくなってしまう論理式のこと。
基本的に、if文は可能
結論にはnotは付かない。
条件は一般には0個以上ある。
条件の数にはたくさんあってもよい。
しかしながら、結論は一個でなければならない。
これが、prologの特徴となっている。
?- add(0, s(0), X), add(X, X, Y)
?- means :- または "←"
基本的には、まず"or"でバラす。
つまり、¬add(0, s(0), X) ∨ add(X, X, Y)
orで繋がっていない分はfalseであるといえる!
false ← ¬add(0, s(0), X) ∨ add(X, X, Y)?
つまり、矛盾であることを言っている。
つまり、prologとは否定疑問文で解釈している?
正確に書くと、
∧∀X∀Y(¬add(0, s(0), X) ∨ add(X, X, Y))
= 全てのXに対して、いないので、
・教科書の例
false :- is_ancestor_of(X,jim)
⇒for all X, X is not an ancewstor of jim
⇒is there no ancestor of jim?
Yes! pat is an ancestor!
yes! ann is an ancestor!
・もう一つの解釈の可能性
条件文の略記。
左辺にyes(x)は
If X is an ancesstor of jim, say "yes" and answer C.
⇒yes, pat is an answer.
⇒yes, ann is an answer
否定疑問文が入ったらyesと答えようとして、証明手続きが機能
P⇒yes, not Pは非常に近いといえる。
・変数の役割
もう一つ大事なことは、変数というのはfor all という前提が付いていた。
試験問題では、∀X∀Yは書く?
∀=universal con~~? ⇒ 全称記号
who is ancestor of jimと聞くところを、prologでは
is there ancestor of jimと聞いている。
質問の中の変数ではどうなっているのか?
例:is_ancestor_of(X, jim)という変数があったとすると、
¬(ヨX is_ancestor(X, jim))
XがYのgrandfatherだというとき、その中にzさんの記号を書くと、
zさんの存在記号となる?
つまり、
∀X∀Y∀Z(g_father(X, Y) ← (father(X,Z)∧father(Z,Y)))
と
∀X∀Y(g_father(X,Y) ← ヨZ(father(x,Z)∧father(Z,Y)))
は、同じことを言っている。
↑情報数学の復習
条件文に入れてしまうと存在記号に化ける!
・三段論法について
bottom-up
⇒ P P⇒Q
-------------
⇒Q
prologでは、ちょっと違う。
⇒top-down
Q⇒ P⇒Q
----------
P⇒
↑Qという手続きが呼ばれたので、Pという手続きが呼ばれたと考える。
どちらも、下記のルールの特殊な場合に過ぎない。
A⇒B B⇒C
------------
A⇒C
となる。
・prologの実行メカニズムの基本
知識として、二つの方法を使っている
P :- Q,R.
P :- S,T.
↑の2通りについて調べる。
1と折り目で間違っていた場合は、
S、Tに展開して、"やり直す"!
↑これはprolog独自のアルゴリズム。
このようなアルゴリズムを決定性アルゴリズムという?
反対を、非決定性のアルゴリズムという?
最初にやって、駄目だったら次の方法を試してみる。
このような振る舞いをbacktrackを使うという。
つまり、試行錯誤するということ!
普通のprologの処理系は、書いた順番に実行する。逐次的に実行する。
論理値だと思ったときには、規則の中の条件の順序はどうでも良いが、
基本的には、上に書いた文から、左に書いてる節から評価していく。
一般ruleというものがある。
・帰納的定義
nの階乗定義の場合、
n! = 1 (n=0) ----- base case
= n(n-1)! (n>0)
base caseを先に書く!
一個のルールのときには、条件を絞っていく。
なるべくさきに、条件を絞っていった方がよい。
計算に時間のかかるものは、後にやった方がよい!
例:
条件を4つ書いたとき、XもYも女兄弟ですか?というとき、
親はせいぜい二人しかいないのだから、まず共通の親を見つけたほうが良い!
XとYは別人だ、といいたいとき。
もし、誰かの女兄弟を探してくるとき。
Iは与えられた人物の女今日はを探してくる。
女の人を探してくる。
Yさんと違う人を探す。
↑コレはnaive
Xという人を探すんだとしたら、
確立1/2になるようなものは後に探した方がよい。
なるべきたくさんある可能性を速く絞らせた方がよい。
・問20
(2,2)のような場所でも、;を打ってたら、そのうち出てくるものでなくてはいけない。
(0,X)を最初に出力しようとしていくと、(2,2)は出てこない。
⇒実現するためには
論理式を入れたら、自動的に証明してくれる。
・prolog
他の言語に比べたら、知能的っぽいけど、そこまで万能ではない。
・まとめ
今までは、ifとか条件否定とかやってきたが、
whoとかwhatが引数としてきた場合、
どうやって変数に代入するのか、という話はまだやっていない。
論理式を弄くりながら、学んでいく。
一階述語論理の三段論法だと、
human(socrates) ∀X(~以下略
+と-でキャンセルできる。
prologでは =は"=="の意味になる。
来週はbacktrackに基づいて、unificationは何をやっているかを調べる。
orz
反省しなくては。
こんな事態になった原因は、俺の脳内処理能力+課題解決能力が糞なせいに他ならない。いつでもどこでもtoggle switch一つで脳をフル稼働させられる人間になりたいわ。
----- Computational Intelligence note May 12th, 2008 -----
[Computational Inteligence]
・述語とは
あるものがカテゴリへの所属しているとか student(bob)
性質を持っているとか tall(bob)
動作をするとか runs)bob)
関係とか loves(bob,liz)
述語に引数として与えると原始論理式(atomic formula)となる。
・prologと一階述語論理で扱う記号
定数、変数、関数を一階述語論論理で扱う
定数 bob, 0, june, nil
変数は大文字
数学と情報では変数の概念が違う
⇒単一代入変数
一回決まったら、他の値にはならない
k=3としたら、途中でk=6とかにはしない。
逆の振る舞いを"破壊的代入"という
⇒一回与えた変数を書き換えること
関数 s(X),date(dec,31)
ものからものを作る
"一階"とは、遠陬にはものを表す変数しか入らないということ!
⇒変数にはものしか入らないということ!
・記号 vs. 記号の意味
記号は何らかの意味を担っている。
計算機の中で閉じた意味を作ることが出来る
計算機の中といっても計算機の外とも関係がある。
計算機の中のbobというシンボルと
計算機の外のbobという実在する人物は
人間が結び付けている。
結びつけは全て人間が行っている。
記号の意味はプログラマが決める。
論理式が言及している集合のことを、対象領域という。
・記号による知識表現の例
例えば、生死を扱うとき
定数:socrates
述語:Human, mortal
あらゆるものに名前をつけるということは大変なこと
⇒monthは別々でもいいが、dayにいちいち名前をつけることは大変!
5 = s(s(s(s(s(0))))) means 0の次の次の次の次の次の数
rectangle()関数を使えば、
(x0, y0)と(x1,y1)を貰うことで
長方形を作ることが出来る。
⇒関数と考えるよりもデータ構造と考えた方が自然な場合もある。
書いたものが何を表すかというと、ある複素数を表す"つもり"になっている。
prologでは、f()は定数の親戚と考えても構わない。
・解釈
知識には宣言的と手続き的がある。
prolgにはその両方が備わっている。
prologはどうやって与えられた質問に答えているのか?
例えば、
宣言的な顔:兄弟とか足し算の概念を宣言的に定義している。
⇒何回やっても答えが同じでなくてはならない。
⇒証明をする必要がある。
・宣言的な解釈
基本的には論理学の復習
プログラムとは、ruleを書き並べたもの。
個々のruleがandかorでつながっている。
⇒programではandで繋がっている。
とりあえずデータベースみたいなプログラムを考える。
cf.家族関係(2) - 用語の意味の定義
個々のruleはprogrammerは正しいと思って書かれている。
どれか一個が正しいのではなく、全て正しいと思って書かれている。
では、個々のruleはどうなっているのか?
規則(rule) --- 節とかclauseとか言う。
自然言語で言うと条件文に対応している
factとは肯定平叙文!
質問(query) --- も「clause」
一種の疑問文となる。
正確に言うと、否定疑問文に対応。
・では、何が無いのか?2つある。
普通の否定平叙文がない!
ちなみに、≠は否定ではない。≠は違う人だ、と宣言しているだけ。
つまり、肯定的に二つのものが異なると解釈する。
ORでつながった複文もない。
・演習
is_parent_of(pam, bob)
femail(pam)
is_mother_of(X, Y) :- is_parent_of(X, Y), femail(X)
↑全体はandで繋がっていると考えて、書き直すと、
is_parent_of(pam, bob)
∧ femail(pam)
∧ ∀X∀( Yis_mother_of(X, Y) (is_parent_of(X, Y) ∧ femail(X)) )
となる。さらに三行目は、別の書き方をすると
is_mother_of(X, Y) ∨¬is_parent_of(X, Y) ∨ ¬femail(X)
となる。また、↑のことをclauseという。
・ここまでのまとめ
つまり、節とは、原始論理式やその否定をorで繋げたもの。
原子論理式はばらすことが出来ない論理式。
これ以上バラスと、論理式ではなくなってしまう論理式のこと。
基本的に、if文は可能
結論にはnotは付かない。
条件は一般には0個以上ある。
条件の数にはたくさんあってもよい。
しかしながら、結論は一個でなければならない。
これが、prologの特徴となっている。
?- add(0, s(0), X), add(X, X, Y)
?- means :- または "←"
基本的には、まず"or"でバラす。
つまり、¬add(0, s(0), X) ∨ add(X, X, Y)
orで繋がっていない分はfalseであるといえる!
false ← ¬add(0, s(0), X) ∨ add(X, X, Y)?
つまり、矛盾であることを言っている。
つまり、prologとは否定疑問文で解釈している?
正確に書くと、
∧∀X∀Y(¬add(0, s(0), X) ∨ add(X, X, Y))
= 全てのXに対して、いないので、
・教科書の例
false :- is_ancestor_of(X,jim)
⇒for all X, X is not an ancewstor of jim
⇒is there no ancestor of jim?
Yes! pat is an ancestor!
yes! ann is an ancestor!
・もう一つの解釈の可能性
条件文の略記。
左辺にyes(x)は
If X is an ancesstor of jim, say "yes" and answer C.
⇒yes, pat is an answer.
⇒yes, ann is an answer
否定疑問文が入ったらyesと答えようとして、証明手続きが機能
P⇒yes, not Pは非常に近いといえる。
・変数の役割
もう一つ大事なことは、変数というのはfor all という前提が付いていた。
試験問題では、∀X∀Yは書く?
∀=universal con~~? ⇒ 全称記号
who is ancestor of jimと聞くところを、prologでは
is there ancestor of jimと聞いている。
質問の中の変数ではどうなっているのか?
例:is_ancestor_of(X, jim)という変数があったとすると、
¬(ヨX is_ancestor(X, jim))
XがYのgrandfatherだというとき、その中にzさんの記号を書くと、
zさんの存在記号となる?
つまり、
∀X∀Y∀Z(g_father(X, Y) ← (father(X,Z)∧father(Z,Y)))
と
∀X∀Y(g_father(X,Y) ← ヨZ(father(x,Z)∧father(Z,Y)))
は、同じことを言っている。
↑情報数学の復習
条件文に入れてしまうと存在記号に化ける!
・三段論法について
bottom-up
⇒ P P⇒Q
-------------
⇒Q
prologでは、ちょっと違う。
⇒top-down
Q⇒ P⇒Q
----------
P⇒
↑Qという手続きが呼ばれたので、Pという手続きが呼ばれたと考える。
どちらも、下記のルールの特殊な場合に過ぎない。
A⇒B B⇒C
------------
A⇒C
となる。
・prologの実行メカニズムの基本
知識として、二つの方法を使っている
P :- Q,R.
P :- S,T.
↑の2通りについて調べる。
1と折り目で間違っていた場合は、
S、Tに展開して、"やり直す"!
↑これはprolog独自のアルゴリズム。
このようなアルゴリズムを決定性アルゴリズムという?
反対を、非決定性のアルゴリズムという?
最初にやって、駄目だったら次の方法を試してみる。
このような振る舞いをbacktrackを使うという。
つまり、試行錯誤するということ!
普通のprologの処理系は、書いた順番に実行する。逐次的に実行する。
論理値だと思ったときには、規則の中の条件の順序はどうでも良いが、
基本的には、上に書いた文から、左に書いてる節から評価していく。
一般ruleというものがある。
・帰納的定義
nの階乗定義の場合、
n! = 1 (n=0) ----- base case
= n(n-1)! (n>0)
base caseを先に書く!
一個のルールのときには、条件を絞っていく。
なるべくさきに、条件を絞っていった方がよい。
計算に時間のかかるものは、後にやった方がよい!
例:
条件を4つ書いたとき、XもYも女兄弟ですか?というとき、
親はせいぜい二人しかいないのだから、まず共通の親を見つけたほうが良い!
XとYは別人だ、といいたいとき。
もし、誰かの女兄弟を探してくるとき。
Iは与えられた人物の女今日はを探してくる。
女の人を探してくる。
Yさんと違う人を探す。
↑コレはnaive
Xという人を探すんだとしたら、
確立1/2になるようなものは後に探した方がよい。
なるべきたくさんある可能性を速く絞らせた方がよい。
・問20
(2,2)のような場所でも、;を打ってたら、そのうち出てくるものでなくてはいけない。
(0,X)を最初に出力しようとしていくと、(2,2)は出てこない。
⇒実現するためには
論理式を入れたら、自動的に証明してくれる。
・prolog
他の言語に比べたら、知能的っぽいけど、そこまで万能ではない。
・まとめ
今までは、ifとか条件否定とかやってきたが、
whoとかwhatが引数としてきた場合、
どうやって変数に代入するのか、という話はまだやっていない。
論理式を弄くりながら、学んでいく。
一階述語論理の三段論法だと、
human(socrates) ∀X(~以下略
+と-でキャンセルできる。
prologでは =は"=="の意味になる。
来週はbacktrackに基づいて、unificationは何をやっているかを調べる。
2008-05-01
Computational Intelligence 2
今日から一限が無い日は、9時に友達と集まってspeakingの練習をはじめました。TopicはAdvance Englishで、今まで放置プレイしてきたacademic word list "570"。周りの視線をやけに浴びてる気がするけど、きっと気のせいだろう。
ところで、先週のTOEFLの前日に、ちょっと面白いイベントに参加したらなんと某企業のT-shirtを手に入った!キタコレ!でもそれ着て外に行くのは、色々と勘違いを起こしそうだから遠慮がちだったり。
またまた話し変わって、今週の月曜日はVijay Saswat Doctorの講義が早稲田理工学部であったので、参加しました。内容は「Programming for concurrency and distribution」。
今、IBM researchが研究しているX10 programmingの説明みたいな講義です。
並行処理をどう実現するか、って説明からX10 programmingの概要、
最後にX10 programmingのサンプルソースコードの解説といった内容。
threadの知識が既に乏しい自分は蚊帳の外ですたorz
まぁとりあえず凄くいいと思ったのは、X10 programmingで作ったソースコードはJVMでもC compilerでも動くらしい。すげぇwでも、原理は理解できずw
参考
http://x10.sourceforge.net/x10home.shtml
講義に関して言えば、最初はゆっくりしゃべってくれたたから理解できたけど、だんだんスピードアップしてきて、イミフワールドへww言ってることをスライドと照らし合わせながら、大まかにしか理解できなかったorzまぁ理解度は1,2割ってところかorz orz orzアメリカの理工系講義もこんな感じなんかなぁ。まだまだ、今のレベルじゃ太刀打ちできないね。
今年は早稲田CS学科主宰(?)のGlobal COE programがある関係で、今後も色々なCSの著名人を大久保キャンパスに招待するらしい。次の講義では、最低でも、講義で示される理論の5割は理解できるようになりたいもんです。
------ assignment memo -----
Take8easy俺。情報数学復習しないとまずいっぽいなorz
【課題内容】
主張1:「コンピュータが知的なはずが無い(P1),だって、プログラムされたことしか出来ない(Q1)のだから」
Q1は正しいか?Q1はP1を含意するか?
主張2:「人間が知的なはずが無い(P2),だって、遺伝子に組み込まれたことしか出来ない(Q2)のだから」
Q2は正しいか?Q2はP2を含意するか?
以上に関する自分の意見をレポートにまとめて提出。両主張の関係をよく分析してください。
主張1と主張2は全く同じ格好をしている。
同じロジックなら同じ答えになるはず。
答えが違っていたらどこかで言葉の認識のズレがある。
→「知的」の定義?
→人間ににとっての「知的」とコンピュータにとっての「知的」は同じ尺度か?
【与えられた命題の整理】
P1 = コンピュータが知的なはずが無い
¬P1 = コンピュータは知的なはずである。
Q1 = プログラムされたことしか出来ない
¬Q1 = プログラムされたこと(以外)も出来る。
Q1'= プログラムされていないことは出来ない。
→Q1 = Q1' ??
P2 = 人間が知的なはずが無い
¬P2 = 人間は知的なはずである。
Q2 = 遺伝子に組み込まれたことしか出来ない
¬Q2 = 遺伝子に組み込まれたこと(以外)も出来る。
Q2'= 遺伝子に組み込まれなかったことは出来ない
Q2 = Q2' ??
・命題の否定、置換
Q1 → P1 プログラムされたことしか出来ないのだから、コンピュータは知的ではない。
¬Q1 →¬P1 プログラムされたこと以外も出来るのだから、コンピュータは知的である。
Q1'→ P1 プログラムされていないことは出来ないのだから、コンピュータは知的ではない。
Q2 → P2 遺伝子に組み込まれたことしか出来ないのだから、人間は知的ではない。
¬Q2'→¬P2 遺伝子に組み込まれたこと以外も出来るのだから、人間は知的である。
Q2'→ P2 遺伝子に組み込まれなかったことは出来ないのだから、人間は知的ではない。
【言葉の定義】
・「プログラムされたことしか出来ない」とは?
→プログラムに書かれたことしか出来ない。
・「遺伝子に組み込まれたことしか出来ない」とは?
遺伝子に組み込まれたこと≒本能? ←定義できない?
→本能でしか行動できない。
・「○○しか出来ない」とは?
コンピュータにしか出来ないことがある。
→複雑な計算、膨大なデータの処理
人間にしか出来ないことがある。
→人の顔の判別(現在の段階では)
・○○しかできない = 知的ではない。
ならば、「知的である」とは与えられたこと以外も出来ることになる。
・与えられたこととは?
→その人、モノが生まれた目的・使命?
コンピュータの場合:プログラムの仕様、目的
人間の場合:本能 = 子孫を増やすこと?
・「知的=与えられたこと以外のことも出来る」とすると
知的とは?
コンピュータにとっての知的:プログラムの仕様、作られた目的以外のことも出来ること
人間にとっての知的:子孫を増やす以外のことも出来ること
・エラー発生
脳内メモリが足りません
orz
------ note@Artificial Intelligence -----
計算知能(Computational Intelligence, CI)@wikipedia
a successor of artificial intelligence. As an alternative to GOFAI it rather relies on heuristic algorithms such as in fuzzy systems, neural networks and evolutionary computation. In addition, computational intelligence also embraces techniques that use Swarm intelligence, Fractals and Chaos Theory, Artificial immune systems, Wavelets, etc.
Computational intelligence combines elements of learning, adaptation, evolution and Fuzzy logic (rough sets) to create programs that are, in some sense, intelligent. Computational intelligence research does not reject statistical methods, but often gives a complementary view (as is the case with fuzzy systems). Artificial neural networks is a branch of computational intelligence that is closely related to machine learning.
Computational intelligence is further closely associated with soft computing, connectionist systems and cybernetics.
人工知能研究の一分野であり、数理論理学に基づく従来的な人工知能とは一線を画すものである。計算知能の研究は、ファジィシステムやニューラルネットワークや進化的計算といったヒューリスティック的アルゴリズムを中心とする。その他にも、群知能、フラクタル、カオス理論、人工免疫系、ウェーブレットといった技法も利用する。
計算知能の研究では、学習や適応や進化やファジィ論理(ラフ集合)といった要素を駆使して、ある意味で知的なプログラムを作成することを目指している。計算知能の研究では、統計的手法を拒絶するものではなく、しばしば相補的な考え方を提供することもある(例えば、ファジィシステム)。ニューラルネットワーク研究は計算知能研究の一部であり、機械学習と密接に関連している。
計算知能はソフトコンピューティング、みすぼらしい(scruffy)AI、コネクショニズムのシステム、およびサイバネティックスと密接に関連している。
・課題補足
プログラムしたことしか、主張できないのか。
人間は遺伝子に組み込まれたことしか出来ない。だったら知的とはいえない。
主張の1と2がねじれてなかったら一貫する。
ずれていたら、どこがずれているのか?そこを良く分析する。
提出先の変更:63号館の1階
4月28日 Global COE Vijay Saswat Doctor
Programming for concurrency and distribution
マルチコアを使いこなすときの考え方:並列処理、並行処理、分散処理
今回は並行処理
今まで見たいなプログラムではいけない、という話。
X10という言語について。
IBMは、クラスターとか作ってる。javaの普及に貢献。
APGASという考え方に基づいて。
明日、X10の演習できる。
Ambient Global COE
--------------------------------------------
今日の目的:prologを使ってみよう。
疑問文から始まる。
最初はプログラムを読み込む。
コマンドpwd.
cd('c:/~~')
もしくはconsultボタン
list.
→読み込んだものを確認
家計図
赤 女、
青 男。
この家計図をコンピュータに入れるためには
述語部分に値する関数を作ってあげればよい。
is_parent_of(parent, chile).
female(human).
ex:
is_parent_of(pam, bob)
femail(pam).
↑ここまでが具体的な事実。
これらはデータみたいなもの。
prologはデータとプログラムの境目が薄い。
ある家計図のある家族のことが書ける。
辞書にはどういうことが書いてあるのか。
用語の意味の定義。
is_mother_of(X,Y) :- is_parent_of(X,Y) , female(X).
:- = ⇒ ⊂
, = ∧
is_sister_of(X,Y) :-
自分が自分の兄弟かどうかは適当に。
アンダーライン = ワイルドカード
XはYの祖先である。
父親、おじいちゃん、色々ある→再帰呼び出しにする必要がある。
is_ancestor_of() :- is_parent_of()
もうちょっと定義すると
is_ancestor_of(X,Y):-
is_parent_of(X,Y),
is_ancestor_of(Z,Y)
[bobの状況]
bobには子供が二人いるが、もしかしたらそれ以上の子供がいるかもしれない。
yes / noの処理系と(昔)
true / failの処理系がある。(今)
noとfailの違いは微妙。
証拠が無いという意味がfail。
Who, whatの場合:
Whoは変数みたいなもの。
is_parent_of(Who,bob).
Who = pam .
is_parent_of(Who,bob).
Who = pam ;
Who = tom ;
fail.(わかんない)
・もっと複雑な疑問
is_parent_of(X,Y).
データベースにあるものを片っ端から調べる。
→入れた順番に六通りの答えが存在する。
X=
Y=
X=
Y=
......
・条件を並べる
is_parent_of(X,Who), is_parent_of(X,pat).
共通の親がbobで
X = bob
Who = ann
自分が自分の兄弟としているので、
X= bob
Who = pat
・定義を見るとき
listing(is_mother_of).
・is_mother_of(Who,bob).
同じ格好のものを見つけて、当てはまるものを返すだけ。
→データベース検索と同じ
・デバッグ - 中の人が何やってるか知りたいとき
trace.
ワンステップずつ実行する。
Exit = 無事確認された。
・is_ancestor_of(Who,bob).
誰がbobの祖先ですか、と見えるが
子孫も同時に探索できる。
Ex
is_ancestor_of(pam, Who).
bob,ann,pat,jim
G507とかはシステム内部で作った変数。
子孫は二通りある。
Redo:一つ見つかったけど、それだけじゃ満足しないでやり直しをする。続きをする。
→子供の子孫を探しに行っている。
問い14,15は簡単なので各自やっておく。
・論理式
A&BもB&Aも同じ。
→兄弟もひっくり返しても良い
・is_ancestor_of(X,Y) :-
is_parent_of
is_ancestor_of
↑上と下を入れ替えても構わない。
・祖先の定義の仕方は一杯ある。
X ------ Z -------- Y
parent ancestor
X -------- Z ------ Y
ancestor parent
・問15
再帰呼び出しは、下手に書くと止まらない。
→is_ancestor_of -> is_ancestor_of -> is_ancestor_of ....... loop
・足し算のプログラム
非常に原始的な足し算が出来る。
→物事を根本から考える
add(0,Y,Y)
0の次と次は自然数
s(X) = sの次を読む。
xの次の数にyを足したらzの次の数になる。
= add(X,Y,Z).
multiply(0,_,0)
・読み込みコマンド
['prologファイル名']
add(s(s(0)),s(s(s(0))),X)
X = s(s(s(s(s(0))))))) = 5
add(X,Y,s(s(s(0)))).
X + Y = 3となるX,Yを出力できる。
・add(X,Y,Z).
プログラムはこうやって答える↓
X=0のとき
Y=Zが同じ。
X=s(0)
Z = s(Y)
…こんな感じで一般解を永遠と繰り返す。
→prologは一般解を扱う力がある。
変数を含んでいないものをground termという。
問:三つの足し算を計算するprologを書いてみよう!
勿論X is 1234+ 1234なんてことも出来るが、
足し算を根本的に計算すると、
遅い代わりに逆向きに走ることが出来る!
・半加算器と全加算器(half adder, full adder)
FA = 前の繰り上がりも考慮した加算器。
fa fa haという回路を作る。
加算器という述語。
これをつなげていけばaddが出来る。
・prologには二つあって
事実(fact)と規則(rule)がある。
if sentence:rule
足し算はruleで出来る。
3ビットだから2+3とかやってみる。
add(0,1,0 ,0,1,1, X3,X2,X1,X0)
add(X2, X1,X0, Y2,Y1,Y0, 0,1,0,1).
順番はともかくとして、答えが出てくる。
出力を入れると入力を出すこともできる!
house.pl
人工知能→モノが何故動くのか、何故動かないのかの診断に使う
炊く無い敗戦データベース
cd curcuit braiker
l light
w wire
s switch
dynamic宣言の説明は省略。
down(s1) = s1 is down
lit = 電気がつく
lit :- light(L) , ok(L), live(l)
live(outside)
live(Y)
この状態で初めて、家中に電気がつく!
lit(L) このうちで光るものはなんだ!
・switchを落とすには
データを書き換える→プログラムを書き換える。
retract(down(s1)). 入れた知識を引っ込める
assert(up(s1)). 新たな知識を入れる。
こんな感じで、家の状況を論理式で書くことが出来る。
w0とp1は繋がっているのか、とか質問できる。
ところで、先週のTOEFLの前日に、ちょっと面白いイベントに参加したらなんと某企業のT-shirtを手に入った!キタコレ!でもそれ着て外に行くのは、色々と勘違いを起こしそうだから遠慮がちだったり。
またまた話し変わって、今週の月曜日はVijay Saswat Doctorの講義が早稲田理工学部であったので、参加しました。内容は「Programming for concurrency and distribution」。
今、IBM researchが研究しているX10 programmingの説明みたいな講義です。
並行処理をどう実現するか、って説明からX10 programmingの概要、
最後にX10 programmingのサンプルソースコードの解説といった内容。
threadの知識が既に乏しい自分は蚊帳の外ですたorz
まぁとりあえず凄くいいと思ったのは、X10 programmingで作ったソースコードはJVMでもC compilerでも動くらしい。すげぇwでも、原理は理解できずw
参考
http://x10.sourceforge.net/x10home.shtml
講義に関して言えば、最初はゆっくりしゃべってくれたたから理解できたけど、だんだんスピードアップしてきて、イミフワールドへww言ってることをスライドと照らし合わせながら、大まかにしか理解できなかったorzまぁ理解度は1,2割ってところかorz orz orzアメリカの理工系講義もこんな感じなんかなぁ。まだまだ、今のレベルじゃ太刀打ちできないね。
今年は早稲田CS学科主宰(?)のGlobal COE programがある関係で、今後も色々なCSの著名人を大久保キャンパスに招待するらしい。次の講義では、最低でも、講義で示される理論の5割は理解できるようになりたいもんです。
------ assignment memo -----
Take8easy俺。情報数学復習しないとまずいっぽいなorz
【課題内容】
主張1:「コンピュータが知的なはずが無い(P1),だって、プログラムされたことしか出来ない(Q1)のだから」
Q1は正しいか?Q1はP1を含意するか?
主張2:「人間が知的なはずが無い(P2),だって、遺伝子に組み込まれたことしか出来ない(Q2)のだから」
Q2は正しいか?Q2はP2を含意するか?
以上に関する自分の意見をレポートにまとめて提出。両主張の関係をよく分析してください。
主張1と主張2は全く同じ格好をしている。
同じロジックなら同じ答えになるはず。
答えが違っていたらどこかで言葉の認識のズレがある。
→「知的」の定義?
→人間ににとっての「知的」とコンピュータにとっての「知的」は同じ尺度か?
【与えられた命題の整理】
P1 = コンピュータが知的なはずが無い
¬P1 = コンピュータは知的なはずである。
Q1 = プログラムされたことしか出来ない
¬Q1 = プログラムされたこと(以外)も出来る。
Q1'= プログラムされていないことは出来ない。
→Q1 = Q1' ??
P2 = 人間が知的なはずが無い
¬P2 = 人間は知的なはずである。
Q2 = 遺伝子に組み込まれたことしか出来ない
¬Q2 = 遺伝子に組み込まれたこと(以外)も出来る。
Q2'= 遺伝子に組み込まれなかったことは出来ない
Q2 = Q2' ??
・命題の否定、置換
Q1 → P1 プログラムされたことしか出来ないのだから、コンピュータは知的ではない。
¬Q1 →¬P1 プログラムされたこと以外も出来るのだから、コンピュータは知的である。
Q1'→ P1 プログラムされていないことは出来ないのだから、コンピュータは知的ではない。
Q2 → P2 遺伝子に組み込まれたことしか出来ないのだから、人間は知的ではない。
¬Q2'→¬P2 遺伝子に組み込まれたこと以外も出来るのだから、人間は知的である。
Q2'→ P2 遺伝子に組み込まれなかったことは出来ないのだから、人間は知的ではない。
【言葉の定義】
・「プログラムされたことしか出来ない」とは?
→プログラムに書かれたことしか出来ない。
・「遺伝子に組み込まれたことしか出来ない」とは?
遺伝子に組み込まれたこと≒本能? ←定義できない?
→本能でしか行動できない。
・「○○しか出来ない」とは?
コンピュータにしか出来ないことがある。
→複雑な計算、膨大なデータの処理
人間にしか出来ないことがある。
→人の顔の判別(現在の段階では)
・○○しかできない = 知的ではない。
ならば、「知的である」とは与えられたこと以外も出来ることになる。
・与えられたこととは?
→その人、モノが生まれた目的・使命?
コンピュータの場合:プログラムの仕様、目的
人間の場合:本能 = 子孫を増やすこと?
・「知的=与えられたこと以外のことも出来る」とすると
知的とは?
コンピュータにとっての知的:プログラムの仕様、作られた目的以外のことも出来ること
人間にとっての知的:子孫を増やす以外のことも出来ること
・エラー発生
脳内メモリが足りません
orz
------ note@Artificial Intelligence -----
計算知能(Computational Intelligence, CI)@wikipedia
a successor of artificial intelligence. As an alternative to GOFAI it rather relies on heuristic algorithms such as in fuzzy systems, neural networks and evolutionary computation. In addition, computational intelligence also embraces techniques that use Swarm intelligence, Fractals and Chaos Theory, Artificial immune systems, Wavelets, etc.
Computational intelligence combines elements of learning, adaptation, evolution and Fuzzy logic (rough sets) to create programs that are, in some sense, intelligent. Computational intelligence research does not reject statistical methods, but often gives a complementary view (as is the case with fuzzy systems). Artificial neural networks is a branch of computational intelligence that is closely related to machine learning.
Computational intelligence is further closely associated with soft computing, connectionist systems and cybernetics.
人工知能研究の一分野であり、数理論理学に基づく従来的な人工知能とは一線を画すものである。計算知能の研究は、ファジィシステムやニューラルネットワークや進化的計算といったヒューリスティック的アルゴリズムを中心とする。その他にも、群知能、フラクタル、カオス理論、人工免疫系、ウェーブレットといった技法も利用する。
計算知能の研究では、学習や適応や進化やファジィ論理(ラフ集合)といった要素を駆使して、ある意味で知的なプログラムを作成することを目指している。計算知能の研究では、統計的手法を拒絶するものではなく、しばしば相補的な考え方を提供することもある(例えば、ファジィシステム)。ニューラルネットワーク研究は計算知能研究の一部であり、機械学習と密接に関連している。
計算知能はソフトコンピューティング、みすぼらしい(scruffy)AI、コネクショニズムのシステム、およびサイバネティックスと密接に関連している。
・課題補足
プログラムしたことしか、主張できないのか。
人間は遺伝子に組み込まれたことしか出来ない。だったら知的とはいえない。
主張の1と2がねじれてなかったら一貫する。
ずれていたら、どこがずれているのか?そこを良く分析する。
提出先の変更:63号館の1階
4月28日 Global COE Vijay Saswat Doctor
Programming for concurrency and distribution
マルチコアを使いこなすときの考え方:並列処理、並行処理、分散処理
今回は並行処理
今まで見たいなプログラムではいけない、という話。
X10という言語について。
IBMは、クラスターとか作ってる。javaの普及に貢献。
APGASという考え方に基づいて。
明日、X10の演習できる。
Ambient Global COE
--------------------------------------------
今日の目的:prologを使ってみよう。
疑問文から始まる。
最初はプログラムを読み込む。
コマンドpwd.
cd('c:/~~')
もしくはconsultボタン
list.
→読み込んだものを確認
家計図
赤 女、
青 男。
この家計図をコンピュータに入れるためには
述語部分に値する関数を作ってあげればよい。
is_parent_of(parent, chile).
female(human).
ex:
is_parent_of(pam, bob)
femail(pam).
↑ここまでが具体的な事実。
これらはデータみたいなもの。
prologはデータとプログラムの境目が薄い。
ある家計図のある家族のことが書ける。
辞書にはどういうことが書いてあるのか。
用語の意味の定義。
is_mother_of(X,Y) :- is_parent_of(X,Y) , female(X).
:- = ⇒ ⊂
, = ∧
is_sister_of(X,Y) :-
自分が自分の兄弟かどうかは適当に。
アンダーライン = ワイルドカード
XはYの祖先である。
父親、おじいちゃん、色々ある→再帰呼び出しにする必要がある。
is_ancestor_of() :- is_parent_of()
もうちょっと定義すると
is_ancestor_of(X,Y):-
is_parent_of(X,Y),
is_ancestor_of(Z,Y)
[bobの状況]
bobには子供が二人いるが、もしかしたらそれ以上の子供がいるかもしれない。
yes / noの処理系と(昔)
true / failの処理系がある。(今)
noとfailの違いは微妙。
証拠が無いという意味がfail。
Who, whatの場合:
Whoは変数みたいなもの。
is_parent_of(Who,bob).
Who = pam .
is_parent_of(Who,bob).
Who = pam ;
Who = tom ;
fail.(わかんない)
・もっと複雑な疑問
is_parent_of(X,Y).
データベースにあるものを片っ端から調べる。
→入れた順番に六通りの答えが存在する。
X=
Y=
X=
Y=
......
・条件を並べる
is_parent_of(X,Who), is_parent_of(X,pat).
共通の親がbobで
X = bob
Who = ann
自分が自分の兄弟としているので、
X= bob
Who = pat
・定義を見るとき
listing(is_mother_of).
・is_mother_of(Who,bob).
同じ格好のものを見つけて、当てはまるものを返すだけ。
→データベース検索と同じ
・デバッグ - 中の人が何やってるか知りたいとき
trace.
ワンステップずつ実行する。
Exit = 無事確認された。
・is_ancestor_of(Who,bob).
誰がbobの祖先ですか、と見えるが
子孫も同時に探索できる。
Ex
is_ancestor_of(pam, Who).
bob,ann,pat,jim
G507とかはシステム内部で作った変数。
子孫は二通りある。
Redo:一つ見つかったけど、それだけじゃ満足しないでやり直しをする。続きをする。
→子供の子孫を探しに行っている。
問い14,15は簡単なので各自やっておく。
・論理式
A&BもB&Aも同じ。
→兄弟もひっくり返しても良い
・is_ancestor_of(X,Y) :-
is_parent_of
is_ancestor_of
↑上と下を入れ替えても構わない。
・祖先の定義の仕方は一杯ある。
X ------ Z -------- Y
parent ancestor
X -------- Z ------ Y
ancestor parent
・問15
再帰呼び出しは、下手に書くと止まらない。
→is_ancestor_of -> is_ancestor_of -> is_ancestor_of ....... loop
・足し算のプログラム
非常に原始的な足し算が出来る。
→物事を根本から考える
add(0,Y,Y)
0の次と次は自然数
s(X) = sの次を読む。
xの次の数にyを足したらzの次の数になる。
= add(X,Y,Z).
multiply(0,_,0)
・読み込みコマンド
['prologファイル名']
add(s(s(0)),s(s(s(0))),X)
X = s(s(s(s(s(0))))))) = 5
add(X,Y,s(s(s(0)))).
X + Y = 3となるX,Yを出力できる。
・add(X,Y,Z).
プログラムはこうやって答える↓
X=0のとき
Y=Zが同じ。
X=s(0)
Z = s(Y)
…こんな感じで一般解を永遠と繰り返す。
→prologは一般解を扱う力がある。
変数を含んでいないものをground termという。
問:三つの足し算を計算するprologを書いてみよう!
勿論X is 1234+ 1234なんてことも出来るが、
足し算を根本的に計算すると、
遅い代わりに逆向きに走ることが出来る!
・半加算器と全加算器(half adder, full adder)
FA = 前の繰り上がりも考慮した加算器。
fa fa haという回路を作る。
加算器という述語。
これをつなげていけばaddが出来る。
・prologには二つあって
事実(fact)と規則(rule)がある。
if sentence:rule
足し算はruleで出来る。
3ビットだから2+3とかやってみる。
add(0,1,0 ,0,1,1, X3,X2,X1,X0)
add(X2, X1,X0, Y2,Y1,Y0, 0,1,0,1).
順番はともかくとして、答えが出てくる。
出力を入れると入力を出すこともできる!
house.pl
人工知能→モノが何故動くのか、何故動かないのかの診断に使う
炊く無い敗戦データベース
cd curcuit braiker
l light
w wire
s switch
dynamic宣言の説明は省略。
down(s1) = s1 is down
lit = 電気がつく
lit :- light(L) , ok(L), live(l)
live(outside)
live(Y)
この状態で初めて、家中に電気がつく!
lit(L) このうちで光るものはなんだ!
・switchを落とすには
データを書き換える→プログラムを書き換える。
retract(down(s1)). 入れた知識を引っ込める
assert(up(s1)). 新たな知識を入れる。
こんな感じで、家の状況を論理式で書くことが出来る。
w0とp1は繋がっているのか、とか質問できる。
登録:
投稿 (Atom)