Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>
Docbook 원문

pthread_kill(3)

1장. pthread_kill(3)

차례
1.1. 사용법
1.2. 설명
1.3. 반환값
1.4. 에러
1.5. 예제
1.6. 참고문헌

쓰레드 시그널 관련 함수들


1.1. 사용법

#include <pthread.h>
#include <signal.h>

int pthread_kill(pthread_t thread, int signo);
int  pthread_sigmask(int  how,  const  sigset_t  *newmask,
               sigset_t *oldmask);
int sigwait(const sigset_t *set, int *sig);
		


1.2. 설명

이 함수는 현재 쓰레드에 시그널newmask와 how 를 이용해서 시그널 마스크를 만든다. how는 SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK중 하나를 선택할 수 있다. SIG_BLOCK는 현재 설정된 시그널 마스크에 newmask를 추가하며 SIG_UNBLOCK는 현재 설정된 시그널 마스크에서 newmask를 제거하고 SIG_SETMASK는 newmask로 현재 시그널 마스크를 설정한다

pthread_kill()은 시그널번호signo를 가지는 시그널을 스레드 식별번호thread를 가지는 쓰레드에 전달한다.

sigwait()는 시그널 셋set에 지정된 시그널이 전달될 때까지 해당영역에서 대기한다. 만약 시그널을 받게 되면 받은 시그널 번호를 sig에 복사하고 리턴한다. set에 명시된 시그널들은 반드시 봉쇄로 지정되어야 한다. 그래야만 sigwait()에 의해서 검출되고 리턴된다. 만약 해당 시그널에 대해서 시그널 핸들러가 지정되어 있다면 함수는 호출되지 않게 된다.


1.3. 반환값

성공하면 0을, 실패하면 0이 아닌 값을 리턴한다.


1.4. 에러

ESRCH

th식별자를 가진 쓰레드가 존재하지 않는다.

EINVAL

th식별자를 가진 쓰레드가 이미 detach상태에 있다.


1.5. 예제

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

/*
 * 시그널 핸들러
 * 핸들러가 호출된 쓰레드의 ID와 시그널 번호를 출력한다.
 */
void sig_handler(int signo)
{
    printf("SIGNAL RECV TH ID %d : %d\n", pthread_self(),signo);
}

void *threadfunc2(void *arg);
void *threadfunc(void *arg);
void *s_signal(void *arg);

// 쓰레드 ID를 저장한다.  
int sigid[2];

int main()
{
    int n, i, j;
    pthread_t threadid;

    // 원하는 쓰레드로 시그널이 전달하는지 확인하기 위해서
    // 쓰레드 ID를 확인한다.
    if ((n = pthread_create(&threadid, NULL, threadfunc2, NULL)) != 0 )
    {
        perror("Thread create error ");
        exit(0);
    }
    sigid[0] = threadid;
    printf("thread2 id %d\n", threadid);

    if ((n = pthread_create(&threadid, NULL, threadfunc, NULL)) != 0 )
    {
        perror("Thread create error ");
        exit(0);
    }
    sigid[1] = threadid;
    printf("thread id %d\n", threadid);

    if ((n = pthread_create(&threadid, NULL, s_signal, NULL)) != 0 )
    {
        perror("Thread create error ");
        exit(0);
    }

    pthread_join(threadid, NULL);
}

void *threadfunc(void *arg)
{
    int i=0, j;
    struct sigaction act;
    sigset_t newmask;

    // 결과의 확인을 위해서 쓰레드 ID를 출력한다.
    printf("SIGINT Thread Start (%d)\n", pthread_self());

    // SIGINT에 대해서 시그널 핸들러를 등록했지만 
    // SIGINT를 블럭하도록 했으므로 시그널은 전달되지 않는다.  
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGINT);
    act.sa_handler = sig_handler;
    sigaction(SIGINT, &act, NULL);
    pthread_sigmask(SIG_BLOCK, &newmask, NULL);	

    while(1)
    {
        printf("%d\n", i);
        i++;
        sleep(1);
    }
    return ;
}

void *threadfunc2(void *arg)
{
    struct sigaction act;
	int lsigno;

    sigset_t newmask;
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGINT);

	// 시그널 핸들러를 등록 시켰지만 
	// sigwiat()가 가디리고 있으므로 실행되지 않는다.  
    act.sa_handler = sig_handler;
    sigaction(SIGINT, &act, NULL);

    while(1)
    {
		sigwait(&newmask, &lsigno);
		printf("i receive signo %d\n", lsigno);
        sleep(1);
    }
}

/*
 * SIGINT를 두개의 쓰레드로 서로다른 시간간격으로 
 * 전달한다. 
 */
void *s_signal(void *arg)
{
    int i = 1;
    while(1)
    {
        sleep(1);
        i++;
        if((i % 7) == 0)
        {
            printf("Send SIGINT %d\n", sigid[0]);
            pthread_kill(sigid[0], SIGINT);
        }
        if((i % 11) == 0)
        {
            printf("Send SIGINT %d\n", sigid[1]);
            pthread_kill(sigid[1], SIGINT);
        }
    }
}