• 締切済み

Linuxのgccでセマフォをやりたい。

gccプログラムでマルチタスクのプログラミングをやっています。 https://sourceforge.jp/projects/cc1101driver/scm/svn/blobs/2433/trunk/20140411/main.c 以前、H8マイコンに組み込みOSを使用した際に、複数のタスクを動作させている際に、各タスクがwhile(1)で永久ループの状態をしている際に、その永久ループを一時停止するためのロック・アンロック専用のタスクを1つ作って、各タスクのロック・アンロックして動作を制御することをやったことがありました。 確かロックの場合はSempend();というので、アンロックというのはSempost();という物だったと思いました。 例えばTASK1,TASK2,TASK3という3つのタスクを作成し、それぞれを制御したい場合は、 例えばTASK1のセマフォをアンロックしたい場合は Sempost(LockTask1); このようにしたらTASK1が動作し始め、ロックしたい場合はSempend(LockTask1);というようにしたいと思います。 次の例のようなセマフォ制御をLinuxのgccのセマフォプログラミングで行うことは可能でしょうか? どうぞ、ご教示頂きますようお願い致します。 (例) //タスクセマフォ制御用タスク TASK_SEM_CTL() { while(1) { Sempost(LockTask1); delay(1000) //1sec wait Sempost(LockTask2); delay(1000) //1sec wait Sempost(LockTask3); delay(1000) //1sec wait } } TASK1 { while(1) { Sempend(LockTask1); printf("TASK1_done"); Sempost(LockTask1); } } TASK2 { while(1) { Sempend(LockTask2); printf("TASK2_done"); Sempost(LockTask2); } } TASK3 { while(1) { Sempend(LockTask3); printf("TASK3_done"); Sempost(LockTask3); } }

みんなの回答

回答No.1

condition variable を使うのはいかがでしょう。 /* CだとめんどっちーのでC++で軽くやってみた */ #include <iostream> #include <chrono> #include <thread> #include <condition_variable> using namespace std; condition_variable cond; bool work; mutex mtx; unique_lock<mutex> lck(mtx); void worker() { int count = 0; while(true && count < 100) { cond.wait(lck, [&]() { return work; }); // work が true になるまで待機する cout << ++count << endl; this_thread::sleep_for(chrono::milliseconds(30)); } } int main() { work = false; thread thr(worker); // スレッドを起こす for ( int i = 0; i < 10; ++i ) { // 500msごとに止めたり動かしたり this_thread::sleep_for(chrono::milliseconds(500)); work = !work; cond.notify_one(); } work = true; cond.notify_one(); thr.join(); }

techhouse
質問者

お礼

回答頂きありがとうございます。この度は大変返事が遅くなり誠に申し訳ありません。 セマフォが使えるという方法があることがわかり大変助かります。C++でのコーディングで可能とのことで検討していきたいと思っております。またこの問題にこの先出くわすと思いますので、その際にはまたご相談のほどよろしくお願い致します。 大変助かります。

関連するQ&A

  • Linuxプログラミングで、キーボードの値がほしい

    Linuxのgccでのプログラミングで、キーボードのどのキーが押されたのかを変数に代入したりして取得したりすることはできないでしょうか? 例えば、while分で永久ループを作っておいて、 while(1) { if(aのキーが押されている場合) printf("A key is pushing!") elseif(sのキーが押されている場合) printf("B key is pushing!") elseif(dのキーが押されている場合) printf("D key is pushing!") ・・・ } このようなプログラムを作ることはできないでしょうか? どうぞ、ご教授の程よろしくお願い致します。

  • RTOSのセマフォの使い方についての疑問

    今、H8S2368というマイコンを使って、RTOSのuCOSについて勉強しているところなのですが、RTOSがどのように動いているのかというのをイメージすることができなくて質問させていただきます。 たとえば、3つのタスクを宣言して、Swというタスクで、OscWaitというセマフォを使って、”OSSemPend(OscWait, 500, &err);”の500ミリ秒でタイムアウトが発生して、”OSSemPost(OscWait);”でセマフォを解除して、OscWaitで止まっていたOsc,Osc02のタスクを動かした場合、この場合、どのようにタスク内のプログラムは動きだすのでしょうか。 たぶんなのですが、Oscのタスクの方がプライオリティが高いので、こちらがまず動いて、while文で再度”OSSemPend(OscWait, 100, &err);”でOscWaitの信号が赤になって止まって、それから、Osc02のタスクが動き始めて、というのを繰り返すものと考えているのですが、そのように考えてよいのでしょうか? #define TASK_SW_ID 5 #define TASK_OSC_ID 6 #define TASK_OSC02_ID 7 #define TASK_SW_PRIORITY 30 #define TASK_OSC_PRIORITY 31 #define TASK_OSC02_PRIORITY 32 #define TASK_OSC_STK_SIZE 0x200 #define TASK_OSC02_STK_SIZE 0x200 #define TASK_SW_STK_SIZE 0x200 DECLARE_TASK(Sw,TASK_SW_STK_SIZE,TASK_SW_ID); DECLARE_TASK(Osc,TASK_OSC_STK_SIZE,TASK_OSC_ID); DECLARE_TASK(Osc02,TASK_OSC02_STK_SIZE,TASK_OSC02_ID); CAEATE_TASK(Sw ,TASK_SW_STK_SIZE ,TASK_SW_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); CAEATE_TASK(Osc ,TASK_OSC_STK_SIZE ,TASK_OSC_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); CAEATE_TASK(Osc02 ,TASK_OSC02_STK_SIZE ,TASK_OSC02_PRIORITY,0x00/*OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR*/); OS_EVENT *OscWaitt; DECLARE_TASK_FUNC(Sw) { BYTE err; OscWait = OSSemCreate(0); parg = parg; while(1) { OSSemPend(OscWait, 500, &err); OSSemPost(OscWait); } } DECLARE_TASK_FUNC(Osc) { BYTE err; OscWait = OSSemCreate(0); parg = parg; while(1) { OSSemPend(OscWait, 100, &err); if(err != 0){ continue; } OSC_temp++; printf("OSC_temp %d \n\r",OSC_temp); } } DECLARE_TASK_FUNC(Osc02) { u16 cur,old; u8 OSC_temp02=0; BYTE err; OscWait = OSSemCreate(0); parg = parg; while(1) { OSSemPend(OscWait, 100, &err); if(err != 0){ continue; } OSC_temp02++; printf("OSC_temp02 %d \n\r",OSC_temp02); } }

  • pthread_cond_wait での mutex

    以下の様なサンプルプログラム(一部省略)があります。 bossスレッドが1秒ごとにworkerスレッドを起こして、workerスレッドは処理後、再び眠ります。 worker () { while (...) { * pthread_mutex_lock(&g_lock); pthread_cond_wait(&g_signal, &g_lock); * pthread_mutex_unlock(&g_lock); : } } boss() { while (...) { wait( 1 ); * pthread_mutex_lock(&g_lock); pthread_cond_signal(&g_signal) * pthread_mutex_unlock(&g_lock); } } waitで待機し、signalで起こされるのはわかるのですが、 mutexでロックしている意味がわかりません。 mutexが不必要な処理の場合、*部分はいらないのでしょうか?

  • マイコンによるDCモータの制御

    マイコンでDCモータの正転、逆転を制御したいのですがうまくいきません。 お力添えをお願いします。 ・使用するマイコン:PIC16F84A IC:TA7291P ・させたい動作 RB1のスイッチが押されると、2秒正転、2秒静止、2秒逆転、2秒静止→ループ ・問題点 マイコンからの出力をLEDに変えるとこの動作はうまくいくのですが、ICに出力するとうまくいきません。下にプログラムの一部を書きますが、while(s_f==1)のループに入れていないようです。 また、ICへの出力をマイコンからではなく、電源からの電流をスイッチングすると正転、逆転はうまくいきます。 マイコンとICの間に何かはさむ必要があるのでしょうか? while(1){ if(RB1==0) { while(s_f==1){ /*動作内容*/ RB4=1; RB5=0; delay(2000); //2秒待つ PORTB=0; delay(2000); RB4=0; RB5=0; delay(2000); RB4=0; RB5=1; delay(2000); } } }

  • デッドロック回避のためのwait() notify()

    学生です。最近javaの勉強をはじめました。 synchronized statementでデットロック回避のためにwait() notify()の使い方がよくわかりません。本にはwait()はスレッドがsynchronizedで獲得してあるロックを解放し、待機状態に入るとのことを書いてありましたが、なぜ、wait()をwhileループでまわすのでしょうか? それと、notifyは待機状態のスレッドに対して通知し、通知されたスレッドは待機状態から実行状態に移るとのことですが、whileループで再びwait()を実行し永遠に抜け出せないと思うのですがどうなんでしょうか? お手数ですが、詳しい方がいらしたら教えていただけないでしょうかお願いします。

  • スレッドの待機と再開

    お世話になります。 マルチスレッドのプログラムで悩んでいます。 public class ThreadLocker {  private static boolean isLocked = false;    public static void lock() {   isLocked = true;   while(isLocked) { ; }  }    public static void unlock() {   isLocked = false;  } } まず、このようなクラスを定義しました。そして複数のスレッドが ThreadLocker.lock(); を呼び出して、処理の進行をストップしている状態があるとします。この状態に対して、とある別のスレッドが ThreadLocker.unlock(); を呼び出すと、それまで無限ループしていたスレッドが解放されて処理を始める、という感じです。 この方法を試してみましたが、無限ループで何も処理をしていないとは言え、リソースを食いまくっているようで、マシンが重くなってしまいました。 そこで、スレッドの待機・再開を行う事ができる wait / notify(All?) メソッドを使用すれば良いのではないかと考えたのですが、具体的な方法が分からず、質問させていただきました。 具体的に、どのインスタンスの wait 及び notify(All?) を呼び出せば良いのかが分かりません。 APIリファレンスの「現在のスレッドはこのオブジェクトのモニターのオーナでなければなりません。」の意味もよく分かりません。 ちなみに、待機しているスレッドは複数あり、class Lock の method execute 中で ThreadLocker.lock() しているとします。 また、再開を促すスレッドは1つで、class Unlock の method execute 中で ThreadLocker.unlock() を呼び出すものとします。 そして、それぞれのスレッドは、お互いのインスタンスを知りません。(説明しづらいので、補足要求があれば、ソースで示します。) よろしくお願いいたします。

    • ベストアンサー
    • Java
  • 作成したbシェルを実行すると無限ループになってしまいます

    テストの為のデータをファイルに出力したいんですが無限ループになります。 #!/bin/sh i=1001 x=1 y=1 while [ $x -le 100 ]; do printf "$i,1019,001,3989,01" while [ $y -le 100 ]; do printf "01,00987,0,0,11,高橋," y='expr $y + 1' done i='expr $i + 1' x='expr $x + 1' y=1 done > test.csv カンマで区切った最初のデータを100個、 次のデータを100個ファイルに入れたいんですが、 実行すると無限ループになります。

  • OSSemCreate関数に引数”1”と入れた場合動作。

    セマフォを作るためのOSSemCreate関数について質問なのですが、 ”OscWait = OSSemCreate(1);”という引数に1を入れた場合は ”OscWait = OSSemCreate(0);”の時と動作にどのような違いがでるのでしょうか? H8S2368マイコンにuCOSというRTOSを組み込んでいるプログラムを見せてもらっているのですが、セマフォを作る場合は ”OscWait = OSSemCreate(0);”というように記述すればよいというのはなんとなくわかったのですが、 所々、”OSSemCreate(1);”という記述もあり、どのように使い分けているのかがわかりません。 どのような意味で、このようにして使っているのでしょうか? DECLARE_TASK_FUNC(Sw) { BYTE err; OscWait = OSSemCreate(1); parg = parg; while(1) { OSSemPend(OscWait, 500, &err); OSSemPost(OscWait); } } DECLARE_TASK_FUNC(Osc) { BYTE err; parg = parg; while(1) { OSSemPend(OscWait, 100, &err); if(err != 0){ continue; } OSC_temp++; printf("OSC_temp %d \n\r",OSC_temp); } } DECLARE_TASK_FUNC(Osc02) { u16 cur,old; u8 OSC_temp02=0; BYTE err; parg = parg; while(1) { OSSemPend(OscWait, 100, &err); if(err != 0){ continue; } OSC_temp02++; printf("OSC_temp02 %d \n\r",OSC_temp02); } }

  • C言語(初心者です

    C言語(超初心者です) 二重ループを中断する 2 通りの方法についてのソースコード を書きたいのですが 方法 1:フラグだけを使い,ジャンプを使わない. 方法 2:ジャンプだけを使い,フラグを使わない. #include <stdio.h> int main() { int f = 0; char *ans; printf("Loop {\n"); while ( ... ) { ... printf(" Loop {\n"); while ( ... ) { ... printf(" Break ? "); scanf("%s", ans); if (ans[0] == 'y') ... else if (ans[0] == 'q') ... ... } printf(" }\n"); } ... printf("}\n"); printf("Done.\n"); return (0); } 実行例: % ./a.out Loop { Loop { Break ? no Break ? no ... Break ? yes } Loop { Break ? no ... Break ? quit } } Done. % このソースコードをどう変えればいいのでしょうか 方法1のフラグを使って2重ループを脱出するっていうのどういうことかちょっとわからないです。 方法2ではbreakを使うのですか。 yesが入力されたら外にでる?みたいな感じでしょうか。

  • PICでサーボモータ制御(C言語)

    個人的PICでのにサーボ制御をしてみようとしています。 まず、動作確認をしてみようとPIC(16F84A)を用いて、PICの基本回路を構成してあります。 次にサーボ制御をしてみようという事で、信号をRB1から得る事にします。 (電源、グランドはしっかり接続してあります) そこで、以下のプログラムを走らせてみました。 ※コンパイラはHI-TECH社の無料版を使っています。 #include<pic.h> #include<delay.h> main(void){ int a, b;    TRISA = 0x00;    TRISB = 0x00; while(1){ RB1=1; for(a=0;a<16;a++)DelayUs(100); //PointA RB1=0; for(b=0;b<186;b++)DelayUs(100); //PointB } } ※DelayUs関数はμsecの待ち発生関数です。 サーボが約20secのパルスということなので、動作確認のために組みました。 PointA,Bと記述した部分をいくら変動させても動作がかわらず一定の角度方向にしか動きません。 ただ、確認のために組んだプログラムなのですが、これではだめなのでしょうか?