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

今年は開発案件を進めたい

or 管理画面へ

タグ「C言語」を含む投稿[64件]

Icon of admin
 今年も師走です。
 現場は現地照明をもう1件やれば終わり。今期の年末年始は人並みにユックリ出来そうです。
 そんな時は机上の勉強を進めたいものです。物理的な加工や開発・設計ではなくお勉強。特にC言語の勉強です。
 一応書けるのですが、ポインタや構造体についてボンヤリしているところを整理したい。Art-Net関連には特に重要な基礎ですから抑えないといけません。

#C言語
Icon of admin
 セマフォの使い方が見えたので構造の重要な要素は獲得出来ました。
 構成ですが、起動し mmap や pipe を定義し子プロセスの状態を監視する親プロセス「ArtNetPatch」、ユーザーの操作の相手やデータを画面表示をする子プロセス「ArtNetConsole」、Art-Netを送受信しパッチ処理やプロファイルカーブ処理を行う子プロセス「ArtNetEngine」の3本柱にしようと思います。
 子プロセスの生成は fork を使います。fork ならば mmap、pipe、semaqhoe を子プロセスに渡すのが楽です。メモリの消費は多くなるようですが、実体の複製ですからポインタ祭りにならずに済みます。メモリの消費が多いと言っても、私が作るソフトウェアの規模などたかが知れていますので RaspberryPiCM4 の8GBモデルなら楽勝でしょう。
 こういった構造は面倒な気もしますが、プロセス構造をシッカリ作っておけば開発が楽になると思いますし、何よりも「ArtNetEngine」の処理にリソースを集中したいのです。状態監視やユーザー相手は100msec毎で十分ですが、Art-Net の処理は5msec毎が欲しいのです。分散処理というより、求めるラップが違う処理を明確に分けたいのです。
 処理時間を意識してしまうのは PIC マイコンからのクセですが、RaspberryPiCM4 で8ユニバースのパッチ処理をするならダイエットが大事かと。

#[Art-net] #C言語
Icon of admin
 ArtNet-Patch で共有メモリの mmap を使うために セマフォ を勉強しています。mmap へのアクセスを排他的にするためです。
 ただ、プロセス間のセマフォを使うような人は上級者が多いのか解説ページを見てもわかりにくい。
 POSIX系のセマフォは物凄くシンプルな感じがしますが、とどのつまりがわからない。
 man もわかっている人向けなのか引数の記述があるだけ。
 もっと勉強です。

追記
 なんて愚痴っていたらよい記事がありました。
 開始が sem_init だったり sem_open だったりするけど、同じことみたいですからヘッダファイルのプロトタイプ記述を読めば良さそう。
「sem_overview - POSIX セマフォの概要」
「man-pages-ja sem_init(3)」
 次の記事は、パーミッションにおける umask のことが主題ですが、セマフォの使い方がよくわかる。シンプルな記述を示してくれるこんな記事が嬉しい。
「sem_openで、Permission denied になる」
 わかった気になった。

#[Art-net] #C言語
Icon of admin
 少し時間が空いたので ArtNet-Patch を考えていました。
 部分はなんとなく出来ているので、全体の構造をどうするか。
 まずプロセスを分けます。シングルプロセスではたぶんダメ。画面やキーボード操作を親プロセスにし、Art-Net の受信、パッチ処理、送信などを子プロセスとしようかと。子プロセスはタイムアウトする様にし、親プロセスからのリフレッシュが一定時間無ければ自動的に閉じることにします。こうしておけば親プロセスが飛んでも子プロセスがゾンビにならずいいかなと。操作が飛んでも Art-Net は生きている方がいいとする考え方もありますが、タイムアウト処理をコメントにすればそうなります。少なくとも開発中はタイムアウトした方がいいでしょう。
 プロセス間は mmap や Pipe で繋ぎます。データには mmap を用い、コマンドには Pipe を用いるイメージです。
 子プロセスの Art-Net 処理をイメージしながら表示画面やキーボード操作を考えてみましょう。

#[Art-net] #C言語
Icon of admin
 ncurses はウィンドウも定義出来ます。
 今時のウィンドウとは違い、画面の中に子領域を作るイメージです。この領域内で文字位置が指定出来ます。子領域の左上を文字位置の 0,0 として扱えます。
 ダイアログウィンドウを描くことも出来ますし、画面の区分けにも使えます。
 今ネタになっている ArtNet-Patch では、すべてのレイアウトに共通する要素をメイン画面に描き、機能ごとの要素をウィンドウにして描こうかなと。表示位置のオフセット管理が楽になりますし、複数のレイアウトで共通する要素は使いまわしがしやすくなります。
 ncurses はキー入力も受け取れますので、ユーザーの相手にする部分は ncurses で全て作れそうです。
 後は string の使い方を頭に刷り込めば画面は作れるかなと。C言語の欠点は文字列の扱い難さですが、文字列は char の配列であることを頭に染み込ませてから string を勉強しなおしましょう。

 アホかと思うくらいC言語について検索してきたので、これまで ncurses を知らなかったのは何故だろう。

#[Art-net] #C言語
Icon of admin
 C言語のライブラリである ncurses を勉強しています。ANSIエスケープシーケンスを簡単に使える様にしたライブラリです。
 コマンドで全て描画するので今時の画面作りツールに比べたら面倒ですが、ANSIエスケープシーケンスを直接触ると思えば超簡単。歴史の長いライブラリのためか、奇妙な変化球がなくシンプルなのが私好み。
 x-windowベースのグラフィカルな画面にしてもいいのですが、リソースの節約をしたいし、あえてレガシーな風味がいいかなと思っております。
 Art-Netを受信して処理して送信する機能は一応出来ているので、まずは画面作りのお勉強をしましょう。データのモニターが出来ないと見えない部分の動作のチェックもし難いですしね。

#[Art-net] #C言語
Icon of admin
 こんなん欲しいなぁ~と思っていた RaspberryPiCM4 用のマザーボードを発見!
20241109224720-admin.jpg
 中華電機のサイト
 EtherNet が2系統、RTC、電源入力がUSB-Cでなく裏側にある、etc.
 PCI-Ex1 もあれば満点ですが、USB-3.0 が3系統あるので十分です。
 これが入荷したら ArtNet-Patch の開発を再開しようかと。晩酌の肴ですけどね。
 画面作りに ncurses を使えばと思っていましたが、ふと思いついて調べ直したらこれは便利。ネットにも man にもわかり易く整理された情報がないので、お試ししながらオレオレマニュアルを作成して本体ページにアップしましょう。自分の為にですけどね。
 最近、RaspberryPi の価格も下がってきました。CM4 が 中華電機で1万円せずに買えます。

#RaspberryPi #C言語 #[Art-Net]
Icon of admin
 C言語ネタです。
 セマフォを使ったプロセス間での排他制御
 セマフォは異なるプロセスが共有メモリへ同時に読み書きをしないために使おうを思っています。この記事だけではどう使ったらいいか見えませんが、セマフォの機能についてはシンプルに要点を突いて分かりやすい。こういう蛇足が無い説明は好きです。
 ここでは他のプロセスの挙動は説明されていませんが、同じ名前のセマフォ(この記事では"/unko")を開いて同じ様に使います。同じセマフォを持った二つのプロセスがあるとして、後から sem_wait(sem) を実行した側は先に sem_wait(sem) を実行した側が sem_post(sem) を実行するまでブロック(動作を一時停止)します。sem_trywait(sem) を用いればブロックせずに戻りますので戻り値を見て処理を続行出来ます。
 自力でセマフォを作ろうと思っていましたが、この方法でいいんでないかなと。

 セマフォの方針が決まれば必要なことが一通りまとまったことになるので書き始められそうです。
 まずは Art-Net を丁寧に受信する処理から進めます。ネットワーク上のすべての ArtDMX(スロットデータが列挙されたパケット) と存在する送信機の一覧を取得し、別プロセスから読み出して階層的に表示することを当面の目標とします。一種の Art-Net モニタでしょうか。画面を横に3分割し、左に送信機の一覧、中間に選択された送信機が扱うユニバース、右にスロットデータといった構成です。送信機とユニバースをキーボード(カーソル)操作で選択することも習作の一部となります。
 これが作れなければ ArtNetPatch など作れませんし、最終的なパッケージでも欲しい機能です。 

#C言語
Icon of admin
 コンソールの画面操作では「ANSIエスケープシーケンス」を使うイメージでいましたが、「ncurses」と呼ばれる便利なライブラリがあることを今更知りました。これを使えばコンソール画面作りが楽になりそうです。
 キー操作の扱いを調べていたのですが、「C言語で矢印キーの入力を完璧に検出する5つのステップ」を読んでいたら「ncurses」が便利とのこと。ここから調べを進めたところナルホドが連発。「cursesライブラリの超てきとー解説」を読むと概要がわかるような。

#C言語
Icon of admin
 SharedMemory(共有メモリ)であるmmapの使い方が整理出来つつあります。
 検証はこれからですが、理解出来たところをオレメモとして書いておきます。
 あくまで「オレメモ」です。間違いアリアリでよろしくお願いします。
 なお、mmapには様々な用法あるらしい。下記はプロセス間の共有メモリに限った使い方です。
/* mmapを使うためのライブラリ */
#include <sys/mman.h>

/* 共有メモリにテキストを代入する */
char *st;    // 扱うデータの型でmmapのポインタを設定
int msize = 4096;
st = mmap( NULL, msize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 );  // ここまでやってからfork()でプロセスを分ける
*st = 'TEST';    // mmapに「TEST」が代入される(変数をポインタで扱う方法で扱える)

/* 使用後は共有メモリを解放する */
munmap( st, msize );

mmapの引数
1つ目(addr/NULL):mmapを定義するメモリアドレスを設定する項目だが、NULLにしておけばOSが決めてくれる。
2つ目(size/msize):確保するメモリサイズの指定。ページメモリのサイズの倍数にするベシというご意見と、欲しいメモリサイズを指定すればOSが調整してくれるというご意見など色々ある。変数の型からsizeofで得る方法(sizeof(int)など)を使われている方もいる。
3つ目(prot/PROT_READ | PROT_WRITE):読み書きモードを設定する。この書き方だと読み書き両方可能にする。
4つ目(flag/MAP_ANON | MAP_SHARED):MAP_ANONはファイルをマッピングせずに使う指定(共有メモリとして使うだけならこれでいい)、MAP_SHAREDはプロセス間で共有するという指定。
5つ目(fd/-1):ファイルディスクリプタの指定だが、上記でMAP_ANONにしているので-1で無しとする。
6つ目(offset/0):スタートアドレスからどれくらいずらしたところを使うか。

 共有メモリは読み書きのタイミングをマネージしれくれませんので、何かしらの管理をしないといけません。

参考:ページメモリのサイズを取得する
#include <unistd.h>
#include <stdio.h>
long page_size = sysconf( _SC_PAGESIZE );


 ついでにpipeも。
 ただし、ここではpipe2(Linux固有)を使います。pipeの上位互換で引数でノンブロッキングの設定が出来るからです。通常のpipeはパイプが空の場合に有効なデータが取り出せるまで待ってしまいますがO_NONBLOCKを設定すると待ちません。
 なお、以前の書き込みでpipeは単純なスタックと書きましたが、Queue程マネジメントされていないFIFOです。訂正します。
/* pipeを使うためのライブラリ */
#define _GNU_SOURCE  // よくわからないけど必要なおまじない?
#include <fcntl.h>  // O_*(ここではO_NONBLOCK) 定数の定義の取得
#include <unistd.h>  // pipeの本体を呼ぶ

/* pipeの定義 */
int pipefd[2];   // ファイルディスクリプタとしてint配列を用いる 変数の名前は任意
if( pipe2( pipefd, O_NONBLOCK ) < 0 ) {  // ファイルディスクリプタとする配列とノンブロッキングのフラグを引数にする
 // pipe2の戻り値が-1なら設定エラー
}

/* pipeへの書き込み */
char *st = "TEST";
write( pipefd[1], st, strlen( st ) );  // strlenは<string.h>が必要。成功なら書き込んだバイト数、失敗なら-1が戻る。

/* pipeからの読み出し */
char buf[128];
read( pipefd[0], &buf, sizeof( buf ) );  // パイプが空の場合はEOFを得るか戻り値が0になると思われる。成功なら読み取ったしたバイト数、失敗なら-1が戻る。

/* pipeを閉じる(fork()して読み出し側書き込み側に分かれる場合はfork()した後に使わない側を閉じて運用する。もちろん終了する際にはすべて閉じる) */
close( pipefd[0] );  // 読み出しを閉じる
close( pipefd[1] );  // 書き込みを閉じる

 int配列pipefdは[0]が読み出し[1]が書き込みになるファイルディスクリプタ。
#define MEMREAD 0
#define MEMWRITE 1
 などとして使うとわかりやすいかも。

 OSに寄りますが、スタック長は65536バイトが一般的らしい。
 pipeは読み書きのタイミングをマネージしてくれます。


 どちらもファイルを読み書きする手法を応用していますので、ファイルの読み書きの仕方を勉強しなおしてから取り組むとわかりやすいかもしれません。

#C言語

■思ってみた

春ですねぇ~。
花粉症の部下は死にそうですが、暖かいってのはいいことです。

編集

■全文検索:

複合検索窓に切り替える

■複合検索:

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

■日付検索:

■カレンダー:

2024年12月
1234567
891011121314
15161718192021
22232425262728
293031

■カテゴリ:

■最近の投稿:

最終更新日時:
2025年4月29日(火) 20時16分48秒