Perl Study #9

PROCESS

 

현재 실행 중인 프로세스로부터 새로운 프로세스를 만들고 관리하는 방법

 

Create New Process (system, exec, fork)

system 함수 : system(“프로그램 실행파일명”); – 전달받은 인자를 /bin/sh로 넘겨줌

①      쉘에서 실행하는 것과 동일한 효과를 나타냄. 쉘을 쓰듯이 사용
system(“date > right_now”);             # date의 결과를 right_now라는 파일로..

②      STD(IN, OUT, ERR)은 부모 프로세스로부터 상속받음

③      실행결과를 리턴(0: True, Other: False, perl에서의 T/F정의와 반대)
system(“date > right_now”) && die “can’t run : $!”;    # system 실패시 die

④      함수에 전달되는 인자가 많을 때 perl은 첫번째를 명령으로, 나머지는 명령의 인자로 전달
@cfiles = (“fred.c”, “barney.c”);                                  #
@options = (“-DHARD”, “-DGRANTE”);                        #
system “cc –o slate @options @cfiles”;                      # 쉘이 모든 것을 부담
system “cc”, “-o”, “slate”, @options, @cfiles;            # 위와 동일(적은 부하)

⑤      호출한 프로세스가 종료할 때까지 기다림

 

환경변수 : 프로세스의 실행 환경을 나타내는 변수. (HOME, LANG, LONNAME, PATH…)

①      perl의 경우 %ENV가 환경변수를 나타냄. 키는 환경변수의 이름.
$oldpath = $ENV{“PATH”};                # ENV.PATH를 임시로 저장
$ENV{“PATH”} = “/bin:/usr/bin:/usr/ucb”;     # 알려진 경로로 제한
system(“grep fred bedrock > output”);          # 위에 제한된 경로에서만 grep을 실행
$ENV{“PATH”} = $oldpath;                # 복구하기

 

역 인용부호 : `실행할 프로그램 파일명` – 실행 결과를 프로세스의 변수로 가지고 올 수 있음

①      $now = “the time is now “ . `date`;     # date의 결과는 출력되지 않음
일반적으로 하나의 행 만을 가지고 옴

②      foreach (`who`) {                 # 여러 행의 출력을 가지고 오기
($who, $where, $when) = /(S+)s+(S+)s+(.*)/;
print “$who on $where at $when ”;
}

 

파일 핸들로 프로세스 사용하기 : open(핸들, “(|) 명령어 (|)”); 파이프(참조: popen())

①      실행할 명령의 왼쪽에 파이프가 있으면 -> 쓰기 전용, 즉 부모 프로세스에서 해당 파일핸들에 출력하는 것은 자식 프로세스의 표준입력으로 처리됨

②      오른쪽에 파이프가 있으면 -> 읽기 전용, 자식 프로세스의 표준출력을 부모 프로세스가 파일 핸들을 통해 가지고 올 수 있음

③      생성된 파일 핸들에 대한 읽기/쓰기는 보통의 파일 핸들과 동일

④      여러 개의 파이프가 올 수 있음
open(WHOPR, “ls | tail –r |”);            # ls의 결과를 tail로, 그리고 그 결과를 읽어옴

 

fork : UNIX system call. 현재 프로세스와 동일한 자식 프로세스를 만들어냄.

①      예제
if (!defined($child_pid = fork())) {      # 실패시 undef 반환. defined로 케치
die “can’t fork: $!”;
} elsif ($child_pid) {
# 부모 프로세스의 실행코드
} else {
# 자식 프로세스의 실행코드
}

②      반환값을 통해 부모/자식을 구분(부모 : 자식의 pid, 자식 : 0, 실패 : undef)

③      부모와 자식은 fork의 리턴 값을 제외한 모든 것이 동일함(코드, 스택, 힙, 파일핸들 등) 하지만 공유가 아닌 복사! 자식/부모 모두 fork이후부터 실행하며 각자의 길을 걸어감

④      race condition 발생(같은 화면에 출력하려고 한다면? -> 결과 뒤섞임) -> wait!

 

exec : 전달받은 프로그램으로 대체됨. 새로 만들어진 프로세스는 아니므로 pid는 그대로

①      exec(“프로그램파일”); 실행이 성공하면 그 뒤로 원래 프로세스는 실행되지 않음.

②      fork()->자식 프로세스 exec() = system()과 같은 효과. 하지만 system의 경우 부모 프로세스는 자식이 끝날 때까지 기다림. fork->exec는 race condition 발생 가능.

③      if (!defined($kidpid = fork())) {
die “can’t fork: $!”;
} elsif ($kidpid == 0) {          # 자식 프로세스
exec(“date”);                  # date 프로세스로 대체됨
die “can’t exec: $!”;         # exec가 성공하면 실행되지 않는 부분
} else {
waitpid($kidpid, 0);          # 자식 프로세스를 기다림(끝날 때 까지), 0은 옵션
}

 

wait(pid) : 자식 프로세스가 실행을 종료할 때까지 기다림. 차이점은 옵션의 가능 여부, 기다릴 자식 프로세스의 pid 명세

 

< 차이점 요약 >

CALL STDIN STDOUT STDERR WAIT?
System 프로그램에서 상속 프로그램에서 상속 프로그램에서 상속 Yes
` ` 프로그램에서 상속 값에따라 capture 프로그램에서 상속 Yes
open( , “|…”) 파일핸들로 연결 프로그램에서 상속 프로그램에서 상속 Only close()
open(, “…|”) 프로그램에서 상속 파일핸들로 연결 프로그램에서 상속 Only close()
fork,exec, wait(pid) user 선택 user 선택 user 선택 user

 

signal : 가장 간단한 프로세스간 통신 방법. 특정한 값을 권한있는 프로세스에게 보낼 수 있고, 받는 쪽에서는 받은 시그널을 처리하는 함수(action)를 실행하게 됨

①      권한 : 슈퍼유저 이거나 보내는 프로세스와 받는 프로세스의 사용자 ID 가 같은 경우에만

②      생성 : 명시적으로 생성하여 보내기/OS에서 자동으로 보내기(보통 ERR시 발생)

③      시그널의 종류 : %SIG에 있음. 키는 종류(INT, QUIT, KILL 등. man signal, man kill 보기)

④      시그널 처리함수 정하기 : $SIG{‘해당 시그널’} = ‘함수이름’;

⑤      보통 시그널은 특정한 상황을 알리기 위해 사용된다.

⑥      sub my_sigint_catcher {      # 시그널 처리 함수
$saw_sigint = 1;                # 받은 시그널에 해당하는 플래그를 On
}

$saw_sigint = 0;                   # 플래그 초기화
$SIG{‘INT’} = ‘my_sigint_catcher’;      # 처리기 등록
foreach (@huge_array) {                   # 어떠한 동작
……………………               # 언제 멈춰야 하지?
if ($saw_sigint) {                          # SIGINT를 받으면 (거의)바로 처리기가 실행되고
last;                                          # 플래그가 On되며 last가 실행됨
}
}
$SIG{‘INT’} = ‘DEFAULT’;                   # 원래의 SIGINT처리기로 복구하기

 

REFERENCES :  SP책(APUE) Ch.8 Process, Ch 10. Signals

manpage (각종 함수…)

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다