RubyのThreadのステータスに関して
class Thread (Ruby 2.4.0)
instance method Thread#status (Ruby 2.4.0)
instance method Thread#alive? (Ruby 2.4.0)
Rubyのスレッドに関して各ケースのステータスまとめ
各項目がとる値
- thread object(thread.inspect)
- run
- sleep
- aborting
- dead
- thread.status
- run
- sleep
- false
- nil
- thread.alive?
- true
- false
調査
通常時(スレッドが生きているとき)
ソース
t1 = Thread.start{ loop do sleep 1 end } loop do p t1 # run, sleep, aborting, dead puts t1.status || t1.status.class # run, sleep, false, nil puts t1.alive? # true, false puts "--------------------------------" sleep 1 end
実行結果
#<Thread:0x55e80d30 sleep> run true -------------------------------- #<Thread:0x55e80d30 sleep> run true -------------------------------- #<Thread:0x55e80d30 sleep> run true --------------------------------
各ステータス
- thread object : (run), sleep
- thread.status : run, (sleep)
- thread.alive? : true
正常終了時
ソース
t1 = Thread.start{ 2.times{|n| sleep 1 puts n+1 } } loop do p t1 puts t1.status || t1.status.class # run, sleep, aborting, false, nil puts t1.alive? # true, false puts "--------------------------------" sleep 1 end
実行結果
#<Thread:0x566a0c48 run> sleep true -------------------------------- 1 #<Thread:0x566a0c48 sleep> sleep true -------------------------------- 2 #<Thread:0x566a0c48 dead> FalseClass false -------------------------------- #<Thread:0x566a0c48 dead> FalseClass false -------------------------------- #<Thread:0x566a0c48 dead> FalseClass false --------------------------------
各ステータス
- thread object : dead
- thread.status : false
- thread.alive? : false
異常終了時
ソース
t1 = Thread.start{ 2.times{|n| sleep 1 puts n+1 } raise } loop do p t1 puts t1.status || t1.status.class # run, sleep, aborting, false, nil puts t1.alive? # true, false puts "--------------------------------" sleep 1 end
実行結果
#<Thread:0x558e8bf0 run> sleep true -------------------------------- #<Thread:0x558e8bf0 run> sleep 1 true -------------------------------- #<Thread:0x558e8bf0 run> 2 sleep false -------------------------------- #<Thread:0x558e8bf0 dead> NilClass false -------------------------------- #<Thread:0x558e8bf0 dead> NilClass false
各ステータス
- thread object : dead
- thread.status : nil
- thread.alive? : false
まとめると
- thread.statusはスレッドが生きている間はrunかsleepで、正常終了するとfalseになり、異常終了するとnilになる
- thread.alive?はスレッドが生きている間はtrueで、終了すると正常・異常に関わらずfalseになる
- thread情報を直接見ると、スレッドが生きている場合はrunかsleepで、終了処理中はabortingになり、完全に終了するとdeadになる
raspberryPiでRTCを使おうとしたときにargument Errorになる
前提条件として、raspberryPiにはRTCがついていないため、シャットダウンしてしまうと時間を保持しておくことが出来ない。
なので通常は起動時にntpでシステムの時刻をあわせるのだが、当然インターネット環境がない場合はその時間合わせをすること自体が出来ない。
そういう場合などのために個別にRTCを取り付けることが出来るのだが、以下のようにエラーが出てRTCへアクセスが出来ないことがたまにある。
hwclock: ioctl(RTC_RD_TIME) to /dev/rtcX to read the time failed: Invalid argument
調べていくと割とメジャーなつまづきポイントらしい。
Raspberry Pi • View topic - Wierd RTC(ds1307) problem
調べていくとfake_hwclockというものが悪さをしているらしく、上の方でraspberryPiにはRTC(hwclock)はついていないといったのだが、その代わりにのっているのがfake_hwclockらしい。
これは何かというと、普通ならば時刻データを保持できないのでネット環境がない場合は起動するたびに初期値の1970年1月1日0時0分0秒になってしまうのだが、
このfake_hwclockというシステムが有効化されていると、起動している時間を定期的(shutdown時にも?)にtxtとして保存しておき、次回起動時にこの時間を現在時刻として
使おうという機能である。
今回は本物のhwclockであるRTCとこのfake_hwclockが競合してしまったために上記のエラーが出たものと思われる。
解決方法としてはこいつを無効化してやればよい。
sudo update-rc.d fake-hwclock disable
これで競合することはなくなり、上記のエラーが出ることもなくなった。
raspberryPi3のIPを固定する方法(static ip)
raspberryPiは通常自動でIPをアサインしてくれますが、それでは困る場合などに固定IPアドレスにする方法です。
raspbianのversion upに伴い、raspberryPi2の時とは方法が変わっているようです。
ちなみにversionは8.0です
$ cat /etc/debian_version 8.0
/etc/network/interfacesの確認
$ cat /etc/network/interfaces # interfaces(5) file used by ifup(8) and ifdown(8) # Please note that this file is written to be used with dhcpcd # For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf' # Include files from /etc/network/interfaces.d: source-directory /etc/network/interfaces.d auto lo iface lo inet loopback iface eth0 inet manual allow-hotplug wlan0 iface wlan0 inet manual wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf allow-hotplug wlan1 iface wlan1 inet manual wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
上のほうのコメントを見ると、staticIPにするにはdhcpcd.confを編集すればよいことがわかります。
とりあえず書かれている通りにmanを見ます
$ man dhcpcd.conf static value Configures a static value. If you set ip_address then dhcpcd will not attempt to obtain a lease and just use the value for the address with an infinite lease time. Here is an example which configures a static address, routes and dns. interface eth0 static ip_address=192.168.0.10/24 static routers=192.168.0.1 static domain_name_servers=192.168.0.1 Here is an example for PPP which gives the destination a default route. It uses the special desti- nation keyword to insert the destination address into the value. interface ppp0 static ip_address= destination routers
staticで検索すると上記のような記入例が出てくるので、自分のIPに変更して実際に書き込みます
/etc/dhcpcd.confの編集
$ vi /etc/dhcpcd.conf ### ファイル末尾に追加 interface eth0 static ip_address=192.168.0.10/24 static routers=192.168.0.1 static domain_name_servers=192.168.0.1 ### wifi(wlan0)の場合は interface wlan0 . . .
これで完了です。
後はraspberryPiを再起動して設定したIPでアクセスできることが確認できればOKです。
raspberryPi3へWiringPiGPIOを設定する手順
GPIO:General Purpose Input/Output
$ git clone git://git.drogon.net/wiringPi Cloning into 'wiringPi'... . . . Checking connectivity... done. $ ls -l total 4 drwxr-xr-x 10 pi pi 4096 Nov 29 15:10 wiringPi $ cd wiringPi/ ./build wiringPi Build script . . . All Done. . . . $ gpio -v gpio version: 2.32 Copyright (c) 2012-2015 Gordon Henderson This is free software with ABSOLUTELY NO WARRANTY. For details type: gpio -warranty Raspberry Pi Details: Type: Pi 3, Revision: 02, Memory: 1024MB, Maker: Embest * Device tree is enabled. * This Raspberry Pi supports user-level GPIO access. -> See the man-page for more details -> ie. export WIRINGPI_GPIOMEM=1
Rubyでシリアル通信する方法(serialport gem)
Rubyでシリアル通信する場合は、serialport gemを使うと簡単にできます。
install serial port
$ gem install serialport
How to Use
require 'serialport' sp = SerialPort.new('/dev/ttyS0', 115200, 8, 1, 0) # device, rate, data, stop, parity # 送信 sp.puts("foobar") # 受信 sp.gets sp.readline.chomp.strip # こっちだと空白とか余分な情報をそぎ落としてくれる
sinatraでhashデータをJSONとして返す方法
方法
require 'json' return #{hash}.to_json
例
require 'sinatra' require 'json' get '/top' do hash = { "key1" => 1, "key2" => 2, "key3" => 3, } return hash.to_json end
raspberryPi3とWindowsPCでシリアル通信する方法
環境
RaspberryPi3
WindowsPC
USB-serial変換ケーブル
FTDI USB・シリアル変換ケーブル(3.3V): 半導体 秋月電子通商 電子部品 ネット通販
接続
raspberryPi側
調べると色々出てきますが、変換ケーブルのGND, TXD, RXDをRaspberryPiのGPIOに差し込みます
ここで注意が必要なのが、送信と受信を対にするために以下のように接続します
PC側
PC側は普通にUSBに差すだけです。
差したあとにデバイスマネージャーで認識されているか確認しましょう
設定
raspberryPi側
調べていくと、raspberryPiのシリアル通信ポートは既に他の用途で使われているようで、これを使えるようにする方法がRaspberryPiのモデルやRaspbianのversionによって様々で、ちょっと苦戦しました。
最終的に私がうまくいった方法は・・・
1. raspi-configでserial通信を有効化する
2. /boot/config.txtへ追記
$ sudo vi /boot/config.txt enable_uart=1 # 末尾へ追記する
3. getty無効化
sudo systemctl stop serial-getty@ttyS0.service
sudo systemctl disable serial-getty@ttyS0.service
4. 再起動する
通信(確認)
PC側 ⇒ raspberryPi
今回はターミナルとしてteratermを利用しました
接続方法を選択する際にTCP/IPではなくシリアルを選択します
raspberryPiのボーレートは115200なので、「設定 > シリアルポート」から、ボーレートの変更を行います
変更後にエンターキーを一度押すとログイン画面が表示されます。
raspberryPi ⇒ PC側
色々方法はあるようですが、今回はscreenを利用して確認をします
screen /dev/ttyS0 115200
これでscreen経由で入力した情報がシリアル側へ表示されればOKです
おまけ
/boot/cmdline.txtの編集
このままだとシリアル通信側に全てコンソール情報が常に表示されてしまうので、cmdline.txtファイルを編集することでそれを防ぐことができます
$ sudo vi /boot/cmdline.txt dwc_otg.lpm_enable=0 console=tty1 console=serial0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait # console=serial0, 115200を削除します