🗐 電装工芸日記 - 舞台照明機器の製作とか -

能登半島地震で被災された方々にお見舞い申し上げます。

or 管理画面へ

2023年1月 この範囲を時系列順で読む この範囲をファイルに出力する

Icon of admin
 秋月電子通商さんでRaspberryPi4Bが販売されていました。
 特需ですぐに無くなってしまう?
 お金は辛いですが、とりあえず3個発注しました。

#RaspberryPi
Icon of admin
 本業が落ち着いたので所属会社の作業部屋を片付けをしています。
 コンセプトマシンで使うオンジナオイルの20Lの空き缶2個の処分で悩む。捨てようと思えば捨てられますが、一般家庭ゴミでは出せませんので面倒。
 ならば、イスにしてしまいましょう。
 上面に丸く切ったコンパネを貼り、床を傷つけないように底面の縁にゴムのエッジ材を取り回しました。すべて余り材とジャンク品で済んだので目先のお金はゼロ。
 しばらくは作業部屋とジャンク材の片付けです。キレイ好きとは真逆ですが、次の作業のためにもやっておかないといけません。

#本業
Icon of admin
 Art-Netを受信する準備を進めています。
 思った以上に面倒だったのはデータの比較です。受信値と期待値を比較して処理を分岐する処理は重要です。文字列ならstrcmp、バイナリならmemcmpを使います。どちらもstring.hの関数です。
 どちらにしてもバイナリな感覚を持ち合わせていないと使えませんが、アセンブラに慣れた体にとって違和感はありませんし、ある意味とても明確な処理になるので悪い気はしません。Pythonが如何に簡単に書けるかを感じたりはしましたけどね。
 あとはエンディアンの処理です。RaspberryPiはARM系なのでリトルエンディアンです。受信したArt-Netを仕分けて情報にするには2-4バイトのバイナリを数値化しないといけませんが、エンディアンを気にしながらバイナリを並べて処理します。並べたバイナリを数値化するにはカッコとアンパサンドを使った不思議な記述をしますが、理解不能なので定型句と思って使っています。
 こんな底辺処理が整理出来たら受信テストですが、これらを先にやっておかないと受信値を人が読める形で表示することが出来ないのです。

#[Art-Net] #C言語
Icon of admin
 RaspberryPiをアップデートしたらネットワーク関連が動かなくなった。
 起動パレードを見ると「Failed to start DHCP Client Daemon.」と出る。

 このサイトの通り手直ししたら治った。

 抜粋すると次の通り。

$ sudo nano /etc/systemd/system/dhcpcd.service.d/wait.conf

Change from:
[Service]
ExecStart=
ExecStart=/usr/lib/dhcpcd5/dhcpcd -q -w

To:
[Service]
ExecStart=
ExecStart=/usr/sbin/dhcpcd -q -w


 wait.confを訂正するってことです。

#RaspberryPi
Icon of admin
 ここ数日は本業で手一杯でした。ライトアップの施工があったのですが、建物の窓を光らせたいとのことで専用の行燈を製作してました。
 簡単な作りではあったのですが思った以上に時間がかかり、徹夜して間に合わせたのはいいですが、その余波で心身共にキツイここ数日。
 8月のお盆明けからの大連チャンでしたが、この後3月中旬までは緩い日程なので、各種製作や開発を進めて行けそうです。

 同時にイロイロ進めますが、とにかくArt-Netエンジンを完成させたい。
 Art-Netエンジンとは、Art-Netを受信し、Merge、In-Delay、Patch、Out-Curve、Out-Delayを施し、Art-Netとして送信するデバイスドライバの様なモジュールです。ユーザーインターフェースなどは別途製作ですが、これが完成すれば求めることの半分は完成です。
 そのためにC言語を学習しているワケですが、ポインタ、構造体、共有メモリ、マルチプロセスの基本が見えてきましたので、これからしばらくはArt-Netの要であるscoketを試そうと思います。C言語でscoketを扱う情報は高位者による高位者向けの高度な物ばかりですが、幸いPythonでの前例がありますので、これをC言語に置き換える方向で読み解いていこうと思います。
 学習を進めれば進める程「ライブラリの使い方はmanとヘッダーファイルを読めば分かるだろ!」という圧を強く感じますが、この感覚が自分にとっても当たり前になるように精進したいものです。

#C言語 #本業 #[Art-Net]
Icon of admin
 C言語の教科書を幾つか読んでいます。
 熟知した人でないと書けないことですが、熟知した人は初心者の気持ちを忘れた人たちです。どんなに優しく書こうとしても初心者向けの説明など書けません。部分的に初心者の理解を助けてくれる文章があるので複数読んだ方がいいのです。
 お勧めというか、理解しやすかった教科書を2つご紹介します。

「新・明解C言語 入門編」
 初心者が挫折しやすい変数の型、ポインタ、構造体を後回しにして書いているのでC言語の全体像が見えやすい。変数の型、ポインタ、構造体で悩みたくないなら他の言語を使うべきですが、冒頭から「変数の型がぁ~」「ポインタがぁ~」と書かれた解説書は挫折率が高い(俺評価)のでよろしくありません。簡単とは言いませんが、これは挫折し難い内容です。

「苦しんで覚えるC言語」
 書籍にもなっていますが、webでも読める解説書です。途中息切れを感じるところはありますが、これはこれでわかりやすい。

 あと、以前ご紹介した「改訂第3版(5版) ANSI C 対応 はじめてのC」は和文規格書かもしれません。わかりやすい記述も多いのですが、誰もが悩むポインタは触るだけだったりと、誰もが躓くところほど流している傾向があります。すでに習得している人の参考書としてなら悪くありませんケド。

 ただ、総じて言えることですが、C言語はこの時代に初めてプログラムを書く人が使う言語ではありません。画面とキーボード、マウスで完結するシステムならPythonなどの高度にマネージされた言語を使うべきです。なぜなら、CPUのレジスタとかフラグ、メモリの概念が体に染み込んでいないと書式の意味を理解することが難しいからです。私の課題は対象がハードウェアですからPythonよりもC言語の方が適切ってだけです。

#C言語
Icon of admin
 ランチャーに行く前にscoketの基本動作の確認かな?
 受信したArt-Netパケットをそのまま送信する実験。
 これが求める機能の基本ですから確認せんといかん。

#[Art-Net] #C言語
Icon of admin
 共有メモリの衝突回避ですが、共有メモリの中にハンドシェイク表すフラグを入れたらそれでいいんじゃないかと。
 そのフラグが立っていれば極々わずかな時間sleepを繰り返す処理です。

while(flag1 == 1)
{
 sleep(0.001);
}
flag2 = 1;
/* 共有メモリ処理 */
flag2 = 0;


 みたいなものです。
 別プロセスがフラグを0にすればwhileを抜けます。
 簡易的なモノですが、フラグを書き換えられるプロセスを一つにしておけばイイんじゃないかと。最も簡単なセマフォはこういうことですし。

 子プロセスの停止制御も同様の考え方が使えます。
 動作し続けるってことは繰り返し処理です。単なる繰り返しはwhile(1)とかで無限ループすることが多いので、while(flag==1)とかにすればいい。共有メモリ上のフラグが1ならwhileでループし0になったら抜ければいいのです。抜けたら終了処理をしてプロセスを落とすと。子プロセスが完全に終わったことはスタックしておいたプロセスIDを見ればわかります。

 この辺りまで決まれば次はランチャーです。

#C言語
Icon of admin
 共有メモリに構造体を配置してみましたが、割と簡単でした。
 構造体のタグ(ひな形)をヘッダーファイルに作り、親プロセスと子プロセスにinclude。共有メモリのサイズは構造体のタグから得て設定。共有メモリ上に置く変数を独立したポインタにするとオフセットをそれぞれ計算して与えないといけませんが、構造体なら一括設定出来て便利です。
 構造体をポインタにすると表記が独特になりますが、意味合いが明示的となって読みやすいかもしれません。
 この辺りには、本文中に出来るだけ定数を直書きしないという方針にも繋がってきます。

 次は共有メモリの衝突回避を調べないといけません。

#C言語
Icon of admin
 屋外で開催される成人式関連のイベントで電源出しです。
 起動してしまえばやることはありません。
 本日の課題は共有メモリのテストです。

 次のページにあるソースをそのまま使って挙動を確認です。
 プロセス間でのメモリ共有

 親プロセス「ShareMemTest1」を起動した後、待機時間(20秒)のうちにコンソールで「ShareMemTest2」に共有メモリのIDを与えて起動するというもの。一貫したプログラムではありませんが、やりたいことはプロセス間でのメモリ共有ですからむしろわかりやすい。
 ちなみに、コンソールでプログラムを起動する際、末尾に「&」を付けると新規プロセスで実行します。

 ここサンプルを使うなら、

 <親プロセスを起動>
$ ./ShareMemTest1 &

 <起動後表示>
nShareMemID = 23 /* IDは都度変わります */
process1 : nVar1 = 1, nVar2 = 2
・・・ここで20秒Sleepしてます・・・

 <子プロセスを起動>
$ ./ShareMemTest2 23 &

 <起動後表示>
nShareMemID = 23
process2 : nVar1 = 1, nVar2 = 2
process2 : nVar1 = 2, nVar2 = 2
・・・子プロセスはここで終了・・・

・・・20秒後、親プロセスが再開・・・
process2 : nVar1 = 2, nVar2 = 2
・・・親プロセスも終了・・・

 となります。
 正に記述にある通り。

$ ipcs -m
 や
$ free
 を用いるとSharedメモリの状況がわかります。

 実際のテストではgetpid()を用いてプロセスIDも表示しながら確認しましたが、確かに別プロセスでした。
 共有メモリの容量は、無意味に8MBくらい設定してみましたが何の問題も無し。

 親側の設定は、typedefで構造体を定義し、構造体のポインタ変数を作り、構造体のメモリサイズ(sizeof()で取得)をもとに共有メモリを作り、構造体のポインタ変数に共有メモリを割り当てる、といった流れでしょうか。
 子側は、typedefで構造体を定義し、構造体のポインタ変数を作り、親から取得したIDから構造体のポインタ変数に共有メモリを割り当てる、といった流れ?
 共有メモリ上に変数(構造体)を構築した後は共有メモリを意識する必要は無いと思います。もちろん、衝突回避は常に考えないといけませんけど。

 勘違いしていた点ですが、共有メモリのIDは管理用の通し番号であってポインタに設定するアドレスではないことです。C言語では何かにつけてポインタ渡しなのでこれもそうかと思ってしまいました。

 共有メモリに構造体を配置することが次の課題ですが、構造体についてもう少し勉強してからです。

#C言語

■当面の課題

桜のライトアップの季節です。花粉症の季節でもあります。
自分は平気ですが、花粉症の部下は死にそうな顔をしています。

編集

■複合検索:

  • 投稿者名:
  • 投稿年月:
  • #タグ:
  • カテゴリ:
  • 出力順序:

■日付検索:

■カレンダー:

2023年1月
1234567
891011121314
15161718192021
22232425262728
293031

■カテゴリ:

■最近の投稿:

最終更新日時:
2024年4月24日(水) 18時16分16秒