C의 다른 프로세스에서 데몬 프로세스 제어

Jinku Hu 2023년10월12일
  1. forksetsid함수를 사용하여 데몬 프로세스 생성
  2. daemon함수를 사용하여 데몬 프로세스 만들기
C의 다른 프로세스에서 데몬 프로세스 제어

이 기사에서는 C의 다른 프로세스에서 데몬 프로세스를 제어하는 방법에 대한 여러 방법을 소개합니다.

forksetsid함수를 사용하여 데몬 프로세스 생성

데몬 프로세스에는 장기 실행 프로세스라는 몇 가지 특성이 있으며 시스템 시작시 데몬이 시작될 수 있습니다. 데몬 프로세스는 강제로 종료하거나 일시 중지하거나 시작시 비활성화하는 사용자 명령으로 제어 할 수 있습니다. 그러나 일반적인 시나리오에서는 일부 시스템 특정 스크립트를 사용하여 시스템 종료시 데몬이 종료됩니다. 데몬은 일반적으로 제어 터미널없이 백그라운드에서 실행되며 이러한 기능을 사용하는 프로그램은 외부 인터럽트를 처리하기 위해 다양한 신호 처리기를 구현해야합니다.

데몬 프로세스를 생성하고 모니터링하는 방법은 여러 가지가 있지만이 예제에서는 생성 단계를 보여줍니다. 여기서fork함수를 호출하여 자식 프로세스를 생성합니다. 그런 다음 상위 프로세스가 종료되고 하위 프로세스가init프로세스의 하위가되면서 계속 실행됩니다 (Linux 시스템에서init프로세스는 시작시 첫 번째 프로세스 임). 하위 프로세스는setsid함수를 호출하여 새 세션을 시작하고 제어 터미널에서 프로세스를 제거합니다. 마지막으로fork를 다시 한 번 호출하고 부모 프로세스를 종료하여 데몬이 제어 터미널을 얻지 못하도록합니다. 이제 데몬 프로세스를 실행하고 있습니다. 시스템 또는 사용자가 해당 인터럽트를 전달할 때 리소스 정리 및 정상 종료를 수행하기 위해SIGTERM신호 처리기를 등록하는 것이 중요합니다.

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define errExit(msg)    \
  do {                  \
    perror(msg);        \
    exit(EXIT_FAILURE); \
  } while (0)

void cleanupRoutine(int signal_number) {
  write(STDERR_FILENO, "hello", 5);
  _exit(EXIT_SUCCESS);
}

int main(int argc, char *argv[]) {
  fprintf(stderr, "[pid - %d] running...\n", getpid());

  switch (fork()) {
    case -1:
      errExit("fork");
    case 0:
      break;
    default:
      _exit(EXIT_SUCCESS);
  }
  fprintf(stderr, "[pid - %d] running...\n", getpid());

  if (setsid() == -1) errExit("setsid");

  switch (fork()) {
    case -1:
      errExit("fork");
    case 0:
      break;
    default:
      _exit(EXIT_SUCCESS);
  }
  fprintf(stderr, "[pid - %d] running...\n", getpid());

  struct sigaction sigterm_action;

  memset(&sigterm_action, 0, sizeof(sigterm_action));
  sigterm_action.sa_handler = &cleanupRoutine;
  sigterm_action.sa_flags = 0;

  // Mask other signals from interrupting SIGTERM handler
  if (sigfillset(&sigterm_action.sa_mask) != 0) {
    perror("sigfillset");
    exit(EXIT_FAILURE);
  }
  // Register SIGTERM handler
  if (sigaction(SIGTERM, &sigterm_action, NULL) != 0) {
    perror("sigaction SIGTERM");
    exit(EXIT_FAILURE);
  }

  while (1) {
    getpid();
  }

  exit(EXIT_SUCCESS);
}

daemon함수를 사용하여 데몬 프로세스 만들기

앞의 예제는 겉보기에 올바른 코드를 보여 주지만 부모로부터 상속 된 모든 열린 파일 설명자를 닫는 단계가 없습니다. 작업 디렉토리가 변경되고 표준 입력을/dev/null로 리디렉션하는 식입니다. 이 단계는 데몬이 특정 기능을 호출하더라도 특정 기능이 실패하지 않고 일부 이상한 동작이 관찰되지 않도록 보장합니다.

예를 들어, 터미널 창에서 이전 프로그램을 시작한 다음SIGTERM신호를 데몬 프로세스로 보내면cleanupRoutine신호 처리기의write함수가 새 프롬프트가 표시된 후에도 동일한 터미널에 인쇄됩니다. 표시됩니다. 따라서daemon함수는 GNU C 라이브러리에서 제공합니다. 새로 생성 된 데몬 프로세스에 대한 깨끗한 컨텍스트를 보장하기 위해 위 단계를 자동으로 처리합니다. daemon함수는 두 개의 정수 인수를 사용합니다. 첫 번째 (0과 같으면) 현재 작업 디렉토리를 루트 디렉토리로 변경해야하는지 여부를 지정합니다. 표준 I/O 스트림이/dev/null로 리디렉션되어야하는지 여부를 나타내는 두 번째 정수 (0과 같은 경우)입니다.

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define errExit(msg)    \
  do {                  \
    perror(msg);        \
    exit(EXIT_FAILURE); \
  } while (0)

void cleanupRoutine(int signal_number) {
  write(STDERR_FILENO, "hello", 5);
  _exit(EXIT_SUCCESS);
}

int main(int argc, char *argv[]) {
  fprintf(stderr, "[pid - %d] running...\n", getpid());

  if (daemon(0, 0) == -1) errExit("daemon");

  fprintf(stderr, "[pid - %d] running...\n", getpid());

  struct sigaction sigterm_action;

  memset(&sigterm_action, 0, sizeof(sigterm_action));
  sigterm_action.sa_handler = &cleanupRoutine;
  sigterm_action.sa_flags = 0;

  // Mask other signals from interrupting SIGTERM handler
  if (sigfillset(&sigterm_action.sa_mask) != 0) errExit("sigfillset");

  // Register SIGTERM handler
  if (sigaction(SIGTERM, &sigterm_action, NULL) != 0) errExit("sigaction");

  while (1) {
    getpid();
  }

  exit(EXIT_SUCCESS);
}
작가: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

관련 문장 - C Process