Computer Science/운영체제

[운영체제] 파이썬으로 프로세스와 스레드 다루기

이도하나 2023. 5. 2. 21:25
이 글은 혼자 공부하는 컴퓨터 구조+운영체제 교재와 강의를 참고하여 정리한 글입니다. 오타나, 잘못된 내용이 있으면 언제든지 알려주세요! 감사합니다.😊

 

파이썬으로 프로세스와 스레드 다루기

프로세스 다루기

프로세스 생성하기

print("hello, os!")
  • 단순히 "hello, os!"라는 문자열을 출력하는 코드이다.
  • 이 소스 코드를 실행하면 "hello, os!"라는 문자열을 출력하는 프로세스가 생성된다.
    • 이 프로세스 또한 PID를 가지고 있다.
    • 파이썬에서는 os 모듈의 getpid() 함수를 통해 현재 프로세스의 PID 값을 확인할 수 있다.
import os

print("hello, os!")
print("my pid is", os.getpid()) # 현재 프로세스의 PID 값을 확인할 수 있다.

위 소스 코드를 실행해 보면 다음과 같은 결과를 확인할 수 있다.

  • PID 값은 운영체제가 그때그때 부여하는 값이기 때문에 여러 번 반복적으로 실행했을 때 다른 PID 값이 출력될 수 있다.

 

자식 프로세스를 생성해 보자.

from multiprocessing import Process # 자식 프로세스를 생성하기 위해 multiprocessing 모듈을 불러온다.
import os

# 동시에 실행되어야 하는 코드가 있다고 가정하자.
def foo():
    print("foo: child process: ", os.getpid()) # foo를 실행하는 자식 프로세스의 PID를 확인
    print("foo: parent process: ", os.getppid()) # 부모 프로세스의 PID를 확인

if __name__ == '__main__':
    print("parent process: ", os.getpid())
    # 프로세스를 새롭게 생성
    # 새롭게 만든 프로세스는 foo() 함수를 실행하는 자식 프로세스이다.
    child = Process(target=foo).start()
  • 프로세스를 생성하기 위해 multiprocessing 모듈을 불러온다.
  • multiprocessing 모듈에서 프로세스 스포닝은 Process 클래스의 인스턴스를 생성한 후 start() 메서드를 호출하면 된다.
    • 스포닝이란 부모 프로세스가 운영체제에 요청하여 자식 프로세스를 새로 만들어내는 과정을 말한다.
  • 파이썬에서는 os 모듈의 getppid()를 통해 부모 프로세스의 PID 값을 확인할 수 있다.

 

위 소스 코드를 실행해 보면 다음과 같은 결과를 확인할 수 있다.

  • 자식 프로세스가 부모 프로세스의 PID 값인 PPID를 출력했을 때 자식 프로세스를 생성한 프로세스의 PID가 나오는 것을 확인할 수 있다. (32557)

 

동일한 작업을 하는 프로세스 생성하기

자식 프로세스를 여러 개 만들어보자.

from multiprocessing import Process # 자식 프로세스를 생성하기 위해 multiprocessing 모듈을 불러온다.
import os

# 동시에 실행되어야 하는 코드가 있다고 가정하자.
def foo():
    print("foo: child process: ", os.getpid()) # foo를 실행하는 자식 프로세스의 PID를 확인
    print("foo: parent process: ", os.getppid()) # 부모 프로세스의 PID를 확인

if __name__ == '__main__':
    print("parent process: ", os.getpid())
    
    # foo() 함수를 실행하는, 동일한 작업을 수행하는 여러 개의 자식 프로세스를 생성한다.
    child1 = Process(target=foo).start()
    child2 = Process(target=foo).start()
    child3 = Process(target=foo).start()

소스 코드를 실행해 보면 다음과 같은 결과를 확인할 수 있다.

  • child 1, 2, 3은 동일한 부모 프로세스로부터 생성되었기 때문에 동일한 부모 PID, PPID를 출력하는 것을 확인할 수 있다.
  • 자식 프로세스끼리의 PID는 다른 것을 확인할 수 있다. 엄연히 다른 프로세스이기 때문이다.
  • 동일한 작업(foo 함수 실행)을 동시에 수행하는 여러 자식 프로세스를 생성할 수 있다.

 

각기 다른 작업을 하는 프로세스 생성하기

각기 다른 작업을 하는 자식 프로세스를 만들어보자.

from multiprocessing import Process # 자식 프로세스를 생성하기 위해 multiprocessing 모듈을 불러온다.
import os

def foo():
    print("foo executed!!")  

def bar():
    print("bar executed!!")   

def baz():
    print("baz executed!!")  

if __name__ == '__main__':
    # 각기 다른 작업을 하는 자식 프로세스를 생성한다.
    child1 = Process(target=foo).start()
    child2 = Process(target=bar).start()
    child3 = Process(target=baz).start()

소스 코드를 실행해보면 다음과 같은 결과를 확인할 수 있다.

위 프로그램을 워드 프로세서 프로그램이라고 가정해 보자.

  • foo 함수는 사용자로부터 입력받는 기능
  • bar 함수는 사용자가 입력한 값을 화면에 출력하는 기능
  • baz 함수는 사용자가 입력한 값의 맞춤법을 검사하는 기능

즉, 각기 다른 작업을 하는 프로세스를 생성해 각기 다른 작업을 동시에 수행하는  소스 코드를 작성할 수 있다.

 

스레드 다루기

스레드 생성하기

import threading # 스레드를 생성하기 위해 threading 모듈을 불러온다.
import os

# 스레드가 실행할 함수
def foo():
    print("foo: my thread id is: ", threading.get_native_id()) # 스레드 id를 출력한다.
    print("foo: my process id is: ", os.gepid()) # pid를 출력한다.

if __name__ == '__main__':
    print("my pid is : ", os.getpid())
    # foo() 함수를 실행하는 스레드를 생성한다.
    thread1 = threading.Thread(target=foo).start()
  • 스레드를 생성하기 위해 threading 모듈을 불러온다.
  • threading.Thread()를 통해 스레드를 생성하고, start()를 통해 스레드를 실행하면 된다.
  • threading.get_native_id()를 통해 스레드 ID를 출력할 수 있다.

소스 코드를 실행해 보면 다음과 같은 결과를 확인할 수 있다.

  • 프로세스 내에서 ID가 344477인 스레드를 생성했다.
  • pid 값이 같은 것을 확인할 수 있다. 스레드는 프로세스를 이루고 있는 자원들을 공유하고 있기 때문이다.

 

동일한 작업을 하는 스레드 생성하기

import threading # 스레드를 생성하기 위해 threading 모듈을 불러온다.
import os

# 스레드가 실행할 함수
def foo():
    print("foo: my thread id is: ", threading.get_native_id()) # 스레드 id를 출력한다.
    print("foo: my process id is: ", os.getpid()) # pid를 출력한다.

if __name__ == '__main__':
    print("my pid is : ", os.getpid())
    # 동일한 작업을 하는 스레드를 생성한다.
    thread1 = threading.Thread(target=foo).start()
    thread2 = threading.Thread(target=foo).start()
    thread3 = threading.Thread(target=foo).start()

소스 코드를 실행해보면 다음과 같은 결과를 확인할 수 있다.

  • foo()라는 함수를 실행하는 세 개의 스레드를 만들었다.
  • 세 개의 스레드 모두 각기 다른 스레드이지만, 이들은 모두 동일한 프로세스를 공유하고 있다.
  • 따라서 스레드 ID는 모두 다르게 출력되지만, 프로세스 ID는 모두 동일하게 출력된다.

 

각기 다른 작업을 하는 스레드 생성하기

import threading # 스레드를 생성하기 위해 threading 모듈을 불러온다.
import os

# 스레드가 실행할 함수
def foo():
    print("executed foo")

def bar():
    print("executed bar")

def baz():
    print("executed baz")

if __name__ == '__main__':
    # 각기 다른 작업을 하는 스레드를 생성한다.
    thread1 = threading.Thread(target=foo).start()
    thread2 = threading.Thread(target=bar).start()
    thread3 = threading.Thread(target=baz).start()

소스 코드를 실행해보면 다음과 같은 결과를 확인할 수 있다.

  • 이처럼 하나의 프로세스 내에 여러 개의 실행 흐름을 만들어낼 수 있다.