簡體   English   中英

系統調用C信號和分支

[英]System Calls in C signals and fork

嗨我用C中的功能程序來解決這個問題。

“編寫一個C程序,其中進程F創建子進程C.子進程C等待用戶輸入密碼,如果正確則向父親發送SIGUSR1信號,如果3次嘗試后密碼仍然不正確則會發送SIGUSR2向父親發信號並終止;如果從父親收到SIGUSR1信號,則必須停止查看“超時”消息。

他的父親在30秒后(如果沒有收到來自孩子的任何信號)必須將信號SIGUSR1發送給孩子並以退出(1)結束; 如果收到SIGUSR1信號必須以exit(0)結束; 如果收到信號,SIGUSR2必須以exit(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;
    }

我用這種方式編輯了我的程序:

#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;
}

現在它完美無缺,但我不知道我是否尊重練習文本。

正如評論中提到的(由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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM