ami_GS's diary

情報系大学院生の備忘録。ネットワークの勉強にハマっています。

Raspberry Piのアクセスポイント化 & ルータ化がうまくいかない時はこの通りにやればおk

はじめに

こんにちは。RPiのアクセスポイント化、ルータ化で詰まっていた情弱です。
今回、自分がはまっていた所を解決してくれた記事(英語)を見つけたので、それに沿って手順を書いて行きますね。

必要なステップ
  1. ワイヤレスアダプタ固定IPアドレス
  2. DHCPサーバのインストール及び構築
  3. アクセスポイントデーモン(hostapd)のインストール及び構築
  4. Wifiイーサネット間のルーティング設定


この例では、192.168.42.n のIPアドレスWifiネットワーク、192.168.1.nをイーサネット側のIPアドレスとして使います。

ワイヤレスアダプタ固定IPアドレス

"/etc/network/interfaces"を編集します。

sudo emacs /etc/network/interfaces

次に、
"allow-hotplug wlan0" 以外のwlan0、wpaに関する行をコメントアウトし、以下のように固定IPアドレスの設定をします。(/etc/network/interfacesの後半部分)

allow-hotplug wlan0
iface wlan0 inet static
address 192.168.42.1
netmask 255.255.255.0
gateway 192.168.1.1

#iface wlan0 inet manual
#wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
#iface default inet dhcp

DHCPサーバのインストール及び構築

DHCPサーバをインストールします

sudo apt-get install isc-dhcp-server

設定

sudo emacs /etc/dhcp/dhcpd.conf

"option domain-name"の部分(2行)をコメントアウトし、"authoritative"の部分をアンコメントします。

#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

そして同ファイルの最後に以下のモノを加えてください

subnet 192.168.42.0 netmask 255.255.255.0 {
    range 192.168.42.10 192.168.42.50;
    option broadcast-address 192.168.42.255;
    option routers 192.168.42.1;
    default-lease-time 600;
    max-lease-time 7200;
    option domain-name "local";
    option domain-name-servers 8.8.8.8, 8.8.4.4;
    }

次に以下を設定します。

sudo emacs /etc/default/isc-dhcp-server

そして、INTERFACES=""  →  INTERFACES="wlan0"   と書き加えてください。

これを終えたら、次のコマンドでdhcpサーバを再起動します。

sudo service isc-dhcp-server restart

wifiドングルを指してからでないとdhcpサーバが起動しないので注意!

アクセスポイントデーモン(hostapd)のインストール及び構築

インストール

sudo apt-get install hostapd


以下の様にWifiネットワークの設定を書きます。

sudo emacs /etc/hostapd/hostapd.conf
interface=wlan0
driver=nl80211
#driver=rtl871xdrv  #最後に説明します
ssid=MyPi
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=raspberry
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

そして、上記の設定を/etc/default/hostapdから読み込むようにします。

sudo emacs /etc/default/hostapd
DAEMON_CONF="/etc/hostapd/hostapd.conf"

Wifiイーサネット間のルーティング設定

以下をアンコメントしてフォワーディング設定をします。

sudo emacs /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
echo 1 > /proc/sys/net/ipv4/ip_forward

以下のコマンドでRPiをルータにする設定をします。

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
sudo iptables-save > /etc/iptables.ipv4.nat #ルーティングテーブルのセーブ

なお、hostapd.confを書き換えた場合はこれをもう一度行ってください


最後に、起動時にルーティングテーブルの読み込みを行うようにします。

sudo emacs /etc/network/interfaces

以下を最後の行に加えてください

pre-up iptables-restore < /etc/iptables.ipv4.nat

これでうまくいかない場合.....

“hostapd.conf”に"driver="が2行ありましたね、そこが肝になってきます。
それぞれが使っているUSBのWifiドングルにより、どちらを使うかが決まってきます。


どちらが使えるかは、以下のコマンドでわかります

sudo apt-get install iw
iw list

"nl80211 not found"
という出力が出た場合、"driver=nl80211"は使えません。"driver=rtl871xdrv"を使いましょう。


さらに、rtl871xdrvを使う場合は、使うべきhostapdも変わってきます。
以下のように設定するだけでOKです!

wget http://www.adafruit.com/downloads/adafruit_hostapd.zip 
unzip adafruit_hostapd.zip 
sudo mv /usr/sbin/hostapd /usr/sbin/hostapd.ORIG 
sudo mv hostapd /usr/sbin
sudo chmod 755 /usr/sbin/hostapd

これでアクセスポイント(SSID:MyPi)を見つけられるはずです。

以上。

日本語の記事では"driver=nl80211"を扱った記事がたくさんあったのですが、"driver=rtl871xdrv"を扱ったものが無くて全然構築が出来ずに困っていたわけです。

これで皆もRPiをアクセスポイントに出来る!やったね!!


Project euler #14 メモ化

3日に1記事挫折しそうやばいやばい

今回はProject eulerを題材にメモ化について書きます。

The following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)
n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. 
Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?

NOTE: Once the chain starts the terms are allowed to go above one million.

nが偶数:n = 3n + 1
nが奇数:n = n/2
を繰り返して、nが1になるまでのステップが最大になるnは何か、(n <= 1000000)
という問題。

単純に書くと

max = 0
n = 0
upper = 1000000

def length(n):
    if n == 1:
        return 1
    elif n%2 == 0:
        return 1 + length(n >> 1) #n/2のシフト演算版
    else:
        return 1 + length(3*n+1)

for i in range(1, upper):
    step = length(i)
    if step > max:
        max = step
        n = i

こんなバカ正直に書くと、僕の環境では計算終了まで30秒弱もかかります。
おそスギィ!!!!




メモ化手法

問題文に

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

とあるように、
n=13なら10ステップ、n=40なら9ステップ、n=20なら・・・と解が続いていきますね、


例としてあげたコードのように、1から総当たりで解を探していく場合、
n=5ならば6ステップという解が出ているのに、n=10の場合に、

10 → 5 → 16 → 8 → 4 → 2 → 1

のように計算し続けてステップ数を数えるのは非効率です。
そこで、n=5ならば6ステップという解をどこかに補完しておけば、

10 → 5

のように、1回の計算だけで「n=10ならば7ステップ」という解が出せます。




実装

(この場合は)実装は単純です。

memo = {}
max = 0
n = 0
upper = 1000000

def length(n):
    if n in memo:
        return memo[n]#メモにnの値が記録されていたらそのvalueを返す
    if n == 1:
        return 1
    elif n%2 == 0:
        return 1 + length(n >> 1)
    else:
        return 1 + length(3*n+1)

for i in range(1, upper):
    step = length(i)
    if step > max:
        max = step
        n = i
    memo[i] = step#メモにステップ数を記録

これだけ!

これを実行すると3秒切ります。

これだけで1/10も速くなるなんてすごい!

ー終ー

Raspberry Pi初期設定(ブート、ssh設定、固定IP)

卒論提出完了しました。これで自分の勉強に集中できるぞ!(3週間後に発表あり)


今回は、Raspberry Piの初期設定について書こうかと思います。
研究室の先生が僕に貸してくれてありがたやありがたや・・・


必要な物

作業環境Mac OS X
Raspberry Pi (Type B)
SD カード (今回はclass4 8GBの物を仕様)
電源用のアダプタ&マイクロUSBケーブル
HDMIケーブル&ディスプレイ
LANケーブル
キーボード
GUI操作をするのであればマウス


※microSDカードをSDカードの大きさにできるアダプタ?を使うと起動時に認識されないので注意



全部装着した物がこちら
f:id:ami_GS:20140125010143j:plain
電源が入ると左下のLEDが光り輝きます。

続きを読む

Pythonにおける*及び**の役割

3日に1回書く宣言してたけど人生稀に見る多忙さ故に挫折しそう。

なので簡単な事かきます。



色々な人のソース見てると、たま〜に、

def func(*foo, **bar):

このような物を見かけると思います。
Cでつまずいた人だと、ポインタだと思ってびっくりしちゃうかもしれません(びっくりしました)

結論から言うとポインタではありません。安心してください。

Pythonにおけるアスタリスクは可変長引数の役割をします。
引数の数に制限を欠けたくないときに便利ですね。

まず、*の場合(一つ)

def func(foo, bar, *args):
    print foo+bar

    for arg in args:
        print arg ,

func(1,2,"a","b","c")

とすると、出力は

3
a b c

となります。

foo及びbarに入る引数以外はタプルになります!便利ですね。
ちなみに入力が0個になっても動きます。


次に、**の場合(二つ)

def func(foo, bar, **kwargs):
    print foo+bar
    print kwargs

func(1,2,a="10",b="20",c="30")

とすると、出力は

3
{'a': '10', 'c': '20', 'b': '30'}

となります。辞書型ですね。


はい、見たところ確実にポインタではないようです。

LaTeXで載せたeps画像がずれてしまう時の対処(過去サイトから)

LaTeXでeps画像がズレるんだけど(半ギレ)って時の対処法です。

(2014-1-24:フォント修正)

 

友達とほぼ同じ画像を使っているのに、自分がコンパイルするとズレてしまうので試行錯誤してました。

 

色々調べたのですが、Bounding Boxを編集して図が表示される位置を直すってのが一般的?な方法らしいです。

もちろんわかりません。 (Bounding Boxってなんや)

 

 

他に調べたところ、epstopdf及びpdftopsコマンドを用いる方法が見つかりました。

※ 手持ちのMac OS XDebianにはepstopdf、pdftopsではなくてps2pdf、pdf2psが入っていたのでそれを使いました。

 

処理は簡単で、eps画像をpdfに変換し、pdfからeps画像に戻すだけです。

 

これによりBounding Boxの数値が初期化されるため有効だとかなんとか。

 

以下、簡単なスクリプト

#!/bin/sh                                                                       
for FILE in *eps
do
    IN=${FILE%.eps}
    ps2pdf -dEPSCrop -dPDFSETTINGS=/prepress $IN.eps $IN.pdf
    pdf2ps $IN.pdf $IN.eps
    rm $IN.pdf
done
 

説明

ps2pdf -dEPSCrop -dPDFSETTINGS=/prepress $IN.eps $IN.pdf
 

 

-dEPSCrop:これでeps画像にあわせたpdfを作成できます。

※ 注意:これをやらないとpdfに変換した際、eps画像の端が切れてしまう。ここで詰ま\\

ってる人も結構いるぽい

                      ちなみに-sPAPERSIZE=a4のようにするとa4サイズに指定できます。

 

-dPDFSETTINGS:変換の際の品質を指定します。多分これが一番良い品質なのかな・・・・?

                                            ごちゃごちゃしてる画像にはこれを使った方がいいかも

 

 

それ以降はpdfからepsに戻し、pdfを削除しています。

 

これで図形がズレなくなった!やったね! 

飽きっぽすぎワロタ

約240日ぶりですが再会いたします。

 

研究室でもらったグーグルサイトをブログ代わりに使おうとしたら、あまりのレイアウトの酷さでこっちに戻ってきた訳さ。

 

 

今回はどんどん書いていこうと思いますがんばります。