Како се користе руковаоци сигнала на језику Ц?

How Use Signal Handlers C Language



У овом чланку ћемо вам показати како се користе манипулатори сигналом у Линуку помоћу језика Ц. Али прво ћемо разговарати о томе шта је сигнал, како ће генерисати неке уобичајене сигнале које можете користити у свом програму, а затим ћемо погледати како програм може да обради различите сигнале док се програм извршава. Дакле, почнимо.

Сигнал

Сигнал је догађај који се генерише да би обавестио процес или нит да је стигла нека важна ситуација. Када процес или нит прими сигнал, процес или нит ће зауставити оно што ради и предузети одређене радње. Сигнал може бити користан за међупроцесну комуникацију.







Стандардни сигнали

Сигнали су дефинисани у датотеци заглавља сигнал.х као макро константа. Назив сигнала је почео са СИГ -ом, а затим следи кратак опис сигнала. Дакле, сваки сигнал има јединствену нумеричку вредност. Ваш програм увек треба да користи назив сигнала, а не број сигнала. Разлог је то што се број сигнала може разликовати у зависности од система, али ће значење имена бити стандардно.



Макро НСИГ је укупан број дефинисаних сигнала. Вредност НСИГ је један већи од укупног броја дефинисаних сигнала (Сви бројеви сигнала се додељују узастопно).



Стандардни сигнали су следећи:





Назив сигнала Опис
СИГХУП Прекините процес. Сигнал СИГХУП се користи за пријављивање искључења корисничког терминала, вероватно зато што се даљинска веза изгубила или прекинула везу.
СИГИНТ Прекините процес. Када корисник откуца знак ИНТР (обично Цтрл + Ц), шаље се сигнал СИГИНТ.
СИГКУИТ Напустите процес. Када корисник откуца знак КУИТ (обично Цтрл + ), шаље се сигнал СИГКУИТ.
СЕАЛ Незаконито упутство. Када се покуша извршити смеће или привилегована инструкција, генерише се сигнал СИГИЛЛ. Такође, СИГИЛЛ се може генерисати када се стек преплави, или када систем има проблема са покретањем руковаоца сигналом.
СИГТРАП Трап трап. Инструкција тачке прекида и друга инструкција замке генерисаће сигнал СИГТРАП. Отклањач грешака користи овај сигнал.
СИГАБРТ Прекид. Сигнал СИГАБРТ се генерише када се позове функција аборт (). Овај сигнал указује на грешку коју је програм открио и пријавио позивом функције аборт ().
СИГФПЕ Изузетак са покретном тачком. Када дође до фаталне аритметичке грешке, генерише се сигнал СИГФПЕ.
СИГУСР1 и СИГУСР2 Сигнали СИГУСР1 и СИГУСР2 могу се користити како желите. За њих је корисно уписати обрађивач сигнала у програм који прима сигнал за једноставну међупроцесну комуникацију.

Подразумевана радња сигнала

Сваки сигнал има подразумевану радњу, једну од следећих:

Термин: Процес ће се прекинути.
Језгро: Процес ће се прекинути и произвести датотеку думпа језгре.
Паљење: Процес ће игнорисати сигнал.
Зауставити: Процес ће се зауставити.
Рачун: Процес ће се наставити са заустављањем.



Подразумевана радња се може променити помоћу функције руковаоца. Подразумевана радња неког сигнала не може се променити. СИГКИЛЛ и СИГАБРТ подразумевана радња сигнала не може се променити или занемарити.

Руковање сигналом

Ако процес прими сигнал, процес има избор акције за ту врсту сигнала. Процес може занемарити сигнал, може навести функцију руковаоца или прихватити подразумевану радњу за такву врсту сигнала.

  • Ако се наведена радња за сигнал занемари, сигнал се одмах одбацује.
  • Програм може регистровати функцију руковаоца помоћу функције као што је сигнал или сигацтион . Ово се назива руковаоцем који хвата сигнал.
  • Ако сигнал није обрађен нити игнорисан, извршава се његова подразумевана радња.

Можемо да управљамо сигналом помоћу сигнал или сигацтион функција. Овде видимо како је најједноставније сигнал () функција се користи за руковање сигналима.

интсигнал() (интзнак, празнина (*функција)(инт))

Тхе сигнал () позваће функција функција ако процес прима сигнал знак . Тхе сигнал () враћа показивач на функцију функција ако је успешан или враћа грешку на еррно и -1 у супротном.

Тхе функција показивач може имати три вредности:

  1. СИГ_ДФЛ : То је показивач на подразумевану функцију система СИГ_ДФЛ () , изјављено године х заглавна датотека. Користи се за предузимање подразумеваних радњи сигнала.
  2. СИГ_ИГН : То је показивач на функцију занемаривања система СИГ_ИГН () , изјављено године х заглавна датотека.
  3. Кориснички дефинирани показивач на функцију руковаоца : Кориснички дефинисани тип функције руковаоца је воид (*) (инт) , значи да је повратни тип воид и један аргумент типа инт.

Пример основног руковаоца сигналом

#инцлуде
#инцлуде
#инцлуде
празнинасиг_хандлер(интзнак){

// Повратни тип функције хандлер треба да буде воид
принтф (' нУнутрашња функција руковаоца н');
}

интглавни(){
сигнал(СИГИНТ,сиг_хандлер); // Регистрирајте управљач сигналом
за(инти=1;;и++){ // Бесконачна петља
принтф ('%д: Унутар главне функције н',и);
спавај(1); // Одлагање за 1 секунду
}
повратак 0;
}

На снимку екрана излаза из Примера 1.ц можемо видети да се у главној функцији извршава бесконачна петља. Када је корисник откуцао Цтрл+Ц, извршавање главне функције се зауставља и позива се функција руковалаца сигналом. Након завршетка функције хендлера, извршавање главне функције је настављено. Када је корисник откуцао Цтрл+, процес се прекида.

Пример игнорисања сигнала

#инцлуде
#инцлуде
#инцлуде
интглавни(){
сигнал(СИГИНТ,СИГ_ИГН); // Регистрирајте управљач сигналом за игнорисање сигнала

за(инти=1;;и++){ // Бесконачна петља
принтф ('%д: Унутар главне функције н',и);
спавај(1); // Одлагање за 1 секунду
}
повратак 0;
}

Овде је функција хендлера регистрована на СИГ_ИГН () функција за игнорисање радње сигнала. Дакле, када је корисник откуцао Цтрл+Ц, СИГИНТ сигнал се генерише, али се радња занемарује.

Поново регистрирајте пример руковаоца сигналом

#инцлуде
#инцлуде
#инцлуде

празнинасиг_хандлер(интзнак){
принтф (' нУнутрашња функција руковаоца н');
сигнал(СИГИНТ,СИГ_ДФЛ); // Поново регистрирајте управљач сигналом за задану радњу
}

интглавни(){
сигнал(СИГИНТ,сиг_хандлер); // Регистрирајте управљач сигналом
за(инти=1;;и++){ // Бесконачна петља
принтф ('%д: Унутар главне функције н',и);
спавај(1); // Одлагање за 1 секунду
}
повратак 0;
}

На снимку екрана излаза из Примера3.ц можемо видети да се, када је корисник први пут откуцао Цтрл+Ц, позвала функција руковаоца. У функцији руковаоца, обрађивач сигнала се поново региструје на СИГ_ДФЛ за подразумевано деловање сигнала. Када је корисник други пут откуцао Цтрл+Ц, процес се прекида, што је подразумевана радња СИГИНТ сигнал.

Слање сигнала:

Процес такође може експлицитно слати сигнале себи или другом процесу. раисе () и килл () функција се може користити за слање сигнала. Обе функције су декларисане у датотеци заглавља сигнал.х.

инт подићи (интзнак)

Функција раисе () која се користи за слање сигнала знак до процеса позивања (самог). Враћа нулу ако је успешна и вредност различиту од нуле ако не успе.

интубити(пид_т пид, интзнак)

Функција килл која се користи за слање сигнала знак процесу или групи процеса коју одређује пид .

Пример обраде сигнала СИГУСР1

#инцлуде
#инцлуде

празнинасиг_хандлер(интзнак){
принтф ('Унутрашња функција руковаоца н');
}

интглавни(){
сигнал(СИГУСР1,сиг_хандлер); // Регистрирајте управљач сигналом
принтф ('Унутар главне функције н');
подићи (СИГУСР1);
принтф ('Унутар главне функције н');
повратак 0;
}

Овде процес шаље сигнал СИГУСР1 себи помоћу функције раисе ().

Подигните помоћу програма Пример примера

#инцлуде
#инцлуде
#инцлуде
празнинасиг_хандлер(интзнак){
принтф ('Унутрашња функција руковаоца н');
}

интглавни(){
пид_т пид;
сигнал(СИГУСР1,сиг_хандлер); // Регистрирајте управљач сигналом
принтф ('Унутар главне функције н');
пид=гетпид(); // ИД самог процеса
убити(пид,СИГУСР1); // Пошаљите СИГУСР1 себи
принтф ('Унутар главне функције н');
повратак 0;
}

Овде се процес шаље СИГУСР1 сигнал за себе користећи килл () функција. гетпид () користи се за добијање самог ИД -а процеса.

У следећем примеру видећемо како родитељски и подређени процеси комуницирају (међупроцесна комуникација) користећи килл () и сигналну функцију.

Комуникација родитеља са сигналима

#инцлуде
#инцлуде
#инцлуде
#инцлуде
празнинасиг_хандлер_парент(интзнак){
принтф („Родитељ: Примио сигнал одговора од детета н');
}

празнинасиг_хандлер_цхилд(интзнак){
принтф („Дете: Примио сигнал од родитеља н');
спавај(1);
убити(гетппид(),СИГУСР1);
}

интглавни(){
пид_т пид;
ако((пид=виљушка())<0){
принтф ('Форк Фаилед н');
излаз (1);
}
/ * Подређени процес */
елсе ако(пид==0){
сигнал(СИГУСР1,сиг_хандлер_цхилд); // Регистрирајте управљач сигналом
принтф („Дете: чека сигнал н');
пауза();
}
/ * Родитељски процес */
елсе{
сигнал(СИГУСР1,сиг_хандлер_парент); // Регистрирајте управљач сигналом
спавај(1);
принтф („Родитељ: шаље сигнал детету н');
убити(пид,СИГУСР1);
принтф („Родитељ: чека одговор н');
пауза();
}
повратак 0;
}

Овде, виљушка () функција ствара подређени процес и враћа нулу у подређени процес, а ИД подређеног процеса у родитељски процес. Дакле, пид је проверен како би се одлучило о родитељском и подређеном процесу. У родитељском процесу, он је спаван 1 секунду, тако да подређени процес може регистровати функцију руковаоца сигналом и сачекати сигнал од родитеља. Након 1 секунде родитељског процеса послати СИГУСР1 сигнал детету и сачекајте сигнал детета за одговор. У подређеном процесу, прво се чека сигнал од родитеља, а када се сигнал прими, позива се функција руковаоца. Из функције хандлер, подређени процес шаље другу СИГУСР1 сигнал родитељу. Ево гетппид () функција се користи за добијање ИД -а матичног процеса.

Закључак

Сигнал у Линуксу је велика тема. У овом чланку смо видели како се рукује сигналом из основних ствари, а такође смо стекли знање о томе како сигнал генерише, како процес може послати сигнал себи и другим процесима, како се сигнал може користити за међупроцесну комуникацију.