簡體   English   中英

在同一台計算機上的兩個進程之間發送/處理信號時遇到問題-C編程

[英]Problems sending/handling signals across two processes on same computer - C programming

我在計算機上運行的兩個進程之間無法處理信號。 scheduler.c正在發送信號,producer.c接收它們。 生產者應該打印“打印n”,其中每收到SIGUSR1,n就會增加1。 我已經嘗試使用信號和信號處理信號,但是都沒有用。

scheduler.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");
        }
    }
}

producer.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);
    }

}

該代碼對我有用(在Mac OS X 10.7.5上):

生產者

#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);
        }
    }
}

調度程序

#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. 使nvolatile 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。

一句話:

有一些安全的函數,還有其他一些不安全的函數可以從信號處理程序中調用。

不能從信號處理程序中調用printf 另一方面write是安全的。

該列表由POSIX-1指定,但不同的操作系統可能有所不同。 對於Linux,您可以在signal(7)中找到該列表:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM