新千葉 ガーベージ・コレクション

FPGA マガジンやインターフェースで書けなかったこと等をちょぼちょぼ書いてます。@ryos36

Kiss4 の環境作り

f:id:ryos36:20161008233416j:plain
Kiss4 という Zynq のボードのために、環境作り。Yocto で環境を作っている。krogoth という branch を使用。

  • poky
  • meta-xilinx
  • meta-openembedded

と zybo からぱくった

  • meta-kiss4

まちがえて meta-openembedded の branch を master にしたら、

python-dbus fails configure with "could not find Python headers"

というエラーが出て止まってしまった。branch をちゃんと krogoth に合わせたらうまくいった。
yocto に bug として出ていたのでバグかと思ってしまった。単純ミスだった。
https://bugzilla.yoctoproject.org/show_bug.cgi?id=2072

Pynq に大きく水をあけられてしまったので、こつこつ環境を構築して、追いつきたいと思う。

Mini Caml コンパイラ その1

github.com

ここにある pdf をみながら、社内でコンパイラ(型推論)の勉強会を開く。
http://esumii.github.io/min-caml/jpaper.pdf
いま、見たら tutorial-minicaml.doc なんてのがあった。

最初から躓くよね。「単相性」ってなによ。K くんの指摘で「多相型がないこと」の意味をちょっと理解する。template のように型をいくつも取れるのが多相型という理解をした。よんでいくと、決定できないときは int と推論するとある。そういうことか。

サンクとクロージャの違いが明確にわからん。とか、(クロージャは遅延評価とは関係ないのか、、、)正格性とか線形性とか、、、軽く読み飛ばす(深い理解もなく先に行く)。最初の週は OCamlLex と OCamlYacc をある程度理解すればいいと。MinCaml の抽象構文と型ってのが、そもそも Ocaml を理解してないとダメだ。数か月前に読んだんだけど、、、fix record の問題も軽く読み飛ばし。非カリー化、、う~む。先にいこう!!

ということで、3.1 に字句・構文解析にたどり着く。そして、3. 型推論を経て、K正規化で時間切れ。

まずはちゃんと OCaml を思い出して、構文を理解しないとね。そして、K正規化に突入していかないといけない。だれかがそういえば、Scheme で書いていたような。

Docker + WordPress 試してみた

Docker を試してみた。FreeBSD の jail みたいなものと理解している。というより、技術的なものは一切理解せずに使っている。

Docker のインストール

qiita.com
この辺のを見てインストールした。単に Docker からシェルプロを wget して(記事の中では curl だが)、sudo で実行しただけ。もう、勝手に何かしらインストールされてしまいました。何がインストールされたかはわからずじまいです。

$ wget -qO- https://get.docker.com/ | sh
$ sudo usermod -aG docker $USER

Docker を run させる。

よくわからないけど、まずは hello world を run させました。この時点で、何が起こっているのかわからない!!という状態です。つまり、 Docker (仮想環境というくらいは知っているが、基本的な知識としてはこのキーワードだけ)が何者かわからないうちに hello world 終了

$ docker run hello-world

ubuntu を起動させる

なんか ubuntu も起動させることが出来るらしいぞ、ということで ubuntu も起動。

$ docker run -i -t ubuntu /bin/bash

この時点でどうやら、どっかにイメージを作っているらしいことに気が付く。df でみてみると、確かにマウントしている。つまり、Docker は誰かが作った image を mount して Jail みたいにプロセスに割り当てて起動する技術らしい(今も詳細がわかっていないので、あくまで、らしいってことで)
一旦抜けても後から bash を起動できる

$ docker exec -it ubuntu /bin/bash

目的の WordPress を起動

tutum/wordpress というのを使ってみた。もう簡単。

$ docker run -d -p 8080:80 --name=wordpress tutum/wordpress

これで 8080 を 80 へフォワードする。後で調べると、じつはこのコンテナのなかで Linux + Apache + MySQL + PHP (いわゆる LAMP) が動いていることが分かった。調子に乗って、いくつも wordpress 入りのコンテナを作る。イメージがどこにあるのかしらないが、イメージなら、スナップショットが取れるのでは?と調べると commit というコマンドで取れることが分かった。

$ docker stop wordpress
$ docker commit wordpress wordpress-snap0

tutum/wordpresswordpress の旧バージョンが入っている。しかし、パーミッションの設定が悪く、WordPress 内部からアップデートできない。

$ cd /var/www/html
$ chown -R www-data:www-data .

てなぐあいにしてやると、うまくいく。あと、ついでに sendmail (WordPress が必要とする) がなかったので、apt-get でいれる。apt-get が古かったようなので update もする。

$ apt-get update
$ apt-get install postfix
$ service postfix start
$ service postfix stop

最初 sendmail を入れたら重かったので、postfix に変更。postfix の設定はしていない。(メールの送信だけだから)。service を stop していて大丈夫のはずだが、、、、stop しても ps でみるとデーモンが動いている。もう、目的主義で、その辺は気にしないことにする。

WordPress の設定

ここから混沌の道に入る。WordPress は簡単な言葉を使っているせいで、いままで Linux のサーバを使っていた人はかえってわからない。そして、うまく apache の裏に隠れてくれない(Proxyね)。

  • WordPress アドレス
  • サイトアドレス

この用語がわからない。どうやら、複数のコンテキストを管理できるように、WordPress の一般的な cgi とコンテンツ向けの cgi に分かれているようだ。生成される HTML のソースを見るとそう見える。なので、WordPress アドレスはコンテンツに関連なく共通の cgi のための URL。サイトアドレスはコンテンツのための URL。
結局どちらも、普通に同じ URL を設定し、おおもとの Apache で Proxy で転送。

ProxyPass / http://localhost:8080/

かな?ProxyPassReverse は WordPress が勝手にやってくれるから設定しない。WordPress 側は、もともとは http://192.168.0.XXX:8080 みたいになているはずなので、これを http://www.example.com のように(WordPress アドレスもサイトアドレスも)変更。
そしておまじないの

$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];

を wp-config.php に追加。追加するときは

require_once(ABSPATH . 'wp-settings.php');

より前にする必要があるらしい。WordPress 的には次のコメントの前に書くということになっている。

/* That's all, stop editing! Happy blogging. */

SSL

これはちょっとややこしい。が、結局、次のを wp-config.php に足しこむので OK だった。

define('FORCE_SSL_ADMIN', true);
$_SERVER['HTTPS']='on';

これを例のコメントの前に設定する。$_SERVER はどうやら apache のサーバの環境変数らしい。PHP の if 文なんかも書けるみたいだから、intra から接続したときは (192.168.0.X からの接続とか) は https を使わずに、、、、みたいな複雑なことも phpapacherewrite engine で可能、、、、らしいぞ。

危ない処理をする前にはイメージを commit すればよい

Docker 便利!!スナップショット取れるから、やり直しが簡単。あと、WordPress 的には wp-config.php

define('WP_SITEURL', 'http://192.168.0.XXX:8080/');
define('WP_HOME', 'http://192.168.0.XXX:8080/'); 

の両方或いは片方。を(例のコメントより前に)書き加えれば DB の設定を使わずに固定で立ち上がるぞ。こまったら、直接たぶん MySQL を書き戻せばいい(やらなかった。Docker で手戻りした。その方が簡単だったので、、、<= いや、今考えるとシェルプロで MySQL を書き戻すようにしたほうがよかった。後々その方が使える)

WordPress おすすめのテーマはこれだ!

標準なら Twenty Ten がお勧めかな。ロゴがはれないのがちょっと残念。インストールするなら Clean Journal が気に入っている。無料版がある。無駄にオシャレになれます。あとプラグインでは bbPress を使うとフォーラムとか作れるみたいだ。

でもって Docker だけど、、、

技術的に全く理解していない Docker。

  1. Dockerfile なるものを github に登録して、
  2. Docker hub の ID を取得して
  3. Docker hub で github の Dockerfile を読み込ませて、
  4. Docker hub でイメージを作成する

と一般に公開できるらしいぞ。Dockerfile をみるといろいろスクリプトがかいてあるので、debootstrap だっけ?で生成した root image に対して、コマンドを実行して DB つくったり、デーモン立ち上げたりをするみたいだ。実際に使っていないからなんともいえない。

vivado の dbg_hub ではまったのでメモ

Vivado で波形を見ようと mark debug したときにはまったのでそのメモ。

やろうとしたことは AXI Stream の波形を見ようとしていた。AXI Stream のクロックは Zynq から供給される。なので、そのクロックに合わせて Setup Debug を設定した。

しかし、bit stream をダウンロードしても

WARNING: [Labtools 27-3123] The debug hub core was not detected at User Scan Chain 1 or 3.
Resolution: 
1. Make sure the clock connected to the debug hub (dbg_hub) core is a free running clock and is active OR
2. Manually launch hw_server with -e "set xsdb-user-bscan <C_USER_SCAN_CHAIN scan_chain_number>" to detect the debug hub at User Scan Chain of 2 or 4. To determine the user scan chain setting, open the implemented design and use: get_property C_USER_SCAN_CHAIN [get_debug_cores dbg_hub].
WARNING: [Labtools 27-1974] Mismatch between the design programmed into the device xc7z045_1 and the probes file I:/TSDI/RGB_test/RGB_test.runs/impl_1/debug_nets.ltx.
The device design has 0 ILA core(s) and 0 VIO core(s). The probes file has 1 ILA core(s) and 0 VIO core(s).
Resolution: 
1. Reprogram device with the correct programming file and associated probes file OR
2. Goto device properties and associate the correct probes file with the programming file already programmed in the device.

というエラーが出てしまう。よくよく調べると、debug hub というモジュールにクロックが供給されていないことが原因だ。該当回路図を追って行くと、Zynq の FCLK_CLK2 から”ちゃんと”クロック供給がされている、、、、

というのはうそで、FCLK_CLK2 は Zynq の設定をちゃんとすると供給する。おそらく、ps7_init をちゃんと設定しないとクロックが出てくれない。そこで、SDK を起動して、Hello world のプロジェクトを作って、デバッグで実行。main で止まったところで、再度、bit stream をダウンロード。おーこれでちゃんとデバッグができるようになりました。ときどき vio でうまく以下なったのもこれが原因か、、、

SSLv3 のエラーだが apache.conf で解決

SSL を導入して通常のブラウザからはうまく https が見えるのだが、Smart HTTP(git-http-backend) 経由で Eclipse から import しようとするとエラーが出る。

[Wed Jul 06 15:01:32.119075 2016] [ssl:info] [pid 11614] [client 192.xxx.xxx.xxx:63694] AH02008: SSL library error 1 in handshake (server rt:443)
[Wed Jul 06 15:01:32.119169 2016] [ssl:info] [pid 11614] SSL Library Error: error:140943F2:SSL routines:SSL3_READ_BYTES:sslv3 alert unexpected message (SSL alert number 10)

ログだけ見ると SSLの v3 でエラーになっているように見える。しかし、いまや SSL の v3 は脆弱性が発見されているので使いたくない。でいろいろ調べてみると単純に apache.conf の書き方の問題。

ServerName www.sample.com

みたいに conf を書いておけばいいだけだった。いい加減に www とかにしてたのがよくなかった。
このページを発見していなければ解決できなかった。感謝。

Java - HTTPS通信が失敗するようになる: javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name - ttshikoのブログ

あと、Smart HTTP
Git - Smart HTTP
このページがかなり上位に来るのだが、Order が間違っているのか、この通りにするとうまく認証しない。ちゃんと apache の認証が通るようにしないとダメ。

ついでに SSLv3 も通さないように apache の設定をする。

        SSLProtocol all -SSLv3

確認は openssl コマンド

openssl s_client -connect www.sample.com:443 -ssl3

g++ あやまったリンクをした際の残骸

あやまったリンクをした際の残骸
記録として残してある。
reent.c
void *_impure_ptr;
newlib のリエントラントな構造を保持するための大域変数。
newlib 内の実装に必要。
libstdc++ を --use-newlib でコンパイルすると、exception の unwind に
この変数が必要となってしまう。
newlib に依存しているという誤った libstdc++ をリンクするとこの現象が出る。
一次的に回避するのに -fno-exceptions を使う。
exception を使いたいのであれば g++ が要求する unwind 用の関数を
実装する必要がある。

cxa_atexit.c
デストラクタの登録に cxa_atexit が呼ばれる。
RTOS として大域変数として登録されたオブジェクトは
そもそもデストラクタを呼ぶ契機がない。
タスクの関数内で登録されているのなら、exit の代わりに
タスク終了の API でデストラクタが呼ばれるようにしないといけない。
-fno-use-cxa-atexit でコンパイルすれば、そもそもこの関数は呼ばれない。

dso_handle.c
ダイナミックローディングされたライブラリをアンロードするときも
デストラクタが呼ばれる。その際に、(おそらく)ダミー的に本体の
オブジェクトにも dso を識別するための変数が要求される。
ダイナミックローディングを使っていないのに、上の cxa_atexit の
第3引数で必要とされるため、自動的に要求されるようだ。
-fno-use-cxa-atexit で回避可能。

C++ を embedded な環境でつかう

結局、素の C++ を使うのがベスト。うっかりすると素ではなくていろんなものに依存するので注意。たとえば arm-xilinx-linux-gnueabi-gcc/g++ これは当然、Linux 環境に依存する。だから単純に printf とかすると Linux の /usr/include/stdio.h の printf を使おうとしたりする。
arm-xilinx-eabi-gcc/g++ 。これは(xilinxが) newlib + libstdc++ に(意図的に)依存させて作っている。したがって、printf とかすると newlib の stdio.h の printf を使おうとしたりする。なので、newlib が要求する Unix システムコール(もどき)のシミュレーションを(自分で作ったライブラリを)用意する必要がある。例えば open とか read/write とか close とか。xilinx はこれを Standalone と称して用意している。さらに、リンク時には、”コンパイラを作った時の”環境に依存する crt (C RunTime ?) をリンクする。xilinx は作った時に何も考えていなかったのか、空の crt がリンクされる。crt にはシステムの初期化用の _init が含まれる。
embedded な環境で使うには -nostdlib を指定すると、crt やら libc libstdc++ やらをリンクしない。
g++ でコンパイルするとデフォルトではデストラクタの登録に __cxa_atexit を使おうとする。cxa はどうやら c++(cxx) abi の略のようだ。g++ では -fno-use-cxa-atexit を指定すると cxa_atexit を使わないオブジェクトを生成することが出来る。__aeabi_atexit が undefine の時はこれで”一時的に”解決する。全部解決したと思わない方がよい。RTOS などの設計にもよるが、いつデストラクタを呼ぶのかはちゃんと考えないといけない。タスクやスレッドが終わった時にどうするのか?が主な注意点だろう。これは RTOS の設計。
libc を自分で設計するならリエントラントに設計する必要があるかどうか?それらの情報どうするかは考えないといけない。g++ は exception を使う設定にしておくと、__gxx_personality_v0 と __cxa_end_cleanup の実装を要求される。これはいずれも exception ハンドラに関連する関数。特に __gxx_personality_v0 は try catch を使うなら実装が必須。最近では setjmp/longjump は使わないみたいだ(未確認)。下のblogが役に立ちそう。

g++の例外を捕まえよう!!(素手で)

exception を使わないなら(不便になるけど)-fno-exceptions を使えばよい。結局、g++ ではオプションで次の設定をしておけば(コンパイラ自身が持っている環境を無視するので)だいだい使える。

-nostdinc -nostdlib -fno-use-cxa-atexit -fno-exceptions

さぁこれで vx-schemeコンパイルがどこでもできるんじゃないかな?

やってはいけないこと

そんでもって -nostdlib を選択したということはコンパイラが持つ libc や libstdc++ を使わないということ。なので、-lc なんかしちゃだめ。-lm も当然ダメ。中途半端にライブラリをリンクすると dso_handle がないとか言われる。あと __impure_ptr 。これは newlib の環境内のリエントラントな構造を保つ大域変数。つまり newlib が前提。newlib を前提としてコンパイルされた libstdc++ は exception の回収にこのポインタを使う。だから、そんなことが起こったらきっと環境が間違っている。exception を使わないことがわかっているなら -fno-exceptions で回避できる。もし、使うなら、自分で unwind するための関数である 、__gxx_personality_v0 と __cxa_end_cleanup の実装が必要。
まちがっても、いろんなものを”くっつけて”解決しようとしないように。私は dummy.c というファイルを作って、知らない関数や変数をいっぱい定義して回避している”プロジェクト”を見たことがある。当然、崩壊してたね。まぁ趣味ならいい気はする。

new や delete

これをつかうと動的にメモリ確保開放を必要とする。RTOS で使うときは注意。動的にメモリ獲得するということは結局ガベージコレクション(的な現象)を生む。これはスクリプト言語を使わなくても malloc を使えば起こるということ。malloc の実装にもよるけど、メモリが足りなくなったらエラーになるならまだよいが、他のタスクが解放してくれるのを待つという実装になっていると RTOS の意味がなくなる場合(ケースバイケースだが)がある。だからやってはいけないというわけではなくて、注意。
まぁ TCP/IP つかっちゃうと結局動的にメモリ確保をするので(mbuf とかね)ここも本来注意なんだけど、、、最近では気にする人はいなくなっちゃたね。
new や delete を使うと operator が足りないと言われるので(言われなかったら何か怪しい libstdc++ をリンクしているぞ。危険)自分で実装する。malloc で実装してもよいし、簡単に自分で RTOSAPI を使ったり、単純な配列を使ったりしてもよい。要は delete と連動していればよい。
あと、うろ覚えだけど、クラスに new や delete を関連付けることが出来たような、、、、
placement new と delete(2)

placement new

RTOS ではこちらがおすすめ。new や delete のオペレータを使わない。
placement new と delete(1)

自分専用の gcc を作る

何度かトライしたけどめちゃめんどくさい。みんないい加減にやっている(やっていた)。しかし、Android や Yocto がうまくコンパイラコンパイルを隠ぺいして開発環境を自動的に作ってくれる環境を作ったので、みんな何も考えずにできるようになったね。ぱちぱち。2000 の初めにはなんか自分で gcc をつくらなきゃいけなかったので、毎晩、nightly build を追ってた。特に sh。
Linux 用のコンパイラを作る手順はざっと書くと次のような感じ

  • build 用のコンパイラを作る(i386 -> i386 ってことね。最近では x64 -> x64 かな)
  • cross 用のコンパイラをとりあえず作る。たとえば arm-unkown-eabi-gcc みたいなもの。newlib に依存してもしなくてもよい。これはいずれ捨てる。
  • arm-unkown-eabi-gccLinux カーネルコンパイルする。これで Linux の一時環境が出来た。この時点でやろうと思えば Linux のアプリは作れる。APILinuxシステムコールだけだが。ここで用意されるのは Linux が用意する include の類でこれをどっかクロスコンパイラ用 root にインストールする。
  • libc をつくる。Linux の環境とコンパイラがあれば libc が作れる。作れるはずなのだが、、、libc を作るときに libc 入りのコンパイラを要求されたり、例によって途中でバージョンの依存関係でエラーになったりと、苦労する。jこれを Linux の クロスコンパイラ用 root にインストール。ここを明示的に参照することで Linux アプリが書ける。(はず)
  • Linux の クロスコンパイラ用 root を元に cross 用のコンパイラを作り直す。arm-linux-gnueabi-gcc みたいもの。このクロスコンパイラは include とか lib とかはこのクロスコンパイラ用の root を"自動的に"参照することになる。
  • 出来たコンパイラで次々とライブラリをコンパイル・インストールする。そうすると、クロスコンパイラ用 root がいつのまにか Linux の root のようになる。これをファイルシステムにすればよい。これはオールドスタイルの root fs だ。
  • 出来た クロスコンパイラ用 root は実は i386 で動くクロスコンパイラが出来てたりする。だから、これをファイルシステムにしてしまうと i386 オブジェクトが含まれることになる。そこで、deploy 用の root fs を別に作る。ここにこつこつライブラリなどをインストールすれば本当の root fs ができる。

これを gcc のバージョン違いやいろんなライブラリを作るときのエラーの回避なんかをしてると、らちが明かない。Yocto は上を全部自動でやってくれる。そして、注目したいところだけ、自分でつくりこめばいいのだ。これは楽だね。

基本的には RTOS も上の手順を踏めば、正しく標準ライブラリを組み込んだ gcc ができる(はず)。