alarmの使用について

このQ&Aのポイント
  • Cの学習中にalarmの使用法についての質問です。SIGALRMを捕らえてシグナルハンドラの関数に飛び、LONGJMPで戻ってくると2回目以降alarmが使用できなくなりますか?
  • 質問者は、入力待ちをしていて5秒待っても入力がなかった場合に再入力をするようなプログラムを5回繰り返したいと考えていますが、うまくいかないそうです。
  • 要約文3
回答を見る
  • ベストアンサー

alarmの使用について

こんにちわ, 今Cの学習をしています。 alarmの使用法なんですが,1度SIGALRMを捕らえて,シグナルハンドラの関数に飛んだ後,LONGJMPでもどってくると,2回目以降,alarmは使用できないのでしょうか。具体的には下記のとおりです。 jmp_buf fin; main(){ int i, x =0; for(i=1;i<=5;i++){ signal(SIGALRM, timeout); x=setjmp(fin); if(x=1){    alarm(5); /*何かを入力等を行う*/    alarm(0);  } else { x=0; } } } void timeout() { longjmp(fin,1); return; } このように何か入力まちをしていて入力されずに5秒まつと再度入力をするようなプログラムを5回,回したいのですが,うまくいきません。 よろしくおねがいします。

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

  • ベストアンサー
回答No.2

#1です。 ちょっと訂正します。 #1の回答で、2回目以降もプロセスが終了することはなくなるはずですが、今度は5回でも100回でもforループを抜けないはずです。 というか、正確に言うと、ループしてないんですよ。 longjmp()でsetjmp()のところに舞い戻ってくるんですから、何回繰り返してもループ1回目なんですよね。 /*何か入力等をおこなう*/ という部分がSIGALRMの発生によってブロック解除されるものであれば(大抵の入力待ち関数はerrno=EINTRでエラー終了するものです)、 単純にsetjmp()とlongjmp()を削除してみてください。 こんどこそ、お望みの動作になるはずです。 参考まで。

その他の回答 (1)

回答No.1

ループ2回目でプロセスが死んでしまう、という状況ですよね? SIGALRMは発生すると、デフォルトに戻ります。 (SIGALRMのデフォルト動作はプロセス終了です。) 言い換えると、 ループ一回目は、signal(SIGALRM, timeout)が効いていますが、 ループ二回目は、signal(SIGALRM, SIG_DFL)状態 ということです。 signal(SIGALRM, timeout); x=setjmp(fin); を x=setjmp(fin); signal(SIGALRM, timeout); とすると、お望みの動作になりますよ。 参考まで。

関連するQ&A

  • C言語のプログラミングについて教えてください

    課題で下記に示すのようなデータをファイル名を入力してのそのデータを読み込みyの最大値とそのときのxの値を表示するプログラムを作成しろと言われたのですが、僕はプログラミングが初心者でむしろ苦手でホント困ってます。だれか助けてください、お願いします! データ    x  y 0.12132 3.45355 0.12353  3.415451 . . . . . . のようにxとyの行列となっていて、その数は2000個を超えています。 自分なりにやってみたのですがデータをすべて読み込まないし、まずどのようにして、yの最大値をだし、なおかつそのxの値を表示させるのもわかんなくてホント困っています。 本末転倒になりますが、プログラムを書いていただけるとほんと助かります。よろしくお願いいたします。 ちなみにこれが自分で考えたプログラムです。とりあえず、yの値がでかいのでyの最大値だけだすつもりでやってみたけど駄目でした。 #include <stdio.h> #include <stdlib.h> int main(void) { FILE *fin; char *list[256]; char buf[1024]; char filename1[80]; printf("入力ファイル名"); gets(filename1); fin=fopen(filename1,"r"); if (fin ==NULL) { printf("%sをオープンできません\n",filename1); exit(1); } while (fgets(buf, 1024, fin) !=NULL) { printf("%s",buf); } static float max; int x; fscanf(fin,"%f",&x); if(x>max){ max=x; printf("yの最大値=%f\n",max); } fclose(fin); }

  • ポインターにポインターを加えようとしました。のエラーについて

    よろしくお願いします。環境 WIN98 VC++6.0 MFC にて 下記において、 //m_InputData=m_InputData+buf+crlf;では問題無いのに、m_InputData=buf+crlf;にするとポインターにポインターを加えようとしました。とエラーが出ます。 どうしてなのでしょう? また、対処方法はどうすれば良いのでしょうか? ************************* void CInput::OnButton4() //読出し { int n; char buf[256]; char crlf[]="\x0d\x0a"; FILE *fin; UpdateData(TRUE); m_InputData=""; if((fin=fopen("d:\\qqq.txt","r"))==NULL){ AfxMessageBox("読み込みファイルオープン出来ません"); return; } while((fgets(buf,256,fin))!=NULL){ n=strlen(buf); buf[n-1]='\0'; //AfxMessageBox(m_text); //m_InputData=m_InputData+buf+crlf;//問題無し m_InputData=buf+crlf;//エラー } fclose(fin); UpdateData(FALSE); }

  • gccのオプションは必要ですか?

    ubuntuを使ってc言語の勉強(スーパービギナー編ですが)をしています。 以下のプログラムを実行すると、Segmentation faultが出ます。 以前、-lmのオプションを付けないと、math.hが使えない事が、ありましたが、今回の場合、何か必要でしょうか? #include<stdio.h> #include<stdlib.h> int main(void) { FILE *fin; char buf[256]; char filename1[80]; printf("入力ファイル名="); gets("filename1"); fin = fopen(filename1,"r"); if(fin==NULL){ printf("%sをオープンできません。\n",filename1); exit(1); } while(fgets(buf,256,fin) !=NULL){ printf("%s",buf); } fclose(fin); return 0; }

  • acceptをalarmでタイムアウトさせる処理がうまくいきません

    お世話になります。 C言語でソケット通信でサーバ側のaccept処理のブロック状態を alarm関数で事前にタイムアウトする秒数を設定しておき、割り込みをおこさせて割り込み処理後、再開した際にaccept関数がエラーを返しerrnoにEINTRが返ってきているかを判断してタイムアウト処理を行うという目的で以下のソースを作成しました。 しかし、実際に動作させてみるとalarmが呼び出されシグナルハンドラとして設定しているsigcatch関数が呼び出され、標準出力にsigcatch関数中で出力しているメッセージが出力されますが、そのままブロック状態から変化しませんでした。 ソケットのクライアントプログラムを接続したところ、acceptが成功して接続が確立されました。 この方式による実現が可能かどうか、不可能であれば代替方法を教えていただきたいと考えております。 お手数おかけしますが、ご回答のほどよろしくお願いします。 コンパイルおよび実行環境は以下となっています。 Red Hat Enterprise Linux ES release 4 (Nahant Update 3) Kernel 2.6.9-34.ELsmp on an i686 glibc-2.3.4-2.19 ###################以下、C言語のソースです##################### #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <signal.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <stdlib.h> #define BUFFER_SIZE 256 void sigcatch(int); int main() { unsigned short port = 9876; int srcSocket; int dstSocket; struct sigaction sa_sigint; struct sockaddr_in srcAddr; struct sockaddr_in dstAddr; int dstAddrSize = sizeof(dstAddr); int numrcv; char buffer[BUFFER_SIZE]; int status = 0; int select_cnt = 0; fd_set readfds; int n; struct timeval timeout; int re; char *toSendText = "This is a test"; memset(&srcAddr, 0, sizeof(srcAddr)); srcAddr.sin_port = htons(port); srcAddr.sin_family = AF_INET; srcAddr.sin_addr.s_addr = htonl(INADDR_ANY); srcSocket = socket(AF_INET, SOCK_STREAM, 0); bind(srcSocket, (struct sockaddr *) &srcAddr, sizeof(srcAddr)); listen(srcSocket, 1); printf("Waiting for connection ...\n"); memset(&sa_sigint, 0, sizeof(sa_sigint)); sa_sigint.sa_handler = sigcatch; sa_sigint.sa_flags = SA_RESTART; if (sigaction(SIGALRM, &sa_sigint, NULL) < 0) { perror("sigaction"); exit(1); } alarm(10); dstSocket = accept(srcSocket, (struct sockaddr *) &dstAddr, &dstAddrSize); if ( dstSocket == -1 ){ if ( errno == EINTR ){ printf("accept timeout!\n"); }else{ printf("accept error![%d]\n",errno); } exit(-1); } signal( SIGALRM , SIG_IGN ); printf("Connected from %s\n", inet_ntoa(dstAddr.sin_addr)); while(1) { FD_ZERO( &readfds ); FD_SET( dstSocket , &readfds ); n = dstSocket + 1; timeout.tv_sec = 0; timeout.tv_usec = 0; re = select( n , &readfds , NULL , NULL , &timeout ); select_cnt++; if( re > 0 ){ printf("select count %d\n",select_cnt); if ( FD_ISSET( dstSocket , &readfds ) ){ numrcv = recv(dstSocket, buffer, BUFFER_SIZE, 0); if(numrcv == 0 || numrcv == -1) { status = close(dstSocket); break; } printf("received: %s\n", buffer); send(dstSocket, toSendText, strlen(toSendText)+1, 0); } } } } void sigcatch(int sig) { printf("catch signal %d\n", sig); if (sig == SIGALRM) { printf("catch SIGALRM and exit.\n"); } }

  • 一番大きい奇数を表示する

    scanf関数を使用して、文字列を10回入力し一番大きい文字列を表示するプログラムを作ったのですが、 一番大きい「奇数」を表示するように条件を加えた場合どうすればよいのでしょうか? 偶数=割り切れる 奇数=割り切れない ということまでは分かるのですがその先が分かりません。 一応一番大きい文字列を表示するプログラムを貼っておきます。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } if (strcmp(buf, str) > 0) { strcpy(str, buf); } printf("output>\n%s\n" , str); getchar(); }

  • バッファオーバーランの危険性検出について

    下に示すmsg_file.txtの内容を読み込んで表示するプログラムを使ってバッファオーバーランの危険性を検出するプログラムを作りたいのですが、どのように書き換えたら良いでしょうか。 プログラムソース 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define FILEPATH "msg_file.txt" 6 7 int main(); 8 void vuln(const char* line); 9 void stack_dump(void* ptr, int counts); 10 void hello(); 11 12 int main() 13 { 14 char linebuf[1024]; 15 FILE *fp; 16 long mark1 = 0x11111111; 17 memset(linebuf, 0, sizeof(linebuf)); 18 19 fp = fopen(FILEPATH, "r"); 20 fgets(linebuf, sizeof(linebuf)-1, fp); 21 fclose(fp); 22 23 vuln(linebuf); 24 25 printf("------------- end of main() -------------\n"); 26 } 27 28 void vuln(const char* line) 29 { 30 char msg[20]; 31 long mark2 = 0x22222222; 32 memset(msg, 0, sizeof(msg)); 33 34 strcpy(msg, line); 35 36 stack_dump(&mark2, 13); 37 38 printf("INPUT[%s]\n", msg); 39 } 40 41 void stack_dump(void* ptr, int counts) 42 { 43 int i; 44 unsigned long *ulong_ptr = (unsigned long *)ptr; 45 unsigned char uchar_buf[4]; 46 47 printf("-----------------------------------------\n"); 48 printf(" address | long var | +0 +1 +2 +3 | 0123\n"); 49 printf("-----------------------------------------\n"); 50 for(i=0; i<counts; i++) { 51 printf(" %08x| %08x", &ulong_ptr[i], ulong_ptr[i]); 52 memcpy(uchar_buf, &ulong_ptr[i], sizeof(uchar_buf)); 53 printf(" | %02x %02x %02x %02x", 54 uchar_buf[0], uchar_buf[1], uchar_buf[2], uchar_buf[3]); 55 if(uchar_buf[0]<32 || uchar_buf[0]>126) uchar_buf[0] = '.'; 56 if(uchar_buf[1]<32 || uchar_buf[1]>126) uchar_buf[1] = '.'; 57 if(uchar_buf[2]<32 || uchar_buf[2]>126) uchar_buf[2] = '.'; 58 if(uchar_buf[3]<32 || uchar_buf[3]>126) uchar_buf[3] = '.'; 59 printf(" | %c%c%c%c\n", 60 uchar_buf[0], uchar_buf[1], uchar_buf[2], uchar_buf[3]); 61 } 62 printf("-----------------------------------------\n"); 63 } 64 65 void hello() 66 { 67 printf("+----------+\n"); 68 printf("| HELLO! |\n"); 69 printf("+----------+\n"); 70 exit(0); 71 }

  • ファイルからの入力

    たとえば, 3行2列のテキストデータ 1 2 3 4 5 6 を,ファイルから読み込むとします. 入力用オブジェクトとして ifstream fin; として, while (!fin.eof()) { fin >>x>>y; x_array[i]=x; y_array[i]=y; i++; } といった感じでファイルから入力しています. 2列程度なら問題ないと思うのですが, 入力データが,たとえば 3行100列 となった場合には,上記のソースのような書き方では,対応できないと思います. どのように,すればいいのでしょか?? ご教授,お願いいたします.

  • 強制終了されていまいます。

    標準入力された1行を"<"から">"までと文字のところにわけるプログラムを書いたのですが、コンパイルして実行して入力すると、画面が黒くなって止まってしまいます。以下のところが問題の部分だと思うんですが、理由がわかりません。よろしくお願いします。 while(fgets(buf, 1024, stdin) != NULL){ i = 0; j = 0; while(buf[i] != '\n' || buf[i] != '\0'){ if ((x = (char *)malloc(sizeof(char))) == NULL){ printf("malloc error\n"); exit(1); } if(buf[i] == '<'){ j = i; while(buf[j] != '>'){ j++; } strncpy(x, &buf[i], j-i+1); i = j + 1; x[strlen(x)] = '\0' putRear(deq, x); } else if(isalpha(buf[i])){ j = i; while(buf[j] != '>'){ j++; } strncpy(x, &buf[i], j-i); i = j + 1; x[strlen(x)] = '\0'; putRear(deq, x); } } }

  • 一番大きい奇数を表示する

    scanf関数を使って数字を10回入力して一番大きなものを表示させるプログラムをつくったのですが、 さらに一番大きな奇数を表示するにはどうすればいいのでしょうか? 偶数=割り切れる 奇数=割り切れない というところまでは分かるのですが、以下のプログラムに奇数を判別するソースを追加するのにはどうすればいいのでしょうか。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; int w; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } for (i = 0; i < 10; i++) { if ((buf[i] & 1) == 1) /* 奇数であるか */ { if (strcmp(buf, str) > 0) { strcpy(str, buf); } } } printf("output>\n%s\n" , str); getchar(); }

  • P900i 設定していない時間にアラームが鳴る・・・

    お世話になります。 P900iを使用しているのですが、 アクセサリ→アラーム を設定していないのに、 毎日同じ時間になるとアラームのような音が鳴ります。 (ピポーピポーピポー、と3回だけ) 何か変な設定をしてしまったのでしょうか? 解除の仕方をご存知でしたら教えてください・・・