2013-12-07 4 views
0

В функции createProcess (pid_t pidArray []) я создаю новый процесс, и если это ребенок, я его распечатаю. Но во время цикла i каждый раз проверяйте 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; 
} 

ответ

1

Ваш killFlagsprintAllowed) ошибочно объявлен. Он должен быть объявлен

volatile sig_atomic_t killFlags, printAllowed; 

volatile классификатор действительно важно. В противном случае компилятор оптимизировал бы, предположив, что killFlags может быть явно изменен (он не знает, что обработчик сигнала мог бы изменить его в любой момент, поэтому он мог бы оптимизировать, сохранив эту переменную в регистре и т. Д.).

Прочтите внимательно signal(7) man page.

Если ваш цикл является опросом event loop (возможно, на основе poll(2) ...), вы можете подумать об использовании специального вызова signalfd(2) для Linux.

Смежные вопросы