如何设置信号回路检查? [英] How to set signal checking in loop?

查看:103
本文介绍了如何设置信号回路检查?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在的CreateProcess(将为pid_t pidArray [])功能,我创建新的进程,如果它是孩子,我打印出来。但在while循环每次我检查killFlag,和我的程序没有efficiant。我怎样才能解决这个问题?感谢您的任何帮助。在我的计划,你可以通过pressing +添加过程或pressing删除它 - 或者只是由pressing Q退出

这是我的code:

 的#include< ncurses.h>
#包括LT&;&unistd.h中GT;
#包括LT&; SYS / wait.h>
#包括LT&;&signal.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&stdlib.h中GT;布尔printAllowed = FALSE;
布尔killFlag = TRUE;
布尔标志= FALSE;
INT processesCount = 0;
INT currentProcessNumber = 0;
静态为const char *颜色[] = {\\ X1B [0米,\\ X1B [31米,\\ X1B [32米,\\ X1B [33米,​​\\ X1B [34米,\\ X1B [35米 \\ X1B [36米,\\ X1B [37米};结构sigaction的printSignal,killSignal;无效allowPrint(INT标志){
  printAllowed = TRUE;
}无效setKillFlag(INT标志){
  killFlag = TRUE;
}INT的CreateProcess(将为pid_t pidArray []){  如果(processesCount→100)返回1;  pidArray [processesCount] =叉();
  processesCount ++;  开关(pidArray [processesCount - 1]){    情况下0:{
      killFlag = FALSE;
      字符的buff [255];
      INT colorNumber =(processesCount大于7)? 0:processesCount;
      sprintf的(BUFF,%sProcess%d个||,颜色[colorNumber],processesCount);
      而(!killFlag){
        usleep(10000);
        如果(printAllowed){
          的for(int i = 0; I<的strlen(浅黄色);我++){
            如果(killFlag){返回-1;};
            的printf(%C,BUFF [I]);
            刷新();
            usleep(50000);
          }
          printAllowed = FALSE;
          //信号母公司这一过程中停止打印
          杀死(getppid(),SIGUSR2);
        }
      }
      返回-1;
    }    情况-1:输出(%!sError,颜色[1]);返回1;    默认:1的回报;
  }
}布尔killProcess(将为pid_t pidArray []){
  如果(processesCount< = 0)返回1;  processesCount--;
  //停止最后一个子进程
  杀死(pidArray [processesCount],SIGUSR2);
  waitpid函数(pidArray [processesCount],NULL,NULL);
  //如果在打印停止现在的过程
  如果(currentProcessNumber> = processesCount){
    currentProcessNumber = 0; //从开始启动
    标志=真实的; //标志按编号最后一道工序
    killFlag = TRUE; //结束的标志打印当前进程
  }  返回1;
}INT controlProcesses(将为pid_t pidArray []){
  halfdelay(1);
  开关((炭)的getchar()){
  情况下=:返回的CreateProcess(pidArray);
  案例' - ':返回killProcess(pidArray);
  案例'Q':返回0;
  默认:1的回报;
  }
}无效killAllProcesses(将为pid_t pidArray []){
  如果(pidArray [ - processesCount]!= 0)
    为(; processesCount> = 0; processesCount - ){
      杀死(pidArray [processesCount],SIGUSR2);
      waitpid函数(pidArray [processesCount],NULL,NULL);
    }
}诠释主(){  initscr的();
  明确();
  NOECHO();
  刷新();
  printSignal.sa_handler = allowPrint;
  的sigaction(SIGUSR1,&安培; printSignal,NULL);  killSignal.sa_handler = setKillFlag;
  的sigaction(SIGUSR2,&安培; killSignal,NULL);  将为pid_t pidArray [100];  而(INT I = controlProcesses(pidArray)){    如果(我== -1)返回0;
    如果(killFlag&安培;&安培; processesCount大于0){//如果当前进程停止印刷
      killFlag = FALSE;
      如果(currentProcessNumber&GT = processesCount - 1)currentProcessNumber = 0; //如果当前进程的数量是最后,从开始开始
      否则,如果currentProcessNumber ++(旗!); //否则,如果上次停止的过程不是最后按编号进入下道工序
      标志= FALSE;
      杀死(pidArray [currentProcessNumber],SIGUSR1); //信号,子进程开始打印
    }
    刷新();
  }
  //停止所有子进程
  killAllProcesses(pidArray);  明确();
  endwin();  返回0;
}


解决方案

killFlags (和 printAllowed )是错误声明。它应该被宣布

 挥发性sig_atomic_t killFlags,printAllowed;

借助挥发性预选赛是非常重要的。否则,编译器会假定 killFlags 优化只能明确地改变(它不知道,信号处理程序可以在任何时刻改变它,所以它可以通过保持了优化在寄存器变量,等等...)。

请仔细阅读信号(7)手册页。

如果你的循环是一个轮询事件循环(可能基于的民意调查(2) ...),你可以考虑使用Linux特有的 signalfd(2)调用。

In createProcess(pid_t pidArray[]) function i create new process and if it's child i print it. But in while loop i everytime check killFlag, and my program no efficiant. How can i fix this issue.? Thank you for any help. In my program you can add process by pressing + or delete it by pressing - or just quit by pressing q.

This is my code:

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

解决方案

Your killFlags (and printAllowed) is wrongly declared. It should be declared

volatile sig_atomic_t killFlags, printAllowed;

The volatile qualifier is really important. Otherwise, the compiler would optimize by assuming killFlags can only be explicitly changed (it does not know that a signal handler could change it at any moment, so it could optimize by keeping that variable in a register, etc...).

Read carefully signal(7) man page.

If your loop is a polling event loop (probably based upon poll(2) ...) you might consider using the Linux specific signalfd(2) call.

这篇关于如何设置信号回路检查?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆