Ch.10. Procces

서버 유형

1. 단일 접속

- 연결을 요청하는 클라이언트를 순차적으로 연결

2. 다중 접속

- 연결을 요청하는 모든 클라이언트에게 동시에 서비스 제공

- 네트워크 프로그램은 CPU 연산이 필요치 않으며, 데이터의 송수신 시간의 비중이 높아 다중 접속이 효과적이다.

- 종류

    a. 멀티프로세스 - 다수의 프로세스를 생성해 연결하는 방식

    b. 멀티플렉싱 - 입출력 대상을 묶어서 관리해 연결하는 방식

    c. 멀티스레딩 - 클라이언트의 수만큼 쓰레드 생성해 연결하는 방식

Procces

Process(프로세스)란?

"메모리 공간을 차지한 상태에서 실행중인 프로그램"

"OS 프로그램 관리 기본 단위"

"하나의 프로그램이 여러개의 프로세스 >> 멀티프로세스 서버"

PID - Process ID

프로세스 생성

#include <unistd.h>

pid_t fork(void);

// 성공시 PID , 실패시 -1 반환
// 실행중인, fork() 함수를 호출한 프로세스를 복사한다.
// fork() 이후의 문장을 새로운 프로세스로 실행한다.

프로세스 종료

좀비 프로세스

- fork() 호출로 생성된 프로세스가 종료되지 않고, 시스템 리소스를 차지하고 있는 상태

생성 원인

- fork() 호출로 생성된 프로세스가 종료되는 경우는 1. exit 호출 2. main의 return 이다. 운영체제는 부모 프로세스가 존재할 경우, 부모 프로세스의 exit, return 값이 전달되기 전까지 자식 프로세스를 종료시키지 않는다.

해결책

- 부모 프로세스에서 명시적으로 자식 프로세스를 종료 처리해야 한다.

1. wait()

#include .<sys/wait.h>

pid_t wait(int *statloc);

// 성공시 종료된 자식 프로세스의 PID, 실패시 -1 반환
// 이미 종료된 자식 프로세스가 있다면, 종료시 전달값 (exit 인자, return 반환 값)
// 이미 종료된 자식 프로세스가 없다면, 임의의 자식 프로세스가 종료될때까지 Blocking
WIFEXITED   // Wait IF Exited
            // 자식 프로세스가 정상 종료한 경우 ‘참(true)'을 반환
WEXITSTATUS // Wait Exit Status
            // 자식 프로세스의 전달 값을 반환
            
if(WIFEXITED(status)) // 정상 종료인가?
{
	puts("Normal termination!");
	printf("Child pass num: %d", WEXITSTATUS(status)); // 그렇다면 반환 값은?
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
	int status;
	pid_t pid=fork();
	
	if(pid==0)
	{
		return 3;   	
	}
	else
	{
		printf("Child PID: %d \n", pid);
		pid=fork();
		if(pid==0)
		{
			exit(7);
		}
		else
		{
			printf("Child PID: %d \n", pid);
			wait(&status);
			if(WIFEXITED(status))
				printf("Child send one: %d \n", WEXITSTATUS(status));

			wait(&status);
			if(WIFEXITED(status))
				printf("Child send two: %d \n", WEXITSTATUS(status));
			sleep(30);     // Sleep 30 sec.
		}
	}
	return 0;
}

2. waitpid()

#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *statloc, int options);

// 성공시 종료된 자식 프로세스의 PID (or 0), 실패시 -1 반환
// pid     종료를 확인하고자 하는 자식 프로세스의 PID 전달, 
//         이를 대신해 -1 경우, wait와 마찬가지로 임의의 자식 프로세스가 종료될때까지 Blocking 
// statloc wait의 statloc과 동일
// options 헤더파일 sys/wait.h에 선언된 상수 WNOHANG을 인자로 전달하면, 
//         종료된 자식 프로세스가 존재하지 않아도, Blocking 없이 0을 반환
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
	int status;
	pid_t pid=fork();
	
	if(pid==0)
	{
		sleep(15);
		return 24;   	
	}
	else
	{
		while(!waitpid(-1, &status, WNOHANG))
		{
			sleep(3);
			puts("sleep 3sec.");
		}

		if(WIFEXITED(status))
			printf("Child send %d \n", WEXITSTATUS(status));
	}
	return 0;
}

/*
root@my_linux:/home/swyoon/tcpip# gcc waitpid.c -o waitpid
root@my_linux:/home/swyoon/tcpip# ./waitpid
sleep 3sec.
sleep 3sec.
sleep 3sec.
sleep 3sec.
sleep 3sec.
Child send 24 
*/

3.3 Signal Handling

wait() 함수는 자식 프로세스가 종료되었음을 확인 할 수 있다.

하지만 자식 프로세스의 종료 시점을 알 수 없기에 wait() 함수가 대기한다.

 

signal == 특정 상황이 발생했음을 알림

handling == 상황에 따른 메시지에 반응해 연관된 작업 진행

 

함수의 반복 호출 or 대기 상태가 아닌, 운영체제에게 "fork()로 생성된 프로세스가 종료되면 signal handler 실행" 명령

#include <signal.h>

void (*signal(int signo , void ( *func)(int)))(int);

// 시그널 발생시 호출되도록 이전에 등록된 함수의 포인터 반환
// 첫 번째 매개변수로 특정 상황 정보
// 두 번째 매개변수로 특정 상황에서 호출될 함수의 주소값(포인터)
// 첫번째 매개변수
SIGALRM    alarm 함수호출을 통해서 등록된 시간이 된 상황
SIGINT     CTRL+C가 입력된 상황
SIGCHLD    자식 프로세스가 종료된 상황
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void timeout(int sig)
{
	if(sig==SIGALRM)
		puts("Time out!");

	alarm(2);	
}
void keycontrol(int sig)
{
	if(sig==SIGINT)
		puts("CTRL+C pressed");
}

int main(int argc, char *argv[])
{
	int i;
	signal(SIGALRM, timeout);
	signal(SIGINT, keycontrol);
	alarm(2);

	for(i=0; i<3; i++)
	{
		puts("wait...");
		sleep(100);
	}
	return 0;
}

sigaction

#include <signal.h>

int sigaction(int signo , const struct sigaction *act, struct sigaction *oldact);

// 성공시 0, 실패시 -1 반환
// signo  signal 함수와 마찬가지로 시그널 의 정보를 인자로 전달
// act    첫번째 인자로 전달된 상수에 해당는 시그널 발생시 호출될 함수(시그널 핸들러)의 정보 전달
// oldact 이전에 등록되었던 시그널 핸들러 의 함수 포인터를 얻는데 사용되는 인자, 필요 없다면 0 전달

프로세스 생성과 종료

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

void read_childproc(int sig)
{
	int status;
	pid_t id=waitpid(-1, &status, WNOHANG);
	if(WIFEXITED(status))
	{
		printf("Removed proc id: %d \n", id);
		printf("Child send: %d \n", WEXITSTATUS(status));
	}
}

int main(int argc, char *argv[])
{
	pid_t pid;
	struct sigaction act;
	act.sa_handler=read_childproc;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	sigaction(SIGCHLD, &act, 0);

	pid=fork();
	if(pid==0)
	{
		puts("Hi! I'm child process");
		sleep(10);
		return 12;
	}
	else
	{
		printf("Child proc id: %d \n", pid);
		pid=fork();
		if(pid==0)
		{
			puts("Hi! I'm child process");
			sleep(10);
			exit(24);
		}
		else
		{
			int i;
			printf("Child proc id: %d \n", pid);
			for(i=0; i<5; i++)
			{
				puts("wait...");
				sleep(5);
			}
		}
	}
	return 0;
}

/*
root@my_linux:/home/swyoon/tcpip# gcc remove_zombie.c -o zombie
root@my_linux:/home/swyoon/tcpip# ./zombie
Hi! I'm child process
Child proc id: 9529 
Hi! I'm child process
Child proc id: 9530 
wait...
wait...
Removed proc id: 9530 
Child send: 24 
wait...
Removed proc id: 9529 
Child send: 12 
wait...
wait...

*/

댓글

공지사항
업데이트
인기 글
최근댓글
태그
m1 윈도우 단축키 인터넷 속도 단위 MariaDB Connector M1 Parallels Ubuntu QT c 알고리즘 fgets( ) 개행('\0')과 NULL 처리 m1 페러렐즈 단축키 실제 인터넷 속도 2진수 실수 표현 littem endian 이진수 음수표현 mysql 외부 Ip 오류 C2011 'timespec': 'struct' 형식 재정의 return 0 성공 이유 C networking fputc( ) C2027 정의되지 않은 형식 'timespec' A2449 실제 저장 용량 MK293KE/A 포인터와 참조 네이퍼 적립 계산 네이버 맴버쉽 계산 맥북 독 반응 c# 클래스 if(false) 빅엔디안 2진법과 기수 리틀 엔디안과 빅 엔디안 독 속도 조절 Visual Studio에서 inet_ntoa( ) 경고 알고리즘이란 2진법과 서수 소켓 m1 매직 키보드 c언어 스트림 fputs( ) 표준 입출력 스트림 ubuntu 우분투 독 에러 connect() 네이버 적립 스트림 버퍼 효과적인 if 코드 윈도우 db 2진수와 Byte 네이버 제휴 카드 적립 M1 Parallels Ubuntu QT install 버퍼란 mariadb 외부접속 Apple Silicon Mac용 터치아이디 탑재형 매직 키보드 - 미국 영어 (MK293KE/A) #define HAVE_STRUCT_TIMESPEC c언어 버퍼 listen() db 외부접속 MariaDB Connector/C++ mysql 방화벽 우분투 qt M1 독 바로 보기 네이버 포인트 적립 계산 stream buffer 네이버 페이 결제 m1 페러렐즈 윈도우 맥 단축키 네이버 제휴 통장 적립 io stream M1 dock window mysql 리턴 0 이유 MariaDB 방화벽 스트림과 버퍼 mariaDB 외부 접속 C++ connector 2진수 음수 표현 puts( ) db 방화벽 mariadb 재설치 우분투 디스코드 MK293KH/A 윤성우의 열렬 TCP/IP 소켓 프로그래밍 socket programming m1 Shift space Magic Keyboard with Touch ID mariadb 삭제 How to show/hide the macOS Dock instantly 우분투 독 비활성화 고정 소수점 몬트레이 Shift Space 이진수 실수표현 socket M1 dock speed 맥 독 반응 속도 C# 메서드 socket networking if 가독성 if 코드 구조 pointer reference if(0) 윈도우 timespecs 네이버 맴버쉽 적립 몬트레이 한영 전환
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31