Skip to main content
 首页 » 编程设计

c之如何在循环中设置信号检查

2023年11月22日21zhenyulu

在 createProcess(pid_t pidArray[]) 函数中我创建了新进程,如果它是子进程我打印它。但是在 while 循环中我每次都检查 killFlag,我的程序没有效率。我该如何解决这个问题?感谢您的任何帮助。在我的程序中,您可以通过按 + 添加进程或按 - 删除它,或者按 q 退出。

这是我的代码:

#include <ncurses.h>  
#include <unistd.h>  
#include <sys/wait.h>  
#include <signal.h>  
#include <string.h>  
#include <stdlib.h>  
 
bool printAllowed = false;  
bool killFlag = true;  
bool flag = false;  
int processesCount = 0;  
int currentProcessNumber = 0;  
static const char *colors[] = { "\x1B[0m", "\x1B[31m","\x1B[32m","\x1B[33m","\x1B[34m","\x1B[35m","\x1B[36m","\x1B[37m" };  
 
struct sigaction printSignal, killSignal;  
 
void allowPrint(int sign){  
  printAllowed = true;  
}  
 
void setKillFlag(int sign){  
  killFlag = true;  
}  
 
int createProcess(pid_t pidArray[]){  
 
  if(processesCount > 100) return 1;  
 
  pidArray[processesCount] = fork();  
  processesCount++;  
 
  switch(pidArray[processesCount - 1]){  
 
    case 0:{  
      killFlag = false;  
      char buff[255];  
      int colorNumber = (processesCount > 7)? 0 : processesCount;  
      sprintf(buff,"%sProcess %d || ", colors[colorNumber], processesCount);  
      while(!killFlag) {  
        usleep(10000);  
        if(printAllowed){  
          for(int i = 0; i < strlen(buff); i++){  
            if(killFlag) { return -1;};  
            printf("%c", buff[i]);  
            refresh();  
            usleep(50000);  
          }  
          printAllowed = false;  
          // signal to parent that process stop print 
          kill(getppid(), SIGUSR2);  
        }  
      }  
      return -1;  
    }  
 
    case -1: printf("%sError!", colors[1]); return 1;  
 
    default:  return 1;  
  }  
}  
 
bool killProcess(pid_t pidArray[]){  
  if (processesCount <= 0) return 1;  
 
  processesCount--;  
  // stop last child process 
  kill(pidArray[processesCount], SIGUSR2);  
  waitpid(pidArray[processesCount], NULL, NULL);  
  // if the process that printing now stopped 
  if (currentProcessNumber >= processesCount){  
    currentProcessNumber = 0; // start from beginning 
    flag = true;  // flag last process by number 
    killFlag = true; // flag of end printing current process 
  }  
 
  return 1;  
}  
 
int controlProcesses(pid_t pidArray[]){  
  halfdelay(1);  
  switch((char)getchar()){  
  case '=': return createProcess(pidArray);  
  case '-': return killProcess(pidArray);  
  case 'q': return 0;  
  default: return 1;  
  }  
}  
 
void killAllProcesses(pid_t pidArray[]){  
  if(pidArray[--processesCount] != 0)  
    for( ;processesCount >= 0; processesCount--){  
      kill(pidArray[processesCount],SIGUSR2);  
      waitpid(pidArray[processesCount],NULL,NULL);  
    }  
}  
 
int main(){  
 
  initscr();  
  clear();  
  noecho();  
  refresh();  
 
 
  printSignal.sa_handler = allowPrint;  
  sigaction(SIGUSR1,&printSignal,NULL);  
 
  killSignal.sa_handler = setKillFlag;  
  sigaction(SIGUSR2,&killSignal,NULL);  
 
  pid_t pidArray[100];  
 
  while(int i = controlProcesses(pidArray)) {  
 
    if(i == -1) return 0;  
 
 
    if(killFlag && processesCount > 0){  // if current process stop printing 
      killFlag = false;  
      if(currentProcessNumber >= processesCount - 1) currentProcessNumber = 0; // if the number of current process is last, start from beginning 
      else if(!flag) currentProcessNumber++; // else if last stopped process wasn't the last by number go to next process 
      flag = false;  
      kill(pidArray[currentProcessNumber], SIGUSR1); // signal to child process start the printing 
    }  
    refresh();  
  }  
  // stop all child processes 
  killAllProcesses(pidArray);  
 
  clear();  
  endwin();  
 
  return 0;  
} 

请您参考如下方法:

您的 killFlags(和 printAllowed)声明错误。应该声明

volatile sig_atomic_t killFlags, printAllowed; 

volatile预选赛真的很重要。否则,编译器会通过假设只能显式更改 killFlags 来优化(它不知道信号处理程序可以随时更改它,因此它可以通过将该变量保存在寄存器中来优化,等等) ...)。

仔细阅读signal(7)手册页。

如果你的循环是轮询 event loop (可能基于 poll(2) ...)您可能会考虑使用特定于 Linux 的 signalfd(2)打电话。