システム操作 - スレッド/プロセス操作
1.1. マルチスレッドの概要
プロセスとスレッドの概念は、オペレーティングシステム(OS)と一般的なマイコンの最大の違いです。マルチタスクシステムではシステムリソースを分割し、異なるタスクを独立して実行させることができます。また、マクロな視点で見ると、複数のアプリケーションが同時に実行されているように見えます(例:ウェブブラウザを見ながら音楽を再生するなど)。これがプロセスとスレッドを導入する重要なポイントです。
1.2. クイックスタート
1.2.1 開発環境の準備
このドキュメントを初めて読む場合は、『スタートガイド/開発環境の準備/Easy-Eaiコンパイル環境の準備と更新』を一読し、その手順に従ってコンパイル環境の構築を行ってください。
PC上のUbuntuシステムで runスクリプトを実行し、EASY-EAIコンパイル環境に入ります。詳細は以下の通りです。
cd ~/develop_environment./run.sh 22041.2.2 ソースコードのダウンロードとサンプルのコンパイル
EASY-EAIコンパイル環境下で、ソースコードリポジトリを管理するディレクトリを作成します。
cd /optmkdir EASY-EAI-Toolkitcd EASY-EAI-Toolkit- ダウンロードリンク: Demos.zip 上記のリンクから Demos.zip 圧縮ファイルをダウンロードし、仮想マシンの /opt/EASY-EAI-Toolkit ディレクトリにアップロードして解凍します。 対応するサンプルのディレクトリに移動し、コンパイル操作を実行します。具体的なコマンドは以下の通りです。
cd EASY-EAI-Toolkit-1126B/Demos/common-system_opt/./build.sh💡 注意 : 依存ライブラリがボード上に配置されているため、クロスコンパイル中は必ず/mnt のマウントを維持してください。

1.2.2 ソースコードのダウンロードとサンプルのコンパイル 図27
1.2.3 サンプルの実行
シリアルデバッグまたはSSHデバッグを通じてボードのバックグラウンドに入り、サンプルが配置されている場所に移動します。以下の通りです。
cd /userdata/Demo/common-system_opt
1.2.3 サンプルの実行 図28
サンプルの実行コマンドは以下の通りです。
./test-thread-opt1.2.4 実行結果
実行結果は以下のようになります。

1.2.4 実行結果 図29
APIの詳細な説明、およびAPIの呼び出し(本サンプルのソースコード)については、以下の説明を参照してください。
1.3. スレッド操作APIの説明
1.3.1 インクルード/参照方法
EASY EAI api ライブラリは、本リポジトリの easyeai-apiディレクトリにあります。お客様がローカルプロジェクトで EASY EAI apiライブラリを直接呼び出せるように、プロジェクト内でリンクする必要があるライブラリやヘッダーファイル等を以下にリストアップしています。
| 説明 | CMakeでの記述 | Makefileでの記述 |
|---|---|---|
| api.cmake | ${common_root}/system_opt/api.cmake | 無し |
| ヘッダーファイルディレクトリ | ${SYSTEM_OPT_INCLUDE_DIRS} | -I ../../easyeai-api/common/system_opt |
| ソースファイルディレクトリ | ${SYSTEM_OPT_SOURCE_DIRS} | ../../easyeai-api/common/system_opt |
| ライブラリファイルディレクトリ | 無し | 無し |
| ライブラリリンクパラメータ | ${SYSTEM_OPT_LIBS} | 無し |
APIソースコードのパスはEASY-EAI-Toolkit-1126B/easyeai-api/common/system_opt/です。ユーザーはソースコードを通じてインターフェースの実装を確認でき、ソースコードを直接変更することも可能です。
1.3.2 スレッドタスクのプロトタイプ
スレッドタスクのプロトタイプは以下の通りです。スレッドタスクはプログラム実行の最小単位であり、以下のように定義されます。
typedef void \*(\*ThreadEntryPtrType)(void \*);1.3.3 スレッド作成関数
スレッド作成関数のプロトタイプは以下の通りです。
int32_t CreateNormalThread(ThreadEntryPtrType entry, void \*para, pthread_t \*pid);具体的な説明は以下の通りです。
| 関数名:CreateNormalThread() | 詳細 |
|---|---|
| ヘッダーファイル | easyeai-api/common/system_opt/system_opt.h |
| 入力パラメータ | entry:スレッドの本体となる実行関数 para:スレッドに渡す引数(共有変数として使用) pid:新規作成される pthread_t 型オブジェクトへのポインタ |
| 戻り値 | 作成失敗時は -1 を返す 作成成功時は 0 を返す |
| 注意事項 | pid 変数はシステムが割り当てるスレッドIDを格納するために使用されます。NULLを渡すとプログラムが異常終了する原因になります。 |
1.3.4 シェルコマンドの実行 - system() の呼び出し
シェルコマンドを実行する関数のプロトタイプは以下の通りです。
int32_t exec_cmd_by_system(const char \*cmd);この関数は system() を呼び出すことで実装されています。具体的な説明は以下の通りです。
| 関数名:exec_cmd_by_system() | 詳細 |
|---|---|
| ヘッダーファイル | easyeai-api/common/system_opt/system_opt.h |
| 入力パラメータ | cmd:シェルコマンド |
| 戻り値 | forkに失敗した場合、system() 関数は -1 を返します。execが成功し、コマンドが正常に終了した場合、コマンドが exit または return で返した値を返します。 |
| 注意事項 | 1. エラー時により有用な情報を得るため、system() 実行後の errno 値を監視することを推奨します。 2. 非同期(ノンブロッキング)実行の注意点:コマンドをバックグラウンドへ移行させるため & を付与し、同時に出力をリダイレクトしてください。そうしないとブロッキング実行になります。 |
1.3.5 シェルコマンドの実行 - popen() の呼び出し
シェルコマンドを実行する関数のプロトタイプは以下の通りです。
int32_t exec_cmd_by_popen(const char \*cmd, char \*result);この関数は popen() を呼び出すことで実装されており、実行結果を取得することができます。具体的な説明は以下の通りです。
| 関数名:exec_cmd_by_popen() | 詳細 |
|---|---|
| ヘッダーファイル | easyeai-api/common/system_opt/system_opt.h |
| 入力パラメータ | cmd:シェルコマンド result:シェルコマンド実行後、返された結果がこのメモリ領域に格納されます |
| 戻り値 | 呼び出し失敗時は -1 を返す 呼び出し成功時は 0 を返す(result に正常に書き込まれた状態) |
| 注意事項 | コマンドの実行に失敗した場合、子プロセスはエラーメッセージを標準エラー出力にプリントするため、親プロセスはそれを取得できません。 エラーメッセージをキャプチャする必要がある場合は、子プロセスのエラー出力を標準出力にリダイレクト(2>&1)してください。これにより、親プロセスでエラー情報を取得できるようになります。 例:exec_cmd_by_popen(“ls 2>&1”, result); |
1.4. スレッド操作APIの使用例
スレッド操作APIの使用例となるコードのパスは以下の通りです:
EASY-EAI-Toolkit-1126B/Demos/common-system_opt/test-thread-opt.c スレッド作成のケースは、「スレッド実行本体」と「スレッド作成操作」の2つの部分で構成されています。
スレッド実行本体は以下の通りです。
void *testThreadBody(void *arg){int *share_para = (int *)arg;while(1){printf("[tesThread] --- share_para = %d\n", *share_para);if(*share_para > 10){printf("[tesThread] --- exit\n");break;}sleep(1);}pthread_exit(NULL);}スレッド作成操作は以下の通りです。pId変数はプロセス(スレッド)IDの格納に使用され、share_para変数は入力パラメータを保持します。
pthread_t pId;int share_para = 0;if(0 == CreateNormalThread(testThreadBody, &share_para,&pId)){while(1){printf("[mainThread] --- \n");share_para++;sleep(1);}}