본문 바로가기
linux

프로세스와 신호

by 상레알 2010. 8. 13.

출처: Beginning Lenux Programming

프로세스 (process)와 신호(Signal)는 리눅스 운영 환경의 토대를 형성한다.

프로세스와 신호는 리눅스와 기타 모든 UNIX류 컴퓨터 시스템들에서 일어나는 거의 모든 활동을 제어한다. 리눅스와 UNIX의 프로세스 관리 방식에 대한 이해는 시스템 프로그래머는 물론 응용 프로그램 프로그래머와 시스템 관리자에게도 크게 도움이 된다고 한다.

우선 프로세스라는것은 하나 이상의 스레드 들과 그 스레드들에 필요한 시스템 자원들을 포함하는 하나의 주소공간 으로 정의한다.

여기서 스레드는 하나의 프로세스 내에서 더 작은 단위로 독립적으로 실행시키며 제어가 가능한 흐름으로 정의되며
Excecution context (실행 컨텍스트)또는  Light weight(경랑급) 프로세스라고도 한다.

전통적인 프로세스들은 공유변수를 사용하지 못하는 문제점 이외에도 fork에 의한 프로세스 생성시에 데이터 영역과 스택 영역을 모두 복사하여 생성하므로 긴 생성시간과 메모리를 많이 차지하는 오버헤드를 안고 있다. 이러한 이유로 전통적인 프로세스를 중량급 프로세스(heavy weight process)라 부른다.

리눅스 같은 다중 태스킹 운영체제에서는 한 시점에서 여러 개의 프로그램들이 실행될 수 있다. 실행중인 각 프로그램은 하나의 프로세스가 되며 여러 프로세스들이 동시에 실행된다는 점은 X Window system (줄여서 X)같은 윈도우 시스템 을 보면 확실히 알 수 있다. MS Windows 처럼 X는 여러개의 응용프로그램들이 동시에 실행될 수 있는 그래픽 사용자 인터페이스를 제공한다.

리눅스는 다중 사용자 시스템인 만큼 동시에 여러 명의 사용자들이 시스템에 접근할 수 있다. 각 사용자는 동시에 여러 개의 프로그램들을 실행할 수 있으며, 심지어는 같은 프로그램의 여러 인스턴스들을 실행할 수도 있다. 시스템 자체도 시스템 자원을 관리하고 사용자 접근을 제어하기 위해 여러개의 프로그램들을 실행한다.

실행 중인 프로그램 (즉 , 프로세스)은 프로그램 코드, 자료, 변수들 ,(시스템 메모리를 차지한다. ) , 열린 파일들, 그리고 환경으로 구성된다.

리눅스 시스템은 한 시점에서 메로리에 코드의 복사본 하나만이 존재할 수 있도록 프로그램 코드와 시스템 라이브러리들을 여러 프로세스들이 공유하게 된다.

각 프로세스에는 고유한 식별 번호가 부여된다. 이를 프로세스 식별자 PID 라고 부르며 프로세스가 실행되면 아직 쓰이지 않은 일련번호가 부여되는데 일련번호는 2에서 시작하는 양의 정수로, 최대값을 일반저긍로 32,768이다. 만일 최대값을 넘기면 2에서 다시 시작하게 된다. 번호 1은 항상 init 프로세스에 쓰이는데 이 프로세스는 다른 프로세스들을 관리하는 특별한 프로세스이다.

grep 명령이 수행할 프로그램 코드는 디스크 파일에 저장되어 이싿. 일반적으로 리눅스 프로세스들은 프로그램 코드를 담고 있는 메모리 영역에 ㅏ료를 기록하지 못하므로, 해당 코드는 메로리에 읽기 전용 모드로 적재된다. 이영역은 비록 수정할 수는 없지만, 안전하게 여러 프로세스들에 의해 공유될 수는 있다.

시스템 라이브러리들 역시 공유될 수 있다. 예를 들어 실행중인 여러 프로그램들이 printf를 호출한다고 해도 printf 코드의 복사본은 하나로 충분하다. 이는 Windows에서 동적 연결 라이브러리 (DLL)가 쓰이는 방식과 비슷하다.(사실 더 정교하다고 한다)

라이브러리들에 대한 공유는 디스크상의 실행 파일의 크기를 줄이는 데에도 도움이 된다. 공유 라이브러리 코드를 실행 파일 마다 담아둘 필요가 없기 떄문이다. 프로그램 하나만 놓고 생각한다면 그로 인한 절약이 별로 크지 않을 것 같지만, 운영체제 전체로서는 표준 C 라이브러리처럼 수 많은 프로그램들이 사용하는 코드를 공유함으로써 상당한 양의 공간을 절약할 수 있다.

물론 프로그램의 실행에 필요한 모든 것을 공유할 수는 없다. 예를 들어 프로그램이 사용하는 변수들은 각 프로세스마다 개별적이다. 그리고 통상적인 방법으로는 한 프로세스가 다른 프로세스의 변수를 읽는 것이 불가능하다. 프로세스들은 각자 자신만의 파일 서술자들을 가지고 파일들에 접근한다.

프로세스가 함수의 지역 변수들과 함수 호출 및 반환의 제어에 쓰이는 정보를 관리하는 데 사용하는 스택 공간 역시 각 프로세스마다 독립적이다. 또한 프로세스는 자시만의 환경 공간을 가진다. 환경 공간은 환경 변수들을 담으며 더 나아가서 프로그램은 자신만의 프로그램 카운터를 가진다. 프로그램 카운터는 프로세스가 실행되고 있는 실행 스레드 (excution thread) 안에서의 현재 실행 위치를 가리킨다. 하나의 프로세스는 여러개의 실행 스레드들을 가질 수 있다.

프로세스 테이블

리눅스의 프로세스 테이블은 현재 적재된 모든 프로세스의 정보를 담은 자료 구조이다. 각 프로세스 항목은 ps가 출력하는 정보에 해당하는 필드들을 가진다.(PID, 상태, 명령 문자열 등) 운영체제는 PID를 이용해서 프로세스를 관리하는데, PID는 이 프로세스 테이블에 대한 색인으로 쓰인다. 이 테이블의 크기에는 한계가 존재하며, 따라서 시스템이 동시에 돌릴 수 있는 프로세스의 개수에도 한계가 주어진다. 초기 UNIX 시스템들은 최대 256개의 프로세스들을 돌릴 수 있었다. 좀 더 최근의 구현들에서는 이 상한이 훨씬 커졌다. 메모리가 허용하는 한 프로세스 테이블의 크기에는 한계가 없다고 말 할 수 있을 정도 이다.

프로세스 확인시 열...설명

ps -ef 명령시

TTY  열은 해당 프로세스가 어떤 터미널에서 실행되었는지 말해준다.  예를 들어 tty4 면 4번 가상 콘솔에서 로그인했음을 말해준다. 이것에 대한 자세한것은 모르겟지만... 하다보면 알게 되겟지 뭐 -_-;

TIME은 지금까지 프로세스가 소비한 CPU 시간을 가리킨다.

CMD 열은 프로세스를 시작하는데 쓰인 명령줄에 해당한다.

기본적으로 ps  프로그램은 터미널이나 콘솔, 직렬 회선, 가상 터미널과 연결을 유지하고 있는 프로세스들만을 보여준다. 그런 프로세스들 외에, 터미널을 통해 사용자와 상호작용하는 일없이도 실행되는 프로세스들이 있다. 이들은 일반적으로 리눅스가 공유 자원을 관리하는데 사용한는 시스템 프로세스들이다. 이런 프로세스들 모드 보고 싶다면  -e 옵션을 주어야한다. 그리고 -f 옵션을 주면 프로세스들의 완전한 정보가 출력된다.

ps 명령 구문과 출력 형태는 시스템마다 다들ㄹ 수 있다. 리눅스에 쓰이는 GNU 버전의 ps는 이전의 여러 ps 구현들 (BSD, AT&T unix 등)의 옵션들을 지원할 뿐만 아니라 자신만의 고유한 옵션들도 가진다. ps의 여러 옵션들과 출력 형식에 대해서는 해당 매뉴얼 페이지를 참고하는게...ㅋㅋ

일반적으로 프로세스를 시작한 프로세스를 부모 프로세스 (parent process)라고 부리고, 부모 프로세스가 시작한 프로세스를 자식 프로세스( child proces) 라고 부른다. 리눅스 시스템은 하나의 프로그램으로부터 시작된다. 바로 init 이라는 프로그램인데, 이 프로그램은 리눅스 시스템 전체의 조상 프로세스 역활을 하는 것으로 PID는 항상 1이다. 간단히 말하자면 운영체제 프로세스 관리자 인것이다. 이후의 모든 프로세스는 init이 또는 init이 시작한 다른 어떤 프로세스가 시작하게 된다.

init이 시작하는 프로세스의 한 예로 로그인 절차가 있다. init은 사용자가 로그인에 사용하는 직렬 터미널 또는 전화선 모뎀에 대해 getty 프로그램을 실행한다.

getty 프로세스는 터미널의 작동을 기다렸다가 전형적인 로그인 프롬프트를 사용자에게 제시하고는 로그인 프로그램에게 제어권을 넘긴다. 로그인 프로그램은 로그인된 사용자를 위해 사용자 환경을 설정하고 사용자의 셸을 시작한다. 사용자의 셸이 종료되면 init는 또 다른 getty 프로세스를 시작한다.

새 프로세스를 시작하고 그것이 종료되기를 기다리는 능력이 운영체제의 근본적인 기능에 해당함은 충분히 이해할 수 있다. fork, exec, wait라는 시스템 호출들을 이용해서 그러한 일을 수행하는 것이 가능...




'linux' 카테고리의 다른 글

좀비 프로세스  (0) 2010.08.17
프로세스 이미지 복제  (0) 2010.08.15
프로세스 이미지 대체하기  (0) 2010.08.15
새 프로세스 시작하기  (0) 2010.08.15
프로세스 일정 관리  (0) 2010.08.14
vim 설정  (0) 2010.06.30
모듈의 상호참조  (0) 2010.06.03
모듈에 대해 알아야 할것들  (0) 2010.06.03
Hello 커널 모듈 작성 예제  (0) 2010.06.02
모듈 개발.  (0) 2010.06.01