2013-10-09 4 views
1

я столкнулся с проблемами по обработке сигнала при написании оболочки, как программы на C.
Вот это упрощенная версия моего кода:Неправильные печати при использовании обработчика сигнала

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <unistd.h> 
#define SIZE 255 

void sig_handler(int sig){ 
if (sig == SIGINT) 
    printf("\n[shell]$\n"); 
} 

int main() 
{ 
    char input[SIZE]; 
    printf("[shell]$"); 
    signal(SIGINT,sig_handler); 
    while(gets(input) != NULL){ 
    // code of the shell including command interpreter and command execution 
     printf("[shell]$"); 
    } 
    return 0; 
} 

Когда я запускаю программу и попробовать SIGINT с командой - «кошка», выход показывает, как:

[shell]$ ^C (ctrl+C pressed for the first time) 
[shell]$  
^C   (the input position go to the next line, which is unwanted) 
[shell]$ 
cat   (I want it in the same line with [shell]$) 
^C 
[shell]$ 
[shell]$  (duplicate printing occurs) 

Я попытался изменить функцию недействительным sig_handler (INT Sig), удалив второй \ п. Однако ситуация становится хуже, чем раньше. Программа не запускает автоматически событие сигнала при первом нажатии ctrl + C.

Чтобы уточнить мою проблему, вот два вопроса, которые я задаю:
1. Как сделать входную позицию на той же линии с [shell] $?
2. Как решить проблему дублирования печати?

+1

Не уверен в дублировании, но вы можете сделать что-то печататься в одной строке, удалив \ n в конце напечатанной строки (хотя вам может понадобиться использовать 'fflush (stdout)', чтобы он появился) , – zneak

+0

Большое вам спасибо! Для проблемы с дублированием я обратился к ней, создав еще одну функцию обработки сигнала без printf. –

ответ

1

Что @zneak, это правда, вы можете использовать fflush и удалять в sig_handler второго \n,

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <unistd.h> 
#define SIZE 255 

void sig_handler(int sig){ 
if (sig == SIGINT) 
    printf("\n[shell]$"); 
    fflush(stdout); 
} 

int main() 
{ 
    char input[SIZE]; 
    printf("[shell]$"); 
    fflush(stdout); 
    signal(SIGINT,sig_handler); 
    while(gets(input) != NULL){ 
    // code of the shell including command interpreter and command execution 
     printf("[shell]$"); 
    } 
    return 0; 
} 
+0

Спасибо вам большое! Моя программа работает так, как я хочу сейчас. –

0

Прежде всего, печать из обработчика сигнала является плохой идеей. Обработчик сигналов подобен обработчику прерываний - он происходит асинхронно, он может быть поднят, находясь внутри вашего стандартного кода библиотеки, и вызов другой процедуры stdlib может испортить его с не-реентерабельными внутренностями (представьте, что вы поймаете SIGINT, а внутри printf() в вашей петле) ,

Если вы действительно хотите вывести что-то изнутри, лучше использовать необработанный write() вызов stderr дескриптор файла.

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