はうすてんぼぶ

コードかいてて疑問に思ったことや、興味あることをつらつらと暇なときに書く場所、ここはそんな場所

iノードとリンク

はじめに

前回に引き続いて、ファイルシステムの勉強。

前回は、ファイルシステムの基礎となるiノードについて触れた。

iノードのところで、ファイル名とiナンバは対になっていて、ファイル名→iナンバ→iノード→データブロック(ファイル実体)、みたいな流れで、ファイルの中身を持ってきていた。

しかし、1つのファイル名からiナンバは一意に定まるが、どうも1つのiナンバからファイル名は一意に定まらないらしい。
これは、iノードとリンク処理の関係の話になる。

てなわけで、今回はハードリンク、シンボリックリンクについてやるよー。

参考書はいつもどおり、『Amazon.co.jp: 改訂 新Linux/UNIX入門: 林 晴比古: 本』を使います。

リンク処理

ハードリンク

同じiナンバのファイルが複数できる、ということをハードリンクという。

ファイル名 iナンバ
file1 10
fileA 10

このように、ファイル名は異なっても、同一のiナンバを持つため、はじめににも書いた流れ的に同一のファイル実体を指すことになる。

そして、あるファイル実体に対応しているファイル名数を、リンク数(リンクカウント)と呼ぶ。
このリンクカウントの大事なところは、「値が0になったらファイルを削除する」ということ。
上の表だと、2。

もし、fileAを削除した場合は-1されて、リンクカウントは1になり、file1も削除すると0になってファイルが削除される。

これは「ファイルの削除≠ファイル実体の削除」ということで、
今までずっとそこが=だと思ってた俺は、Unixすげーなーって思うのです。

リンクの貼り方はlnコマンドを用いる。
ハードリンクの場合は、

ln [to] [from]

で、[to]と同一のiナンバを持つ[from]ファイルが作られる。

シンボリックリンク

シンボリックリンクは、「ファイルは作られるけど、そのファイル実体は別のファイル実体を指す」みたいな感じで頭を痛ませる。

シンボリックリンクファイルAの実体にリンクを張ろうとすると新しいファイルBができる。
で、このファイルBファイルAとは別のiナンバを持っているのがハードリンクとは大きく異なる点。

そして、ファイルBの実体を辿るまでの過程でiノードに「これシンボリックリンクだから」みたなことが書いてあって、
さらにファイルBの実体を見ると、「ファイルAを見てね」的なことが書かれている。

そしてそして、それに従ってファイルAでディレクトリにiナンバを問い合わせて、ファイルAのiナンバからファイルAの実体まで参照しにいく感じ。

遠い、やたらファイルAの実体に行くまで遠い。
でも、このシンボリックリンクは以外と役立つこともあるようである。

ちなみにシンボリックリンクの貼り方は、ハードリンクと同じくlnコマンドを用いて、

ln -s [to] [from]

のように、-sオプションを付けて実行すれば良い。

ハードリンクとシンボリックリンクのちがい

ハードリンクは、同一ディレクトリ内でしか張れない、ファイルシステムをまたいだリンクを作成できないことが特徴、というか短所。
これは、別のディレクトリやファイルシステムが同じiナンバを既に使用していた場合、同じiナンバにも関わらず別のファイルを指している、といったことが起きてしまうから。

シンボリックリンクは、そのハードリンクの持つ欠点が無いため、広く使われている。
iナンバに依存せずにファイルへのリンクを張っているため、ファイルシステムが違ってもちゃんと動く。
シンボリックリンクは、WIndowsでいうショートカットとほぼ同様で、ショートカットと同じようにリンク先の実体が削除されるとエラーが起こる点に注意。

じゃあハードリンクってなんのために存在してるんだよ、ってなるけども。
どうもファイル名の呼ばれ方で処理を変えるものがあるらしい。
Linuxのシンボリックリンクとハードリンクはどう使い分けますか.. - 人力検索はてなのNo.2の回答に書かれているが、gzipはその呼ばれ方(gcat、gunziip)で処理を変える、とのこと。

おわりに

とまぁこんな感じでUnixファイルシステムのiノードに関する箇所はひとまず終了。

iノードの考え方は、初めてだったけどもシンプルでありながら良くできてるなぁ、といった感想を持った。
それを踏まえたリンクの貼り方も、ハードリンクは結局あまりなんのために存在しているか分からなかったけど、シンボリックリンクは便利!といった感じ。

次はファイルシステムと関連のあるFHSに触れて、Unixファイルシステムに関しては終わりにする。

参考資料

Amazon.co.jp: 改訂 新Linux/UNIX入門: 林 晴比古: 本, p106-p107.
MISTY-NET UNIXコマンド講座, http://cmd.misty.ne.jp/environment/03.html.
UNIXの部屋 コマンド検索: ln, http://x68000.q-e-d.net/~68user/unix/pickup?ln.
Linuxシンボリックリンクとハードリンクはどう使い分けますか.. - 人力検索はてな, http://q.hatena.ne.jp/1265361495, 回答 No.2.

iノードの理解を深める

はじめに

Unixファイルシステムに関してちょいちょい勉強してくよー。

という感じで今日はiノードについて。

参考資料はお馴染みの『Amazon.co.jp: 改訂 新Linux/UNIX入門: 林 晴比古: 本』とネットから。

iノードって?

iノードはindex-nodeの略で、
ファイルが作られるたびに、それに1対1対応するように作成される管理情報のことを指す。

管理情報というと難しそうに見えるが、よくお目にかかるファイルサイズや最終更新日などもこれに含まれる。
他には、リンク数、作成時間、所有者のユーザID,最終アクセス時間、ブロック番号などが含まれる

「ブロック番号」ってあまり馴染みがないけども、ディスク上でのファイル本体の格納場所の情報が入っているらしい。
いわゆる、CやC++でいうポインタ。

また、それぞれのiノードには、iナンバというユニークの識別番号が付与され、
ディレクトリは、このiナンバとファイル名をたくさん持っているもの、として考えることができる。

例えば"Hello World"と書かれたfile1.txtを、cat file1.txtとして出力する処理は以下のようになる。

  1. ディレクトリを見て、ファイル名(file1.txt)と対になるiナンバ(1000とする)を特定する
  2. iナンバ(1000)を用いて、iノードテーブルから該当するiノードを取り出す
  3. iノード中のブロック番号(3000とする)を見る
  4. ディスク領域でブロック番号(3000(が指す箇所を参照しにいく
  5. その箇所にあるファイルの実態を見つける→出力される

DBのテーブル的な感じで管理されていて、主キーのiノードから全部引っ張ってくる、といった印象を受けたけども実際そんな感じなのだろうか。

ブロック番号と関節指定ポインタ

iノードで指定できるブロック番号

上の例でfile1.txtが出てきたけど、これぐらいファイルサイズの小さいものなら1つのブロックに収まる。
ただ、動画や高解像度の画像となるとそうはいかないので、複数個のブロックを指定する必要がある。

Linuxのext3というファイルシステムは、iノードのブロック番号を12個指定できる。
一個のブロックの大きさは、1024byteか、2048byteか4096byteから指定できる。
UNIXの中には8192byteを指定できるものもあるらしいが、そうするとファイルサイズが小さい際に無駄な領域が多くなってしまって非効率。

例えば1つのブロックの大きさを1024byteとすると。
iノード中でそのブロックを指す番号を12個まで指定できるということは、1024byte✕12で約12Kbyte。
一昔前のフロッピーディスクに収まるぐらいでとても少ない。

それ以上のファイルサイズのものを持ってこようとすると、以下の関節指定ポインタを使う必要が出てくる。

関節指定ポインタ

端的に言うと、1つのブロック(X)に、他のブロック(Y)を指し示す4byteのポインタを256個入れれば巨大なファイルも扱える。
さらに、その他のブロック(Y)を指し示す先のブロック(Z)に4byteのポインタを256個入れれば…、といった感じ。

関節指定ポインタは、Linuxだと三重にまですることができ(四重とかもいける?)、
1ブロックの大きさが1024byteだと以下の表のようになる。

単一関節指定ポインタ 256✕1024 256KB
二重関節指定ポインタ 256✕256✕1024 64MB
三重関節指定ポインタ 256✕256✕256✕1024 16GB

関節指定することで、12KBまでしか扱えなかったのに16GBまでのファイルを格納することができるようになった。
仕組みはシンプルなだけに、なんかすげー。

おわりに

今回はiノードに関しての理解を深めるとこまで。
次は、iノードを絡めたシンボリックリンクとハードリンクについて書くよー。

疑問

Windowsだとファイルサイズが2GBか4GBぐらいまでしか扱えないのは、一つのブロックサイズが小さいからなのかな?

無駄が小さくなる代わりに巨大なファイルが扱えなくなるってのは、OSごとにどっちを優先するかに寄るのかも。

いや、でも1ブロックサイズを1024とすると、
64MB以上のファイルを扱う際に無駄なブロックがでてくるからどっちもどっちか。

でも無駄といっても、使われていないのなら他のために使われてるんだよなぁ。
100MBの動画で16GBディスク容量を食うってことになるし。

うーむ、もっと調べる必要がありそうだ。

参考資料

改訂 新Linux/UNIX入門: 林 晴比古, p102-p107

ファイルとファイルシステム

SSHとは?

はじめに

sshはたびたび使ったことあるのだけども、「そもそもsshって何々です?」という感じなので調べて、ちゃんと学んでから使ってみてるよ。

Unixというより、シェルなのか、いつも頼りにしてる参考書に該当項目がなかったので、ネットの海をソースに頼りに書くよー。

セキュリティ屋のお隣さんに聞いたほうが良い気もするけどね!

えすえすえいちって?

Secure SHellの略。

wikipediaによると、

Secure Shell(セキュアシェル、SSH)は、暗号や認証の技術を利用して、安全にリモートコンピュータと通信するためのプロトコル。パスワードなどの認証部分を含むすべてのネットワーク上の通信が暗号化される。

ふむ。やりとりするデータを暗号化してくれるから、盗聴とかの心配がなくなって良い!ということらしい。

Telnet、rlogin、ftpは暗号化せずにデータを渡すんだから、
そりゃ、皆、暗号化してやりとりできるsshを使うよね。

公開鍵認証

SSHは、この公開鍵認証という仕組みを採用している。

これは大学の頃セキュリティの講義でさんざん聞いたからちょっと分かる。

鍵を2つ用意して、1つを暗号化するために使って(公開鍵)、もう1つを暗号化したものを復号するために使う(秘密鍵)。

サーバとクライアントだと、サーバはクライアントに公開鍵を渡して、クライアントはサーバに公開鍵を渡す。
こうすれば、互いにやりとりするときに、受け取った公開鍵で暗号化したものを相手に渡せば周りからは見れなくなる。

秘密鍵を渡しちゃ、ダメ、絶対。

以下のサイトを参考にしました。
第12回 SSHについて - Linux入門講座

プロトコル

SSH1とSSH2がある。
ただ、別に2になったからといって上位互換ではない、という点に注意が必要とのこと。

どっちも公開鍵認証を使うのだけれども、まず、その暗号化方式が異なる。というか異なっていた。
SSH1の暗号化方式は、RSA。SSH2は(元)DSA。

なんで1と2に分けられたかっていうと、RSAに特許問題があって、それを回避するためにDSA方式を採用したSSH2が生まれた。
その特許が2000年9月に失効しているため、SSH2でもRSAで暗号化してやりとりができるようになった。

特許が失効して互いに同じ暗号化方式を使うならもう一つでいいじゃん、と思うけど。
データ改竄をチェックするためのアルゴリズムがSSH2のほうが強力な分、2を推奨、といった現代の流れ。

SSH1はCRC、SSH2はHMACアルゴリズムを採用している。

以下のサイトを参考にしました。
SSHプロトコルの種類(SSH1とSSH2)

速さは?

すぐ疑問に思ったのが、暗号化してやりとりするってことは転送速度が遅くなるのでは、という点。

調べたらいい感じの記事が見つかった。

【Linux小技】 scp(ssh)での暗号化方式の違いによる転送速度ベンチマーク 「知ったかブログ」
によると、ftpsshでざっと50MB/sぐらい差がでるみたい。
これに起因しているのがCPUの処理速度で、暗号と復号にがしがしCPU使うせいで転送速度が落ちる、とのこと。

ただ、採用する暗号化方式に寄るらしく、
arcfourという手法だとそんなに下がらない。
AESだと半分くらいに落ちるらしい。(それでも50MB/s出ているけども)

速度と暗号強度との兼ね合いで好きなのを採用しよう!といった感じ。

SFTP? SCP?

頭のSがSecureのSなのは分かるけど、こいつらなんなんです?

と思って調べたら、SSH、SFTP、SCPは同じレイヤーにいるのではなく、SFTPとSCPはSSHを利用した安全なファイル転送方式のことを指すらしい。

分かりやすくまとめているサイトさんがあったので、そこから引用する感じでまとめとく。
SCPとSFTPの違い - たこにありがちなこと。

SCPは、

SSHサーバでUNIXスタイルのシェルを起動してSCPコマンドを使ってファイル転送を行う。

SFTPは、

SSHサーバからSFTPサーバを起動して、SFTPのコマンドを用いてファイル転送を行う。

違いを表にざっとまとめると。

項目 SCP SFTP
パケット確認 しない する
信頼性 低い 高い
速度 速い 遅い
4GB以上の転送 できない できる
転送中断からの再開 できない できる
機能面 シンプル 高機能

こんな感じ。SFTPのほうが転送速度も遅いけど色々できるから使うなら俺はこっちにするね。

おわりに

なんとなく分かった気がする。
何がともあれ、セキュアなの使おうぜ!って感じだから俺も使う。

使ってみて感じたことがあったらまた記事を書こうと思う。

RSAやDSAやarcfourやAESなどの暗号化方式はおいおい調べて、おいおいお隣さんに確認を取ります。
というか教えてもらいます。

オプションに書いたスクリプトが展開されない@Eclipse CDT

タイトルどおり困ったので、ちょっと調べて見た。

まず、同じ事で悩んでた記事を探した。
Eclipse Community Forums: CDT » Linker parameters

この解決策に書いてある通りやってもダメだったので、
もうちょい調べたら以下の記事を見つけた。
非実在業務日誌: 【備忘録】eclipse CDT で GTK+アプリケーションをビルドする

結局、
Eclipse CDTのLinkerやCompilerのオプションに書いたスクリプトが展開されない問題は、

$(shell [script])

とすれば解決することが分かった。

本来は、

'/opt/local/bin/wx-config --libs'

のスクリプトが実行された結果をオプションに入れて欲しいのだけれども、
なぜかそのまま文字列で、実行されてしまう。

なので、上の例の場合だと、

$(shell /opt/local/bin/wx-config --libs)

のように書くと、ちゃんとEclipse CDT上でもシェルが実行されて実行結果が入る。

うーん、でもなんで展開されないのかなぁ…

Unixシェルコマンドの勉強 part 1

さて、何を隠そう、自分はUnixシェルの基本的操作すらおぼつかないので勉強がてらまとめとく。

はじめに

全4パートぐらいでひとまず基本的なコマンド周りを復習する。

対象は、
2 UNIXのコマンド http://akita-nct.jp/yamamoto/lecture/2006/5E/unix/html/node2.html
の「2.1 使用頻度の高いコマンド」に載ってた使用頻度の高いコマンド11個。

具体的には、

man, pwd, ls, cd, mkdir, rmdir, rm, cp, mv, cat, less

の11個。
part 1では、manpwdlsまで触れる

ちなみに、この記事のこの文を書いてる段階で自分が使える全Unixコマンドは、

cd, ls, rm, pwd, cp, mkdir, rmdir, chmod, man, which, grep

ぐらい。ちょっと死にたくなったけど頑張る。

使えるコマンドって言ってもそのほとんどが最低限しか使えてないので、調べつつ使ってみて、ここに書いてくよ。

参考資料は、ネットの海と、昔買った参考書「Amazon.co.jp: 改訂 新Linux/UNIX入門: 林 晴比古: 本」。

man

概要

マニュアルを表示する。
manualが語源

こんな感じに使う。

% man [name]
% man [n] [name]

[name]にコマンドを入れる。[n]を指定すると、マニュアルの第n章から探して表示してくれる。

例えばmanのマニュアルを見たい場合には、

% man man

実行結果は、

man(1)                                                man(1)

NAME
       man - format and display the on-line manual pages

SYNOPSIS
       man  [-acdfFhkKtwW]  [--path]  [-m system] [-p string]
       [-C config_file] [-M pathlist] [-P pager] [-B browser]
       [-H htmlpager] [-S  section_list] [section] name ...

マニュアルページは矢印キーでも動けるけど

  • [b] : back 前のページへ
  • [f][Space] : forward 次のページへ
  • [Enter] : 次の行へ
  • [q] : quit マニュアルを閉じる

ココらへんを覚えておくと便利!

オプション

とりあえず参考書に載ってた2つだけ。

-f

本格的に数ページに渡るマニュアルを読みたいわけでもないし…ってときは-fオプションを付けるとコマンドの意味を一行で知ることができる。

whatisでも同じ結果が得られる。また、結果を返すのもオンラインマニュアルからでなく、ローカルのDBから探す分whatisのほうが早いみたい。

% man -f [name]
% whatis man

実行結果、catが付くコマンドが複数あったので色々でてきてるけど、本来知りたいcatもその中にある。

% man -f cat
cat(1)                   - concatenate and print files
git-cat-file(1)          - Provide content or type and size information for repository objects
fc-cat(1)                - read font information cache files

何の省略表記はわからなかったので、first-lineと覚えとく。
findと紛らわしいかな…。

-k

-kオプションを使うと、正確なコマンドを忘れたときでも、コマンドの一部から、該当するコマンドを表示してくれる。コマンドだけを検索してるのではなく、一行説明文のとこからも探してくれるので便利!

aproposでも同じ結果が得られる。これもwhatisと同様の理由で、man -kとするより早い。

% man -k chmo
% apropos chmo

実行例。

% man -f chmo
chmo: nothing appropriate

% man -k chmo
chmod(1)                 - change file modes or Access Control Lists
chmod(2), fchmod(2)      - change mode of file
lchmod(3)                - change mode of file
~~~~ 省略 ~~~~

これも何の省略表記は分からないので、keywordとして覚えておく。

pwd

概要

カレントディレクトリを表示する。

語源は、print working directory

passwordとは無関係である。

使い方はシンプルで、ただ

% pwd

と打って実行するのみ。

実行結果は、こんな感じ

% pwd
% /Users/silent_bob

余談だけど、シェルの設定ファイルに現在地を常時表示するようにしとくとあまり使わなくなるコマンドな気がする。

zshを使っている今の自分の環境だと、

/Users/silent_bob% pwd
/Users/silent_bob

こんな感じになってるので、あまり使わないね。

オプション

pwdは、オプションは付けられない。

ls

概要

ディレクトリの内容を表示する。

「内容」というとちょっと分かりづらいが、要はディレクトリに入ってるファイルやらディレクトリを表示してくれるコマンド。

語源は、list segments。
listの短縮形かと思っていたらどうも違うみたい。

使い方は、

% ls [option] [path]

[option]は、-aのようなオプションが入る。
[path]は、内容を表示したいディレクトリへのパスを入れる、指定しなければカレントディレクトリのパスが自動的にそこに入る。

実行結果は、こんな感じ

%ls
Desktop  Music  Developer  Pictures  Documents
~~~~~ 省略 ~~~~~

lsでディレクトリの中身を見て、cdで別ディレクトリに移動したり、vimでファイルを開いたり、比較的起点になるコマンドなのかも。

オプション

実用的なオプションが他のコマンドに比べると、とても多い。
今のところ-A-lぐらいしか使ってない。

参考書に、主なオプションとして挙げられていたのは以下の10個。
実際はもっとあって気が遠くなる。

オプション 内容 語源
-a ドットファイルも表示("."から始まるファイル) all
-A -aと同じだが、"."と".."は表示しない All
-l ロング形式で表示(更新日やファイルサイズ、modなど) long
-F ファイル種類記号を付加 File (?)
-d ディレクトリの詳細情報を表示 directory
-t 最近更新された順に表示 times
-R サブディレクトリの内容も表示 Recursively
-1 1行にひとずつつ表示 1 line
-C 1行に複数表示(-1を指定しなければデフォルトで-Cになる) multi-Column
-h 合計サイズとファイルサイズを単位(M, K)付きの短い数字で表示 human readable

ここでは、教科書に載っていた複数オプションを使った例について取り上げる。
これ以外にも使いやすいオブションがあったら教えて下さい。

複数のオプション

といっても、教科書に載ってる例は全部何かに-lを加えたものしかなかった。

複数指定方法

別々にして記述する方法と、まとめて記述する方法がある。
これは別にlsに限った話じゃないだろうけどね!

下の2つの実行結果は同じ。

% ls -A -l
% ls -Al
-tl

更新時刻の新しい順に、詳細情報を表示してくれるオプション。

% ls -tl
total 360
-rw-r--r--@ 1 bob  OFFICE\Domain Users  35117  6 25 18:28 kikyo.png
-rw-r--r--@ 1 bob  OFFICE\Domain Users  66573  6 25 18:28 azarashi.gif
-rw-r--r--  1 bob  OFFICE\Domain Users  47554  6 25 17:39 cake.jpg
-rw-r--r--@ 1 bob  OFFICE\Domain Users  27405  6 23 20:29 caramel.jpg

使ってみたけど、使う場面はよくわかんなかった。

-Rl

サブディレクトリの内容を、詳細情報として表示してくれるオプション。

実行例は以下のようになる。

% ls -Rl
total 80
-rw-r--r--  1 bob  OFFICE\Domain Users    574  6 25 18:25 cake.css
-rw-r--r--  1 bob  OFFICE\Domain Users    510  6 26 13:24 cookie_page.html
-rw-r--r--  1 bob  OFFICE\Domain Users  28862  6 25 17:43 favicon.ico
drwxr-xr-x  6 bob  OFFICE\Domain Users    204  6 26 11:02 img
drwxr-xr-x  4 bob  OFFICE\Domain Users    136  7  3 17:48 secret

./img:
total 360
-rw-r--r--@ 1 bob  OFFICE\Domain Users  66573  6 25 18:28 azarashi.gif
-rw-r--r--  1 bob  OFFICE\Domain Users  47554  6 25 17:39 cake.jpg
-rw-r--r--@ 1 bob  OFFICE\Domain Users  27405  6 23 20:29 caramel.jpg
-rw-r--r--@ 1 bob  OFFICE\Domain Users  35117  6 25 18:28 kikyo.png

./secret:
total 8
-rw-r--r--  1 bob  OFFICE\Domain Users  509  7  3 17:48 index.html

再帰的に全部出力するからサブディレクトリが多いと表示結果がえらいこっちゃになるから注意。

んー、grepとかと相性がいいのだろうか、と思ったので、
あまり使いなれないgrepでhtmlファイルだけ検索してみた結果が下のようになる。

% ls -Rl | grep -E "*\.html$"
-rw-r--r--  1 bob  OFFICE\Domain Users    510  6 26 13:24 cookie_page.html
-rw-r--r--  1 bob  OFFICE\Domain Users  509  7  3 17:48 index.html

おお、おお?
でも、このままだとファイルの場所が分からないのか…。
うーむ、下の例みたいに権限での検索もできるけど、他のUnixシェルコマンドにないのかそういうの。

% ls -Rl | grep -E "^-rw-r--r--"
-rw-r--r--  1 bob  OFFICE\Domain Users    574  6 25 18:25 cake.css
-rw-r--r--  1 bob  OFFICE\Domain Users    510  6 26 13:24 cookie_page.html
-rw-r--r--  1 bob  OFFICE\Domain Users  28862  6 25 17:43 favicon.ico
~~~~~ 省略 ~~~~~

おわりに

とりあえず3つdone!
ちょっとずつ時間を見つけて書いてくよー。

Windows7でAppleのUSキーボードを使う

Ubuntuで結構手こずったけど、Windows環境でもAppleのキーボードを使えるようにしとこう、と思って設定したので、その方法を書くよ。

環境

本体:Acer Aspire 5750
OS:Windows 7 Home Premium Service Pack1
[コントロールパネル]→[地域と言語]→[形式]を見ると、「日本語(日本)」ってなってた。いじった記憶はないので買ったときからこのままだったと思う。
キーボード:Apple製のUSキーボード

WindowsでのAppleキーボードの設定

これはAppleKbWinという便利なソフトがあるので、それをダウンロードする。

AppleKbWin (Vectorへのリンク)
AppleKbWinの詳細情報 : Vector ソフトを探す!

AppleKbWinの設定

Readme.txtに書いてあるけど、一応こっちにもメモ。

  1. 解凍したディレクトリを任意の場所に置く(自分の場合は、~/apps/AppleKbWinにした)。
  2. AppleKbWinをダブルクリックする。
  3. (デフォルトのままなら)右下のタスクトレイに黄色い背景にAの字が描かれたアイコンが出るので、それを[右クリック]→[設定]。
  4. 設定用のウィンドウが開くので、キーの入れ替えや、日本語と英筋の交互切り替えの設定などを行なう。
  5. 最後に起動のタブを押して、「□スタートアップに登録し自動起動する」にチェックを付けておく。

これでcommandキーがctrlとかに割り当てられたと思うので、AppleキーボードをWindows上でイライラなく使えるようになった!

WindowsでのUSキーボードの設定

コントロールパネルのキーボードからできるかなぁと思ったけど、別にそんなことなかったぜ!

Windowsの場合は、レジストリを書き換える必要があるなんて知らなんだ…。

レジストリの書き換え

Microsoftサポートに該当する記事があったのでそれを見ながら書き換えたよ。

  1. プログラムとファイルの検索に「regedit」と入力してレジストリエディタを開く
  2. [HKEY_LOCAL_MACHINE]→[SYSTEM]→[CurrentControlSet]→[services]→[i8042prt]→[Parameters]とどんどん押していって移動する。
  3. 下の項目の部分を書き換える。
名前 種類 変更前データ 変更後データ
LayerDriver JPN REG_SZ kbd106.dll kbd101.dll
OverrideKeyboardIdentifier REG_SZ PCAT_106KEY PCAT_101KEY
OverrideKeyboardSubtype DWORD 2 0
OverrideKeyboardType DWORD 7 7

※変更前データは自分の環境の場合での値です。環境に寄って変わるかも。

これで本体を再起動すると、USキーボードに対応してキーが打てると思う。
このときに、さっきのAppleKbWinがOS起動に合わせて起動されているかもチェックしておこう。

まとめ

これでWindows環境でもこの前買ったAppleのUSキーボードが使える!やったね!

今後の課題

今はcommand + spaceでかな・英数入力の切り替えをやってるんだけどちょっとレスポンスが悪い。
というかしっかり押さないと切り替わらない感じなので、原因を突き止めねば…。

あと、レジストリを書き換えてるため、本体側のJISキーボードで打つときは不具合が生じる。日本語キーボード⇔英語キーボードの切り替えがワンクリックでできるようなアプリケーションを探すか、C++で作っておくと便利なのかも。

あと何故かAppleのキーボードから#を打とうとすると£ってなる。不思議!

参考サイト

Apple製キーボードをWin環境で快適に使うドライバ=3つ » New! Mac Trouble Hunter ~Macのトラブル解決
http://lovemac.moe.in/mac_hunter/?p=535

コンピューターに USB キーボードを接続したときに Windows で正しいキーボード レイアウトが使用されないことがある
http://support.microsoft.com/kb/927824

astah* UML + DoxygenでC++のクラス図を自動生成 @Mac

C++コードレビューに向けてクラス図を作ろうと思い、astah*とDoxygenの力を借りて作ってみたので、その方法をまとめとく。

公式サイトにも詳しい説明があるのだけれども、Windows環境のことしか書いてないのでMac環境でのやり方をここに書くよ。
あとC++のクラス図の生成のやり方しかトライしてないので、他の言語でのやり方は分かりません!

準備するもの

  1. Mac
  2. astah* UML
  3. Doxygen(Doxygen GUIがあると便利)
  4. コード(今回はC++)

環境

astha* UML

astah* UMLは、UMLモデリングツールastha* communityの機能強化版。商用
30日間使用できるけど、有料だからそこんとこ注意。1ライセンス5,250円で、1年ごとに更新が必要がある。これは安いのか高いのかよくわからんが、定期更新する必要があるのはちょっと辛い。

UMLは、Javaのコードをリバースエンジニアリングしてクラス図を作ってくれる機能を持っているらしい。
C++Doxygenが無いとクラス図の生成はできないっぽい。C++のコードをリバースエンジニアリングするためのプラグインはあるにはあるんだけど、どうなんだろ。もうちょと調べてみる必要がありそう。

インストール

公式サイトの製品 > astah* UMLのページからダウンロードできる。
URL:http://astah.change-vision.com/ja/product/astah-uml.html

で、ここがとても重要で、Mac OS X用をダウンロードするのではなく、Linux用のをzipでダウンロードすること

理由として、

  • なぜかMac版にはクラス図生成までの過程に必要なjarファイルが色々と無い
    • jarファイルへのパスが間違ってるというより「存在しない」
  • Linux版だと全部入ってるからそっちのほうが良い
    • Mac OS X版をインストールした後、必要なjarファイルだけ移してもいいかも

追記:Mac版にもjarがあるとのことをコメントにて教えていただいたので、そっちの解説も加えます。

astah* UMLのダウンロードページに飛んだら、
Mac版のdmgか、Linux版のzipをダウンロードしてください。Mac版の場合、修正箇所が2点あるので注意。

Mac版の場合

ダウンロードしたdmgを開いて普通にインストール。おそらく「/Applications/astah UML/」にインストールされているはず。
確認できたら、astah UMLディレクトリ以下の「/api/sample/sample_doxygen_cplus」に移動。

% cd /Applications/astah\ UML/api/sample/sample_doxygen_cplus/ 

その後、compile.shとrun.shを編集して、以下の様にする。今回の環境だと両方とも8行目。

# ASTAH_HOME=../../../ 変更前 
ASTAH_HOME="../../../astah UML.app/Contents/Resources/Java" # 変更後

これでMac版はおっけー。

Linux版を落とした場合

zipのダウンロードが終わったら解凍したディレクトリastah_umlを適当な場所に置きましょう。
俺は「~/Developer」に置いた。

Linux版は解凍したのをわかりやすいところに置いとけばおっけー。

Doxygen

Doxygenは、javaでいうdocを作ってくれるアプリ。

これ単体だと無理だけど、Graphvizと併せて使うとクラス図や参照関係を図で出力してくれるから便利!

インストール

方法は2つ

MacPortsを使う
% sudo port install doxygen

注意しなければいけないのは、この方法だとDoxygen GUIが付いてこないこと。
下の公式ページからダウンロードしてインストールしたほうが良いと思う。

ただ、MacPortsを使うとクラス図とか出力する際に使われるGraphvizが自動でインストールされるので便利。

公式サイトからダウンロード

ダウンロードページへのリンク:http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc
今日付けでSnow Leopard用みたいなこと書かれてるけど、Lionでも大丈夫。

設定

一応パスが通ってるか確認しましょう。

% which doxygen
/opt/local/bin/doxygen
GUIを使う場合

astah*の公式サイトに載ってるのでそちらを参照した方がわかりやすいかも。
http://astah.change-vision.com/ja/feature/cpp-reverse.html

こっちのほうがオススメ。Doxygenの設定ファイルを自力で編集しても良いけどね!

GUIを使わない場合

ソースの置いてあるフォルダで、

% doxygen -g [ConfigFileName]

と入力してまず設定ファイルを作る。
ファイル名が空だとDoxyfileという名前で設定ファイルが作られるが、俺は.doxyrcとした。

次にこの設定ファイルをvimなりで開いて編集する。

絶対に変更が必要な箇所は、3点で以下のようにする。

GENERATE_XML = YES #デフォルトではNO
RECURSIVE = YES #デフォルトではNO
MACRO_EXPANSION = YES #デフォルトではNO

RECURSIVEが無いと設定ファイルの置いてあるディレクトリしか探索してくれないので、RECURSIVEをYESにしておくのは必須。
GUIだとOptimize output C++の項目があるんだけど、GUI経由で設定ファイルを作っても該当する項目は見つからないのでデフォルトでそうなってるんだと思う。

状況に応じて変更したほうが良い箇所は、

DOXYFILE_ENCODING = UTF-8
INPUT_ENCODING = UTF-8
PROJECT_NAME = "My Project"
OUTPUT_DIRECTORY =

文字コードはコードの文字コードといっしょになるように気をつけないといけない。

不要なファイルの生成を防ぎたいなら、以下のようにする。

GENERATE_HTML = NO #デフォルトではYES
GENERATE_LATEX = NO #デフォルトではYES

これをやらないと今回は必要ないものまで出力されるので今回はNOでいいと思う。
普通にDoxygenだけ使う場合はGENERATE_LATEXだけNOにするのがオススメ。

編集が終わったら保存して、

% doxygen [ConfigFIleName]

と打ってちょっと待てばxmlというディレクトリが、設定ファイルの置いてあるディレクトリ内に作られるはず。

このxmlディレクトリへのパスは後で使うのでメモっておこう。

これでDoxygenの準備はおっけー。

クラス図を作成

あとちょっと。

astah*で開けるようにxmlファイルをコンバート

まず、「/Applications/astah UML」に移動(Linux版の場合は、さっき解凍したastah_umlディレクトリ)以下の「/api/sample/sample_doxygen_cplus」に移動する。

# Mac版の場合
% cd /Applications/astah\ UML/api/sample/sample_doxygen_cplus/

# Linux版の場合
% cd ~/Developer/astah_uml/api/sample/sample_doxgen_cplus/

そしたら、そのディレクトリ内にあるcompile.shとrun.shの2つのファイルがあると思うので権限を705に変更する。

% sudo chmod 705 compile.sh run.sh

変更が終わったら、compile.shを実行。

% ./compile.sh

追記:Mac版だとsudoが必要かも。
文字化けでなんか警告っぽいのがでるかもしれないけど、doxygen_cplus以下のjavaファイルがコンパイルされてclassファイルが生成されていればおっけー。

classファイルができてることを確認したら、run.shを実行する。

% ./run.sh [XmlFolderPath] [OutputPath]

追記:Mac版だとsudoが必要かも。
第一引数にはさっきメモったxmlディレクトリまでのパス、第二引数には生成されるファイルのパス。
自分の環境の場合は以下のような感じになる。

% ./run.sh ~/Developer/workspace/TestProject/src/xml ~/Developer/workspace/TestProject/src/converted.asta
Importing... please wait..
Import Done.

converted.astaのconvertedは自由だろうけど、.astaにしておくとそのままastah* UMLで開けるので便利だよ。

上みたいにImport Done.って出ればコンバートは成功!

astah* UMLでクラス図を作成

あとは、今作られたファイルをダブルクリックして、astah* UMLで開いてワンアクションするだけ!

具体的には、下の画像のようにコンバート時に生成したファイル名のとこで[右クリック]→[詳細クラス図を自動生成する]でおっけー!
f:id:Silent-Bob:20120712153105p:image:w100

そうするとこんな感じにクラス図が生成されるので、あとはいらないクラスとかを間引いて全体を整えましょう。
f:id:Silent-Bob:20120712153139p:image:w100

間引いたあとにメニューバーの[整列]→[全図要素の自動レイアウト]を選ぶと再配置されるよ。

まとめ

astah* UMLDoxygenを使った、C++プロジェクトのクラス図の生成方法について書いた。
この2つを使うと結構簡単にクラス図ができてイイね!
astah*を使えば後から間引いたり配置の調整ができたりするので見やすさも整えやすいってのもイイ。

DoxygenGraphvizを使ってもクラス図を作ることはできるけど、
これは後から要素位置の調整ができないし、何より全体のクラス図の生成は作ってくれなかった気がする(選択したクラスの周辺だけ)。

全体のクラス図を作りたい時はastah* UML + Doxygenが良いのかも。
Doxygen + Graphivizもdoc生成ツールとして優秀なので、活用しましょう。

以上。


他にもクラス図を自動生成してくるようなアプリがあったら誰か教えて下さい。

C++の変換コンストラクタについて

C++を勉強してると、ふとした拍子に「何故?」となることが多いので、今日から定期的に書いてくよ。

はじめに

今日は最近あった何故の一つ、変換コンストラクタについて。

class mystring{
private:
    char* str_;
public:
    mystring(const char*str);
    ~mystring();
    const char* toChar() const{return str_;}
}

こんな感じに書いていたときに、

mystring str = "hogehoge";

と何気なく、書いたコードがコンパイルを通り疑問に思ったがきっかけ。

ちょっと調べてみると、原因は、コンストラクタと、その引数に関わっていることが判明した。

どうもある条件が当てはまるときに暗黙的にコンストラクタが呼び出され型を変換してくれることが分かった。

この暗黙的に呼ばれるコンストラクタは「変換コンストラクタ」と呼ばれており、そのことに関してちょっとここにまとめておく。

変換コンストラクタの例

以下の状態のコンストラクタは、変換コンストラクタとして扱われる

  1. コンストラクタの引数が1つである(2つ目以降が引数省略可能なら複数あっても大丈夫)
  2. explicitがコンストラクタについていない
class mystring{
public:
    mystring(const char* str);          //A
    explicit mystring(double d);      //B
    mystring(int i, int length = 0);   //C
    mystring(const char* str1, const char* str2);//D
}
// ....
mystring str = "hoge"; //A ○ 暗黙的な型変換が行われる
mystring str = 1.23;   //B ☓ explicitによる暗黙的な呼び出し禁止
mystring str(1.23);     //B' ○  明示的な呼び出しなら大丈夫
mystring str = 123;    //C ○ デフォルト引数があるため
mystring str = "huga";//D ☓ 引数が2つ以上あるため
explicitとは

explicitとは、「このコンストラクタの暗黙的な呼び出しを禁止する」ということ。
つまり、explicitを付けて宣言しておくと、そのコンストラクタは明示的な呼び出ししかできなくなる。

=に関して

ここでの「=」は、代入演算子ではない。
mystring str = "hoge";は、mystring str("hoge")に変換されているだけで、
operator=(const char*)がこのときに呼ばれることは無い、とのこと。

利点と欠点

この暗黙的に型変換をしてくれるのは、とても便利に見える。
特に上のような型の場合だと、

mystring str = "hoge";

ができるなんて、ああ、なんて理想的なんでしょう。

この変換コンストラクタがやっかいだ、となるのは、引数の型にそのクラスを使った時だと思う。

//宣言側だと何も問題無い
void setString(const mystring& str);

//それを呼び出す側で困惑する
hoge.setString(123);//これが普通に通るなんて、ああ、なんて恐ろしいのでしょう

まとめ

上のように、型変換コンストラクタを使うと(勝手に使わされているだけかもしれないが)、
呼び出す側は、型変換コンストラクタを持つクラスが、引数の型であることを意識せずに使える。
逆(?)に言うと、使えてしまう

これはその関数名にも依るだろうけど、俺は嫌な感じしかしない。

上のmystringであれば、せいぜいAのみを変換コンストラクタとして扱い、他はexplicitを付けておいたほうが安全なのかな。