5. (1 ~ 4)장에 대한 총괄 예제

System Program/signal 2013. 7. 8. 12:00

1. 시그널 전송 프로그램

 

시그널 SIGUSER2에 대해서 kill()시스템 함수를 통하여 1000000번을 설정한 PID 프로세스에 전송한다.

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>

#define MAX_SEND_SIGNUM 1000000 

int main(int argc, char *argv[])
{
	int i;
	pid_t pid;
	
	puts("insert PID");
	scanf("%ld", &pid);
	getchar(); // fflush(stdin);
	
	printf("%s: sending signal %d to process %ld %d times\n", argv[0], SIGUSR2, (long)pid, MAX_SEND_SIGNUM);
	
	for(i = 0; i < MAX_SEND_SIGNUM; i++)
		if(kill(pid, SIGUSR2) == -1)
			fprintf(stderr, "kill error [%s]\n", strerror(errno));
	
	printf("%s: exiting\n", argv[0]);
	
	exit(EXIT_SUCCESS);
	
	return 0;
}


 

2. 시그널 수신 프로그램

 

위의 송신 프로그램에서 보낸 시그널을 수신하여 시그널별로 얼마나 처리가 되었는지 결과를 카운팅한다.

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>

#define MAX_SLEEP_TIME 25

static int sigCnt[NSIG];
static volatile sig_atomic_t gotSigint = 0;

void printSigSet(FILE *of, const char *prefix, const sigset_t *sigset)
{
	int sig, cnt;
	
	cnt = 0;
	
	for(sig = 1; sig < NSIG /*32*/; sig++)
	{
		if(sigismember(sigset, sig))
		{
			cnt++;
			
			fprintf(of, "%s%d (%s)\n", prefix, sig, strsignal(sig));
		}
	}
	
	if(cnt == 0)
		fprintf(of, "%s<empty signal set >\n", prefix);
}

void signal_handler(int sig)
{
	if(sig == SIGINT)
		gotSigint = 1;
	else
		sigCnt[sig]++;
		
}

int main(int argc, char *argv[])
{
	int n;
	sigset_t pendingMask, blockingMask, emptyMask;
	
	printf("%s: PID is %ld\n", argv[0], (long)getpid());
	
	for(n = 1; n < NSIG; n++)
		(void) signal(n, signal_handler);
	
	sigfillset(&blockingMask);
	if(sigprocmask(SIG_SETMASK, &blockingMask, NULL) == -1)
		fprintf(stderr, "sigprocmask\n");
	
	printf("%s : sleeping for %d seconds\n", argv[0], MAX_SLEEP_TIME);
	sleep(MAX_SLEEP_TIME);
	
	if(sigpending(&pendingMask) == -1)
		fprintf(stderr, "sigpending\n");
	
	printf("%s : pending signals ars : \n", argv[0]);
	printSigSet(stdout, "\t\t",  &pendingMask);
	
	sigemptyset(&emptyMask);
	if(sigprocmask(SIG_SETMASK, &emptyMask, NULL) == -1)
		fprintf(stderr, "sigprocmask\n");
	
	while(!gotSigint)
		continue;
	
	for(n = 1; n < NSIG; n++)
		if(sigCnt[n] != 0)
			printf("%s: signal %d caught %d time%s \n", argv[0], n, sigCnt[n], (sigCnt[n] == 1) ? "" : "s");
	
	exit(EXIT_SUCCESS);
	
	return 0;
}

 

3. 설명

 

수신 프로그램은 초기 시그널 마스크를 sigfillset()함수를 통해서 모두 블록으로 초기화하고 25초간 수면상태로 진입 후

다시 모든 시그널을 블록하지 않는 구조이다.

 

송신 프로그램에서 보낸 시그널이 얼마나 처리되느냐는 위의 각 구간에서 얼마나 시그널이 수신되었느냐에 따라 다르다.

 

만약 초기 블록 후 수면상태까지 시그널이 모두 전송되었다면 단 하나의 시그널만 처리될 것이다. 왜냐하면 초기 블록된 상태에서 수신된 동일 시그널은 모두 보류 상태로 있고 보류 상태가 끝나면 단 하나의 시그널만 처리되기 때문이다.

 

하지만 만약 수면 상태 후에 시그널이 모두 '0'으로 초기화된 후에 전송된 시그널은 커널의 context switching을 고려하여

많은 수가 처리될 것이다.

 

4. 결론

 

시그널 방식은 비동기적인 방식으로 시그널이 프로세스에 제대로 전달되었는지 확인할 수 있는 방법이 없다.

또한 경우에 따라서는 처리가 되지 않고 버려지기 때문에 신호가 전달되었는지를 신뢰할 수 없으므로 비신뢰적인 특징을 가진다고 말할 수 있다.  


 

 

 

'System Program > signal' 카테고리의 다른 글

1. 개념과 개요  (0) 2014.02.19
6. sigaction() 함수에 대한 고찰  (0) 2013.07.08
3. 시그널 전송 방법(시스템 콜)  (0) 2013.07.08
2. 시그널의 종류와 사용법  (0) 2013.07.08
: