イギリスの政府通信本部(GCHQ)が現在採用活動の一環として、「Can you crack it?」と題して暗号解読クイズページを公開しています。
イギリス人であればこれをクリアするとエントリーフォームからエントリーできるみたいです。
で、先日大学の友達と相談しながらクリアしました。
実はこれ、表示されてる問題をクリアしたと思ったらstage 2 of 3が出て来ます(笑)。
面白かったので、解答までの流れをブログに書きたいのですが、期日まであと1日ちょっとあるので、その後にします。
イギリスの政府通信本部(GCHQ)が現在採用活動の一環として、「Can you crack it?」と題して暗号解読クイズページを公開しています。
イギリス人であればこれをクリアするとエントリーフォームからエントリーできるみたいです。
で、先日大学の友達と相談しながらクリアしました。
実はこれ、表示されてる問題をクリアしたと思ったらstage 2 of 3が出て来ます(笑)。
面白かったので、解答までの流れをブログに書きたいのですが、期日まであと1日ちょっとあるので、その後にします。
前回の投稿と打って変わって組込系の話題を。
最近STM32でCANとか使っているのですが、時々送信に失敗してしまうという問題がありました。
たまになので問題ないのですが、気になったので調べてみるとSTMicroが用意しているSTM32F10x standard peripheral libraryのバグでした。バージョンは04/16/2010 のV3.3.0と古いやつですが。
具体的に言うと、現在送信しようとしているメッセージの状態を確認する関数
CAN_TransmitStatus にあります。
ここでは CANxのTSRレジスタのTSS_RQCP0、TSR_TXOK0、およびTSR_TME0ビットの値を見て、
CANTXPENDING(送信中)、CANTXFAILED(失敗)、CANTXOK(成功)を返しています。
が、こんな風にレジスタにアクセスするようなコードになってます。
switch (TransmitMailbox) { case (0): state |= (uint8_t)((CANx->TSR & TSR_RQCP0) << 2); state |= (uint8_t)((CANx->TSR & TSR_TXOK0) >> 0); state |= (uint8_t)((CANx->TSR & TSR_TME0) >> 26); break; case (1): state |= (uint8_t)((CANx->TSR & TSR_RQCP1) >> 6); state |= (uint8_t)((CANx->TSR & TSR_TXOK1) >> 8); state |= (uint8_t)((CANx->TSR & TSR_TME1) >> 27); break; case (2): state |= (uint8_t)((CANx->TSR & TSR_RQCP2) >> 14); state |= (uint8_t)((CANx->TSR & TSR_TXOK2) >> 16); state |= (uint8_t)((CANx->TSR & TSR_TME2) >> 28); break; default: state = CANTXFAILED; break; }
これでは、レジスタに3回アクセスしてしまっており、アクセスとアクセスの間でレジスタの値が変わってしまうと変なstatusになってしまいます。その結果 default で CANTXFAILED がセットされてしまうというのが送信失敗の原因です(実際にはこの瞬間に成功しているが、失敗したと判断してしまう)。
最も修正量の少ない解決策は簡単で、CANx->TSRの値を一旦変数に入れてやればいいのです。
uint32_t _tsr = CANx->TSR; switch (TransmitMailbox) { case (0): state |= (uint8_t)((_tsr & TSR_RQCP0) << 2); state |= (uint8_t)((_tsr & TSR_TXOK0) >> 0); state |= (uint8_t)((_tsr & TSR_TME0) >> 26); break; case (1): state |= (uint8_t)((_tsr & TSR_RQCP1) >> 6); state |= (uint8_t)((_tsr & TSR_TXOK1) >> 8); state |= (uint8_t)((_tsr & TSR_TME1) >> 27); break; case (2): state |= (uint8_t)((_tsr & TSR_RQCP2) >> 14); state |= (uint8_t)((_tsr & TSR_TXOK2) >> 16); state |= (uint8_t)((_tsr & TSR_TME2) >> 28); break; default: state = CANTXFAILED; break; }
こんな風に。
で、最新のV3.5.0ではちゃんと修正されてました。
switch (TransmitMailbox) { case (CAN_TXMAILBOX_0): state = CANx->TSR & (CAN_TSR_RQCP0 | CAN_TSR_TXOK0 | CAN_TSR_TME0); break; case (CAN_TXMAILBOX_1): state = CANx->TSR & (CAN_TSR_RQCP1 | CAN_TSR_TXOK1 | CAN_TSR_TME1); break; case (CAN_TXMAILBOX_2): state = CANx->TSR & (CAN_TSR_RQCP2 | CAN_TSR_TXOK2 | CAN_TSR_TME2); break; default: state = CAN_TxStatus_Failed; break; }
一度でアクセスするようになってます。でも返値変わってて、最新版に置き換えるのは大変そう…
今回はSSL(https)を使えるようにするような設定をnginxにしてみようと思います。
本来はSECOMやVeriSign等に有料で証明してもらうのですが、今回は以前にも紹介したCACertを載せときます。
ということで、証明書の取得は省略します。とりあえず、サーバーの秘密鍵 server.key と サーバーの証明書 server.cer が手に入った事にします。
nginxでの設定は簡単で、既存の設定をコピーして、80番ではなく443番に変更し、SSLを有効にしてサーバーの鍵・証明書のファイルを指定してあげるだけです。
ちょっとその部分だけ書いてみます。
server { listen 443 default_server ssl; server_name _; ssl_certificate /keys/server.cer; ssl_certificate_key /keys/server.key; location / { この辺は適当に } }
リバースプロキシとしてnginxとして使っている場合も同様です。
ドメイン名を複数つかってバーチャルホストを使っている場合もあると思います。SSLではアクセスされたサーバー名がわかる前に証明書を渡さなければならないので、名前ベースのバーチャルホストでSSLは利用できませんでした。
が、SNI(Server Name Indication)というプロトコル拡張ができたので、名前ベースのバーチャルホストでも可能になりました。(ブラウザによっては対応してません)
設定は簡単で、httpと同じくserver_nameを設定するだけです。
リバースプロキシとして使っている場合は、証明書を変えるために、バーチャルホストの数だけServerディレクティブを作ってあげてください。
(多分)一般的なWebサーバーであるApacheは複雑な設定も可能で便利なのですが、その分重いのです。
どう重いのかというと、Apacheは一つのプロセスが一つのHTTPリクエストを同期処理で裁いてるのでその間は他の処理をしません。なので、同時アクセス数が増えるとApacheはプロセスをどんどん生成します。(あるいは後からきたリクエストを待たせる)
なので、アクセス数が増えると急激にパフォーマンスが落ちるという問題を抱えてます。(ほかにもプロセスIDが足りなくなってどんなにリソースがあっても最大プロセスIDで制限されてしまう)
で、最近話題のハイパフォーマンスWebサーバーがnginx(えんじんえっくす)です。
nginxは一つのプロセスで複数のリクエストを非同期で同時に処理します。なので、アクセス数が増えてもパフォーマンスが落ちにくいという特性があります。特に静的ファイルの場合は処理のほとんどがI/O待ちなので効果が大きいです。
そこで、PHPとかSVNとか設定がめんどくさいものはApacheに任せておいて、静的なファイルだけをnginxに処理させてみると、Apacheへのリクエスト数は激減するはずです。
例えば、このブログのトップページの場合PHPで生成されるHTMLが一個にたいして、CSSや画像等の静的ファイルが20個近くあります。単純計算で21個のリクエストのうち1個だけがApacheで処理されるのでApacheへのリクエストは約95%削減されます。
では設定してみましょう。OSはUbuntu Server 10.04(64bit)です。Apacheは既にインストール済みで運用されているとします。設定後はnginxがポート80で待ち受けて、Apacheはポート8080で待ち受けるということにします。
(記事の最後でキャッシュファイルをRAMに置くというのもやってみます)
漸くわかりました。PHPを速くするのは限界があるみたいで、生成したHTMLをキャッシュしとくしかないみたいです。
で、Quick Cacheプラグインをインストールして有効にすると改善しました。
レイテンシ12ms、転送4msです。
ハードウエアのスペックでごり押しはだめですね。ちゃんとキャッシュできるところはしましょうってことです。
さっきの投稿でWordPressが遅い事を書きました。で、先輩のさくらのVPS(nginx+fastcgi)では速いってことも書きました。
ということで、僕も借りてるさくらのVPSで一からセットアップして実験してみました。OSはデフォルトではなくUbuntu 10.04が入ってます。
今回検証したのは、WebサーバーはApache/2.2.14とnginx/1.0.9、RDBMはMySQL(Ver 14.14 Distrib 5.1.41, for debian-linux-gnu (x86_64) using readline 6.1)とPostgreSQL/8.4.9です。なので、合計4通りですね。
Apacheではmod_phpで、nginxでは後ろでspawn-fcgiが動いてます。
で、試してみた結果です。今回検証したいのは静的ファイルではなくPHPの出力なので、画像とかCSSがブラウザでキャッシュされてたりするのは気にしないでください。
平均もとってない1回こっきりのアクセスの結果なので互いの比較はそんなに意味がないです。
が、どれもレイテンシが数百ミリ秒あります。これは何回試しても同じでした。
あれ?…
先輩のVPSと同じ環境のはずなのになんでこんなに違うの?
最近サーバーの設定を変えたり、リバースプロキシをしてる、HTTPのフロントをApacheからnginxに変えたり高速化を試みています。
が、どうしてもこのブログ(にかぎらず、稼働しているWordPress全部)が重い、というより遅いのです。
Memcachedでオブジェクトをキャッシュしてみたりしても改善されず…
で、Safariで開発ツールの「ネットワーク」をつかって取得の時間を見てみました。
ここでPHPのファイルへのアクセスのレイテンシが334msもあることに気づきました。稼働しているどのWordPressもです。
で、WordPressはそうなのかと、さくらのVPSで運用してる先輩のWordPressを見てみると…
速い….レイテンシ45msです。静的ファイルはうちのサーバーのほうがレイテンシ含め速いので(どちらも304なので比較していいかな)、ネットワーク等の問題ではないみたい。
(あと、向こうはnginx+fastcgi(swanかな?)+WordPressですが、うちでもnginx+fastcgiにしてみたけど改善せず…)
なんで?
とりあえず、僕も借りてるさくらのVPSでDBをMySQLからPostgreSQLにしてみたり、いろいろ実験してみます。
前回に引き続き、今回はProFTPdをセットアップし、MySQLのテーブルに記録されたユーザー情報で認証できるようにします。
まずはProFTPdのセットアップから。proftpdをapt-getでinstallするとproftpdの設定画面が出ます。
固定IPではないのでIPマスカレードを利用しないといけませんが、そのためにもスタンダードアローンではなくinetd経由にします。
それでは /etc/proftpd/proftpd.conf を書き換えていきます。
ここまではMySQLによる認証は関係ありません。これからMySQLで認証するための設定を追記します。この部分は「にわか鯖管のメモ – ProFTPD ~ MySQL + quota 編 ~」をもとにというかそのまま。
注意点はmodule.confをいじったときは sudo /etc/init.d/proftpd reload をしないとだめってとこです。
今日からUbuntuでレンタルサーバを構築するまでの記録を載せようと思います。まぁ気力が続けばですけど。
それと、メモみたいなもので解説はたぶんしないとおもいます。LinuxをCUIで使えるぐらいの知識がないともしかすると読めないかもしれないです。解説でなく日記ですね。
レンタルサーバといっても身内、友人、後輩などに貸してるだけですのであまりセキュリティ、特にユーザー間のセキュリティはよろしくない設定をしていくかもしれませんのでそういう意味でもあまり当てにはしないでくださいね。
で、なぜいまさらサーバー構築なのかということなのです。普段はMac OSX Serverの上でこのページ含め個人のサーバと上記のレンタル部分とを稼動させているのですが、いわゆる公私混同の部分の管理がめんどくさくなってきた(なんとなくしんどくなってきた)ので他人の分は仮想環境のUbuntuに移動させてしまおうと思い立ったわけです。
で現状は、Ubuntu 10.04 ServerをLAMP + SSHのみでインストールしたまでです。
このあとユーザー情報をMySQLで管理してユーザーごとにApacheのバーチャルホストを設定し、proftpdはMySQL上の情報で認証できるようにしていくことが目標です。
だいぶ紹介が遅くなってしまいましたが、大変便利な本なので紹介します。
いまAVRとともにメインで使おうとしているSTM32ですが、とっつきにくい原因としてはその莫大な周辺機能のせいで分かりにくいレジスタ。これはライブラリが用意されていているのですが、今度は資料が少ないためどうやって使えばいいのかわからない、ということにあると思います。
事実コンパイルして動作させるまでにかなりの時間を要しました。(ストロベリーリナックスで用意されているサンプルをmakeするだけならできたが動作原理が捉えにくかった)
それを解決する本が徹底マイコン入門(http://miqn.net/)です。実はかなり前に作者の方から相互リンクのお誘いを頂きリンクしておりました。
1ヶ月ほど前からホームページで90日間原稿全てをPDFで閲覧できる企画をなさっているので早速申し込みさせていただき、一ヶ月ほどこの本を頼りにSTM32をいじってきました。
プロジェクトの関係でなかなか時間が取れずレビューを書く事が遅れてしまいました。
で、この本の良いところはマイコン初心者に対しても細かな説明がされており、基礎から学習する(C言語はあるていど理解できているレベルから)のにも対応でき、さらに使いこなすようになってからもリファレンスとして使いやすい構成になっている点です。なかなか両方に対応するのは難しいところですがどちらから見ても便利だと思います。(特に後者については体感しました)
しかも、CANなどのマイナーどころはないにしてもSTM32のほとんどの周辺機能をカバーしており、さらによく使われるモジュール等(i2c液晶、フルカラー液晶やEEPROMなど)、の解説もありすごく便利です。
(かなりニッチな要望ですがCANの解説も欲しいです!)
是非とも発売されたときには部室と自宅に一冊ずつ欲しいなぁと。
近々STM32で作ったライントレーサーの動画をアップします。初めてPID制御にチャレンジしたのでかなりなめらかな動きとなっております。