2013年6月30日(第327回)
- まるよし Train Pops ~ 国語と遊ぼう! 第13便 「手紙」
- 季節の話題 セミ、海、夏・・・
- 国際化について
- スーパームーンの話
担当:前田勝(4EI)、松島(2C)、山野(2C)、西(教員)
Optimal Guardをインストール
担任クラスの学生さんの就職先のOPTiMさんより、 ソフトウェアが送付されてきた。 その学生さんが開発に携わった、 遠隔操作系マルウェア対策ソフト Optimal Guard が 発売されたということで寄贈して頂けたようだ。
といっても、私自身は研究室では Mac OS ばかりなので、 自宅PCにて試してみる。学内だと、遠隔操作系マルウェアの 心配な人も少ないので、みんなの先輩が作ったソフトたぞ… ということで、興味のある学生さんにも使ってもらう。
とはいえ自宅PCは、ウィルス対策ソフトも入れてあるし、 子どもも同じパソコンを使うとはいえ、コンテンツフィルタを しかけてあることから、遠隔操作系マルウエアにかかる 心配はない…はず…
開発したOBに、Facebook で試してみると伝えたら、 ガンガン使ってくださいと言われ、バグ出ししたろか… とも思うけど、その前にマルウェアにひっかかってないがな…
ということで、インストールしたとはいえ、何も起こらないのであった…….
リストを用いたスタックと待ち行列
先週の授業で、リストへの挿入・追加処理について説明したので、 今日はその応用で、リストを用いたスタックと待ち行列(Queue)の説明を行う。 また、今週は公開授業週間ということで、他の先生の見学もあって、ちょっと緊張。
スタック
配列を用いた、LIFO(Last In First Out)=スタックであれば、一般的に 以下のようなコードになる。
int stack[ 100 ] ; int sp = 0 ; void push( int x ) { stack[ sp++ ] = x ; } int pop() { return stack[ --sp ] ; }
しかし、この方法では、配列サイズ以上のデータは保存できない。 これをリストを使うことでサイズを気にしないスタックを実現できる。
struct List* stack = NULL ; void push( int x ) { stack = cons( x , stack ) ; } int pop() { int ans = stack->data ; struct List* del = stack ; stack = stack->next ; free( del ) ; return ans ; }
キュー
待ち行列(Queue)は、FIFO(First In First Out)を配列で実装する場合、 一般的には、以下のようになる。ただしエラー対策は記載していないので、要注意。
int que[ 100 ] ; int wp = 0 ; // 書き込み用ポインタ int rp = 0 ; // 読み出し用ポインタ void put( int x ) { que[ wp ] = x ; wp = (wp + 1) % 100 ; // 循環させる } int get() { int ans = que[ rp ] ; rp = (rp + 1) % 100 ; // 循環させる return ans ; }
このような配列の領域を使い切ったら、先頭から再利用するような方法は、 リングバッファなどと呼ばれる。 このような待ち行列は、キー入力バッファや、プロセス待ち行列などに よく利用される。しかし、このプログラムでも、配列サイズ以上の データは保存できないので、リストを用いる。
struct List* top = NULL ; struct List** tail = &top ; void put( int x ) { *tail = cons( x , NULL ) ; tail = &( (*tail)->next ) ; } int get() { int ans = top->data ; struct List* del = top ; top = top->next ; free( del ) ; return ans ; }
ただし、このプログラムは、常に1件以上データがリストに入っている場合は 問題がないが、get() を実行して、データ件数が0件になると、tail の指す先が おかしくなるので注意が必要。
また、待ち行列では、先頭ポインタと末尾ポインタの2つが必要であるが、 リスト構造の末尾のNULLを、先頭データを指すようにする循環リストと する場合も多い。特に、プロセス待ち行列を実装するときのラウンドロビン方式 などでは、末尾まで処理が及んだ次は先頭に戻って処理を行うため、 循環リストは都合がいい。
OSの歴史と木構造ファイル
前期の後半ということで、OSやファイル処理の話をするため、 まず今週はその導入。OSのありがたみを分ってもらうために、 OSの歴史と木構造ファイルとディレクトリ・PATHについて説明を行う。
OSの歴史
OSの歴史ということで、第1世代あたりでは、OSでの共通機能の提供という 概念がないことを説明し、OSに近いといっても機械語モニターといった程度であることを紹介。 コンピュータの普及と共に、他のコンピュータでも同じようにプログラムが動くようにしたいため、 OSが発達していった。
この後は、汎用機のOSの話は身近でもないし、パソコンのOSで説明を行う。
パソコンは、最初に Intel 4004 による4ビットコンピュータからはじまっていくが、 普及は、Intel 8008 の8bitコンピュータあたりが最初(1970年代)。 このころのOSは、パソコンの共通の使い方の提供という点では、BASICが 開発言語でもありOSでもあった。同じころに Apple社は 6502 を利用してAppleⅡなどが 発表されていた。
処理の増加と共に、1980年頃に16bitコンピュータ8086を使ったパソコンが 作られ、これのOSとして、Microsoft社が創業しMS-DOSが作られる。 同じころに、Apple社は68000を使ったMacintoshを発表している。 Macintoshでは、マウスとアイコンによるGUI(Graphical User Interface)で、 便利であったことから、Microsoft社が Windows を開発する。 このころのコンピュータは、 シングルタスクシングルユーザのことしか考えられていなかった。
WindowsやMacintoshのGUIな環境であたが、グラフィック処理の複雑化と共に、 32bitコンピュータへと性能が上がっていく。この中で、1つのコンピュータを 複数の人で複数の処理を行うマルチユーザ・マルチタスクが必要となる。 このころには、安全にプログラムを動かすためにメモリ保護機能などを持った、 32bitコンピュータ Intel 80386 , MC68020 などから、近代のOSが普及していく。 Windowsは、NT,2000,Xp,7,8 と発達していく。
一方、1970年代には、汎用機のOSをミニコンで動かそうということで、 Multicsの影響を受けながら、マルチユーザ・マルチタスクのOSである、 unix が開発されていく。これらは、1990年代ころのインターネットの普及と共に、 オープンソースの考え方の元で開発された Linux へと続いていく。
ファイルとディレクトリとPATH
前に上げた、MS-DOSの前身である 8bit OSの時代では、コンピュータの中で 扱うファイルも少なかったので、ディレクトリという概念が扱えるOSは、 少なかった。しかし、unix での木構造型ファイルシステムを引継ぎ、 ディレクトリが使われるようになった。これにより、用途別にファイルを 分類管理できるようになった。
この木構造型ファイルシステムでは、ファイルの場所を明記するために、 ディレクト構造の根っこのルートディレクトリから、ディレクトリ名を書き連ねて 場所を示す。ただし、MS-DOS/Windows では、ディレクトリ名区切りは、 バックスラッシュ(日本では¥記号)を使う。Unix 系では、スラッシュを用いる。 この根っこからの経路(PATH)を指定する方式は、絶対PATHと呼ばれる。
しかし、絶対PATHは、深いディレクトリ構造では、PATH表記が長くなり、 場所を簡潔に記載したい場合がある。この場合には、現在注目している 起点(カレントディレクトリ)からの経路を示す方式がとられる。 この方式は、相対PATHと呼ばれる。
相対PATHでは、近隣のディレクトリを簡潔に示すために、 一つ上のディレクトリ(親ディレクトリ)を示すために、「..」が使われる。 また、注目ディレクトリを示す「.」も使われる。
2013年6月23日(第326回)
- まるよし Train Pops ~ 国語と遊ぼう! 第12便 「一人称」
- 五味が答える!~かかってこいや~ 第1回
ゲスト:福井高専OB 大野様、高見様
担当:前田勝(4EI)、五味(教員)
UMLと構造図
UMLの説明として、簡単な歴史と構造図の説明を行う。 基本は、クラス図かな。コンポーネント図とかパッケージ図は、巨大なコードを書いた経験が無い状態では、説明してもピンとこないだろうな。
講義資料は、2011年度資料とほぼ同じなので、過去記事へのリンクで省略。
リストへの追加と挿入
テスト返却にて、嫌味も織り交ぜながらの解説の後、 30分ほど時間があったので、次のステップ。
リストへの追加
前回までの授業では、リストは直接記述していたが、 データを読み取りながらのリスト生成を説明する。
まずは基本ということで、リストの先頭挿入。 ただし、データの入力順序とは逆になってしまう。
struct List* top = NULL ; int x ; while( scant( "%d" , &x ) == 1 ) { top = cons( x , top ) ; }
この欠点の修正ということで、末尾追加型を示す。 Listへのポインタのポインタがわかりづらいけど…
struct List* top = NULL ; struct List** tail = &top ; while( scant( "%d" , &x ) == 1 ) { *tail = cons( x , NULL ) ; tail = &((*tail)->next) ; }
ポインタのポインタは分かりづらいので、改めて式の一部分が 型でどうなっているのかを示す。
リストへの途中挿入
リストが使われる利点は、データの途中挿入。 以下のプログラムは、昇順に並んでいるデータの、適切な場所にデータを 途中挿入するプログラム。 一つ前のnext部を変更する必要があるため、 ひとまずは分かりやすいプログラムということで、p->next でループを回す。 本当は、List**を使いたいんだけどね…
void insert( struct List *p , int x ) { for( ; p->next != NULL ; p = p->next ) { if ( p->next->data > x ) { p->next = cons( x , p->next ) ; break ; } } }
ただし、このプログラムは、データの先頭や末尾への追加は正しく動かない。 このためよく用いられるテクニックは、先頭と末尾に本来なら使わないダミーデータを 入れておき、先頭末尾の特別処理を書かずにすませる方法をとる。 このような方法を番兵(sentinel)と呼ぶ。
緊急連絡システムのmuninが止まってた…
昨日よりニュースで、北陸地区での豪雨警報がでている。 緊急連絡のメールが沢山飛ぶ可能性もあり、 サーバの状況を監視してみる。しかしながら、監視用に動かしている munin の データが、5/1 を最後に更新されていない。 丁度、Debian の更新などをかけていた時期だし、その影響と思われる。
/var/log/munin/munin-update.logを見ると、以下の様な履歴が大量に残っている。 調べてみると、munin のデータをネットワーク越しに返信する、munin-node が正しく動いてないとのことであった。
(( /var/log/munin/munin-update.log )) 2013/06/19 09:35:01 [ERROR] Munin::Master::UpdateWorker <localdomain;localhost.localdomain> died with '[FATAL] Socket read from localhost.localdomain failed. Terminating process. at /usr/share/perl5/Munin/Master/UpdateWorker.pm line 139
改めて、munin-node の動作確認をすると…以下の様なエラーがあることから、 munin-node.conf の allow 項目を修正する。
(( /var/log/munin/munin-node.log )) 2013/06/19-09:34:29 [3696] Denying connection from: 192.168.xx.xx
(( /etc/munin/munin-node.conf )) allow ^(127\.0\.0\.1|192\.168\.xx\.\d+)$
さらに、apache access の状況も確認できていない。 これは、apache の mod_status の問題。
(( /etc/apache2/mod-enabled/status.conf )) <Location /server-status> SetHandler server-status Order deny,allow Deny from all Allow from 127.0.0.1 ::1 Allow from 192.168.xx.0/24 ← 追加 </Location>