👩🏻‍💻개발공부/리눅스

9. 리눅스 프로세스(Process) 예제로 알아보기 🔍(1/2)

리미32 2022. 12. 11. 16:02
728x90

 안녕하세요! 이번 포스팅에서는 리눅스 관련 개념인 프로세스의 예제를 다뤄보겠습니다~ 먼저 시작하기에 앞서 프로세스를 관리해줄 System Call들을 살펴보겠습니다!

1. Process Management System Calls

  • getpid : 프로세스의 ID를 얻는다.
  • getppid : 부모 프로세스의 ID를 얻는다.
  • fork : child 프로세스를 만들기 위해 부모 프로세스를 복제한다.
  • exec : code, data, stack 등을 replace를 교체한다.
  • exit : 프로세스를 종료한다. 종료할 때 상태 변수를 바꾸기 위해 사용한다.
  • wait : 자식 프로세스를 위해 대기한다.

2. fork() 출력 예제 [myfork]

 fork 하는 순간 parent 프로세스에서 리턴 한 번, child 프로세스에서 리턴 한 번해서 리턴을 총 두번합니다! 밑의 코드는 fork()의 리턴값에 따라 자식 프로세스인지 부모 프로세스인지 구별해서 각각 프로세스의 pid를 출력하는 코드입니다.

  • child → 0
  • parent → child의 프로세스의 PID
  • 실패 → -1
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
	pid_t v1;
	v1= fork();
	
	if(v1==0){ //child process
		printf("I'm child \n");
		printf("%d \n",v1);
		printf("pid : %d, ppid: %d \n",getpid(),getppid());	
	}
	else{
		printf("I'm Parent \n");
		printf("%d \n",v1);
		printf("pid : %d, ppid: %d \n",getpid(),getppid());
	}
	return 0;	
	
}

실행 결과

3. fork() 예제에 wait() 추가 [mywait()]

 -> wait를 하지 않으면 좀비 프로세스가 생길 수 있다. 

 좀비 프로세스란? 종료된 child 프로세스는 parent 프로세스가 return 코드를 수락할 때까지 시스템을 떠날 수 없습니다. return을 하지 않은채로 시스템을 종료시킨다면, 자식 프로세스가 좀비 프로세스가 된다. 한마디로, 프로세스 자체는 종료되었지만 부모 프로세스가 wait() 을 호출하지 않아서 시스템 프로세스 테이블에 남아있는 상태입니다.

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

int main(){
	pid_t v1;
	v1= fork();
	
	if(v1==0){ //child process
		printf("I'm child \n");
		printf("%d \n",v1);
		printf("pid : %d, ppid: %d \n",getpid(),getppid());		
	}
	else{
		printf("I'm Parent \n");
		printf("%d \n",v1);

		int exitstatus; //추가
		wait(&exitstatus); //추가

		printf("pid : %d, ppid: %d \n",getpid(),getppid());
	}

	return 0;	
	
}

실행결과(myfork()와 비교)

4. zombie 프로세스 만들기 [myzombie]

 부모 프로세스에서 wait()을 부르기 전에 무한반복을 걸어주면 좀비 프로세스가 생성된다.

  • <defunct> : 좀비 프로세스
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main(){
	pid_t v1;	
	v1= fork();
	
	if(v1==0){ //child process
		printf("I'm child \n");
		printf("%d \n",v1);
		printf("pid : %d, ppid: %d \n",getpid(),getppid());
		exit();
	}
	else{
		printf("I'm Parent \n");
		printf("%d \n",v1);

		int exitstatus;
		for(;;){} //추가
		wait(&exitstatus);

		printf("pid : %d, ppid: %d \n",getpid(),getppid());
	}
	return 0;	
}

 

실행결과 (ps -ef)

5. 프로세스 제작 사이에 숫자 프린트하기

  •  fork()과정 사이에 숫자 프린트 하는 코드를 넣는다. 
  •  WEXITSTATUS() 매크로를 활용하면 exit code를 알 수 있다.
  • fflush() -> printf의 경우 버퍼에 저장한 후 io디바이스에 출력하는 방식이라서 지연 시간이 있다. fflush를 붙일 경우 버퍼에 저장하지 않고 바로 내보내기 때문에 지연시간이 줄어든다.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main(){
	pid_t v1;
	v1= fork();
	
	if(v1==0){ //child process
		printf("child pid : %d, ppid: %d \n",getpid(),getppid());
		for(int i=0;i<100;i++){ //숫자 출력
			printf("%d ",i);
			fflush(NULL); //버퍼 비우기
		}
		printf("\n");
		exit(101);
	}
	else{
		
		int exitstatus;
		for(int i=100;i<200;i++){ //숫자 출력
			printf("%d ",i);
			fflush(NULL); //버퍼 비우기		 
		}

		printf("\n");
		wait(&exitstatus);
		printf("pid : %d, ppid: %d \n",getpid(),getppid());
		printf("exitcode: %d \n",WEXITSTATUS(exitstatus)); //WEXITSTATUS() : exit code를 알 수 있다.
	}

	return 0;	
	
}

실행결과 (child와 parent의 숫자가 나오는 순서는 시스템 os의 스케쥴러에 따라 달라진다.)

 다음 포스팅에서 이어서 진행하겠습니다!!

728x90