0

Linux でリアルタイム信号を使用する簡単なプログラムを作成しようとしています。しかし、私は奇妙な動作に遭遇しました.最初のコード:

#include<signal.h>
#include<sys/types.h>
#include<stdlib.h>
#include<stdio.h>
#include"errhandling.h"
#include<string.h>
#include<errno.h>
#include<unistd.h>

void baz(int sig,siginfo_t* info,void *context)
{
  if (sig==SIGUSR1)
      printf("SIGUSR1 %d\n",info->si_value.sival_int);
  else if(sig==SIGRTMIN)
      printf("SIGRTMIN %d\n",info->si_value.sival_int);
  else 
      printf("SIGRTMIN+1 %d\n",info->si_value.sival_int);
  return ;
}

void sig_output()
{
  sigset_t set;
  sigprocmask(0,NULL,&set);
  printf("blokowane sa: ");
  if (sigismember(&set,SIGUSR1))
      printf("SIGUSR1 ");
  if(sigismember(&set,SIGUSR2))
      printf(" SIGUSR2");
  printf("\n");
  return ;
}


int received=0;
int usr2=0;

void foo(int sig)
{
  return ;
}

void usr1_handler(int sig)
{
  printf("usr1_handler\n");
  //++received;
}



void usr2_handler(int sig)
{
  usr2=1;
}

int main(int argc,char **argv)
{
  int i=0;
  pid_t pid=getppid();
  struct sigaction a;
  struct sigaction a2;
  a.sa_flags=SA_SIGINFO;
  sigset_t set;
  sigemptyset(&set);
  //sigaddset(&set,SIGRTMAX);
  sigemptyset(&(a.sa_mask));
  sigemptyset(&(a2.sa_mask));
  a.sa_sigaction=baz;
  sigaction(SIGRTMIN,&a,NULL);
  a2.sa_handler=usr1_handler;
  sigaction(SIGRTMIN+1,&a2,NULL);
  //sigprocmask(SIG_SET,&(a.sa_mask),NULL);
  while(!usr2)
  {
      printf("while\n"); 
      sigsuspend(&set);

  }
      //pause()
  printf("after while\n");
  return EXIT_SUCCESS;
}

このプログラムを実行し、sigsuspend でこのループに入り、このプログラムに SIGRTMIN を送信すると、すべて問題なく実行されます。ハンドラーが実行され、別のシグナルを待機しますが、SIGRTMIN+1 を送信すると、セグメンテーション違反が発生します。

リアルタイム シグナルの場合、この拡張ハンドラを 3 つの引数で使用する必要があるようですが、なぜですか? どこかに明記されていますか?このプログラムを友人の OpenSUSE 12.1 で実行すると、SIGRTMIN+1 のセグメンテーション エラーは発生しませんが、Xubuntu 11.10 では、SIGRTMIN+1 を送信するとセグメンテーション エラーが発生します。私のシステムに問題がありますか?それとも実装依存ですか?

4

2 に答える 2

2

にハンドラーを割り当てる必要がないようですa2.sa_sigaction


一般に、さまざまなシグナルの定義がプラットフォーム固有である可能性があるため、生の整数値でシグナルを参照することはお勧めできません。


Update:struct sigactionたとえば、構造体memset()を 0に設定して、構造体が適切に初期化されていることを確認してください。

于 2012-04-18T12:23:25.317 に答える
1

シグナルハンドラ内から printf() とその仲間を使用しないでください。頑固にならないでください...ここに代用品があります。

#include <stdarg.h>

int myprintf(const char *fmt, ...);
int myprintf(const char *fmt, ...)
{
    va_list args;
    char buff[512];
    int rc;

    va_start( args, fmt );

    rc = vsnprintf ( buff, sizeof buff, fmt, args );
    va_end (args);

    if (rc >0 && rc < sizeof buff) write(1, buff, rc);

    return rc;
}

更新:これはうまくいくようです:

#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#pragma #include"errhandling.h"
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>

int myprintf(const char *fmt, ...);
int myprintf(const char *fmt, ...)
{
  va_list args;
  char buff[512];
  int rc;

  va_start( args, fmt );
  rc = vsnprintf ( buff, sizeof buff, fmt, args );
  va_end (args);

  if (rc > 0 && rc < sizeof buff) write(1, buff, rc);

  return rc;
}

void baz(int sig, siginfo_t *info, void *context)
{
#define INFO_VAL(p) p?p->si_value.sival_int:0
  if (sig==SIGUSR1)
      myprintf("SIGUSR1 %d\n", INFO_VAL(info) );
  else if(sig==SIGRTMIN)
      myprintf("SIGRTMIN %d\n", INFO_VAL(info) );
  else
      myprintf("SIGRTMIN%+d %p\n", sig-SIGRTMIN, INFO_VAL(info) );
  return ;
#undef INFO_VAL
}

void sig_output()
{
  sigset_t set;
  sigprocmask(0,NULL,&set);
  myprintf("blokowane sa: ");
  if (sigismember(&set,SIGUSR1))
      myprintf("SIGUSR1 ");
  if(sigismember(&set,SIGUSR2))
      myprintf(" SIGUSR2");
  myprintf("\n");
  return ;
}
volatile int received=0;
volatile int usr2=0;

void foo(int sig)
{
  return ;
}

void usr1_handler(int sig)
{
  myprintf("usr1_handler\n");
  //++received;
}



void usr2_handler(int sig)
{
  usr2=1;
}

int main(int argc,char **argv)
{
  int i=0;
  pid_t pid=getppid();
  struct sigaction a, a2;
  sigset_t set;

  sigemptyset(&set);
  //sigaddset(&set,SIGRTMAX);
  sigemptyset(&a.sa_mask);
  sigemptyset(&a2.sa_mask);
  a.sa_flags = 0;
  a2.sa_flags = SA_SIGINFO;
  a2.sa_sigaction = baz;
  a.sa_handler = usr1_handler;
  sigaction(SIGUSR1,&a,NULL);

  a.sa_handler = usr2_handler;
  sigaction(SIGUSR2,&a,NULL);

  sigaction(SIGRTMIN+1,&a2,NULL);
  sigaction(SIGRTMIN+2,&a2,NULL);
  sigaction(SIGRTMIN+3,&a2,NULL);
  //sigprocmask(SIG_SET,&(a.sa_mask),NULL);
  while(!usr2)
  {
      myprintf("while(!usr2)\n");
      sigsuspend(&set);

  }
      //pause()
  myprintf("after while\n");
  return EXIT_SUCCESS;
}
于 2012-04-18T12:31:31.507 に答える