2013年1月14日月曜日

リアルタイムのEthernet通信はないか?

複数の計算機を並列で動かしていると、複数の計算機間で「同期をとって」通信をしたくなります。現状、主流のWindowsやLinuxではEthernetが非常に安価で高速なんですが、いかんせんCSMA/CDというでたとこ勝負の通信方式のため、この「同期」のためのリアルタイム性が保障されていません。(そのかわり、「安価」で非常に頑丈な通信システムにできています)ただ、やっぱ10~20台程度の計算機を並列で動かすとき、リアルタイム性の欲しいシステムを作りたいときがあります。2~4Hz程度なら普通のTCP/IPでもなんとかごまかせますが、10Hzでも怪しくなります。(たまに抜けてもいいというならいいんですが、1個のパケットも抜けちゃダメ!と言われるともう保障できません。数時間くらいならいけると思いますが、たいていそういう要求するシステムは計測のログ収集が目的なんでダメです。

こういう時は、やはり昔IBMが出してたToken-Ring方式が確実です。でも性能-コストの関係でかなり初期の段階でEthernetに負けてしまいました。こうなると物理層はEthernetでTokenとばす通信スタックはないもんかと思って探してみたんですが、同じこと考える人がやはりいました。目的が産業用のセンサーやモーター制御のためなんですが、Ether CatとEthernet/IPというのがありました。どちらも一応Openな規格をうたってるんですが、詳しい仕様は会員にならないと入手できないようです。また参考実装もなく、見つかったのは商品のソフトウェアだけでした。(Ethernet/IPはSourceforgeに通信ソフトがあったんですが、使い方が全然わからない。おまけに、windowsのCygwin環境に調整してあるようで、そのままではLinuxでビルドもできない)もうちょっと頑張ってみますが、簡単にわかった仕様をメモしておきます。

1.Ether CAT
文字通り自分の考えてた構想をそのまま実現してます。TCP/IPの通信スタックをまるきり置き換える感じで、Token飛ばして通信するようです。(イメージ下図)


通信のトポロジーは図のようなものだけでなく、通常のツリー型だろうがサポートするとはありましたが、基本的には図のようにMasterからTokenとばして、端のRepeaterでそれを折り返すという感じです。さすがにこの形態なので反応速度は速く、通信量にもよるんでしょうが、100us以下で通信できるとのことです。(通信帯域も80%くらいは使いきれるとのこと)
ただ文字通り産業用機器の通信のようで、専用のI/Fカードとか使います。(通常のEhternetカードでもいけそうなのもありましたが、基本はセットで販売という感じでした)

2.Ethernet/IP
これはTokenとかは特に使ってないようで、UDPで通信するようです。(ただTCPでもできるとあり、その場合のリアルタイム性どうするんだ?という気はしますが)TCP/IPの通信スタックは既存のものを使い、アプリケーション層でなんとかするというタイプです。そのため、通常のLANも使いながらでもOKらしいんですが、その場合のリアルタイム性の保障はどうするんだ?という不安はあります。そのため、リアルタイム性もぐっと落ちて数10msオーダーの反応速度です。(自分的には産業用の機器制御するつもりはないんで、それで十分なんですが)


調べてたら、オムロンとかキーエンスとかのHPが普通にひっかかり、自分は専門外で知らなかったんですが、結構使われてるんでしょうか?(Ethernetは昔から光ファイバーがありましたから、工場等の雑音が多いところでもその気になれば安定して通信できますから、下手に専用の通信機器作るよりは高速で安価にできそうな気もします)

2013年1月5日土曜日

Androidプログラム開発-ファイル入出力

プログラムを移植するのに、あと一つ乗り越えないといけない壁があります。「ファイル入出力」です。

計算結果をログとしてstorageに出力したいですし、各種設定データをファイルとして読み込む必要があります。またそれらは、Android端末をUSB接続したときに簡単にアクセスできる場所がいいです。
試しに従来のJavaプログラムで作成した簡単なログ書き込みのプログラムを移植してみようとしたら、「そんなクラスはない!」と怒られてしまいました。Android用のiostreamじゃなきゃだめだということが確認できたので(事前に予測はしてました)、ググってみるとどうしてもファイルエクスプローラのアプリ紹介のページにいってしまいます。キーワードを考えて、やっと見つけました。
ファイル出力の方ではFileOutputStreamを使い以下の様なメソッドだとか。

outputStreamObj=context.openFileOutput( )

ところでこのcontextなるインスタンスは何者?ページをよく読むと、Androidプログラムの本体のインスタンスらしく、これを使うと/data/data/(パッケージ名)以下のパスしか指定できないとか。ここ普通のファイルエクスプローラではPermissionがありませんといって、見ることすらできません。(jail breakして、root化すればいけますが、そもそもUSB接続して簡単に参照したいのでそれでは困ります。)
さらに調べると、普通のjava.ioパッケージでもできるとの情報がありました。これならフルパスでファイルを指定できますが、ことごとくPermission denyで怒られます。セキュリティがガチガチですね。
USB接続して簡単にアクセス、というのが目標なので/sdcard以下にファイルを作ろうとしたんですが、そもそもeclipseに”/sdcard”のパスを直接コードするんじゃありません、と注意される始末。調べてみると、以下のメソッドを使いAndroid端末に合わせたパスを取得しろとのこと。

String str = Environment.getExternalStorageDirectory().getPath();
writeFile(str+"/Documents/log.csv","abcdefg","UTF-8");

Environment自体はstaticで定義されていますから、当該パッケージをimportするだけでそのまま使えます。上記ではとりあえずDocuments以下にファイルを作成してみました。
さてこれでいいだろうと思ったら、まだPermissionがないと怒られます。再度、ググった結果当該パッケージのManifest.xmlに以下の記述が必要なのだとか。(デフォルトではファイルアクセス禁止のプログラムしか作れないんですか Orz)

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


Manifest.xmlのどこに記述したらいいのかわからなかったので、そこはeclipseのUIにおまかせしました。(結果見ると、自前でタグ定義しているんでどこでもよさそうです。)

これでやっと準備ができたと思います。(移植しようと考えてるJavaプログラムのファイル入出力のモジュールをAndroid用に修正しないといけません)

追記:
ところで実際にAndroid端末(Nexus7を使ってます)をUSBでPCと接続し、先ほどプログラムで作成したファイルを見てみようとしたんですが、なんと見えません!Nexus7のファイルエクスプローラ・アプリでは確かにファイルが存在しいるんですが、PCではファイルが表示されません。同じディレクトリにある別のファイルはNexus7でもPCでも見えるんですが。。。
またまたググって、しかし今回はどんなキーワードで検索したらいいのか思いつきません。結構時間がかかりましたが、原因と思えるものが見つかりました。

・MTP(メディアデバイス)
Nexus7の設定みているとUSBストレージという名称じゃない別の名称のMTPで接続というのがあります。これは従来のUSBストレージだとUSBスティックのようにFATでファイルシステムを作り、それをPCから参照します。これって考えると結構危険です。Nexus7側のアプリが開いているファイルでもPCから修正できちゃうことになりますから。なのでMTPは一種のネットワークドライブのようにPCからは見せて、ファイルシステムとして認識しなくてもいいようにします。(Android3.1からこの機能がついたようです)
端末によっては従来のUSBストレージによる接続も残しているようですが、Nexus7では見当たりませんでした。(まあAndroidを主導しているGoogleとしては、新しい方式にして欲しいだろうし)

・マルチアカウント
最新のAndroid4.2.1からでしたか、マルチユーザーの機能が付加されました。当然、ファイルシステムだってその影響がでます。具体的には外部ドライブだろうが、各ユーザーが使えるエリアはユーザーアカウント毎に用意されています。具体的にいうと以下のような感じになるそうです。

/sdcard/0/Documents等

数字のところがユーザーに割り振られた番号で(UIDのようなものです)、各ユーザーごとに番号が振られます。つまりNexus7に異なるユーザーで使っていると、他人のユーザーの外部ストレージは見えません。(セキュリティ上のためもあります)更にいやらしいことに、上記の数字よりTopの"/sdcard"というのもAndroidの実装まかせで固定していないんだそうです。(いやこれは強制しようよ、Googleさん)それを回避して一つのアプリで複数の機種に対応するため、/sdcard/0までを取得するメソッド(getExternalStorageDirectory())が用意されたそうです。

さてここまで調べて、ファイルが見えなかった理由の推測ですが、Android4.0になってからでしたっけ、明示的なタスク管理のタスクマネージャーがなくなりました。そのため、試験的に作成したプログラムが停止していると思っても、実は裏でファイルハンドルをつかんで離さないから、PC側からは見えないんではなかろうかと。確実に確認するためにNexus7を再起動して、PCに接続すると無事プログラムが作成したファイルを見ることができました。(設定→アプリケーションで選択して強制終了してもいいと思います)


2013年1月4日金曜日

Androidプログラム開発-数値の入力

久しぶりに、Androidのプログラム開発(あえてアプリとはいいません。個人的に楽しむのが主目的なんで)をしてみました。

Javaで少し計算プログラムを作ってたんですが、それをAndroidに移植したくなりました。Javaプログラムの時はGUIも作ってみたんですが、計算諸元の設定は基本ファイルか、プログラムに直にコーディングで済ませてしまっていましたが、さすがにAndroidプログラムではそれはまずかろうと、GUI作って、その入力部分の作成からです。

Android開発環境ができていれば、GUI部分の開発(?)は簡単です。

(ラベルのところはあえて消してあります。ご容赦を_(._.)_)
ところで、このプログラムはAndroid4.0.3以降(API15)でプロジェクトの作成をしたんですが、昔はあった記憶のあるラベルwidgetがありません。しかたないので、Text widgetを貼り付け、初期の文字列を設定します。(activity_main.xmlに直に文字列書くと、eclipseがwarning出してくるので、面倒くさいんですが、文字列定義はstring.xmlを使うようにしました。多国語対応が簡単にできるようになんでしょうが、どうせ日本語しか作るきはないので無視してもいいんですが。)

1.ラベル相当が作れない
Textでラベルを作ろうと思っても、デフォルトは編集可能です。これをなんとか編集不可にしないといけません。調べてみると、当該widgetのandroid:editableという属性を"false"にすればいいらしいんですが、非推奨ということでeclipseではwarningがでてきます。それじゃどうしたらいいかというと、android:inputTypeで設定しろとのことですが、入力不可の"none"にしても(画面上では)編集はできてしまいます。どうしてもいい方法が見つからず、あきらめてandroid:editable属性をactivity_main.xmlで定義しました。(ただこの方法だと非推奨なので、warningはでます。)

2.(数値の)入力
これが一番苦しみました。widget自体はEditTextで作成すればいいんですが、ここで(符号付)数値のみの入力に制限しようとしますが、なかなかうまくいきません。関連したのは以下です。

number:数値入力する場合に指定します
numberSigned:符号付数値を入力する場合に指定します
numberDecimal:少数入力する場合に指定します

色々試してみましたが、numberSigned|numberDecimalがよさげです。(numberだと小数点が入力できません)
続いてこれの読み取りですが、結局以下のような感じになります。

double ldlat;
EditText latText=(EditText)findViewById(R.id.editLat);
String input=latText.getText().toString();
ldlat = Double.parseDouble(input);

文字列で入力された数値をdouble型に入れたいんですが、結構面倒でした。int型等それぞれparse関数があります。方法を見つけるのに時間がかかったのが、EditTextからgetしてくるとき、どうやってString型にするかでした。それさえわかれば、あとは簡単でした。

本来の作業はこれからですが、入力さえ解決してしまえば後は単純作業です。(問題になるとしたら、Android端末側のCPUパワーやメモリ等のリソースからくる制限でしょうね)

2013年1月2日水曜日

Clangのこと

FreeBSDのデフォルトCコンパイラがLLVM Clangになったとのこと。
従来のgccを2012年11月のFreeBSD 10-Currentから替えたそうです。(もっともgccをデフォルトで使う設定も残されます。完全に互換性がなく、まだgccでないとビルドが通らないものがあるそうです)

なんでこんことをメモしたかというと、gnuの新しいライセンスGPLv3が色々と物議を醸している影響です。実際、LinuxのkernelもGPLv2のままでGPLv3への移行はしないと決定したと聞いています。問題なのが、GPLv3に入れられた条項で、特許を放棄しろというような項目があるんだそうです。わかりやすくいうと、GPLv3を表明しているgccでプログラムを作成すると、当該プログラムは特許を放棄することが要求されるようです。(このあたり解釈が難しいらしい。完全強制するという表現ではないようです。ただ企業としてはいやですよね。)
このところライセンスよりも、企業の利権を守るために特許でさんざん争われてるため、copyleftだけでは自由なプログラムの実現が困難だと考えたんでしょうね、Richard Stallmanさん。ちょっと過激すぎる気もします。(でもLinux kernelはgccでビルドされてたはず。そのあたり完全な強制力はないのか、あるいはLinux kernelは今後GPLv2のgccでしかビルドしないのか、よくわかりませんが)

それでBSDライセンスのLLVM Clangが注目されてるんだそうです。しばらくは、gccのライセンスやら、GPLv3がどうなるのか見てないといけません。(確か、GPLv3の文言決めて公開するのにもずいぶん時間がかかった記憶があるから、まだ流動するでしょう。)

2012年12月31日月曜日

2012年末に思うこと

大晦日に「グーグル ネット覇者の真実」を読んでて、つい4年前に買ったGoogleの技術に関する本も読み返してます。

グーグル ネット覇者の真実

なんというかこの10年ちょっとの間に、ネットの変化(あえて進化とはいいません)のめまぐるしさを思い返してました。それと同時に考えたのが、ここ2,3年の企業や個人へのネット攻撃です。
世の中のセキュリティソフトにも色々ありますが、やっぱりproxyが一番確実だろうと思います。まだ一般的な個人ユーザにそれを提供する会社はないですが、GoogleとかAmazonがその気になったりするんじゃないかと考えてしまいました。
Googleは最良の検索サービスを提供するんだから、さらに一歩進んで「安心」まで提供を始めたりして。。。(それがさらに検索の件数を増やすだろうから)そしてAmazonは自身が販売しているKindle FireのWebがAmazonのクラウド前提のサービスらしいから、Amazon会員ならセキュリティを無料で提供、なんてサービスやりかねんなという気がしています。(その分、子供も安全にwebを使えるとか宣伝文句をうたって)

どちらも必要なコンピュータパワーを考えると気が遠くなりますが、どちらの会社もそれを可能にする基盤システム(OS、ファイルシステム含めて)を自前で揃えてます。来年末くらいにはやりそうでこわい。

ところでファイルシステムで考えたのが、これだけ必要なデータが増えると、ファイルシステムは従来のファイル名によるデータ取得のような(windowsでいうとFATテーブル)ではまかないきれなくなり、DBになるんでしょうね。(昔、windows XPのときに、M$がWinFSとかいうDBでファイルシステムを構築しようとしているという話をきき、当時のPCのパワーでは「無茶だ」と一笑に付しました。実際M$も早々にあきらめましたし。)この状況だと、このデータ量を管理しようと思うと、従来のファイルシステムでは無理ですね。(家庭用のPCでも、もう10年もたない気がする。大体、HDDの容量がTB超えてくるとメンテナンスしないとだんだん使い物にならなくなってくるけど、普通の人にはそんな感覚わからないだろうし。)

linux( Ubuntu ) 古いカーネルの削除

前もどっかでメモした記憶があるんですが、ちょっと困った状態にPCがなり調べてたら、設定やらコマンドが昔と変わってたので、一応メモ。

1.現状
ノートPC(aspire-one)はいろんな実験環境で、windows-XPにUbuntu-11、これにさらにBT5R3をインストールしたという、かなり危ない状態です。BT5R3はUbuntuベースなんで、先に入ってたUbuntu-11と特に問題も起こさず、boot-loaderは同じgrubだったのはよかったんですが、なぜかboot時のメニューリストでUbuntu-11の方が5,6個でてくる状態に・・・

2.調査
こんなときは、grubの設定ファイル(/etc/grub.d/grub.conf)を修正してやれば、と思って「そういえば、現状Ubuntuが2個入ってるけど、どちらのgrub設定で動いてるんだ?」としばし悩み、順当に考えれば、後から入れたBT5R3だろうとそちらで起動。
ところが設定ファイルが見つかりません。/etc/grub.dの下は何かのスクリプトしかない。いつからこんな風になったんだ?しばらく悩んで思い出したのが、そういえばgrubは/boot/grubにあることを。さっそくそこを調べると、何か大量のファイルがあり(以前は設定ファイルと少しだった気が)、grub.confはやはり存在しません。
それらしいのがないか見てみると、grub.cfgというのが見つかりこれだろうと中を見ると、ファイルの最初がなんかスクリプトっぽくて、その後ろにありました、起動時の選択リストのデータが。それで判明したのが、Ubuntu-11の方は何度かカーネル更新してたらしく、古いカーネルが削除されずに残っていて(でも、Ubuntu-11を使っているときはとくに起動時にメニューは増えませんでした)、BT5R3をインストール時に、ご丁寧に調べてくれて、それを全部起動時の選択リストにいれてくれていたことでした。

3.修正
さて現状の状況が把握できました。ということはBT5R3側の/boot/grub/grub.cfgを何とかすればいいんですが、このファイルはread-onlyでファイルの最初に直接編集するな、/usr/sbin/grub-mkconfigを使えとのこと。試しに起動してみると、なにもコマンド入力は要求されず、HDDの状態を自動的に調べて、起動可能なシステムを設定ファイルに列挙するスクリプトのようです。

(1)古いカーネルの削除
ということでまずはUbuntu-11の古いカーネルの削除から始めます。Ubuntu-11でシステムを起動して、以下のコマンドでインストールされているlinux-imageをリストアップします。

dpkg -l | grep linux-image

表示されてくるものは、linux-image-2.6.15-23-386だったり、linux-image-2.6.15-23-genericとかでてきますが、基本注意するのはバージョンの数字のところです。残したい最新のバージョンだけ注意して、古いものを以下のコマンドで削除します。(慎重に作業してください!間違えると、取り返しがつきません。)

sudo apt-get remove --purge linux-image-2.6.15-23-generic


(2)grub設定ファイルの更新
さてこれで古いカーネルは削除できたので、/usr/sbin/grub-mkconfig(当然、sudoつけます)でgrubの設定ファイルを更新してやればいいだろうと、そのままUbuntu-11で実行しましたが、でもここで更新されるgrub設定ファイルはBT5R3のgrubからは見えない位置・・・ ダメじゃん!
今のPCはBT5R3のgrubで起動しているはずなので、BT5R3でシステムを起動しなおして、/usr/sbin/grub-mkconfigを実行しましたが、今度はBT5R3インストール時とは異なり、Ubuntu-11のファイルシステムは調べてくれません。(-"-)
当たり前といえば当たり前の結果に暫く悩み、結局grub.cfgの手動修正を実行、無事起動時にでてくる大量のシステム選択リストはきれいになりました。


PS
その後、別のPCでも同様の問題が発生しました。よくよく調べてみると、ちゃんと以下の様にオプションを与えてあげないとダメでした。(前回は何もオプションなしでやったので、本来grub.cfgに出力される内容を画面に出力していただけで終わっていた)

> /usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg

これで異なるディストリビューションのカーネルも調べて、設定ファイルに反映してくれるようになりました。



2012年12月23日日曜日

Nexus7のアプリ開発

Nexus7のアプリ開発用に、eclipseの環境を整備していましたがその後何にもしてませんでした。せめてHelloAndroidくらい動作を確認しようと思い立ち、まずNexus7の設定を見るも、「開発者向けオプション」が見当たらない(;°ロ°) 何これ?こんなんで大丈夫なのかと思ってUSB接続してみるも、やはりデバイスが認識されていません。だいたい、USB接続するとどうしてもドライブと認識されてしまっているから、これじゃダメでしょ。ググってみて、調べて見つけました、なんというかGoogleの遊び心なのか、これくらい自分で調べれる人じゃなきゃこんなオプションを有効にしちゃだめよ、という意味なのか。昔のMicrosoftにもあった、隠し技で開発者向けオプションがでるようになり、USBデバッグモードをOnにできました。

さあこれでいいだろうと思っても、USB接続するとやはりドライブとして認識してしまい、あいかわらずeclipseからデバイスとして表示されません。再度、ググってみるとドライブとして認識するときMTPという通常のドライブ、それとPTPはカメラデバイスとして認識するようで、PTPにしないとだめなようです。ただ、それでもUSB接続するとやはりドライブとして認識されてしまいますが、今度はドライバがエラーが表示されるようになりました。

さらにググって、ASUS(Nexus7の製造メーカね)のNexus7のページをみると、USBドライバをDLできます。これをDLして、Windowsのデバイスマネージャから(ってことはMacはまた難しいかな、なんかこの展開、Galaxy S2のときと同じだな)ドライバの更新を行い、ドライバのエラーがでなくなり、無事eclipseのデバイスで認識できるようになり、HelloAndroidを実行できました。

それぞれの詳細な方法は割愛しますが、なんともあいかわらずハードルが高い・・・

PS.
ところでMac BookでのAndroid開発ですが、あいかわらずGoogle USB Deviceは非対応です。でもGoogleのHPを見てみると、MacやLinuxは自前のDevice driverでいいとのこと(でも前は、2.3の最初のときだけはよかったけど、その後の更新でダメになったけど。。。)。まあ試してみるかとやってみたら、1回目は何か問題がでてきましたが、Nexus7を一度抜いて、eclipseを再起動したらあっさりうまくいきました。安定してくれるといいけど。。。(ちなみに、そのHPにAndroid4.2からのUSBデバッグモードをOnにする隠し技が記載されてました)

PS(その2)
結局、今はWindows、Macとも安定してNexus7上にてデバッグできています。MTPも特にそのままで何も問題が起きません。当初悩んだのがなんだったのか、という状態です。しかし、実機デバッグが安定してできると快適です。なにせPC上のemulatorが起動は遅いわ、動作も遅いわでひどい状態ですから。AndroidをPC上で直接動かしちゃえというプロジェクトも進行しているそうです。