簡體   English   中英

如何使用帶有 sigint 的標志在一秒內發送兩次時進行通知?

[英]How to use a flag with sigint to notify when it's been sent twice in one second?

我是 C 編程的新手,正在為一項任務而苦苦掙扎。 代碼的基礎是有一個 1 秒的計時器(我正在使用 sleep(1)),它從 1 的增量開始計數。每次我發送 sigINT 時,我將增量增加 1 並且計數器打印出新號碼。 我使用 sigterm 來減少數字。 所有這些都運行良好。

如果我在一秒鍾內使用 sigINT 兩次,最后一部分是終止程序。 我曾嘗試使用對我而言設置為 0 的“標志”來執行此操作。調用 sigINT 時,將其增加 1。在我的 while 循環中將其重置為 0。 我試着寫一個 if 語句,如果增量大於 1,程序就會停止。 但是在此之后使用 sleep(0) 和 flag=0,我永遠無法讓標志大於 1。我知道這可能不是最好的方法,但沒有找到更好的解決方案. 任何幫助表示贊賞。 謝謝。

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

int inc = 1;
int flag = 0;

void handle_sigint(int sig_num)
{
    signal(SIGINT, handle_sigint);
    if (inc < 10)
    {
        inc++;
    }
    flag++;
    printf("\nflag=%d\n", flag);
    printf("\nSIGINT received: Increment is now %d\n", inc);
    fflush(stdout);
}

void handle_sigterm(int sig_num)
{
    signal(SIGTERM, handle_sigterm);
    if (inc > 0)
    {
        inc--;
    }
    printf("\nSIGTERM received: Increment is now %d\n", inc);
    fflush(stdout);
}

int main()
{
    int num = 0;
    signal(SIGINT, handle_sigint);
    signal(SIGTERM, handle_sigterm);
    printf("Process ID: %d\n", getpid());
    while (1)
    {
        if (flag > 1)
        {
            pid_t iPid = getpid();
            printf("\nExiting the program now\n"); 
            kill(iPid, SIGKILL);
        }   
        printf("%d\n", num);
        num = num + inc;
        sleep(1);
        flag = 0;
    }
    return 0;
}

如果在sleep(1)和在檢查if(flag>1)之前設置flag=0 這意味着在將其設置為零和檢查之間沒有時間,並且在那個時候您想將 SIGINT 信號發送到您的程序。 在檢查之后,您最多將標志設置為零。

sleep()調用是可中斷的! 如果sleep()被信號中斷,則返回睡眠剩余的秒數。 供參考閱讀man sleep 由於“1 秒”實際上不能被較小的塊整除,因此您可以使用usleep或僅使用nanosleep調用。 如果在睡眠期間收到信號, nanosleep返回-1並將errnoEINTR 因為它在第二個參數中返回睡眠剩余的時間,所以很容易用它做一個循環。 您必須為errno添加#include <errno.h> ,為nanosleep添加#include <errno.h> #include <time.h>

所以一些東西:

while (1) {
   if (flag > 1) {
          // some code
   }
   // printf("something");

   // set flag before sleeping!
   flag = 0; 

   // wait a second
   struct timespec rqtp = { 1, 0 };
   while (nanosleep(&rqtp, &rqtp) == -1 && errno == EINTR) {
       // repeat until we slept a full second
   }

}

筆記:

  • 好代碼! 請遵循一些縮進樣式並縮進您的代碼。 我推薦linux 內核編碼風格
  • printffflush不是信號安全函數。 從信號處理程序調用它們是未定義的行為。 您不應該從信號處理程序中調用printf
  • 技術上volatile sig_atomic_t類型應該用於與信號處理程序同步。 我想最好將您的flaginc變量至少標記為volatile

暫無
暫無

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

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