IT 그리고 정보보안/Knowledge base

리눅스 프로세스 상호 관계

plummmm 2021. 4. 14. 13:50
반응형

이전까지 프로세스를 어떻게 제어하는지에 대한 내용을 보았다.

이제 이 프로세스들이 서로 어떤 관계들이 성립하는지에 대한 내용을 볼 것이다.

먼저 UNIX 시스템에 사용자가 로그인하는 과정에 대한 얘기를 해볼까 한다.

 

터미널 로그인에 대한 내용을 보겠다.

 

먼저, init 프로세스가 터미널이 생성될 때마다 fork로 복사가 된다.

하나의 터미널당 한번 init을 하나씩 복사하는 것이다.

 

그리고 exec류 함수를 이용하여 fork로 생성된 자식 init 프로세스를

getty 라는 프로그램으로 변경한다. 지금 상태의 getty는 텅텅 비어있다.

(getty는 터미널을 열고 초기환경 설정 및 시스템에 열린 터미널을 관리하는 프로그램이다.)

 

자 이제 getty가 실행이 되었다. 그다음은 getty가 다시 exec류 함수를 이용하여 login 프로그램을 실행시킨다.

 

getty로 환경설정이 끝나면 login을 실행시키는데, init, getty, login 모두다 동일한 프로세스이다.

exec로 실행되는 프로그램만 교체한 것임.. 즉, PID가 모두 동일하다.

login 과정까지는 root 권한으로 실행이 된다.

 

이제 그 후 login이 사용자 패스워드를 불러와 인증과정을 수행한다.

 

login은 하는일이 굉장이 많은데, 먼저 getpwnam()을 불러와 사용자의 패스워드 항목을 가져온다.

그 뒤, getpass(3)을 호출하여 패스워드 입력 프롬프트를 실행하고 패스워드를 받는다.

받은 패스워드를 crypt(3)을 호출하여 암호화 시킨다음 그것을 shadow파일의 pw_passwd 필드의 값과 비교한다.

만약 로그인이 실패하면 exit(1)이 실행되고 처음부터 다시 과정을 밟게 된다.

 

로그인 인증이 완료되면 여러가지 작업이 수행된다.

1. 현재 작업 디렉토리를 사용자의 홈 디렉토리로 변경한다. (chdir)

2. root에서 사용자로 권한을 변경한다. (chown)

3. 터미널 장치에 대한 접근 권한을 설정한다.

4. setgid, initgroups를 호출하여 사용자의 그룹id를 설정한다.

5. login이 가진 정보로 환경을 초기화 한다.

 

6. 그리고 마지막으로 login이 exec함수로 쉘(shell)로 프로그램을 바꾼다.

execl("/bin/sh", "-bash", 0);

 

인자에 -bash에서 '-(하이폰)'은 셸이 하나의 로그인 셸로써 실행되어야 한다는 의미이다.

 

프로세스 그룹

사용자도 그룹을 가지듯이 프로세스도 자신이 속한 그룹을 가진다.

대체 작업이 연관된 녀석들 끼리 모여 그룹을 형성한다.

 

정의를 하자면, 프로세스 그룹(process group) 이란

동일한 터미널로부터 신호들을 받을 수 있는 하나 이상의 프로세스들의 집합이다.

각 프로세스 그룹들은 각각의 프로세스 그룹 id를 가지고 있다.

getpgrp() 이라는 함수로 현재 프로세스 그룹ID를 받아올 수 있다.

 

그리고 프로세스를 지정해 그 프로세스가 속한 그룹의 id를 받아오는 시스템콜도 있다.

 

getpgid는 프로세스를 지정하여 결과값을 받는데,

getpgid(0)이라면, getpgrp()과 같은 결과가 나온다.

 

이렇게 프로세스 그룹id가 있다. 여기에 개념 하나더, 프로세스 그룹에 리더(?)가 있다.

프로세스 그룹 id (pgid) 와 동일한 프로세스 id (pid)를 가진 프로세스가 그 그룹의 리더이다.

 

프로세스 그룹 리더는 프로세스 그룹을 생성할 수 있으며, 그 그룹 안에서 프로세스를 생성할 수도 있다.

프로세스 리더가 종료되어도 그룹 내에 프로세스가 하나라도 남아 있다면 그 그룹은 존재한다.

ps가 프로세스 그룹 리더이고, ps와 cat이 같은 그룹이다.

 

여기에 대한 시스템콜 함수 또한 존재한다. setpgid()라는 함수인데,

자신을 기존의 프로세스 그룹에 속하게 하거나, 새 프로세스 그룹을 생성할 때 사용하는 함수이다.

 

pid, pgid 두가지 인자가 똑같은 값을 가지면 그 프로세스는 그룹의 리더가 된다.

pid 인자가 0이라면 현재 사용중인 프로세스를 지칭하는 것이고,

pgid 인자가 0이라면 pid의 프로세스가 속한 그룹을 지칭하는 것이다.

 

프로세스 세션(Session)

세션(Session)에 대해 알아보자. 프로세스 그룹들은 흔히 셸의 파이프 라인('|')을 통해 형성이 된다.

$ proc1 | proc2 

proc3 | proc4| proc5

 

세션은 여러개의 프로세스 그룹들이 모여서 이루어 진다.

 

그림을 보면 SESS라고 되어있는 부분이 세션ID 이다.

프로세스 그룹이랑 개념이 똑같다고 보면 된다. 한 프로세스가 새 세션을 생성할 때는 setsid()라는 함수를 사용한다.

 

호출한 프로세스가 프로세스 그룹의 리더가 아니라면 setsid함수는 새로운 세션을 생성한다.

이 때 뭔가 작업이 몇가지 일어난다.

1. 호출한 프로세스는 새 세션의 세션 리더가 된다. 즉, 세션을 생성한 놈이 세션리더다.

2. 호출한 프로세스는 새 프로세스 그룹의 리더가 된다. 

3. 호출한 프로세스는 제어 터미널이 없다 (이건 바로 다음에 설명함)

 

방금 위해서 말한 제어 터미널 개념 때문에 세션이라는 개념이 필요하다.

 

호출한 프로세스가 만약 프로세스 그룹의 리더라면 이 함수는 오류를 반환한다.

(보통은 fork로 자식을 만들어 부모를 종료하고 자식이 setsid를 한다.)

 

그리고 세션리더의 pgid 알아보는 함수가 또 있다. 

pid가 0이라면 호출한 프로세스가 속한 세션의 리더 pgid를 반환한다.

 

제어 터미널

위에 제어터미널 때문에 세션이라는 개념이 중요하다고 말했다.

그렇다면 제어 터미널은 뭐하는 녀석일까? 그림을 보면서 설명하겠다.

 

 

하나의 세션에는 하나의 제어 터미널을 가질 수 있다. 보통은 사용자가 로그인한 터미널 장치가 제어 터미널이다.

제어 터미널과 연결을 성립한 세션의 리더를 제어 프로세스(controlling process) 라고 한다.

 

하나의 세션에는 background 프로세스 그룹 foreground 프로세스 그룹으로 구성되는데,

foreground 프로세스 그룹은 딱 하나만 허용된다. background는 여러개.

위에 그림을 보면 proc3,4,5 가 속한 프로세스 그룹이 foreground 프로세스 그룹이다. 나머진 background

세션에 제어 터미널이 있다면, 항상 foreground 프로세스 그룹이 존재하는 것이다.

 

그리고 위 그림에서 보는 것처럼, 인터넷이 끊어졌거나 할 때 hang-up signal 같은 것이 세션 리더에게 전송된다.

background 프로세스 그룹인데, 거기에서 다른 프로세스 그룹으로 시그널을 연쇄적으로 수행한다.

 

지금까지 배운 개념을 하나의 그림에 그려보면 아래와 같다.

반응형