티스토리 뷰

  네트워크 프로그래밍을 알기위해서는 소프트웨어의 기초를 알아야한다. 이런 기초가 되는 것 중 대표적인 부분이 바로 '프로세스'와 '스레드'이다. 아마 소프트웨어에 대해 한번이라도 배워본 사람이라면 저 두 말을 들어본 적이 있을 것이다. 프로세스는 또 일상생활에서 많이 쓰는 단어라 이해하는데 수월하다. 하지만 컴퓨터 공학적으로 두 용어를 정의하라고 했을때 명확하게 대답하는 사람은 많이 없을 것이다. 그래서 이번 시간부터 프로세스와 스레드의 정확한 개념을 잡고 가보자.



현재 CPU에서 실행되고 있는 프로세스


1. 프로세스란?


  우리가 Java 프로그램 하나를 만들었다. 어떤 프로그램이든 상관 없다. 아주 단순한 'Hello World' 프로그램을 개발했다고 하자. 프로그램은 우리가 정한 일종의 정의다. 이 프로그램을 실행 시킨다면 이렇게 작동해야 된다를 담고 있다. 이 프로그램을 실행을 시켜 Hello World를 출력 시켜야 한다. 이렇게 프로그램을 실행시켜 출력 시키는 과정을 프로세스라고 한다. 즉, 우리는 사전에 미리 정의된 프로그램을 실행 시켜 프로세스를 만든다. 프로세스에서는 프로그램에 작성된 코드에 따라 동작을 한다. 그래서 작업(Task)와 거의 동일한 의미를 지닌다. 다만 작업은 보다 추상적인 개념으로 보는 것이고, 프로세스(Process)는 좀더 공학적인 개념을 보는 것이다. 


  우리가 자주 쓰는 작업 표시창에서도 현재 CPU에서 실행되고 있는 프로세스를 쉽게 확인 할 수 있다.




  프로그램은 실행시키는 횟수 만큼 프로세스가 생성된다. (스레드란 개념을 배우기 전이라면) 그리고 프로세스의 가장 큰 특징은 각각의 프로세스는 독립되어 있다. 프로세스 간에는 아무런 공유 행위가 없다. 각각의 프로세스 마다 다른 메모리를 가지게 된다. 프로세스 개념 아래에선 같은 프로그램을 두번 실행 시키게 되면 메모리게 독립된 2개의 공간이 발생한다. 서로 독립성을 지녔기에 CPU는 두 프로세스가 서로 같은 프로그램이라는걸 알지 못한다. 사실 CPU는 생성된 프로세스를 빠르게 처리하는데 관심이 있을 뿐 각 프로세스가 어떤 일을 하는지는 크게 관심이 없다. 즉, 동일한 프로그램의 2개의 프로세스는 정의된 동일한 프로그램의 코드만 바라 볼 뿐 서로 아무런 영향을 끼치지 않는다.


2. 프로세스 상태


  우리가 회사에서 일을 하다 보면 일정한 간격을 두고 일정하게 발생하지 않는다. 갑자기 일이 터질때는 미칠 듯이 오다가 아닐 떄는 또 잠잠하기도 하다. 그래서 대부분의 직장인들은 각각의 일에 우선순위를 매긴다. 당장 급한 일을 진행하고, 비교적 덜 중요한 일을 나중에 하게 한다. 다만 이렇게 진행하다 보면 급한일만 처리하기 되기에 적장하게 시간 배분을 하면서 덜 중요한 일도 같이 처리한다. 즉, 각각의 일에 중요도와 마감기한을 통해 자기자신만의 상태를 만들게 된다. 이 각각의 일을 Process라고 하고 우리의 뇌를 CPU라고 한다면 컴퓨터도 사람과 다르지 않다는 사실을 쉽게 알 수 있다.


  프로세스 관리는 CPU의 주 업무다. 우리가 실행시키는 프로세스륻 빠르게 처리하는 것이 CPU의 주 관심사이다. 이 과정을 편리하게 진행 시키려고 프로세스를 몇가지 상태로 나누어 관리한다. 우리가 프로세스를 실행시킬 떄마다 CPU가 점령당한다면 CPU는 터져 버릴지 모른다. 그래서 각각의 프로세스를 상태로 나누어 관리한다. CPU가 부여하는 프로세스 상태는 아래와 같다.

  • 생성 (Create) : 새로운 프로세스의 생성
  • 실행 (Running) : CPU에서 해당 프로세스를 처리하는 중
  • 준비 (Ready) : 프로세스의 생성은 완료 되었지만, CPU에서 다른 프로세스를 진행하느라고 대기상태에 놓인 프로세스, 우선순위가 존재해                   높은 우선순위의 프로세스가 먼저 진행 됨 
  • 대기 (Waiting) : 프로세스가 진행 되었이나, 다른 프로세스의 출력값이 필요해 기다리고 있는 상태 (ex. 입출력)
  • 종료 (Terminated) : 프로세스의 실행이 완전히 종료 (원하는 결과를 얻었거나, 치명적 오류로 인한 완전 종료)


3. 프로세스 프로그래밍

  Java에도 Process 클래스가 존재한다. JVM은 당신이 만든 자바 프로그램을 실행시키면 CPU에게 새로운 프로세스의 생성을 알릴 것이다. 프로세스 클래스의 역할은 JVM에게 내가 새로운 프로세스를 생성했다는 것을 알리는 것이다. 즉, 프로그램 실행 도중 Process Class 를 생성하는 것은 JVM에게 새로운 프로세스가 생성 되었음을 CPU에게 알려달라는 의미다. 이런 프로세스 클래스는 주로 외부 입출력이 발생할 때 많이 사용된다.


  Process Class를 만드는 방법은 총 2가지 이다. 첫번째는 Rumtime 클래스를 이용하는 방법과 ProcessBuilder 클래스를 이용하는 방법이다. 이 두 방법의 차이를 한번 살펴보자.


 3.1 Runtime 클래스 이용


  소프트웨어 공학에서 런타임(Runtime)이란 프로세스가 작동하고 있는 동작을 의미한다. Java 개발자들이 치를 떠는 런타임 오류 역시 여기서 나온 말이다. 런타임 오류가 발생하는 시점은 바로 프로그램을 실행시킨 이후에 프로세스가 만들어지고, 각각의 동작에서 구문상 오류(Syntax Error)가 존재해 발생한다. 컴파일을 하는 도중에 발생되는 컴파일러 오류와는 대칭이 되는 개념이다. 프로세스 생성후 각각의 런타임에서 무언가 데이터를 주고 받는 과정에서 타입이나 크기가 안맞아 발생되는 것이 대표적인 런타임 오류다. 어렵게 말했지만 즉, 런타임 오류는 우리가 코딩을 잘못해서 생긴 오류다.


  Process 클래스가 프로그램에서 강제로 프로세스를 제어하기 위해 사용한다면, Runtime 클래스 역시 프로그램에서 런타임 클래스를 강제로 제어하기 위해서 사용한다. 프로세스의 동작을 런타임으로 지칭하기 때문에, Process 클래스 동작을 위해 Runtime 클래스가 왜 필요한지에 대한 이유는 충분히 설명 되었다고 생각한다. 이제 아래 예시를 보며 Runtime 클래스를 이용한 Process 클래스의 생성과 동작을 살펴보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package processtest;
 
import java.io.IOException;
import java.util.*;
 
public class Solution {
 
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
 
        
        Runtime runtime = Runtime.getRuntime();
 
        try {
            Process p = runtime.exec("notepad.exe");
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
}
cs


  해당 프로그램은 외부 프로세스를 이용해 메모장을 실행시키는 프로그램이다. 여기서 Process 클래스에서 메모장을 실행시키기 위해 런타임 클래스를 정의하는 방식을 채택했다. Runtime 클래스의 실행 함수는 exec()이다.

 3.2 ProcessBuilder 클래스 이용

  런타임 생성 없이 ProcessBuilder 클래스를 이용해서도 프로세스를 실행 시킬 수 있다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package processtest;
 
import java.io.IOException;
import java.util.*;
 
public class Solution {
 
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
 
        ProcessBuilder builder = new ProcessBuilder("notepad.exe");
 
        try {
            Process p = builder.start();
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
}
cs


  ProcessBuilder 클래스를 사용하는 방법도 런타임 방식과 크게 다르지 않다. Process Builder의 경우 실행시키는 함수가 start()이다.


 3.3 Process 클래스 Method

  앞서 생성한 프로세스를 제어하기 위해서는 Process 클래스에서 사용 가능한 Method의 종류를 알아야 한다. 아래는 Process 클래스에서 사용하는 주요 Method이다. 참고로 우리가 프로그램을 통해 강제로 실행한 프로세스는 자동적으로 자식 프로세스(Subprocess)가 된다. 처음 실행하게 되는 프로그램의 프로세스가 부모 프로세스다. 메모장을 열든 기타 다른 동적을 하든 부모 프로세스의 행동에 의해 실행 되었기 때문이다.

  • destroy() : 프로세스 종료
  • exitValue() : 프로세스 실행 값 변환 (0이면 정상 출력)
  • waitfor() : 현재 진행중인 프로세스가 종료 될때까지 대기

 3.4 Process 클래스 예제

  Process 클래스를 이용해 매우 간단한 프로그래밍을 해보자. 프로그래밍을 진행하는 도중에 계산기 기능이 필요하고 이 계산기 프로세스가 정상적으로 끝나면 그 값을 사용자가 직접 메모장에 옮겨 적는다고 해보자. 그렇다면 우선 계산기 작동이 선행되어야 하고 계산기가 종료되면 이를 프로그램이 인식해 자동으로 메모장을 켜 주어야한다.

  계산기 프로세스 : calcProcess
  메모장 프로세스 : memoProcess

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
package processtest;
 
import java.io.IOException;
import java.util.*;
 
public class Solution {
 
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
 
        ProcessBuilder calcBuilder = new ProcessBuilder("calc.exe");
        ProcessBuilder memoBuilder = new ProcessBuilder("notepad.exe");
 
        
        try {
            Process calcProcess = calcBuilder.start();
            calcProcess.waitFor();
            
            if(!calcProcess.isAlive()){
                Process memoProcess = memoBuilder.start();
                memoProcess.waitFor();
            }
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
}
cs
  
  여기서 waitFor() 를 사용하는 이유는 왜일까? 만약 calcProcess가 실행하고 있는 도중에 waitFor()가 존재하지 않는다면 곧바로 calcProcess 구문을 읽게 되고 아직 프로세스가 작동중이라고 인식하여 memoProcess 객체가 생성되지 않을 수 있다. 이처럼 프로세스 클래스는 CPU의 진행 프로세스의 영향을 많이 받게 되므로 매우 신중하게 작성해야 한다. 다음 시간에 이 부분에 대해 더욱 자세히 알아보도록 하자.



(참고 자료)

- 오라클 자료

Process Class : https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html#Process--

Runtime Class : https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html


- Naver D2

Java에서 외부 프로세스를 실행할 때 : https://d2.naver.com/helloworld/1113548


- 위키 백과

프로세스 문서 : https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4

'Skill > Programming - Network' 카테고리의 다른 글

6. 스레드 폴링, 콜백  (0) 2019.05.07
5. 스레드(Thread)  (0) 2019.04.27
4. 프로세스 관리 (Process Control)  (1) 2019.04.07
2. 스트림 (Stream)  (0) 2019.03.03
1. OSI 7계층  (1) 2019.02.17
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/10   »
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
글 보관함