第 3 章 初歩の RTLinux プログラミング 27
3.6 LinuxプロセスからRTLinuxモジュールを制御する
★終了時の関数
pthread_cancel関数は、引数に終了要求を出すスレッドIDを指定します。pthread_join関数も第1引数に
同じくスレッドIDを指定します。第2引数は、ここではNULLにしています。
なお、pthread_exit関数でRTLinuxスレッドの処理を終わらせた場合、pthread_exit関数の引数が、
pthread_join関数の第2引数に格納されます。
以下に例を示します。
void* input_task(void *arg) {
int status = 10;
・・・
pthread_exit(status);
・・・
}
void cleanup_module(void) {
int value;
pthread_join(send_thread, &value); // valueには10が格納されます ・・・
}
下記Listは、LinuxプロセスとRTLinuxモジュール間で、共通で使う定義ファイルです。ファイル名 を『sample3.h』として入力,保存してください。
sample3.h 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
sample3.h 共通定義ヘッダファイル
Copyright 2002 Interface Corporation. All rights reserved.
*/
#if !defined(___SAMPLE3_H)
#define ___SAMPLE3_H
/* const defines --- */
#define GET_HANDLER_FIFO 1 /* Linuxプロセスから指令を受け取るFIFOチャネル */
#define GET_TASK_FIFO 2 /* ハンドラから指令を受け渡しするFIFOチャネル */
#define SET_TASK_FIFO 3 /* Linuxプロセスへ結果を送るFIFOチャネル */
#define BUFF_SIZE 100 /* Linuxプロセスへ結果を送るFIFOチャネルのサイズ */
/* type defines --- */
/* コマンドID群(RTLinuxスレッドへの指示用) */
enum CMD_IDS {
ID_START, /* スタート指示 */
ID_STOP /* ストップ指示 */
};
/* コマンド指示用の構造体 */
struct CMD_STRUCT {
enum CMD_IDS id; /* コマンドID */
long value; /* 設定用パラメータ*/
};
#endif
下記Listは、Linuxプロセスのソースファイルです。ファイル名を『sample3.c』として入力,保存し てください。
sample3.c 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
sample3.c Linuxプロセスのソースコード
Copyright 2002 Interface Corporation. All rights reserved.
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <rtl_fifo.h>
#include "sample3.h"
/* Linuxプロセスのメインルーチン */
int main(void) {
int fd_ret, fd_ctrl;
fd_set rfds;
struct timeval tv;
struct CMD_STRUCT cmd;
long counter = 0; /* 周期スレッドのチェック用カウンタ */
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
if((fd_ctrl = open("/dev/rtf1", O_WRONLY)) < 0){
fprintf(stderr, "failed to open /dev/rtf1¥n");
return -1;
}
/* RTLinuxスレッドからの結果を受け取るFIFOチャネルのオープン */
if((fd_ret = open("/dev/rtf3", O_RDONLY)) < 0){
fprintf(stderr, "failed to open /dev/rtf3¥n");
return -1;
}
/* RTLinuxスレッドへの実行開始の指示 */
cmd.id = ID_START;
cmd.value = 500; /* 500ms周期実行に設定 */
if(write(fd_ctrl, &cmd, sizeof(cmd)) < 0){
fprintf(stderr, "failed to send the start command¥n");
return -1;
}
/* RTLinuxスレッドのカウンタが10になるまで取得のループ */
do {
FD_ZERO(&rfds);
FD_SET(fd_ret, &rfds);
tv.tv_sec = 30; /* select関数のタイムアウト値の設定:30秒 */
tv.tv_usec = 0;
/* RTLinuxスレッドからのデータ受け取り */
if(select(FD_SETSIZE, &rfds, NULL, NULL, &tv) > 0){
if(FD_ISSET(fd_ret, &rfds)){ /* fd_retに対してFIFOの書き込みがあった */
read(fd_ret, &counter, sizeof(counter));
printf("counter:%ld¥n", counter);
}
}
}while(counter < 10);
/* RTLinuxスレッドへの停止指示 */
cmd.id = ID_STOP;
cmd.value = 0;
if(write(fd_ctrl, &cmd, sizeof(cmd)) < 0){
fprintf(stderr, "failed to send the stop command¥n");
return -1;
}
printf("The Linux process is successfully completed.¥n");
return 0;
}
下記は、RTLinuxで動作するRTLinuxモジュールのソースファイルです。ファイル名を『module3.c』
として入力,保存してください。
module3.c 1
2 3 4
/*
module3.c RTLinuxモジュール
Copyright 2002 Interface Corporation. All rights reserved.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
/* 周期実行を行うRTLinuxスレッド */
void* my_task(void* arg) {
int err;
struct CMD_STRUCT cmd;
long counter = 0, temp_counter;
rtl_printf("call my_task arg=%d¥n", arg);
/* RTLinuxスレッドが組み込み中、動作する永久ループ */
while(1){
/* 自スレッドをスリープさせる */
pthread_wait_np();
/* FIFOチャネルからの取り込み */
if((err = rtf_get(GET_TASK_FIFO, &cmd, sizeof(cmd))) == sizeof(cmd)){
rtl_printf("my_task: get command id=%d value=%d¥n", cmd.id, cmd.value);
switch(cmd.id){
case ID_START: /* 周期実行の設定と開始 */
rtl_printf("my_task: start!!¥n");
pthread_make_periodic_np(pthread_self(), gethrtime(),
cmd.value * 1000 * 1000);
counter = 0; /* 周期カウンタのリセット(ms) */
break;
case ID_STOP: /* 周期実行の停止 */
rtl_printf("my_task: stop!!¥n");
pthread_suspend_np(pthread_self());
break;
default:
rtl_printf("my_task: unknown command!!¥n");
break;
}
}
/* 周期カウンタのカウントアップ */
counter++;
rtl_printf("my_task: counter=%d¥n", counter);
/* カウンタ値を、LinuxプロセスへのFIFOチャネルに書き込み */
temp_counter = counter;
rtf_put(SET_TASK_FIFO, &temp_counter, sizeof(temp_counter));
} return 0;
}
/* Linuxプロセスからの指令を受け取るハンドラ */
int my_handler(unsigned int fifo) {
int ret;
struct CMD_STRUCT cmd;
rtl_printf("call my_handler fifo:%d¥n", fifo);
/* Linuxプロセスからの指示を、RTLinuxスレッドのFIFOチャネルに横流しする */
while((ret = rtf_get(GET_HANDLER_FIFO, &cmd, sizeof(cmd))) == sizeof(cmd)){
rtf_put(GET_TASK_FIFO, &cmd, sizeof(cmd));
rtl_printf("my_handler: get command id=%d value=%d¥n", cmd.id, cmd.value);
pthread_wakeup_np(my_task_info);
}
if(ret != 0){
rtl_printf("my_handler: error!!(%d)¥n", ret);
return -EINVAL;
}
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
}
/* 初期化モジュール(RTLinuxモジュールが起動する時、呼ばれる関数) */
int init_module(void) {
rtl_printf("call init_module¥n");
EXPORT_NO_SYMBOLS;
/* Linuxプロセスからの指示を受け取るハンドラとFIFOチャネルを生成する */
rtf_destroy(GET_HANDLER_FIFO);
rtf_create(GET_HANDLER_FIFO, sizeof(struct CMD_STRUCT));
rtf_create_handler(GET_HANDLER_FIFO, my_handler);
/* ハンドラとLinuxプロセスの間のFIFOチャネルを生成する */
rtf_destroy(GET_TASK_FIFO);
rtf_create(GET_TASK_FIFO, sizeof(struct CMD_STRUCT));
/* Linuxプロセスへ結果を送るFIFOチャネルを生成する */
rtf_destroy(SET_TASK_FIFO);
rtf_create(SET_TASK_FIFO, sizeof(long) * BUFF_SIZE);
/* スレッドを作成、起動する */
return pthread_create(&my_task_info, NULL, (void*)my_task, 0);
}
/* 終了モジュール(RTLinuxモジュールが終了する時、呼ばれる関数) */
void cleanup_module(void) {
rtl_printf("call cleanup_module¥n");
/* FIFOチャネルを閉じる */
rtf_destroy(GET_HANDLER_FIFO);
rtf_destroy(SET_TASK_FIFO);
rtf_destroy(GET_TASK_FIFO);
/* スレッドを終了させる */
pthread_cancel(my_task_info);
pthread_join(my_task_info, NULL);
}
下記は、上記ファイルをコンパイルするメイクファイルです。ファイル名を『makefile』として入 力,保存してください。
makefile 1
2 3 4 5 6 7 8
include /usr/include/rtlinux/rtl.mk all: module3.o sample3
sample3: sample3.c
$(CC) $(INCLUDE) $(USER_CFLAGS) -O2 -Wall -o sample3 sample3.c module3.o: module3.c
$(CC) $(INCLUDE) $(CFLAGS) -o module3.o -c module3.c
コンパイルし、insmodコマンドでRTLinuxモジュールを登録します。
# make
# ls
makefile sample3 module3.c module3.o sample3.c sample3.h
# insmod module3.o ← RTLinuxモジュールを組み込んでいます
次に、Linuxプロセスを実行します。
# ./sample3 ← Linuxプロセスを実行しています
★./を何故付けるか?
上の例で、Linuxプロセスを実行させるのに、「./」を付けて、実行ファイルがカレントディレクトリ上にあること を明示しています。
もし、これを付けないと、「command not found」となってしまいます。
WindowsやMS-DOSでは、相対/絶対パスを付けずに、実行ファイルを呼び出すと、カレントディレクトリから実行
ファイルを検索しますが、Linux(Unix)では、そうはならず、設定されたパス通りに検索が行われます。
カレントディレクトリ上にあるファイルを実行させるには、必ず「./」を付加してください。
実行画面を以下に示します。
(画面左上のウィンドウがLinuxプロセスを実行しているコンソール。画面右下のウィンドウは RTLinuxモジュールのログメッセージを表示させているコンソールです)
sample3を実行させると、「get counter」の値がカウントアップしていき、10を表示した後、プロ グラムが終了します。