C言語のsignal関数を使用した割り込み処理についての疑問

このQ&Aのポイント
  • C言語のsignal関数を使用した割り込み処理についての疑問について説明します。
  • Windows環境で実行した場合、割り込み処理がどのように動作するかについても触れます。
  • コントロール+Cで割り込み処理を起こす際、なぜ2回目のコントロール+Cで終了するのかについての疑問も説明します。
回答を見る
  • ベストアンサー

signalについて

いつもお世話になります。 基本的なことですが、お教えください。 C言語の本に、「signalによる割り込み処理」というプログラムが載っていました。 本の説明では、「UNIXでは、シグナルといったもので、割り込み処理を行うことができます。」と、UNIXの話をしているようです。 私の環境はWindowsですが、かまわずに作って実行してみました。 そのプログラムは以下のとおりです。 #include <stdio.h> #include <signal.h> #include <stdlib.h> /* この行は自分で加えた */ void onsig(int sig) { printf("Control+C\n"); exit(0); } int main(void) { signal(SIGINT, onsig); while(1) { puts("a"); /* ★このputsは自分で加えた ★ */ } return 0; } 意図したとおりに、コントロール+Cを押すと Control+Cが表示されて終わりました。 さて、私はonsig関数の中の exit(0); を削除してみました。 実行すると、はじめたくさんの a が表示され、 コントロール+Cを押すとControl+Cの表示の後すぐにそのままwhileの中に戻っていき、 たくさんのa が表示されて、 再びコントロール+Cを押すとプログラムが終わってプロンプトが戻ってくることがわかりました。 ここで疑問に思ったのは、1回目のコントロール+C の後にすぐにwhileの中に戻っていくのならば、何回 コントロール+Cを押してもwhileの中に戻っていき、コントロール+Cで終わらせることは出来ないのではないか、ということでした。 なぜ2回目のコントロール+Cで終了するのでしょうか。 VC++6.0でWin32 Console Applicationで作成しています。

noname#2045
noname#2045

質問者が選んだベストアンサー

  • ベストアンサー
  • layer13
  • ベストアンサー率47% (37/78)
回答No.1

まずは、参考URLをご覧ください。 参考URLに詳しい説明は有りますが、簡単に言うとsignal()での 関数登録は一回のsignal受信で無効になってしまう。ということですね。 参考URLではUNIXの話しですが、VC++でも同様の事が 起きていると考えれば、説明が付くのではないでしょうか?

参考URL:
http://aglaia.c.u-tokyo.ac.jp/~yamamoto/signal/node16.html
noname#2045
質問者

お礼

ありがとうございました。 7月22日夜、締め切りました。

noname#2045
質問者

補足

ありがとうございました。 参考URL 参考にさせていただきました。☆ onsig内にsignal(SIGINT, onsig);を入れると意図どおりになりました。 ==============自分のまとめ============== 下記のように、onsig内にsignal(SIGINT, onsig);を入れたときは、デフォルトの設定に戻らずに、onsigが呼ばれるように再設定されて、何回でも コントロール+Cを押すと Control+C が表示される。 #include <stdio.h> #include <signal.h> void onsig(int sig) { printf("Control+C\n"); signal(SIGINT, onsig); } int main(void) { signal(SIGINT, onsig); while(1) { ; } return 0; }

関連するQ&A

  • exitってどう使うの?

    exitを使いたいのですが、プログラムが終了しません。 コンパイルも通りません。 警告:コードは効果を持たない(関数 exit) エラー:ステートメントにセミコロンが無い(関数 exit) と出ます。 windowsでC言語書いています。 入力した数値分「警告」を表示するプログラムなのですが #include <stdio.h> #include <stdlib.h> void exit(int x) { while(x-- > 0){ if(x==0){ printf("警告!\n"); exit 0; } printf("警告!残り%d回。\n", x); } } int main() //警告を表示する回数を変数に代入するプログラムvoid exitのxに渡す。 どうすればexitの位置でプログラムが終了するようにできるのでしょうか。 どなたか教えていただけないでしょうか。

  • C言語での方向キー入力判定

    C言語でキーの入力判定をするプログラムを作ってい ます。下の例だとeやエンターを押したときは認識できる のに、方向キー↑を押したときはなぜか無反応です。 コンパイラはボーランドでOSはXPでコンパイルした のですが、何がいけなかったのでしょうか? #include <stdio.h> #include <conio.h> #include <windows.h> void check(void){ int key; key = getch(); switch (key){ case 'e': puts("e"); break; case VK_RETURN: puts("ENTER"); break; case VK_UP: puts("UP"); break; } } int main(void) { while(1){ check(); } return 0; }

  • 「void ( *signal(int sig, void (*func)(int)) ) (int)」の (int)

    signal関数の書式についてですが、   void ( *signal(int sig, void (*func)(int)) ) (int); 最後に付く(int)は一体何でしょうか? このような関数の書式ははじめて見ました。 UNIX系の何かでしょうか。 回答よろしくお願いします。

  • C言語について

    #include <stdio.h> int main(void) { printf("123456\tABC DEFGHIJK\n"); printf("2006/4/14\n"); printf("programing\n"); } のprintfをすべてputsに書き換えてコンパイル・実行すると、 #include <stdio.h> int main(void) { puts("123456\tABC DEFGHIJK\n"); puts("2006/4/14\n"); puts("programing\n"); } になると思うんですけど、そのputsを用いて上のprintfを用いたプログラムと同じ出力を得るにはどのようなプログラムに変えればいいのでしょうか?

  • 2つのプログラムの違い

    どうしても分からなかったので投稿しました。よろしくお願いします。 #include<stdio.h> int main(void) { int c; while((c=getchar())!=EOF){ putchar(c); } return 0; } のプログラムをコマンドプロンプトで入力すると、 abc abc なんですが、 #include<stdio.h> int main(void) { int c,i; i=0; while ((c=getchar())!=EOF) { putchar(c); i++; printf("%d\n",i); } return 0; } の場合、 abc a1 a2 a3 4 になります。 自分は abc a1 a2 a3 になると思ったのですが、a3と4の隙間と4は何故出て来たのでしょうか?

  • C言語の問題で困っています。

    C言語の問題で困っています。 誰か教えてください。 下の問題ですが、intがiだけでプログラムするにはどうしたら良いでしょうか? (a)から(d)に入るプログラムをすいませんが教えてください。 お願いします。 【問題】 1以上10以下の整数を昇順に区切って表示するプログラムです。 実行例 1 2 3 4 5 #include <stdio.h> int main (void) { int i; (A) while ((b)){ (c); (d); } printf("¥n"); return(0); }

  • パイプってどうやって使うの?

    1つ目のプログラムの出力を2つ目のプログラムで受け取りたいのですが、どうすればいいですか? -- 1 -- #include <stdio.h> #include <windows.h> int main(void){     int a=0;     while(1){         fprintf(stdout,"%d\n",a++);         Sleep(1000);     }     return 0; } これを2のプログラムで受け取ります。 #include <stdio.h> int main(void){     char str[128];     while(1){         if(fgets(str,sizeof(str),stdin)==NULL)             break;     printf("%s",str);     }     return 0; } これをコマンドプロンプトで 1 | 2 と入力してみましたが、何も表示されません・・。 個別に実行すると正常に動作します。 環境はXPです。どうしたら受け渡しが出来るのでしょうか?

  • サブ関数、メイン関数

    C言語の質問です! ランダムに九九の計算を出題して、キーボードから答えを入力し、正解かどうかを判定するプログラムをつくりたいです。出題の部分をサブ関数、判定の部分をメイン関数として作成する場合、どのようなプログラムの書き方になるのか、教えてください! #include<stdio.h> #include<stdlib.h> #include<process.h> void kakezan(void); void answer(void); void hanrei(void); int a,b,c; int main() { printf("やめるときは、100と入力してください。\n");   while(1){ kakezan(); answer(); hantei(); } return 0; } void kakezan(void) { a=rand() %10; b=rand() %10; printf("%d×%d=",a,b); } void answer(void) { scanf("%d",&c); if(c==100) exit(0); } void hantei(void) { if(c==a*b) printf(">>正解\n"); else printf(">>不正解\n"); printf("\n"); return; } 一応考えてみたのですが、 ちゃんと、判定→メイン  出題→サブ関数になっているのかなとおもって・・・   このプログラムであっているのでしょうか??

  • 文字列を関数に渡すぷろぐらむなのですがおかしいです。

    <ソース> #include<stdio.h> #include<stdlib.h> void str(char a[]); int main() { char st[10]="abcde"; str(st); str("ABCabc123"); return 0; } void str(char a[]) { int i; printf("%s\n",a); i=0; while(a[i]){ a[i]=toupper(a[i]); putchar(a[i]); i++; } putchar('\n'); } 分からないところがあるので質問します。 toupperは、大文字にするんですよね。 putcharは、基本的にchar型でしたっけ? putsとgetsは、int型でしたっけ? 後、プログラムが暴走してます。 どこがおかしいんでしょう?

  • このプログラムのどこを直せばいいんでしょうか?

    いま、文字列strの中に文字cが含まれている個数を表示するプログラムを作っているんですが、下のように作っても、上手く行きません。 どこをどう直せばいいのか教えてください! #include <stdio.h> int str_chnum (const char str[],int d) { int i=0; int sum=0; while(str[i]!=0){ if(str[i]==d ){ sum++; } i++; } return(sum); } int main(void) { int c; char str[128]; puts("put sentence..."); scanf("%s",str); puts("search character..."); scanf("%d",&c); printf("there are %d %ds in this sentence.",str_chnum(str,c),c); return(0); }

専門家に質問してみよう