月別アーカイブ: 2015年3月

CMakeで自動生成ファイルを出力させる

あるソースコードにテーブルが配列として含まれているという状況で、メンテナンス性を高めるためにその内容を別のファイルに分離して、機械処理で配列として出力し、それをincludeするという手段を考えました。

これをautomakeで実現するのはそれほど難しくないのですが、autotools依存を避けるためにCMakeで実現する方法を調べてみました。

最終的に、以下のようなCMakeLists.txtで実現できました。

cmake_minimum_required(VERSION 2.8)

project(kakasi3)

include_directories( ${CMAKE_BINARY_DIR} )

add_library(libkakasi SHARED ${PROJECT_SOURCE_DIR}/src/kk2.c)

add_custom_command (
  OUTPUT k2rom_hepburn.c
  COMMAND perl "${PROJECT_SOURCE_DIR}/scripts/octtable.pl"
   "${PROJECT_SOURCE_DIR}/table/k2rom_hepburn.txt"
    > "${PROJECT_BINARY_DIR}/k2rom_hepburn.c"
)

add_custom_target( generate_headers DEPENDS k2rom_hepburn.c)

add_dependencies( libkakasi  generate_headers )

src/kk2.cがk2rom_hepburn.cをincludeすることを前提としています。k2rom_hepburn.cはperl scriptを通してtable/k2rom_hepburn.txtから生成します。

生成するスクリプトはadd_custom_commandを使います。OUTPUTに出力するファイル名、COMMANDに実行するコマンドを記述します。行が長くなる場合には、改行を任意の箇所で入れられるようです。

出力するファイルk2rom_hepburn.cを直接ターゲットとして扱えないようなので、add_custom_targetでgenerate_headersというターゲットを明示して作成し、その依存関係としてk2rom_hepburn.cを記述します。

最後に、作成したターゲットを依存関係へ組み込むためadd_dependencyを使います。これで、libkakasiの生成にgenerate_headersが依存することを明記しました。

以上のステップを踏むことによって、k2rom_hepburn.txtからk2rom_hepburn.cが生成された上でkk2.cがコンパイルされ、それをもとにlibkakasi.soが出力されます。

Rowhammer問題私的まとめ

確認できた範囲の情報を記録しておこうと思います。

Rowhammer問題

PC Watchの記事「DRAMスケーリングの課題と打開策」にて解説がなされています。以下当該記事より引用:

Row Hammer問題は、DRAM技術が微細化したことで深刻になり始めたメモリセル間の干渉によって発生するエラーの問題だ。 DRAMメモリセルの同じRow(行)に対する連続したアクセスが、隣接したRowのセルのデータを不安定し、エラーを生じさせる。この問題は2012年頃から話題になり始めた。Intelはメモリ制御に関する特許(Row hammer condition monitoring, US 20140006704 A1など)の中で言及した。そして、今年(2014年)6月のコンピュータアーキテクチャ学会「ISCA (International Symposium on Computer Architecture)」でRow Hammerに関する論文が発表されたことで、コンピュータ業界で広く知られるようになった。

ハードウェアについてあまり詳しくないのですが、高密度化、高速化したメモリで、特定のセル(row)に高い頻度でアクセスすると隣接するrowのメモリ内容が化ける、という現象のようです(Rowhammerの論文PDF)。

攻撃への応用

Googleのセキュリティ対策チーム”Project Zero”が、この現象を応用して攻撃に利用する、という記事を公開しました(“Exploiting the DRAM rowhammer bug to gain kernel privileges“)。応用例として、ChromeのNaClサンドボックス上で本来実行できないはずの命令を実行させたり、カーネルの権限上昇を行う手法が解説されています。

確認手段

userlandで試験を行うツールがgithubで公開されています(“https://github.com/google/rowhammer-test“)。また、memtest86 6.0.0 Free editionにもRowhammerテスト機能が追加されているようです。 rowhammer_testを実行して、実際にエラーが起きると以下のような出力をして停止します。

Iteration 11 (after 16.41s)
  32.448 nanosec per iteration: 1.40176 sec for 43200000 iterations
check
error at 0x7f032bcde188: got 0xffffffffffdfffff
  (check took 0.122344s)
** exited with status 256 (0x100)

自分はデスクトップ(non-ECC)x2、ノート(non-ECC)x1、サーバー(ECC)x1に対して実施してみましたが、以前から挙動が若干怪しげなデスクトップマシン1台でのみ検出されました。 Google Groupsにてある程度報告が上がってきていますが、発生するときは数十~数百程度の試行回数で発生するようです(上記自分の例では11回目で発生)。自分の他のマシンでは1万以上行っても問題が出ませんでした。 自分はVirtualBox環境下でこのテストに引っかかったのですが、GroupsではXen guest上でエラーを検出できたという報告もありました。Cygwinでも確認できるよそうです。

対処方法

2ちゃんねるソフトウェア板のMemtest86スレッドにてメモリアクセスに関するパラメータを試行錯誤している様子があります。

>スケーリングによってDRAMが直面する問題として
>「Refresh」、「Write Recovery Time (tWR)」、「Variable Retention Time (VRT)」の3つを挙げている。

tREFIとtREFIx9, tRFCだけでなくtWRも関係してくるわけか・・・

BIOS等でこれらのパラメータを変える、特にリフレッシュ時間(tREFI)を短くすることで改善が見込めるようです。

ところで、ちょうど今日のタイミングで2chのdatアクセスが閉じられてしまいました(窓の杜の記事:「2ちゃんねる”の配信仕様が本日より変更。専用ブラウザーの更新・乗り換えを」)。そのままでは、Debianパッケージにもなっているnavi2chJDなどが利用できない状態です。Memtest86スレッドのような貴重な情報を得られる場だけに残念です。

追記(2015/3/16)

マシンを再起動する機会があったので、tREFIを設定してみました。設定可能な最小値として800(usec?)に設定したところ、iteratin 3000を超えて問題なくテストが進んでいます(当該マシンのデフォルト値は1700ぐらい)。前回は11回でエラーが発生したことを考えると、かなり改善されているようです。割と思い処理(動画エンコード)を差せているのですが、それほど目立った性能低下も感じられません。

ruby+selenium+chromeでgmail送信

rubyのselenium-webdriverでgmailの操作を試みた結果、なんとか動くものができたのでメモしておきます。

同様のことをC#でやっている事例はあったのですが、rubyのCSSセレクタが思うように動きませんでした。結局、CSSではなくIDを指定してボタンの操作をしました。

require 'selenium-webdriver'

driver = Selenium::WebDriver.for :chrome
driver.get "https://mail.google.com/a/?view=cm&tf=1&to=nokubi@gmail.com&su=test&body=test"
sleep 10

#動かない。空白がまじっているから?
#elem = driver.find_element(:class, "T-I J-J5-Ji aoO T-I-atl L3") 

#C#のCSSセレクタ書式をそのまま入れてみたがだめ
#elem = driver.find_element(:css, "div[class='T-I J-J5-Ji Bq nS T-I-KE L3']>b") 

# div.class 形式がrubyでの書き方らしいのだけどこれもだめ
#elem = driver.find_element(:css, "div.T-I J-J5-Ji Bq nS T-I-KE L3'.b") 

# IDなら動いた
elem = driver.find_element(:id, ":pb") 
elem.click

URLはこんな感じの組み合わせでメールの内容を指定できます。

  • https://mail.google.com/a/?view=cm&tf=1& (定型?)
  • to=nokubi@gmail.com& (toに送信先アドレスを指定)
  • su=test& (suにサブジェクト)
  • body=test (bodyに本文)

これは”Mailto: for GMail“の拡張を参考にしました。