Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Передача сигналов между функциями 
V
    Опции темы
qw1mb0
  Дата 29.3.2012, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Непутевый студент
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.4.2010
Где: Севастополь

Репутация: нет
Всего: нет



Добрый день Есть задание нужно по определенной схеме передать сигналы от процесса предка процессу потомку и из потомка предку.
Вот код в котором потомок получает сигналы, обрабатывает их как надо, НО при передаче сигналов потомку выводится сообщение "Обрыв терминальной линии":
Код

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
static int c=0;
int fib(int);
void term_handler(int sig)
{
  switch(sig)
{
  case SIGHUP:
    printf("Parent send SIGHUP\n");
    printf("Fib - %d\n", fib(c));
    c++;
    break;
  case SIGTERM:
    printf("Parent send SIGTERM\n");
    break;

}
}
void my_handler(int sig)
{
  switch(sig)
  {
    case SIGHUP:
      printf("Child send SIGHUP to parent\n");
      break;
    case SIGTERM:
      printf("Child send SIGTERM to parent\n");
      exit(0);
      break;
  }
}
void parent(int gs)
{
int i,x;
struct sigaction sl;
sigset_t newlset;
sigemptyset(&newlset);
sl.sa_handler = my_handler;
for (i = 0; i < 4;i++){
printf("I am parrent. Send SIGHUP ");
printf("Iter - %d\n", i);
sleep(3);
kill(gs,SIGHUP);
sleep(2);
kill(gs,SIGHUP);
sleep(5);
}
sleep(15);
puts("I am parrent. Send SIGTERM \n");
sleep(5);
if(kill(gs, SIGTERM)==0){
  printf("It's OK to send SIGTERM\n");
}
 while(1){
  sigaction(SIGHUP, &sl, 0);
  sleep(10);
  sigaction(SIGTERM, &sl, 0);
}

printf("It's OK\n");
}
void child()
{
  int i,z;
struct sigaction sa;
sigset_t newset;
sigemptyset(&newset);
sa.sa_handler = term_handler;
printf("I am child. I am waiting...\n");
for(z = 0; z < 10; z++){
  sigaction(SIGHUP, &sa, 0);
  sleep(10);
  sigaction(SIGTERM, &sa, 0);
  
}
for(i = 0; i <4; i++){
  printf("I am child. Send SIGHUP. Iter - %d\n", i);
 sleep(3);
  kill(getppid(),SIGHUP);
  sleep(2);
  kill(getppid(), SIGHUP);
  sleep(5);
}
printf("Child Finished....\n");
}
int main(void){
  int gs;
  if(gs=fork())
  {
    parent(gs);
  }
  else
    child();
  return EXIT_SUCCESS;
}
int fib(int c)
{
  if(c == 0) return 0;
  if(c == 1) return 1;
  return fib(c-1)+fib(c-2);
}

По сигналу SIGHUP потомок вычислеяет следующее число в ряде Фибоначчи, а при передаче сигнала предку должен выводить сообщение, но не выводит. Хотя сигнал отправляется. 
Что выводит:
user posted image

В чем может быть проблема?

PM MAIL ICQ Skype   Вверх
bsa
Дата 29.3.2012, 23:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



qw1mb0, для подобных вещей есть сокеты (не обязательно сетевые), пайпы, ipc...
PM   Вверх
qw1mb0
Дата 29.3.2012, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Непутевый студент
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.4.2010
Где: Севастополь

Репутация: нет
Всего: нет



bsa, Я понимаю, что есть сокеты smile Но это задания из универа. Просто не могу понять, почему предок не обрабатывает сигналы
PM MAIL ICQ Skype   Вверх
xvr
Дата 30.3.2012, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Орригинальное использование функции sigaction  smile !
Почитайте повнимательнее, что именно она делает

PM MAIL   Вверх
qw1mb0
Дата 30.3.2012, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Непутевый студент
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.4.2010
Где: Севастополь

Репутация: нет
Всего: нет



xvr, Изменение действия процесса при получении определенного сигнала, так ведь?
PM MAIL ICQ Skype   Вверх
xvr
Дата 31.3.2012, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(qw1mb0 @  30.3.2012,  20:43 Найти цитируемый пост)
так ведь? 

Нет. Функция sigaction  устанавливает обработчик, который будет вызван при поступлении сигнала в процесс. Звать ее (sigaction) надо 1 раз в начале программы, а не каждый раз тогда, когда может придти сигнал

PM MAIL   Вверх
qw1mb0
Дата 31.3.2012, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Непутевый студент
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.4.2010
Где: Севастополь

Репутация: нет
Всего: нет



Цитата(xvr @  31.3.2012,  10:44 Найти цитируемый пост)
Нет. Функция sigaction  устанавливает обработчик, который будет вызван при поступлении сигнала в процесс. Звать ее (sigaction) надо 1 раз в начале программы, а не каждый раз тогда, когда может придти сигнал

Ну изменил код так, избавился от циклов: 
Код

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
static int c=0;
int fib(int);
void term_handler(int sig)
{
  switch(sig)
{
  case SIGHUP:
    printf("Parent send SIGHUP\n");
    printf("Fib - %d\n", fib(c));
    c++;
    break;
  case SIGTERM:
    printf("Parent send SIGTERM\n");
    break;

}
}
void my_handler(int sig)
{
  switch(sig)
  {
    case SIGHUP:
      printf("Child send SIGHUP to parent\n");
      break;
    case SIGTERM:
      printf("Child send SIGTERM to parent\n");
      exit(0);
      break;
  }
}
void parent(int gs)
{
int i,x;
struct sigaction sl;
sigset_t newlset;
sigemptyset(&newlset);
sl.sa_handler = my_handler;
for (i = 0; i < 4;i++){
printf("I am parrent. Send SIGHUP ");
printf("Iter - %d\n", i);
sleep(3);
kill(gs,SIGHUP);
sleep(2);
kill(gs,SIGHUP);
sleep(5);
}
sleep(15);
puts("I am parrent. Send SIGTERM \n");
sleep(5);
if(kill(gs, SIGTERM)==0){
  printf("It's OK to send SIGTERM\n");
}
//sleep(20);
//for(x = 0; x < 10; x++){
 //while(1){
  sigaction(SIGHUP, &sl, 0);
  //sleep(10);
  sigaction(SIGTERM, &sl, 0);
//}

printf("It's OK\n");
}
void child()
{
  int i,z;
struct sigaction sa;
sigset_t newset;
sigemptyset(&newset);
sa.sa_handler = term_handler;
printf("I am child. I am waiting...\n");
//for(z = 0; z < 10; z++){
  sigaction(SIGHUP, &sa, 0);
 // sleep(10);
  sigaction(SIGTERM, &sa, 0);
  
//}

//sleep(50);
//send:

for(i = 0; i <4; i++){
  printf("I am child. Send SIGHUP. Iter - %d\n", i);
 sleep(3);
  kill(getppid(),SIGHUP);
  sleep(2);
  kill(getppid(), SIGHUP);
  sleep(5);
}
//sleep(5);
//printf("I am child. Send SIGTERM\n");
//kill(getppid(), SIGTERM);
//sleep(5);
printf("Child Finished....\n");
}
int main(void){
  int gs;
  if(gs=fork())
  {
    parent(gs);
  }
  else
    child();
  return EXIT_SUCCESS;
}
int fib(int c)
{
  if(c == 0) return 0;
  if(c == 1) return 1;
  return fib(c-1)+fib(c-2);
}


Вот, что получается 
user posted image

PM MAIL ICQ Skype   Вверх
xvr
Дата 31.3.2012, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(qw1mb0 @  31.3.2012,  13:11 Найти цитируемый пост)
Ну изменил код так, избавился от циклов: 

Этого недостаточно. Перенесите вызов sigaction в начало функции parent в родителе (после строки 42). У вас сейчас обработчик сигналов в родителе устанавливается в самом конце, и когда child посылает сигнал родителю, то обработчик не вызывается, т.к. он еще не установлен. Вместо этого родитель прибивается с сообщением 'обрыв терминальной линии'


PM MAIL   Вверх
qw1mb0
Дата 31.3.2012, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Непутевый студент
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.4.2010
Где: Севастополь

Репутация: нет
Всего: нет



xvr, А разве из моего скриншота не видно, что предок не обрабатывает сигналы посланные родителем? Он должен на каждом сигнале выводить следующее число фибоначчи, а он выводит только 1 раз. Далее не обрабатывая сигнал. 
PM MAIL ICQ Skype   Вверх
xvr
Дата 1.4.2012, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(qw1mb0 @  31.3.2012,  21:02 Найти цитируемый пост)
xvr, А разве из моего скриншота не видно, что предок не обрабатывает сигналы посланные родителем?

В смысле 'потомок не обрабатывает'? Он и не будет, т.к. родитель никаких сигналов не посылает, т.к. его к этому моменту уже убил этот самый потомок (неперехваченным сигналом)

У вас процесс выглядит так:
  •  Стартуют родитель и потомок
  •  Потомок ставит перехватчик на сигналы (стр 77 и 79), предок перехватчиков не ставит
  •  Оба ждут 3 секунды и посылают друг другу сигнал
  •  В потомке срабатывает перехватчик сигнала, печатается первое число фибоначи
  •  В это же время родитель этим самым сигналом прибивается (т.к. перехватчика нет). В окне появляется сообщение от шела ОС 'обрыв терминальной линии'
  •  С этого момента потомок начинает рассылать сигналы в воздух (т.к. процесс, которому они адресованны уже мертв)

PM MAIL   Вверх
qw1mb0
Дата 1.4.2012, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Непутевый студент
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.4.2010
Где: Севастополь

Репутация: нет
Всего: нет



xvr, В таком случае вот этот код должен:
1. parent в цикле посылает всего 8 сигналов SIGHUP
2. В процессе child мы устанавливаем обработчик сигналов sigaction(SIGHUP, &sa, 0 ); в строке 48 с соответствующей реакцией на сигнал SIGHUP определенной в функции term_handler (вывод следющего числа фибоначчи). Судя по вашим словам эта 48 строка должна обработать все 8 сигналов от parent и вывести 8 чисел фибоначчи. 
3. Далее parent шлет сигнал SIGTERM и child должен вывести сообщение и завершить программу так как в обработчике задано exit(0); - 19 строка

Код

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
static int c=0;
int fib(int);
void term_handler(int sig)
{
  switch(sig)
{
  case SIGHUP:
    printf("Parent send SIGHUP\n");
    printf("Fib - %d\n", fib(c));
    c++;
    break;
  case SIGTERM:
    printf("Parent send SIGTERM\n");
    exit(0);
    break;

}
}
void parent(int gs)
{
int i,x;
for (i = 0; i < 4;i++){
printf("I am parrent. Send SIGHUP ");
printf("Iter - %d\n", i);
sleep(3);
kill(gs,SIGHUP);
sleep(2);
kill(gs,SIGHUP);
}
puts("I am parrent. Send SIGTERM \n");
sleep(5);
kill(gs, SIGTERM);

printf("It's OK\n");
}
void child()
{
  int i,z;
struct sigaction sa;
sigset_t newset;
sigemptyset(&newset);
sa.sa_handler = term_handler;
  sigaction(SIGHUP, &sa, 0);
  sigaction(SIGTERM, &sa, 0);
printf("I am child. I am waiting...\n");

printf("Child Finished....\n");
}
int main(void){
  int gs;
  if(gs=fork())
  {
    parent(gs);
  }
  else
    child();
  return EXIT_SUCCESS;
}
int fib(int c)
{
  if(c == 0) return 0;
  if(c == 1) return 1;
  return fib(c-1)+fib(c-2);
}


Но вот, что выводит у меня программа: 
user posted image

Видно, что child не обрабатывает сигналы от parent, хотя обработчик установлен.

Хм... Он не обрабатывает, потому что child успевает завершить работу. Понял свою ошибку. Но почему при добавлении sleep(50); в 51 строку, он все равно обрабатывает только 1 сигнал SIGHUP от parent ?

Это сообщение отредактировал(а) qw1mb0 - 1.4.2012, 21:02
PM MAIL ICQ Skype   Вверх
qw1mb0
Дата 1.4.2012, 21:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Непутевый студент
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.4.2010
Где: Севастополь

Репутация: нет
Всего: нет



xvr
Спасибо большое за обсуждение и критику. Помогла пойти в правильную сторону и код заработал, вот он какой получился:
Код

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
static int c=0;
int fib(int);
void term_handler(int sig)
{
  switch(sig)
{
  case SIGHUP:
    printf("Parent send SIGHUP\n");
    printf("Fib - %d\n", fib(c));
    c++;
    break;
  case SIGTERM:
    printf("Parent send SIGTERM\n");
    //exit(0);
    break;

}
}
void my_handler(int sig)
{
  switch(sig)
  {
    case SIGHUP: 
      printf("Child send SIGHUP\n");
      break;
    case SIGTERM:
      printf("Child send SIGTERM\n");
      exit(0);
      break;
  }
}
void parent(int gs)
{
int i,x;
struct sigaction sl;
sigset_t newlset;
sigemptyset(&newlset);
sl.sa_handler = my_handler;
sigaction(SIGHUP, &sl, 0);
sigaction(SIGTERM, &sl, 0);

for (i = 0; i < 4;i++){
sleep(1);
printf("I am parrent. Send SIGHUP ");
printf("Iter - %d\n", i);
sleep(3);
kill(gs,SIGHUP);
sleep(2);
kill(gs,SIGHUP);
}
sleep(5);
puts("I am parrent. Send SIGTERM \n");
sleep(5);
kill(gs, SIGTERM);
for (x = 0; x < 9; x++){
  pause();
}
printf("It's OK\n");
}
void child()
{
  int i,z;
struct sigaction sa;
sigset_t newset;
sigemptyset(&newset);
sa.sa_handler = term_handler;
  sigaction(SIGHUP, &sa, 0);
  sigaction(SIGTERM, &sa, 0);
printf("I am child. I am waiting...\n");
for (i = 0; i < 9; i++){
  pause();
}
for (z = 0; z < 4; z++){
  sleep(1);
  printf("I am child send SIGHUP ");
  printf("Iter - %d\n", z);
  sleep(3);
  kill(getppid(), SIGHUP);
  sleep(2);
  kill(getppid(), SIGHUP);
  //sleep(2);
}
sleep(4);
printf("I am child send SIGTERM\n");
sleep(5);
kill(getppid(), SIGTERM);
printf("Child Finished....\n");
}
int main(void){
  int gs;
  if(gs=fork())
  {
    parent(gs);
  }
  else
    child();
  return EXIT_SUCCESS;
}
int fib(int c)
{
  if(c == 0) return 0;
  if(c == 1) return 1;
  return fib(c-1)+fib(c-2);
}


А вывод тот, который я хотел выглядит так:
user posted image
PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.1091 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.