IT_Programming/System Programming

[Linux] 데몬 생성 함수 / IPC

JJun ™ 2009. 11. 12. 07:34

------------------------------------------------------------------------------------

참고: TCP/IP 소켓 프로그래밍

------------------------------------------------------------------------------------

 

1. 데몬 함수의 사용

: 프로세스를 데몬화 → 이 프로세스의 부모 프로세스는 init 프로세스가 되는데,
  init 프로세스는 컴퓨터가 꺼지기 전에는 계속 수행되는 프로세스이므로
  강제로 데몬 프로세스를 종료시키지 않는 한 계속적으로 백그라운드로 실행된다.

 

   void makedaemon()
   {
        pid_t pid;
        if((pid = fork()) < 0)
             exit(0);
        else if(pid != 0)
             exit(0);
 
        close(0);
        close(1);
        setsid();
   }

 


2. IPC : 내부 프로세스 통신을 위한 모든 방법

  

   1) PIPE(파이프)를 이용한 프로세스 간 통신

      ☞ 가장 오래된 기법 : 오랜 시간동안 사용되어 오면서 충분히 검증되었다.
      ☞ 파이프는 각 프로세스의 파일 디스크립터를 연결시켜 주는 것의 의미한다.
      ☞ 단점: 부모, 자식 프로세스의 데이터 통신을 위해서만 사용할 수 있다.
                  (다른 프로세스와의 통신 불가능)

 

      ☞ int pipe(int filedes[2]);
         - 인자      : filedes[0]은 읽기 전용(입력), filedes[1]은 쓰기 전용(출력)이다.
         - 반환값    : 성공할 때는 0을 반환하고, 실패하면 -1을 반환한다.
         - 헤더 파일 : unistd.h
         - 읽고(read) 쓸(write) 경우, read, write 함수를 사용하면 된다.
     
      예) #include <sys/types. h>
           #include <unistd. h>
           #include <stdio. h>
           #include <stdlib. h>
 
          /* 파이프로부터 문자들을 읽고 그들은 표준 출력에 출력하라 */
          void read_from_pipe (int file)
          {
                    FILE *stream;
                    int c;
                    stream = fdopen (file, "r");
                    while ((c = fgetc (stream)) != EOF)
                              putchar (c);
                    fclose (stream);
          }
 
          /* 파이프에 어떤 텍스트를 써라 */
          void write_to_pipe (int file)
          {
                    FILE *stream;
                    stream = fdopen (file, "w");
                    fprintf (stream, "hello, world!\n");
                    fprintf (stream, "goodbye, world!\n");
                    fclose (stream);
          }
 
          int main (void)
          {
                    pid_t pid;
                    int mypipe[2];
                   
                    /* 파이프를 만들어라 */
                    if (pipe (mypipe))
                    {
                              fprintf (stderr, "Pipe failed. \n");
                              return EXIT_FAILURE;
                    }
                   
                    /* 자식 프로세스를 만들어라 */
                    if ((pid = fork ()) == 0) /* 이것은 자식 프로세스이다. */
                    {
                              read_from_pipe (mypipe[0]);
                              return EXIT_SUCCESS;
                    }
                    else if (pid < 0) /* fork가 실패했다. */
                    {
                              
                              fprintf (stderr, "Fork failed. \n");
                              return EXIT_FAILURE;
                    }
                    else /* 이것은 부모 프로세스이다. */
                    {
                              write_to_pipe (mypipe[1]);
                              return EXIT_SUCCESS;
                    }
          }

 

 
   2) FIFO(명명된 파이프)를 이용한 프로세스 간 통신

      ☞ 파이프의 단점을 해결하기 위해 만든 IPC 도구
      ☞ 파이프가 작자 불명의 통신 채널인 점에 비해 FIFO는 mkfifo를 호출함으로써 파일 시스템에 삽입된다.

      ☞ 큐(queue)와 같은 데이터 입출력 구조를 가진다.
      ☞ 파이프와는 달리 읽기와 쓰기를 동시에 할 수 있다. (하지만 보통 각각 따로 만든다.)
     
      ☞ int mkfifo(const char *pathname, mode_t mode);
         - 인자      : pathname → 생성하고자 하는 FIFO 파일명, mode → FIFO 파일의 권한을 지정
         - 반환값    : 성공하면 0을 반환하고, 에러가 발생한 경우에는 -1을 리턴한다.
         - 헤더 파일 : sys/stat. h
         - 읽고(read) 쓸(write) 경우, read, write 함수를 사용하면 된다.

 

      예) fifo_server
          #include <stdlib.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <fcntl.h>
          #include <stdio.h>
          #include <unistd.h>

 

          #define FIFO_READ   "/tmp/fifo_c"
          #define FIFO_WRITE  "/tmp/fifo_s"

 

          int main()
          {
              int fp_w;
              int fp_r;
              int i = 0;

              umask(0000); // 파일 생성시 권한에 대한 마스크 설정

              // mkfifo를 이용해서 FIFO파일을 생성한다.
              // FIFO_READ는 클라이언트로 부터 데이터를 읽기 위해서
              if (mkfifo(FIFO_READ, 0666) != 0)
              {
                  perror("mkfifo failure");
              }

              // FIFO_WRITE는 클라이언트로 데이터를 쓰기 위해서 사용한다.
              if (mkfifo(FIFO_WRITE, 0666) != 0)
              {
                  perror("mkfifo failure");
              }

              if( (fp_r = open(FIFO_READ, O_RDWR)) < 0)
              {
                  perror("open error : ");
                  exit(0);
              }

              if((fp_w = open(FIFO_WRITE, O_RDWR)) < 0)
              {
                  perror("open error : ");
                  exit(0);
              }

              while(read(fp_r, (void *)&i, sizeof(int)) > 0)
              {
                  printf("클라이언트로 부터 데이터 읽음 %d\n", i);
                  i = i*2;
                  write(fp_w, (void *)&i, sizeof(int));
              }
 
              exit(1);
          }


      예) fifo_client
          #include <stdlib.h>
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
          #include <stdio.h>
          #include <unistd.h>

 

          #define FIFO_WRITE  "/tmp/fifo_c"
          #define FIFO_READ   "/tmp/fifo_s"

 

          int main()
          {
              int fp_w;
              int fp_r;
              int i = 1;

              if((fp_r = open(FIFO_READ, O_RDWR)) < 0)
              {   
                  perror("open error : ");
                  exit(0);
              }   
         
              if((fp_w = open(FIFO_WRITE, O_RDWR)) < 0)
              {   
                  perror("open error : ");
                  exit(0);
              }   

              while(1)
              {   
                  sleep(1);
                  write(fp_w, (void *)&i, sizeof(int));
                  read(fp_r, (void *)&i, sizeof(int));
                  printf("서버로 부터 데이터 읽음 %d\n", i);
              }   
              exit(1);
          }

 

------------------------------------------------------------------------------------