2016-12-22 4 views
3

Привет Я эту проблему решить с помощью функциональной программы в С.системных вызовов в сигналы C и вилкой

«Напишите программу C, где процесс создания F childprocess C. childprocess C ожидает пользователя для ввода пароля, если он правильно отправляет сигнал SIGUSR1 отцу, если после 3 попыток пароль все еще некорректен, он отправит сигнал SIGUSR2 отцу и прекратит, если он получит от отца сигнал SIGUSR1, должен прекратить просмотр " тайм-аут "

Его отец через 30 секунд (если он не получил никакого сигнала от ребенка) должен отправить сигнал SIGUSR1 ребенку и завершить его с выходом (1), если он получает сигнал SIGUSR1 nal должен заканчиваться выходом (0); .. Если он получает SIGUSR2 сигнал должен заканчиваться с выходом (2)»

Я пытаюсь решить, но я застрял Это то, что я сделал:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <sys/types.h> 
#include <signal.h> 

void fatherprocess(int mysignal){ 
    if (mysignal == SIGUSR1) { 
     printf("ACCESS GRANTED!\n"); 
     exit(0); 
    } 

    if (mysignal == SIGUSR2){ 
     printf("ACCESS DISCARDED! More than 3 tentatives!\n"); 
     exit(2); 
    } 

} 


void childprocess(int mysignal){ 
    if (mysignal == SIGUSR1) { 
     printf("TIMEOUT\n"); 
     exit(1); 
    } 
} 


int main(int argc, char *argcv[]){ 
    int fatherpid, childpid; 
    char enteredpassword[], password[] = "test"; 
    int i =0; 
    unsigned int time_to_sleep = 30; 

    fatherpid = getpid(); 
    childpid = fork(); 

    if (childpid == 0) { 
     printf("Child Process waiting for a password\n"); 
     while (1){ 
      if (i < 3) { 
       printf("Enter Password: "); 
       scanf("%s", enteredpassword); 
       if (enteredpassword == password) 
        signal(SIGUSR1, fatherprocess); 
      } else { 
       signal(SIGUSR2, fatherprocess); 
       exit(1); 
      } 
      i++; 
     } 
    } else { 
     printf("Father Process\n"); 
     while(time_to_sleep){ 
      time_to_sleep = sleep(time_to_sleep); 
      signal(SIGUSR1, childprocess); 
     } 
    } 
    return 0; 
    } 

I «ве отредактирован мою программу таким образом:.

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <sys/types.h> 
#include <signal.h> 

void fatherprocess(int mysignal, int fatherpid){ 
    if (mysignal == SIGUSR1) { 
     printf("ACCESS GRANTED!\n"); 
     kill(fatherpid, SIGUSR1); 
     exit(0); 
    } 

    if (mysignal == SIGUSR2){ 
     printf("ACCESS DISCARDED! More than 3 tentatives!\n"); 
     kill(fatherpid, SIGUSR2); 
     exit(2); 
    } 

} 


void childprocess(int mysignal, int childpid){ 
    if (mysignal == SIGUSR1) { 
     printf("TIMEOUT\n"); 
     kill(childpid, SIGUSR1); 
     exit(1); 
    } 
} 


int main(int argc, char *argcv[]){ 
int fatherpid, childpid; 
char enteredpassword[] = "test", password[] = "test"; 
int i =0; 
unsigned int time_to_sleep = 30; 

fatherpid = getpid(); 
childpid = fork(); 

if (childpid == 0) { 
    printf("Child Process waiting for a password\n"); 
    while (1){ 
     if (i < 3) { 
      printf("Enter Password: "); 
      scanf("%s", enteredpassword); 
      if (strcmp(enteredpassword, password) == 0) 
       fatherprocess(SIGUSR1, fatherpid); 
     } else { 
      fatherprocess(SIGUSR2, fatherpid); 
      exit(1); 
     } 
     i++; 
    } 
} else { 
    printf("Father Process\n"); 
    while(time_to_sleep){ 
     time_to_sleep = sleep(time_to_sleep); 
     childprocess(SIGUSR1, childpid); 
    } 
} 
return 0; 
} 

Сейчас он работает отлично, но я не знаю, если я уважал текст упражнения

+0

это полный код? вы не установили обработчики сигналов. – Nish

+0

Это не полный beacuse, я не знаю, как установить обработчики сигналов :(вы можете мне помочь? – JoKeRxbLaCk

+0

Нужно ли использовать kill systemcall вместо сигнала? – JoKeRxbLaCk

ответ

0

Как было отмечено в комментарии s (Jonathan Leffler), вам необходимо использовать системный вызов kill() (для отправки сигналов) и зарегистрировать обработчик сигнала, используя вызов, например sigaction(). Я связал эти два вызова с онлайн-страницами руководства, которые предоставляют дополнительную информацию о них.

Вот какой код, который демонстрирует, как это можно использовать для достижения поставленной цели. Вам все равно нужно добавить/изменить код для таких вещей, как подсказки и допустимая строка ввода. Пожалуйста, обратите внимание, что я не утверждаю, что это лучший способ сделать это, только то, что это пример того, как это можно сделать (он компилируется и работает для меня):

#include <unistd.h> 
#include <sys/types.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <stdio.h> 

static void get_password(char* buf, int maxbuf) 
{ 
    fgets(buf, maxbuf, stdin); 
} 

static int is_password_correct(char* buf) 
{ 
    return buf[0] == 'a'; 
} 

volatile int got_signal = 0; 
volatile int child_signal = 0; 

static void parent_sig_handler(int signum) 
{ 
    if (!got_signal) 
    { 
     got_signal = signum; 
     printf("parent_sig_handler: got sig %d\n", signum); 
    } 
} 

static void child_sig_handler(int signum) 
{ 
    if (!child_signal) 
    { 
     child_signal = signum; 
     printf("child_sig_handler: got sig %d\n", signum); 
    } 
} 

int main() 
{ 
    struct sigaction act; 
    sigfillset(&act.sa_mask); 
    act.sa_handler = parent_sig_handler; 
    sigaction(SIGALRM, &act, NULL); 
    sigaction(SIGUSR1, &act, NULL); 
    sigaction(SIGUSR2, &act, NULL); 

    pid_t child_pid = fork(); 
    if (child_pid == -1) 
    { 
     perror("error forking"); 
     exit(3); 
    } 
    if (child_pid == 0) 
    { 
     printf("child running\n"); 
     act.sa_handler = child_sig_handler; 
     sigaction(SIGUSR1, &act, NULL); 
     pid_t parent_pid = getppid(); 
     for (int i = 0; i < 3; ++i) 
     { 
      char passwd[64]; 
      passwd[0] = '\0'; 
      get_password(passwd, sizeof(passwd)); 
      if (is_password_correct(passwd)) 
      {  
       kill(parent_pid, SIGUSR1); 
       exit(0);  
      }  
     } 
     kill(parent_pid, SIGUSR2); 
     exit(2); 
    } 

    printf("parent running\n"); 
    alarm(30); /* sets parent up to receive a SIGALRM signal in 30 seconds */ 
    sigset_t sigmask; 
    sigemptyset(&sigmask); 
    while (!got_signal) 
    { 
     sigsuspend(&sigmask); 
    } 

    switch (got_signal) 
    { 
     case SIGALRM: 
      kill(child_pid, SIGUSR1); 
      exit(1); 
     case SIGUSR1: 
      exit(0); 
     case SIGUSR2: 
      exit(2); 
     default: 
      exit(3); 
    } 
    exit(3); 
} 
Смежные вопросы