[제10장] 프로세스와 시그널

돼지털라이프 | 2007/06/25 19:05

=================================================================
  * Subject : [제10장] 프로세스와 시그널
  * Writer: w0rm9 (research.hackerschool.org)
  * Date: 2004/02/10
=================================================================

/* 강의 중심으로 정리했습니다.
 * 예제는 책에 있는걸로 했어요~
 */


0x01. 프로세스
프로세스 - 실행 중인 프로그램

■ 새로운 프로세스 시작하기
사용법)
#include <stdlib.h>

int system(const char *string);
=> string으로 전달되는 명령을 실행하고 나서 실행이 끝날 때까지 기다린다.

■ 프로세스 대체하기
사용법)
#include <unistd.h>

char **environ;

int execl(const char *path, const char *arg[], ..., (char *)0);
int execlp(const char *file, const char *arg[], ..., (char *)0);
int execle(const char *path, const char *arg[], ..., (char *)0, const char *envp[]);
int execv(const char *path, const char *argv[]);
int execvp(const char *file, const char *argv[]);
int execve(const char *path, const char *argv[], const char *envp[]);
=> l 들어가는 것은 인자를 순서대로 나열하면 되고, v 들어가는 것은 인자를 배열 형태로 지정
   e 들어가는 것은 새로 환경 변수를 지정해 줄 수 있고, p 들어가는 것은 현재의 환경 변수를 그대로 사용

테스트)
[w0rm9@work PROCESS]$ cat exec.c
#include <unistd.h>

const char *ps_argv[] = {"ps", "-ax", 0};
const char *ps_envp[] = {"PATH=/bin:/usr/bin", "TERM=console", 0};

main()
{
        execl("/bin/ps", "ps", "-ax", 0);
        execlp("ps", "ps", "-ax", 0);   // /bin이 PATH에 포함되다고 가정
        execle("/bin/ps", "ps", "-ax", 0, ps_envp); // 자체적인 환경을 전달

        execv("/bin/ps", ps_argv);
        execvp("ps", ps_argv);
        execve("/bin/ps", ps_argv, ps_envp);
}

■ 프로세스 복제하기
사용법)
#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);
=> 부모 프로세스에서 fork를 호출하면 새로운 자식 프로세스의 PID가 반환된다. 새로운 프로세스는 자식 프로세스에서 fork에 대한 호출이 0을 반환한다는 것을
   제외하고 원본과 비슷하게 실행을 계속한다. 새로운 프로세스는 원본과 비슷하고, 같은 코드를 실행하지만, 자체적인 데이터 공간, 환경과 파일 기술자를 가진다.

테스트)
[w0rm9@work PROCESS]$ cat fork.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
        char buffer[1024];
        printf("hello wiseguyz~~\n");

        if(fork()==0){
                 sleep(2);
                printf("난 자식 프로세스야!!\n");
                printf("My pid : %d\n", getpid());
                while(1){
                        system("/bin/date");
                        sleep(1);
                }
        }
        else{
                printf("난 부모 프로세스야!!\n");
                printf("My pid : %d\n", getpid());
                while(1){
                        fgets(buffer, 1024, stdin);
                        printf("you typed : %s", buffer);
                }
        }
}

[w0rm9@work PROCESS]$ gcc -o fork fork.c
[w0rm9@work PROCESS]$ ./fork
hello wiseguyz~~
난 부모 프로세스야!!
My pid : 31256
안녕
you typed : 안녕
난 자식 프로세스야!!
My pid : 31257
2004. 02. 11. (수) 02:12:15 KST

■ 프로세스 기다리기
사용법)
#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
=> wait() 자식 프로세스의 하나가 끝날 때까지 부모 프로세스가 기다리게 한다. 자식 프로세스의 PID 반환. stat_loc가 널 포인터가 아니라면 상태 정보는
   이것이 가리키는 위치에 저장됨.
   waitpid() pid 인수는 기다리고자 하는 특정 자식 프로세스 PID지정, option 인수는 waitpid의 동작을 변경하게 해준다.

□ 상태 정보를 구할 때 쓰는 sys/wait.h에 정의된 매크로
 WIFEXITED(stat_val) 자식프로세스가 정상적으로 종료되면 0이 아님
 WEXITSTATUS(stat_val) WIFEXITED가 0이 아니면 이것은 자식 프로세스의 종료 코드를 변환한다.
 WIFSIGNALED(stat_val) 자식 프로세스가 처리할 수 없는 시그널에 의해 종료되면 0이 아님
 WTERMSIG(stat_val) WIFSGNALED가 0이 아니면 이것은 시그널의 번호를 반환한다.
 WIFSTOPPED(stat_val) 자식 프로세스가 중단되었다면 0이 아님
 WSTOPSIG(stat_val) WIFSTOPPED가 0이 아니면 이것은 시그널의 번호를 반환한다.


0x02. 시그널

■ 시그널
사용법)
#include <signal.h>

void (*signal(int sig, void (*func)(init)))(int);
=> 인수 sig는 처리하거나 무시할 시그널을 지정하고, func는 해당 시그널이 전달될 때 호출되는 함수

□ 시그널 이름
 SIGINT  터미널 인터럽트
 SIGKILL  처리하거나 무시할 수 없는 상태
 SIGSEGV  무효한 메모리 세그먼트 액세스
 나머지는 p.506 참조

□ func에 올 수 있는 특별한 두값
 SIG_IGN  시그널을 무시한다.
 SIG_DFL  기본 동작을 복구한다.

테스트)
[w0rm9@work PROCESS]$ cat signal.c
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void ouch(int sig)
{
    printf("OUCH! - I got signal %d\n", sig);
    (void) signal(SIGINT, SIG_DFL);   // SIGINT에 대해 기본 동작을 복구한다.
}

int main()
{
    (void) signal(SIGINT, ouch);   // SIGINT에 대해 ouch호출

    while(1) {
        printf("Hello World!\n");
        sleep(1);
    }
}
[w0rm9@work PROCESS]$ gcc -o signal signal.c
[w0rm9@work PROCESS]$ ./signal
Hello World!
Hello World!
OUCH! - I got signal 2
Hello World!
Hello World!

■ 시그널 전달하기
사용법)
#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);
=> pid에 주어진 식별자를 가지는 프로세스로 지정된 시그널 sig를 보낸다.

사용법)
#include <unistd.h>

unsigned int alarm(unsigned int seconds);
=> 초단위 seconds 시간에 SIGALARM 시그널을 전송을 계획한다.

■ 안정적인 시그널 인터페이스
사용법)
#include <signal.h>

int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
=> 시그널 sig와 관련된 동작을 설정한다. oact가 널이 아니라면 oact가 가리키는 위치에 이전 시그널 동작을 기록한다.
   act가 널이라면 아무 것도 하지 않는다. act가 널이 아니라면 지정된 시그널을 위한 동작을 설정한다.

□ sig에 지정된 시그널을 전달받을 때 수행할 동작을 정의하는 사용되는 sigaction 구조체
 void (*) (int) sa_handler 함수, SIG_DFL 또는 SIG_IGN
 sigset_t sa_mask  sa_handler에서 방지할 시그널
 int sa_flags   시그널 동작 변경자

테스트)
[w0rm9@work PROCESS]$ cat signal2.c
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void ouch(int sig)
{
    printf("OUCH! - I got signal %d\n", sig);
}

int main()
{
    struct sigaction act;  //

    act.sa_handler = ouch;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;

    sigaction(SIGINT, &act, 0);

  while(1) {
    printf("Hello World!\n");
    sleep(1);
  }
}


[w0rm9@work PROCESS]$ gcc -o signal2 signal2.c
[w0rm9@work PROCESS]$ ./signal2
Hello World!
Hello World!
OUCH! - I got signal 2
Hello World!
Hello World!
OUCH! - I got signal 2
Hello World!
Hello World!
OUCH! - I got signal 2
Hello World!
Hello World!

/* 나머지는 생략~~ */

_eof_

Trackback Address :: http://badnom.com/trackback/292
Name
Password
Homepage
Secret
< PREV |  1  |  ...  740  |  741  |  742  |  743  |  744  |  745  |  746  |  747  |  748  |  ...  983  |  NEXT >