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

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

or 管理画面へ

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

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言語
Icon of admin
 プロセス間通信を大別しますと、SharedMemory(mmap含む)、Pipe、Queueです。左から「速いけど扱いが難しい」→「扱いが簡単だけど遅い」となるようです。
 SharedMemoryは初期定義でメモリサイズを指定しなければなりませんが、型の指定は無く、ポインタを使った変数アクセスの要領で使えます。メモリサイズが最初から固定されるので実質的には型が決まった変数となりますが、読み出してもデータが残ることが特性でしょうか。
 PipeはマネージされないQueueと思って捉えています。FIFOみたいな挙動で単純な受け渡しをする一時スタックです。
 QueueはPipeが高度にマネージされFIFOまたはLIFOとして機能するイメージです。遅いのが難点ですが、速度を求めないなら便利な手段です。
 SharedMemoryとPipeはどちらが速いか論争があるようですが、消さなければ残るメモリーと読みだしたら消える一時スタックというそもそもの違いがある上に、転送速度は誤差レベルの違いしか無いように思われますので、用途に合わせて使い分けるだけかなと・・・。

 ネットの情報にも教科書にも、これらの違いを一覧してくれる情報がほとんどありません。関数のパラメータや動作特性などのそもそもの説明がなく、どれが速いか遅いかって比較があればましな方です。コピペの様なソースコードに「俺ってスゲーと思わね?」って感じの斜め上の応用を加えたコードが書かれている物ばかり。説明をしてくれる気持ちはありがたいのだけど、中途半端な応用に本筋が埋もれたサンプルコードを誰が喜ぶのかと疑問を感じたりしています。大変勝手な言い方ですが、検索結果が無駄に多くなって分かりやすい情報が埋もれてしまいますので、ガチのプロは見向きもしない、初心者には伝わらない、そんな「俺スゲーでしょ解説」はお控え願いたいものです。斜め上の応用は書く人それぞれのクセであって一般論とは言い難いのですし。
 上記はネット検索で迷宮を彷徨ってしまった思いからの愚痴です。わかってんなら書けよとか言われそうですが、人に教えられる程習得出来たら是非書きたいものです。

#C言語
Icon of admin
 ホール管理の増員で置きダヌキ。
 こういう時はArt-Netパッチの設計を進めるのがいい。いつでも作業を切れるって意味でも不便がありません。
 構造においてはマルチプロセス化することがとても重要です。RasperryPi4Bは4コアありますが手続き型処理はもちろんマルチスレッドでも1コア動作が原則。Art-Netの入力、パッチ処理、出力、フロントエンドの処理を同時並行で行いたいのですが、複数のコアで動くかはOS次第とはいえプロセスを分散しておけば1コアだけに負担がかかることは無くなるので良いかなと思うのです。
 現在の研究課題はプロセス間通信です。例え一つのアプリケーション内でもプロセスを分けてしまうと同じ変数を触ることが出来ません。これを解消するのがプロセス間通信で、SharedMemory、Pipe、Queueなどの手法があります。それぞれに得手不得手があり、扱いが楽な手法は受け渡しが遅く、受け渡しが速い手法は扱いが難しい傾向があります。このどれを使うかで処理構造が違ってくるので、全体の設計を進める上ではどの手法で繋げるかを予め決めておかないと後が面倒なようです。
 注意する点は読み書きのタイミングとデータ枠が可変するかどうかです。勉強中なので説明するのは難しいのですが、この辺りを十分に整理して手段を吟味しているところです。

#C言語 #[Art-Net]
Icon of admin
 先週末は現場が被りまくりでオロオロしてましたが、今週は比較的ヒマなので少しはネタを進められそうです。
 プロセス間の共有メモリの読み書き管理はフローチャートレベルではまとまりました。デフォルトでは読み書きを禁止しておき、認証プロセス(スレッド)へ要求を出し読み書きの許可を得るものです。どちらかがアクセスしている間は他方の処理を待たせます。いわゆるセマフォです。
 この方法で本当にいいのか、タイムアウトなどの例外処理は必要か、その辺りは今後吟味です。
 主処理の実験は以前の試作で済んでいますので、こういった周辺機能をキチンと書くのが今の課題です。

#C言語 #[Art-Net]
Icon of admin
 共有メモリの読み書きのタイミングを考えています。
 Art-Netを受信して現在値を得る部分とそれを読みだしてパッチなりの加工をする部分はプロセスを分けようと思います。C言語では手続き型で書いても関数型で書いても基本は1プロセスで動作します。RaspberryPiでも1プロセスですべての処理を行っても間に合うと言えば間に合うのですが、プロセスを分けておいた方が処理に余裕が出来て後々いいかなと。
 プロセスを分けることのメリットはあるのですが、問題はプロセス間のデータ共有、共有メモリへのアクセスのタイミングです。受信プロセスが共有メモリに書いている最中に次処理のプロセスが読み出すとデータに不整合が起こります。一つのプロセスやスレッドで読み書きを行うなら手続きの順番的に起こらないことですが、それぞれが平行して勝手に動いていれば起こりうることです。書き込んでいる最中は読み出しを待たせ、読み出している最中には書き込みを待たせる仕組みが必要です。
 共有メモリは単純な機構のために速度が期待できる反面この様なマネージはされていません。書き込んでもいいぞ読み出してもいいぞとタイミングをジャッジする仕組みは自作しないといけないのです。
 機構は単純ですが、吟味しないと潜在的なバグ要因になりそうです。

#C言語
Icon of admin
 「PyOpenDmxUsb」の「DMXServer.cs」を読むと「FTD2XX.dll」をコールしているがわかります。
 ならば、C++ 化することは可能っぽいです。先日書き込みした C/C++ による Python ライブラリ化を参考にすれば作れるかも。
 C#のコードを Python ライブラリ化してもいいのでしょうけど。

 ちなみに DoctorMX については C/C++ の世代変わりの壁で対策がわかりません。
 kuwatecさんが公開されているのは VC6 世代のコードようですが、C++はその後の時代に多くの改変がされているらしいのです。

#器具の製作 #C言語 #Python
Icon of admin
 VSCode でC言語の Python ライブラリを作る際、ラッパーには Python.h が必須です。
 ですが、
#include <Python.h>
 と書くと「Python.h なんて無いよ」と言われてしまいます。
 フルパスで指定すれば通りますがこれは避けたい。
 VSCode の拡張機能 C/C++ の設定に追加をします。「C/Cpp > Default:Include Path」の「項目の追加」から Python.h がある階層のパスを追加します。Python のインストールによってパスが違うのでそれに合わせて指定します。

#C言語 #Python
Icon of admin
 「error: Unable to find vcvarsall.bat」とのエラーで困ったものの解決しました。
 以下、オレメモであります。
 あえて gcc を使うのは Linux で標準だからです。

VSCode で gcc を使う

2023年9月10日実施

● OS
エディション: Windows11 Pro x64
バージョン: 21H2

● Visual Studio Code
バージョン: 1.74.2 (user setup)

※ ダウンロード量が 1.8GB くらいあるのでネット回線が良好な環境での作業を推奨します。

● gcc をインストールする
・gcc を GitHub からダウンロード
 https://github.com/niXman/mingw-builds-b...
 「Release of 13.1.0-rt_v11-rev1」の項から Windows64bit版
 ダウンロード項目: x86_64-13.1.0-release-win32-seh-msvcrt-rt_v11-rev1.7z
・圧縮ファイルなので解凍する。.7z ファイルは CubeICE で解凍可能。「mingw64」フォルダが出来る。
・「mingw64」フォルダごと任意の位置に配置する。"C:\Program Files"が適当?」
・PATH を通しておく。環境変数のPATHに「mingw64\bin」を追加する。今回は"C:\Program Files\mingw64\bin"とする。
 「Windowsメニュー」→「設定」→「システム」→「バージョン情報」
 →「関連リンク」の行の「システムの詳細設定」をクリック。
 → ウィンドウ下の方の「環境変数」をクリック。
 → 上段のリスト、PATHの行をクリックし、「編集」をクリック。
 → 表示されたリストに"C:\Program Files\mingw64\bin"を追記する。
 → 追記したら閉じる。
・確認
 コマンドプロンプトか Power Shell で次を実行
> gcc -v
 もろもろ表示された最後に以下が表示されればOK。
gcc version 13.1.0 (x86_64-win32-seh-rev1, Built by MinGW-Builds project)

● Microsoft C++ Build Tools をインストールする
・microsoft のサイトよりインストーラーをダウンロード
 https://visualstudio.microsoft.com/ja/vi...
 ※「Microsoft C++ Build Tools」で検索しても上記 URL に行きつかない。試行錯誤中、偶然行きついた。
・ブラウザの「Build Tools のダウンロード」をクリックすると「vs_BuildTools.exe」がダウンロードされる
・ダウンロードしたインストーラーを起動する。
・「Visual Studio Installer」と画面が出てファイルのダウンロードが始まる。
・画面が切り替わり、右項目「インストールの詳細」に「MSBuild Tools」が表示されているの確認。
・左項目「C++によるデスクトップ開発」をクリック。右項目「インストールの詳細」に追加されているのを確認。オプションはデフォストのまま。
・右下の「インストール」をクリック。終わるまで待つ。ダウンロード量が 1.7GB ある。かなり時間がかかる。
・終了したら Windows を再起動する。

● VSCode の設定・・・拡張機能をインストール
・C/C++ Extension Pack
・Code Runner

● VSCode の設定・・・拡張機能の設定
・Code Runner
 Code-runner: Run In Terminal
  → チェックを入れる
 Code-runner: Executor Map
  → settings.json をクリック
  → "c" に -fexec-charset=CP932 を書き加える
 - "c" : "cd $dir && gcc $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
 + "c" : "cd $dir && gcc -fexec-charset=CP932 $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",


 次のサイトの例題がコンパイル出来、Python からの呼び出しで動作しました。
「PythonからC言語の関数を呼び出す(基本編)」

 C/C++のライブラリを Python で呼び出せると製作の幅が広がります。
 手始めにしては難しい課題ですが、DoctorMX を Python から使えるようにしてみたいですね。

#C言語 #Python

■当面の課題

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

編集

■全文検索:

複合検索窓に切り替える

■複合検索:

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

■日付検索:

■カレンダー:

2024年3月
12
3456789
10111213141516
17181920212223
24252627282930
31

■カテゴリ:

■最近の投稿:

最終更新日時:
2024年4月26日(金) 20時14分22秒