0

コンピューターで実行している 2 つのプロセス間のシグナルの処理に問題があります。scheduler.c がシグナルを送信し、producer.c がシグナルを受信して​​います。プロデューサは、SIGUSR1 が受信されるたびに n が 1 ずつ増加する "Printing n" を出力することになっています。シグナルと sigaction の両方を使用してシグナルを処理しようとしましたが、どちらもうまくいきません。

スケジューラー.c:

/*
 * scheduler.c
 */


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

int n = 1;


int main(int argc, char *argv[])
{
    int a = 0; // This variable will be used for the switch later

    // Check to ensure correct number of command line arguments
    if(argc != 2){
        printf("Usage error. Wrong number of arguments\n");
        return 1;
    }

    // Grab PID of producer.c
    int producer_pid = atoi(argv[1]);       

    while(1){
        printf("Choose an Option: \n");
        printf("1. Request_Production\n");
        printf("2. Stop_Producer\n");
        printf("3. Stop_Scheduler\n");
        scanf("%d", &a);

        switch( a ) 
        {
            case 1:
                kill(producer_pid, 16);     //Send SIGUSR1 to producer.c
                break;

            case 2:
                kill(producer_pid, 2);      //Send SIGINT to producer.c
                break;

            // Successfully exit program
            case 3:
                return 0;

            // Invalid Choice
            default :
                printf("Invalid choice\n");
        }
    }
}

プロデューサー.c:

/*
 * producer.c
 */

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

int n = 1;

void sigusr1(int signo)
{

    printf("Producing %d", n);
    n++;
}


int main()
{


    struct sigaction act;
    sigset_t block_mask;
    sigfillset(&block_mask);
    act.sa_handler = sigusr1;
    act.sa_mask = block_mask;
    act.sa_flags = 0;

    if(sigaction(SIGUSR1, &act, NULL) == 0){
        printf("success");
    }


    while(1) {

        sleep(2);
        fflush(stdout);
    }

}
4

2 に答える 2

2

このコードは私にとってはうまくいきます(Mac OS X 10.7.5上):

プロデューサー.c

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

static volatile sig_atomic_t n = 0;

static void sigusr1(int signo)
{
    n += signo / SIGUSR1;
}

int main(void)
{
    struct sigaction act;
    sigset_t block_mask;
    sigfillset(&block_mask);
    act.sa_handler = sigusr1;
    act.sa_mask = block_mask;
    act.sa_flags = 0;

    if (sigaction(SIGUSR1, &act, NULL) == 0)
    {
        printf("success %d\n", (int)getpid());
        while (1)
        {
            pause();
            printf("Producer: %d\n", n);
            fflush(stdout);
        }
    }
}

scheduler.c

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int a = 0; // This variable will be used for the switch later

    // Check to ensure correct number of command line arguments
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s pid\n", argv[0]);
        return 1;
    }

    // Grab PID of producer.c
    int producer_pid = atoi(argv[1]);       

    while(1)
    {
        printf("Choose an Option: \n");
        printf("1. Request Production\n");
        printf("2. Stop Producer\n");
        printf("3. Stop Scheduler\n");
        scanf("%d", &a);

        switch (a) 
        {
            case 1:
                if (kill(producer_pid, SIGUSR1) != 0)
                    fprintf(stderr, "Failed to send signal %d to %d\n", SIGUSR1, producer_pid);
                break;

            case 2:
                if (kill(producer_pid, SIGTERM) != 0)
                    fprintf(stderr, "Failed to send signal %d to %d\n", SIGTERM, producer_pid);
                break;

            // Successfully exit program
            case 3:
                return 0;

            // Invalid Choice
            default :
                fprintf(stderr, "Invalid choice (%d)\n", a);
                break;
        }
    }
}

サンプル出力

$ (./producer &)
$ success 40119
$ ./scheduler 40119
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
1
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
Producer: 1
1
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
Producer: 2
1
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
Producer: 3
1
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
Producer: 4
1
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
Producer: 5
1
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
Producer: 6
1
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
Producer: 7
1
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
Producer: 8
2
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
1
Failed to send signal 30 to 40119
Choose an Option: 
1. Request Production
2. Stop Producer
3. Stop Scheduler
3
$

何が変わったのですか?

さまざまな変更がありますが、重要なものは次のとおりです。

  1. 出力メッセージが改行で終わっていることを確認してください。
  2. 変数nにしvolatile sig_atomic_tます。これは、シグナル ハンドラでアクセスできると C 標準で述べられていることです。
  3. プロデューサにメインループを用意してpause()から印刷します。システムコールはpause()、シグナルによって中断された場合にのみ戻ります。
  4. スケジューラーでもシンボリック信号名を使用してください。
  5. プロデューサを終了するのSIGTERMではなく、スケジューラに送信させます。SIGINT プロデューサーがバックグラウンドで実行されている場合、割り込みは無視されます。
  6. kill()呼び出しがいつ失敗したかをスケジューラーに識別させます。
  7. プロデューサーにその PID を特定してもらいます。

ファイルの見出しから余分なヘッダーを削除しました。

シグナルハンドラのsigno / SIGUSR1ユーモアは、未使用の引数に関する警告を回避します。それ以外の目的はありません。示されているように、プログラムは次の環境で正常にコンパイルされます。

gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition scheduler.c -o scheduler  
gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition producer.c -o producer

これは GCC 4.7.1 を使用しています。

于 2013-02-15T05:18:02.263 に答える
1

1 つのコメント:

シグナルハンドラから呼び出すのに安全な関数とそうでない関数があります。

printfシグナルハンドラから呼び出すことはできません。write一方、安全です。

リストは POSIX-1 で指定されていますが、詳細はオペレーティング システムによって異なる場合があります。Linux の場合、signal(7) にリストがあります。

http://linux.die.net/man/7/signal

于 2013-02-15T04:39:26.387 に答える