본문 바로가기
Computer Science/UNIX & Linux

[UNIX/Linux] ep8+) 시그널 함수 실습

by 클레어몬트 2024. 10. 24.

ex1. 자신에게 SIGUSR1 시그널을 보내는 프로그램을 작성하시오. 시그널을 보낸 후 출력문을 넣어 출력이 되는지, 프로그램을 실행하면 어떤 메시지가 출력되는지 확인하시오 (kill을 사용)

kill (getpid(), SIGUSR1);

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

int main() {
    printf("Send SIGUSR1 Signal to me.\n");
    kill(getpid(), SIGUSR1);
    printf("After SIGQUIT Signal.\n");

    return 0;
}

 

 

 

ex2. SIGILL 시그널의 기본 처리는 코어 덤프이다. SIGILL 시그널을 처리하는 시그널 핸들러를 작성해 실행하면 코어 덤프가 발생하지 않는지 확인하시오 (signal, kill을 사용)

kill (getpid(), SIGILL);

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void sig_handler(int signo) {
    printf("Signal Handler signum: %d\n", signo);
    psignal(signo, "Received Signal");
}

int main() {
    void (*hand)(int);

    hand = signal(SIGILL, sig_handler);
    if (hand == SIG_ERR) {
        perror("signal");
        exit(1);
    }

    kill(getpid(), SIGILL);

    return 0;
}

 

 

 

ex3. 리눅스는 시그널 핸들러가 한 번 실행된 후에 다시 기존 처리로 리셋하지 않는다. SIGQUIT을 받아서 두 번째 같은 시그널을 받으면 기본 처리로 실행하도록 작성하시오

kill(getpid(), SIGQUIT);

kill(getpid(), SIGQUIT);

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void sig_handler(int signo) {
    printf("Signal Handler signum: %d\n", signo);
    sleep(1);
    psignal(signo, "Received Signal");
    signal(SIGQUIT, SIG_DFL);
}

int main() {
    void (*hand)(int);

    hand = signal(SIGQUIT, sig_handler);
    if (hand == SIG_ERR) {
        perror("signal");
        exit(1);
    }

    kill(getpid(), SIGQUIT);
    //pause();
    kill(getpid(), SIGQUIT);

    return 0;
}

 

 

 

ex4. 시그널 집합을 정의하고 여기에 SIGQUIT, SIGILL, SIGTRAP 시그널을 설정한 다음 SIGILL 시그널이 설정되었는지 확인하는 프로그램을 작성하시오 (sigismember 사용)

#include <stdio.h>
#include <signal.h>

int main() {
    sigset_t st;

    sigemptyset(&st);

    sigaddset(&st, SIGILL);
    sigaddset(&st, SIGQUIT);
    sigaddset(&st, SIGTRAP);

    if (sigismember(&st, SIGILL)) {
        printf("SIGILL has been set.\n");
    }
    else {
        printf("SIGILL isn't set.\n");
    }

    return 0;
}

 

 

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

 

 

ex1. sigaction() 함수를 이용해 SIGQUIT 시그널을 붙잡고 이에 대한 처리 함수를 작성하시오. SIGQUIT 시그널을 한 번 처리한 다음에는 다시 기본 처리 방법으로 설정이 바뀌게 하시오.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void sig_handler(int signo) {
    psignal(signo, "Received Signal:");
    sleep(3);
    printf("In Signal Handler, After Sleep\n");
}

int main() {
    struct sigaction act;

    sigemptyset(&act.sa_mask);

    // sigaddset(&act.sa_mask, SIGQUIT);

    act.sa_flags = SA_RESETHAND;
    act.sa_handler = sig_handler;
    if (sigaction(SIGQUIT, &act, (struct sigaction*)NULL) < 0) {
        perror("sigaction");
        exit(1);
    }

    fprintf(stderr, "Input SIGQUIT: ");
    pause();
    fprintf(stderr, "After Signal Handler\n");

    return 0;
}

SIGQUIT 입력은 ctrl + \ 로 하면 된다

 

 

 

ex2. 시그널 집합을 이용해 모든 시그널을 집합에 설정하고, 이 중에서 SIGBUS가 설정되었는지 확인하는 프로그램을 작성하시오

#include <stdio.h>
#include <signal.h>

int main() {
    sigset_t st;

    sigfillset(&st);

    if (sigismember(&st, SIGBUS))
        printf("SIGBUS is setting.\n");
    else
        printf("SIGBUS is not setting.\n");

    return 0;
}

 

 

 

ex3. 반복문과 sleep(1) 함수를 사용해 1초 간격으로 “UNIX Programming”을 출력하는 프로그램을 작성하시오. 작성된 프로그램

이 CTRL+C로 종료되지 않도록 sigprocmask() 함수를 이용해 블로킹하시오 (아래 함수들을 적절하게 사용할 것)

sigemptyset(&set); sigaddset(&set, SIGINT);

sigprocmask(SIG_BLOCK, &set, (sigset_t*)NULL;

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int main() {
    sigset_t set;

    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    sigprocmask(SIG_BLOCK, &set, (sigset_t*)NULL);

    while(1) {
        printf("UNIX Programming\n");
        sleep(1);
    }
    printf("End...\n");

    return 0;
}

ctrl + c 를 해도 탈출이 안되는 모습(블로킹)

 

 

 

ex4. 인터벌 타이머를 이용해 프로세스 실행 시간이 1초가 될 때마다 메시지를 출력하는 프로그램을 작성하시오

signal(SIGVTALRM, handler);

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>

void handler() {
    printf("Timer Invoked..\n");
}

int main() {
    struct itimerval it;

    signal(SIGVTALRM, handler);
    it.it_value.tv_sec = 0;
    it.it_value.tv_usec = 100000;
    it.it_interval.tv_sec = 1;
    it.it_interval.tv_usec = 0;

    if (setitimer(ITIMER_VIRTUAL, &it, (struct itimerval*)NULL) == -1) {
        perror("setitimer");
        exit(1);
    }

    while(1);

    return 0;
}

 

 

 

hw1. sigaction() 함수를 이용해 SIGINT시그널을 붙잡고 이를 처리하는 시그널 핸들러를 작성하시오. Sa_flags에 SA_SIGINFO를 설

정하고 sa_sigaction을 사용하며, 시그널 핸들러 함수에서 si_code 값을 출력해 시그널이 발생하는 원인을 확인하시오

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

void signal_handler(int sig, siginfo_t* info, void* context) {
    printf("Received signal: %d\n", sig);
    printf("Signal code: %d\n", info->si_code); // 시그널 발생 원인 확인
}

int main() {
    struct sigaction act;

    memset(&act, 0, sizeof(act));
    act.sa_sigaction = signal_handler; // 시그널 핸들러 지정
    act.sa_flags = SA_SIGINFO; // SA_SIGINFO 설정으로 sa_sigaction 사용

    if (sigaction(SIGINT, &act, NULL) == -1) {
        perror("sigaction");
        return 1;
    }

    printf("Press Ctrl+C to trigger SIGINT\n");

    while (1) {
        sleep(1); // 무한 대기
    }

    return 0;
}

 

 

 

hw2. alarm() 함수를 이용해 1초마다 “Wake up” 메시지를 출력하는 프로그램을 작성하시오. SIGALRM 시그널의 핸들러가 실행되는 동안 SIGINT를 제외하고 모든 시그널을 블로킹하시오

sigfillset(&set);

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void alarm_handler(int sig) {
    printf("Wake up\n");

    alarm(1); // 다음 alarm 설정
}

int main() {
    struct sigaction act;
    sigset_t set;

    sigfillset(&set);
    sigdelset(&set, SIGINT); // 모든 시그널을 채우고 SIGINT는 블로킹에서 제외

    act.sa_handler = alarm_handler; // SIGALRM 핸들러 설정
    act.sa_mask = set; // SIGINT를 제외한 모든 시그널 블로킹
    act.sa_flags = 0;

    if (sigaction(SIGALRM, &act, NULL) == -1) {
        perror("sigaction");
        return 1;
    }

    alarm(1); // 1초 후에 SIGALRM 발생 설정

    while (1) {
        pause(); // 시그널 대기
    }

    return 0;
}

1초 간격으로 "Wake up" 문장이 출력

 

 

 

 

 

 

 

참고 및 출처: 시스템 프로그래밍 리눅스&유닉스(이종원)