짧은 대기 시간 동안 RHEL 최적화


Red Hat Enterprise Linux for Real Time 10

Red Hat Enterprise Linux에서 RHEL for Real Time 커널 최적화

Red Hat Customer Content Services

초록

RHEL for Real Time 커널에서 워크스테이션을 켜면 대기 시간이 지속적으로 짧고 예측 가능한 응답 시간 초과에 민감한 애플리케이션을 구현할 수 있습니다.

Red Hat 문서에 관한 피드백 제공

문서 개선을 위한 의견에 감사드립니다. 어떻게 개선할 수 있는지 알려주십시오.

Jira를 통해 피드백 제출 (계정 필요)

  1. Jira 웹 사이트에 로그인합니다.
  2. 상단 탐색 바에서 생성을 클릭합니다.
  3. 요약 필드에 설명 제목을 입력합니다.
  4. 설명 필드에 개선을 위한 제안을 입력합니다. 문서의 관련 부분에 대한 링크를 포함합니다.
  5. 대화 상자 하단에서 생성 을 클릭합니다.

1장. RHEL 10의 실시간 커널 튜닝

대기 시간 또는 응답 시간은 이벤트의 시간과 시스템 응답을 나타냅니다. 일반적으로 마이크로초(microseconds)로 측정됩니다.

Linux 환경에서 실행되는 대부분의 애플리케이션의 경우 기본 성능 튜닝을 통해 대기 시간을 충분히 향상시킬 수 있습니다. 대기 시간이 짧고, 책임을지고 예측 가능해야 하는 업계의 경우 Red Hat에는 대기 시간이 이러한 요구 사항을 충족하도록 조정할 수 있는 대체 커널이 있습니다. RHEL for Real Time 커널은 RHEL 10과의 원활한 통합을 제공하며, 고객에게 조직 내에서 대기 시간 시간을 측정, 구성 및 기록할 수 있는 기회를 제공합니다.

결정성이 매우 높은 애플리케이션의 경우 잘 조정된 시스템에서 RHEL for Real Time 커널을 사용하십시오. 커널 시스템 튜닝을 사용하면 결정성을 개선할 수 있습니다. 시작하기 전에 표준 RHEL 10 시스템의 일반 시스템 튜닝을 수행한 다음 RHEL for Real Time 커널을 배포합니다.

주의

이러한 작업을 수행하지 않으면 RHEL 실시간 배포의 일관된 성능을 방지할 수 있습니다.

1.1. 튜닝 지침

  • 실시간 튜닝은 반복적인 프로세스입니다. 몇 가지 변수를 조정할 수 없으며 변경 사항이 가장 효과적이라는 것을 알 수 있습니다. 시스템에 가장 적합한 튜닝 구성 세트를 몇 일 또는 몇 주 동안 줄일 수 있습니다.

    또한 항상 긴 테스트 실행을 수행합니다. 일부 튜닝 매개변수를 변경한 후 5분 테스트 실행을 수행하는 것은 특정 튜닝 변경 집합을 확인하는 것이 아닙니다. 테스트 길이를 조정하여 몇 분 이상 실행하십시오. 몇 시간 동안 테스트 실행을 사용하여 몇 가지 다른 튜닝 구성 세트로 좁은 다음 한 번에 여러 시간 또는 며칠 동안 해당 세트를 실행하여 대기 시간이 가장 높은 또는 리소스 소진을 감지할 수 있습니다.

  • 특정 튜닝 변경 집합이 애플리케이션의 성능에 미치는 영향을 정확하게 측정할 수 있도록 측정 메커니즘을 애플리케이션에 빌드합니다. 예를 들어, "더 매끄러운 마우스"는 일반적으로 잘못되어 다를 수 있습니다. 하드 측정을 수행하고 나중에 분석을 위해 기록하십시오.
  • 테스트 실행 간에 변수 튜닝을 여러 번 변경하는 것은 매우 쉽지만, 이렇게 하면 테스트 결과에 영향을 미치는 튜닝 매개변수를 좁힐 방법이 없습니다. 테스트 실행 간 튜닝 변경 사항을 가능한 한 작게 유지합니다.
  • 튜닝할 때 큰 변경을 수행해야 하지만 증분 변경을 수행하는 것이 거의 항상 좋습니다. 가장 낮은 우선 순위 값에서 가장 높은 우선 순위 값까지 작업을 수행하면 장기적으로 더 나은 결과를 얻을 수 있습니다.
  • 사용 가능한 툴을 사용합니다. tuna 튜닝 툴을 사용하면 스레드 및 인터럽트, 스레드 우선 순위 및 애플리케이션 사용을 위해 프로세서를 격리하는 작업을 쉽게 변경할 수 있습니다. tasksetchrt 명령줄 유틸리티를 사용하면 tuna 가 수행하는 대부분의 작업을 수행할 수 있습니다. 성능 문제가 발생하면 ftraceperf 유틸리티에서 대기 시간 문제를 찾는 데 도움이 될 수 있습니다.
  • 애플리케이션에 값을 하드 코딩하는 대신 외부 툴을 사용하여 정책, 우선 순위 및 선호도를 변경합니다. 외부 툴을 사용하면 다양한 조합을 시도하고 논리를 단순화할 수 있습니다. 좋은 결과를 제공하는 몇 가지 설정을 찾으면 애플리케이션에 추가하거나 시작 논리를 설정하여 애플리케이션이 시작될 때 설정을 구현할 수 있습니다.

1.2. 스레드 스케줄링 정책

Linux는 세 가지 주요 스레드 스케줄링 정책을 사용합니다.

  • Cryostat_OTHER (때로는 Cryo stat_NORMAL)

    이는 기본 스레드 정책이며 커널에서 제어하는 동적 우선 순위를 갖습니다. 우선순위는 스레드 활동을 기반으로 변경됩니다. 이 정책이 있는 스레드는 실시간 우선 순위가 0(0)으로 간주됩니다.

  • Cryostat_FIFO (First in, first out)

    우선 순위가 1 에서 99 사이인 실시간 정책은 1 이 가장 낮고 99 가 가장 높습니다. Cryostat _FIFO 스레드는 항상 Cryostat _OTHER 스레드보다 우선 순위가 높습니다(예: 우선 순위가 1 인 스레드는 모든 Cryostat _OTHER 스레드보다 우선 순위가 높습니다). Cryostat _FIFO 스레드로 생성된 모든 스레드는 고정된 우선 순위를 가지며 더 높은 우선 순위 스레드에 의해 차단되거나 선점될 때까지 실행됩니다.

  • Cryostat_RR (Round-Robin)

    Cryostat_RR 은 Cryostat _FIFO 의 수정입니다. 우선 순위가 동일한 스레드는 단일 키이며 모든 동일한 우선 순위의 Cryostat _RR 스레드 간에 라운드 로빈 방식으로 예약됩니다. 이 정책은 거의 사용되지 않습니다.

1.3. 로깅 매개변수 밸런싱

syslog 서버는 네트워크를 통해 프로그램에서 로그 메시지를 전달합니다. 덜 자주 발생하며 보류 중인 트랜잭션이 클 가능성이 큽니다. 트랜잭션이 매우 크면 I/O 급증을 유발할 수 있습니다. 이를 방지하려면 간격을 상당히 작게 유지하십시오.

syslogd 인 시스템 로깅 데몬은 다른 프로그램에서 메시지를 수집하는 데 사용됩니다. 커널에서 보고한 정보도 커널 로깅 데몬인 klogd 에서 수집합니다. 일반적으로 syslogd 는 로컬 파일에 로그되지만 네트워크를 통해 원격 로깅 서버로 기록하도록 구성할 수도 있습니다.

프로세스

원격 로깅을 활성화하려면 다음을 수행합니다.

  1. 로그를 전송할 머신을 구성합니다. 자세한 내용은 Red Hat Enterprise Linux의 rsyslog로 원격 Syslog를 참조하십시오.
  2. syslog 출력이 로컬 파일 시스템이 아닌 서버에 기록되도록 로그를 원격 로그 서버로 보내는 각 시스템을 구성합니다. 이렇게 하려면 각 클라이언트 시스템에서 /etc/rsyslog.conf 파일을 편집합니다. 해당 파일에 정의된 각 로깅 규칙에 대해 로컬 로그 파일을 원격 로깅 서버의 주소로 교체합니다.

    # Log all kernel messages to remote logging host.
    kern.*     @my.remote.logging.server

    위의 예제에서는 모든 커널 메시지를 @my.remote.logging.server 의 원격 시스템에 기록하도록 클라이언트 시스템을 구성합니다.

    또는 /etc/rsyslog.conf 파일에 다음 행을 추가하여 로컬에서 생성된 모든 시스템 메시지를 기록하도록 syslogd 를 구성할 수 있습니다.

    # Log all messages to a remote logging server:
    .     @my.remote.logging.server
중요

syslogd 데몬에는 생성된 네트워크 트래픽에 대한 기본 제공 속도 제한은 포함되지 않습니다. 따라서 Red Hat은 RHEL for Real Time 시스템을 사용할 때 조직에서 원격으로 로깅해야 하는 로그 메시지만 사용하는 것이 좋습니다. 예를 들어 커널 경고, 인증 요청 등입니다. 다른 메시지는 로컬로 로깅되어야 합니다.

1.4. 불필요한 애플리케이션 실행을 방지하여 성능 개선

실행 중인 모든 애플리케이션은 시스템 리소스를 사용합니다. 시스템에서 불필요한 애플리케이션이 없는지 확인하면 성능을 크게 향상시킬 수 있습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. 특히 서버에서 필요하지 않은 그래픽 인터페이스를 실행하지 마십시오.

    시스템이 기본적으로 GUI로 부팅되도록 구성되어 있는지 확인합니다.

    # systemctl get-default
  2. 명령 출력이 graphical.target 이면 텍스트 모드로 부팅하도록 시스템을 구성합니다.

    # systemctl set-default multi-user.target
  3. 튜닝 중인 시스템에서 메일 전송 에이전트(MTA) 를 적극적으로 사용하지 않는 경우 비활성화합니다. MTA가 필요한 경우 올바르게 조정되었는지 확인하거나 전용 시스템으로 이동하는 것이 좋습니다.

    자세한 내용은 MTA 설명서를 참조하십시오.

    중요

    MTA는 cron 과 같은 프로그램에서 실행되는 시스템 생성 메시지를 보내는 데 사용됩니다. 여기에는 logwatch() 와 같은 로깅 함수에 의해 생성된 보고서가 포함됩니다. 시스템의 MTA가 비활성화된 경우 이러한 메시지를 수신할 수 없습니다.

  4. 마우스, 키보드와 같은 주변 장치는 대기 시간에 부정적인 영향을 미칠 수 있는 인터럽트를 보냅니다. 그래픽 인터페이스를 사용하지 않는 경우 사용되지 않는 주변 장치를 모두 제거하고 비활성화합니다.

    자세한 내용은 장치의 설명서를 참조하십시오.

  5. 성능에 영향을 미칠 수 있는 자동화된 cron 작업을 확인합니다.

    # crontab -l

    crond 서비스 또는 불필요한 cron 작업을 비활성화합니다.

  6. 타사 애플리케이션 및 외부 하드웨어 공급업체가 추가한 구성 요소가 있는지 확인하고 불필요한 모든 구성 요소를 제거합니다.

추가 리소스

  • 시스템에 cron(8) 도움말 페이지

1.5. NUMA(Non-Uniform Memory Access)

taskset 유틸리티는 CPU 선호도에서만 작동하며 메모리 노드와 같은 다른 NUMA 리소스에 대한 지식이 없습니다. NUMA와 함께 프로세스 바인딩을 수행하려면 taskset 대신 numactl 명령을 사용합니다.

NUMA API에 대한 자세한 내용은 Andi Kleen's 백서 An NUMA API for Linux에서 참조하십시오.

1.6. debugfs가 마운트되었는지 확인

debugfs 파일 시스템은 특히 디버깅하고 사용자가 정보를 제공하도록 설계되었습니다. /sys/kernel/debug/ 디렉터리의 RHEL 8에 자동으로 마운트됩니다.

참고

debugfs 파일 시스템은 ftracetrace-cmd 명령을 사용하여 마운트됩니다.

프로세스

debugfs 가 마운트되었는지 확인하려면 다음을 수행하십시오.

  • 다음 명령을 실행합니다.

    # mount | grep ^debugfs
    debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime,seclabel)

    debugfs 가 마운트된 경우 명령은 debugfs 의 마운트 지점 및 속성을 표시합니다.

    debugfs 가 마운트되지 않은 경우 명령은 아무것도 반환하지 않습니다.

1.7. 실시간으로 RHEL의 InfiniBand

InfiniBand는 대역폭을 늘리고 QoS (Quality of Service)를 개선하고 페일오버를 제공하는 데 사용되는 통신 아키텍처의 유형입니다. RDMA(Remote Direct Memory Access) 메커니즘을 사용하여 대기 시간을 개선하는 데도 사용할 수 있습니다.

RHEL for Real Time의 InfiniBand 지원은 Red Hat Enterprise Linux 10에서 제공되는 지원과 동일합니다. 자세한 내용은 InfiniBand 및 RDMA 네트워크 구성을 참조하십시오.

1.8. RoCEE 및 고성능 네트워킹 사용

RoCEE (RDMA over Converged Enhanced Ethernet)는 이더넷 네트워크를 통해 RDMA(Remote Direct Memory Access)를 구현하는 프로토콜입니다. 중요한 트랜잭션에 대한 결정적이고 짧은 대기 시간 데이터 전송을 제공하는 동시에 데이터 센터에서 일관적인 고속 환경을 유지할 수 있습니다.

고성능 네트워킹 (HPN)은 커널에 RoCEE 인터페이스를 제공하는 공유 라이브러리 세트입니다. HPN 은 독립적인 네트워크 인프라를 통과하지 않고 표준 이더넷 인프라를 사용하여 직접 원격 시스템 메모리에 데이터를 배치하여 CPU 오버헤드를 줄이고 인프라 비용을 줄일 수 있습니다.

RHEL for Real Time에서 RoCEEHPN 에 대한 지원은 RHEL 10에서 제공하는 지원과 다르지 않습니다.

1.9. 실시간 RHEL을 위한 컨테이너 튜닝

2장. 실시간 RHEL 스케줄링 정책

스케줄러는 실행할 실행 가능한 스레드를 결정하는 커널 구성 요소입니다. 각 스레드에는 sched_priority 라는 연결된 스케줄링 정책 및 정적 예약 우선순위가 있습니다. 예약은 선점되므로 현재 실행 중인 스레드가 더 높은 정적 우선 순위가 있는 스레드가 실행될 준비가 되면 중지됩니다. 그런 다음 실행 중인 스레드는 정적 우선 순위에 대한 대기 목록으로 돌아갑니다.

모든 Linux 스레드에는 다음 스케줄링 정책 중 하나가 있습니다.

  • Cryostat_OTHER 또는 Cryostat_NORMAL: 기본 정책입니다.
  • Cryostat_BATCH: Cryo stat_OTHER 와 유사하지만 방향은 점진적입니다.
  • Cryostat_IDLE: is the policy with lower priority than Cryo stat_OTHER.
  • Cryostat_FIFO: 첫 번째 실시간 정책입니다.
  • Cryostat_RR: 라운드 로빈 실시간 정책입니다.
  • Cryostat_DEADLINE: 작업 기한에 따라 작업의 우선 순위를 지정하는 스케줄러 정책입니다. 가장 빠른 절대 기한을 가진 작업이 먼저 실행됩니다.

2.1. 스케줄러 정책

실시간 스레드는 표준 스레드보다 우선 순위가 높습니다. 정책에는 최소 값 1에서 최대 99까지의 스케줄링 우선순위 값이 있습니다.

다음 정책은 실시간에 중요합니다.

  • Cryostat_OTHER 또는 Cryostat_NORMAL 정책

    이는 Linux 스레드의 기본 스케줄링 정책입니다. 스레드의 특성을 기반으로 시스템에 의해 변경되는 동적 우선 순위가 있습니다. Cryostat_OTHER 스레드는 가장 높은 우선 순위인 -20과 가장 낮은 우선 순위인 19 사이의 값을 갖습니다. Cryostat _OTHER 스레드의 기본 nice 값은 0입니다.

  • Cryostat_FIFO 정책

    Cryostat _FIFO 가 있는 스레드는 Cryostat _OTHER 작업보다 우선 순위가 높습니다. nice 값을 사용하는 대신, Cryostat _FIFO 는 1에서 가장 낮은 우선 순위인 가장 높은 우선 순위인 고정 우선 순위를 사용합니다. 우선 순위가 1인 A Cryostat _FIFO 스레드는 항상 먼저 a Cryostat _OTHER 스레드를 통해 예약합니다.

  • Cryostat_RR 정책

    Cryo stat_RR 정책은 Cryostat _FIFO 정책과 유사합니다. 우선순위가 동일한 스레드는 라운드 로빈 방식으로 예약됩니다. Cryostat_FIFOCryostat_RR 스레드는 다음 이벤트 중 하나가 발생할 때까지 실행됩니다.

    • 스레드가 잠기거나 이벤트를 기다립니다.
    • 우선순위가 높은 실시간 스레드를 실행할 준비가 되었습니다.

      위의 이벤트 중 하나가 발생하지 않는 한 스레드는 지정된 프로세서에서 무기한 실행되지만 우선순위가 낮은 스레드는 실행 대기 중인 큐에 남아 있습니다. 이로 인해 시스템 서비스 스레드가 상주하고 스왑 아웃되지 않고 파일 시스템 데이터 플러시에 실패할 수 있습니다.

  • Cryostat_DEADLINE 정책

    Cryo stat_DEADLINE 정책은 타이밍 요구 사항을 지정합니다. 작업의 데드라인에 따라 각 작업을 예약합니다. 먼저 데드라인(EDF) 일정이 가장 빠른 작업이 먼저 실행됩니다.

    커널을 사용하려면 runtime Cryostatdeadline Cryostatperiod 가 true여야 합니다. 필수 옵션 간의 관계는 runtime Cryostatdeadline Cryostatperiod 입니다.

2.2. Cryostat_DEADLINE 정책에 대한 매개변수

Cryostat_DEADLINE 작업은 마침표,런타임데드라인 매개 변수로 지정됩니다. 이러한 매개변수의 값은 나노초의 정수입니다.

Expand
표 2.1. Cryostat_DEADLINE 매개변수
매개변수설명

기간

기간은 실시간 작업의 활성화 패턴입니다.

예를 들어, 비디오 처리 작업에 처리할 초당 60 프레임이 있는 경우 16밀리초마다 서비스에 대해 새 프레임이 큐에 추가됩니다. 따라서 기간은 16밀리초입니다.

runtime

runtime 은 출력을 생성하기 위해 작업에 할당된 CPU 실행 시간입니다. 실시간으로 최대 실행 시간(WCET)은 런타임 입니다.

예를 들어 비디오 처리 도구가 이미지를 처리하는 데 5밀리초인 잘못된 경우 5밀리초를 사용할 수 있는 경우 런타임 은 5밀리초입니다.

데드라인

데드라인 은 출력을 생성하는 최대 시간입니다.

예를 들어 작업이 10밀리초 내에 처리된 프레임을 제공해야 하는 경우 데드라인 은 10밀리초입니다.

2.3. Cryostat_DEADLINE 매개변수 구성

Red Hat Enterprise Linux의 sched_deadline_period_max_ussched_deadline_period_min_us 매개변수는 Cryostat_DEADLINE 스케줄링 정책의 커널 조정 가능한 매개변수입니다. 이러한 매개변수는 이 실시간 스케줄링 클래스를 사용하여 작업에 대해 허용되는 최대 및 최소 기간(마이크로초)을 제어합니다.

sched_deadline_period_max_ussched_deadline_period_min_us 는 함께 작동하여 period 값에 대한 허용 가능한 범위를 정의합니다.

  • min_us 는 과도한 리소스를 사용할 수 있는 빈도가 높은 작업을 방지합니다.
  • max_us 는 다른 작업의 성능이 저하될 수 있는 매우 긴 기간 작업을 방지합니다.
참고

매개 변수의 기본 구성을 사용합니다. 매개변수 값을 변경해야 하는 경우 실시간 환경에서 사용자 지정 값을 구성해야 합니다.

매개 변수의 값은 마이크로초 단위입니다. 예를 들어 1초는 100000 마이크로초와 동일합니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있어야 합니다.

프로세스

  1. sysctl 명령 중 하나를 사용하여 필요한 값을 일시적으로 설정합니다.

    • sched_deadline_period_max_us 매개변수를 사용하려면 다음 명령을 실행합니다.

      # sysctl -w kernel.sched_deadline_period_max_us=2000000
    • sched_deadline_period_min_us 매개변수를 사용하려면 다음 명령을 실행합니다.

      # sysctl -w kernel.sched_deadline_period_min_us=100
  2. 값을 영구적으로 설정합니다.

    • max_us 의 경우 /etc/sysctl.conf 를 편집하고 다음 행을 추가합니다.

      kernel.sched_deadline_period_max_us = 2000000
    • min_us 의 경우 /etc/sysctl.conf 를 편집하고 다음 행을 추가합니다.

      kernel.sched_deadline_period_min_us = 100
  3. 변경 사항을 적용합니다.

    # sysctl -p

검증

  • max_us 의 사용자 지정 값을 확인합니다.

    $ cat /proc/sys/kernel/sched_deadline_period_max_us
    2000000
  • min_us 의 사용자 지정 값을 확인합니다.

    $ cat /proc/sys/kernel/sched_deadline_period_min_us
    100

3장. 영구 커널 튜닝 매개변수 설정

시스템에 작동하는 튜닝 구성을 결정한 경우 재부팅 시 변경 사항을 유지할 수 있습니다.

기본적으로 편집된 커널 튜닝 매개변수는 시스템이 재부팅되거나 매개 변수가 명시적으로 변경될 때까지만 적용됩니다. 이는 초기 튜닝 구성을 설정하는 데 효과적입니다. 또한 보안 메커니즘을 제공합니다. 편집된 매개 변수로 인해 머신이 잘못된 방식으로 작동하는 경우 시스템을 재부팅하면 매개 변수가 이전 구성으로 반환됩니다.

3.1. 영구 커널 튜닝 매개변수 변경

/etc/sysctl.conf 파일에 매개변수를 추가하여 커널 튜닝 매개변수를 영구적으로 변경할 수 있습니다.

참고

이 절차에서는 현재 세션의 커널 튜닝 매개 변수는 변경 하지 않습니다. /etc/sysctl.conf 에 입력된 변경 사항은 향후 세션에만 영향을 미칩니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. 텍스트 편집기에서 /etc/sysctl.conf 를 엽니다.
  2. 매개 변수의 값을 사용하여 파일에 새 항목을 삽입합니다.

    /proc/sys/ 경로를 제거하고 나머지 슬래시(/)를 마침표(.)로 변경하고 매개 변수의 값을 포함하여 매개변수 이름을 수정합니다.

    예를 들어 echo 0 > /proc/sys/kernel/hung_task_panic 명령을 만들려면 /etc/sysctl.conf 에 다음을 입력합니다.

    # Enable gettimeofday(2)
    kernel.hung_task_panic = 0
  3. 파일을 저장하고 닫습니다.
  4. 변경 사항을 적용하려면 시스템을 재부팅합니다.

검증

  • 구성을 확인하려면 다음을 수행합니다.

    # cat /proc/sys/kernel/hung_task_panic
    0

4장. 애플리케이션 튜닝 및 배포

최적의 구성과 설정을 조합하여 실시간 커널을 튜닝하면 RHEL for Real Time 애플리케이션을 개선하고 개발하는 데 도움이 될 수 있습니다.

참고

일반적으로 POSIX 정의 API(애플리케이션 프로그래밍 인터페이스)를 사용하십시오. RHEL for Real Time은 POSIX 표준을 준수합니다. RHEL for Real Time 커널의 대기 시간 감소도 POSIX 를 기반으로 합니다.

4.1. 실시간 애플리케이션의 신호 처리

기존 UNIXPOSIX 신호에는 특히 오류 처리에 사용이 있지만 실시간 애플리케이션에서 이벤트 전달 메커니즘으로 적합하지 않습니다. 이는 주로 기존 동작 및 지원되는 많은 API 때문에 현재 Linux 커널 신호 처리 코드가 매우 복잡하기 때문입니다. 이러한 복잡성은 신호를 전달할 때 사용하는 코드 경로가 항상 최적이 아니며 애플리케이션에 의해 긴 대기 시간을 경험할 수 있음을 의미합니다.

UNIX 신호의 원래 동기는 서로 다른 실행 "스레드" 간에 하나의 제어 스레드(프로세스)를 멀티플렉싱하는 것이었습니다. 신호는 운영 체제 인터럽트처럼 작동합니다. 즉, 신호가 애플리케이션에 전달되면 애플리케이션의 컨텍스트가 저장되고 이전에 등록된 신호 처리기를 실행하기 시작합니다. 신호 처리기가 완료되면 애플리케이션은 신호가 전달된 위치로 돌아갑니다. 이는 실제로 복잡해질 수 있습니다.

신호는 실시간 애플리케이션에 대한 신뢰에 너무 비 결정적입니다. 더 나은 옵션은 POSIX Threads(pthreads)를 사용하여 워크로드를 배포하고 다양한 구성 요소 간에 통신하는 것입니다. 뮤지션의 pthreads 메커니즘을 사용하여 스레드 그룹을 조정할 수 있습니다. 비교적 새로운 구성을 통한 코드 경로는 신호에 대한 레거시 처리 코드보다 훨씬 깔끔합니다.

4.2. 스레드 동기화

sched_yield 함수는 우선순위가 낮은 스레드를 실행할 수 있는 동기화 메커니즘입니다. 이러한 유형의 요청은 잘못 작성된 애플리케이션 내에서 발행된 경우 실패하기 쉽습니다.

우선 순위가 높은 스레드는 sched_yield() 를 호출하여 다른 스레드에서 기회를 실행할 수 있습니다. 호출 프로세스는 해당 우선 순위에서 실행되는 프로세스 큐의 테일로 이동합니다. 동일한 우선 순위에서 다른 프로세스가 실행되지 않는 경우 호출 프로세스가 계속 실행됩니다. 해당 프로세스의 우선 순위가 높으면 잠재적으로 사용 중인 루프를 생성하여 머신을 사용할 수 없게 될 수 있습니다.

Cryo stat_DEADLINE 작업이 sched_yield() 를 호출하면 구성된 CPU를 포기하고 나머지 런타임은 다음 기간까지 즉시 제한됩니다. sched_yield() 동작을 사용하면 다음 기간이 시작될 때 작업이 발생할 수 있습니다.

스케줄러는 언제, 실제로 실행을 기다리는 다른 스레드가 있는지 확인할 수 있습니다. 실시간 작업에서 sched_yield() 를 사용하지 마십시오.

프로세스

  • sched_yield() 함수를 호출하려면 다음 코드를 실행합니다.

    for(;;) {
      do_the_computation();
      /*
       * Notify the scheduler at the end of the computation
       * This syscall will block until the next replenishment
       */
      sched_yield();
    }

    Cryo stat_DEADLINE 작업은 다음 기간(다음 루프 실행 시작)까지 CBS( conflict-based search) 알고리즘에 의해 제한됩니다.

4.3. 실시간 스케줄러 우선순위

systemd 명령을 사용하여 부팅 프로세스 중에 시작된 서비스의 실시간 우선 순위를 설정할 수 있습니다. 일부 커널 스레드에는 매우 높은 우선 순위가 제공될 수 있습니다. 이를 통해 기본 우선순위는 RRTSJ(Real Time Specification for Java)의 요구 사항과 잘 통합할 수 있습니다. RTSJ에는 10에서 89까지 다양한 우선순위가 필요합니다.

RTSJ를 사용하지 않는 배포의 경우 90 미만의 스케줄링 우선 순위는 애플리케이션에서 사용할 수 있습니다. 필수 시스템 서비스가 실행되지 않도록 할 수 있으므로 우선 49 이상의 애플리케이션 스레드를 예약할 때는 필수 시스템 서비스가 실행되지 않도록 할 때 주의해야 합니다. 이로 인해 차단된 네트워크 트래픽, 차단된 가상 메모리 페이징, 차단된 파일 시스템 저널링 등 예기치 않은 동작이 발생할 수 있습니다.

애플리케이션 스레드가 우선 순위 89 이상으로 예약된 경우 스레드가 매우 짧은 코드 경로만 실행해야 합니다. 이렇게 하지 않으면 RHEL for Real Time 커널의 짧은 대기 시간 기능이 손상되었습니다.

필수 권한 없이 사용자의 실시간 우선 순위 설정

기본적으로 애플리케이션에 대한 root 권한이 있는 사용자만 우선 순위 및 스케줄링 정보를 변경할 수 있습니다. root 권한을 제공하기 위해 설정을 수정할 수 있으며 기본 방법은 사용자를 realtime 그룹에 추가하는 것입니다.

중요

/etc/security/limits.conf 파일을 편집하여 사용자 권한을 변경할 수도 있습니다. 그러나 이로 인해 중복이 발생하고 일반 사용자에게는 시스템을 사용할 수 없게 될 수 있습니다. 이 파일을 편집하려면 주의해야 하며 변경하기 전에 항상 복사본을 만듭니다.

4.4. 동적 라이브러리 로드

실시간 애플리케이션을 개발할 때 프로그램 실행 중에 결정적이지 않은 대기 시간을 피하기 위해 시작 시 기호를 확인하는 것이 좋습니다. 시작 시 기호를 해결하면 프로그램 초기화 속도가 느려질 수 있습니다. LD_BIND_NOW 변수를 동적 링커/로 설정하여 애플리케이션 시작 시 동적 라이브러리가 로드 되도록 지시할 수 있습니다.

예를 들어 다음 쉘 스크립트는 값이 1LD_BIND_NOW 변수를 내보낸 다음 스케줄러 정책이 FIFO 이고 우선 순위 1 인 프로그램을 실행합니다.

#!/bin/sh

LD_BIND_NOW=1
export LD_BIND_NOW

chrt --fifo 1 /opt/myapp/myapp-server &

5장. 시스템 튜닝을 위한 BIOS 매개변수 설정

BIOS는 시스템의 작동에 중요한 역할을 합니다. BIOS 매개변수를 올바르게 구성하면 시스템 성능을 크게 향상시킬 수 있습니다.

참고

모든 시스템 및 BIOS 벤더는 다른 용어와 탐색 방법을 사용합니다. BIOS 설정에 대한 자세한 내용은 BIOS 설명서를 참조하거나 BIOS 공급 업체에 문의하십시오.

5.1. 응답 시간을 개선하기 위해 전원 관리 비활성화

BIOS 전원 관리 옵션은 시스템 클럭 빈도를 변경하거나 CPU를 다양한 절전 상태 중 하나로 전환하여 전원을 저장하는 데 도움이 됩니다. 이러한 작업은 시스템이 외부 이벤트에 응답하는 속도에 영향을 미칠 수 있습니다.

응답 시간을 개선하려면 BIOS의 모든 전원 관리 옵션을 비활성화합니다.

5.2. 오류 감지 및 수정 단위를 비활성화하여 응답 시간 개선

EDAC(Error Detection and Correction) 단위는 오류 수정 코드(ECC) 메모리에서 신호되는 오류를 탐지하고 수정하기 위한 장치입니다. 일반적으로 EDAC 옵션은 ECC 검사를 포함하지 않으며 모든 메모리 노드에 오류가 있는지 정기적으로 스캔합니다. EDAC 수준이 높을수록 BIOS가 사용하는 시간이 더 늘어납니다. 이로 인해 중요한 이벤트 데드라인이 누락될 수 있습니다.

응답 시간을 개선하려면 EDAC를 끕니다. 이 기능을 사용할 수 없는 경우 EDAC를 가장 낮은 기능 수준으로 구성합니다.

5.3. 시스템 관리 인터럽트를 구성하여 응답 시간 개선

SMI(System Management Interrupts)는 시스템이 올바르게 작동하는지 확인하기 위한 하드웨어 벤더 기능입니다. BIOS 코드는 일반적으로 SMI 인터럽트를 서비스합니다. SMIS는 일반적으로 열 관리, IPMI(원격 콘솔 관리), EDAC 검사 및 기타 다양한 하우스키핑 작업에 사용됩니다.

BIOS에 SMI 옵션이 포함된 경우 벤더 및 관련 문서를 확인하여 안전하게 비활성화할 수 있는 범위를 확인합니다.

주의

SMI를 완전히 비활성화할 수는 있지만 Red Hat은 이를 수행하지 않는 것이 좋습니다. SMI를 생성하고 서비스하는 시스템의 기능을 제거하면 심각한 하드웨어 오류가 발생할 수 있습니다.

6장. 실시간 커널의 런타임 확인

런타임 확인은 시스템 이벤트와 공식 사양 간의 동작 동일성을 확인하는 가볍고 엄격한 방법입니다. 런타임 확인에는 추적 지점에 연결하는 커널에 통합된 모니터가 있습니다. 시스템 상태가 정의된 사양에서 벗어나는 경우 런타임 확인 프로그램은 반응기를 활성화하여 로그 파일에서 이벤트를 캡처하거나 시스템 종료와 같은 응답을 활성화하여 극단적인 경우 오류 전파를 방지합니다.

6.1. 런타임 모니터 및 반응기

RV(런타임 확인) 모니터는 RV 모니터 내에 캡슐화되고 정의된 사양과 커널 추적 간에 조정되어 추적 파일에서 런타임 이벤트를 캡처합니다. RV 모니터에는 다음이 포함됩니다.

  • 참조 모델은 시스템의 참조 모델입니다.
  • 모니터 인스턴스는 CPU당 모니터 또는 작업별 모니터와 같은 모니터의 인스턴스 집합입니다.
  • 모니터를 시스템에 연결하는 도우미 기능입니다.

런타임 시 시스템을 확인하고 모니터링하는 것 외에도 예기치 않은 시스템 이벤트에 대한 응답을 활성화할 수 있습니다. 반응 방식은 안전 크리티컬 시스템에서 시스템 실패를 방지하기 위해 종료와 같은 극단적인 반응을 시작하기 위해 추적 파일에서 이벤트를 캡처하는 것과는 다를 수 있습니다.

반응기는 필요에 따라 시스템 이벤트에 대한 응답을 정의하기 위해 RV 모니터에 사용할 수 있는 반응 방법입니다. 기본적으로 모니터는 작업의 추적 출력을 제공합니다.

6.2. 온라인 런타임 모니터

RV(런타임 확인) 모니터는 다음과 같은 유형으로 분류됩니다.

  • 온라인 모니터는 시스템이 실행되는 동안 추적에서 이벤트를 캡처합니다.

    온라인 모니터는 이벤트 처리가 시스템 실행에 연결된 경우 동기적으로 수행됩니다. 이렇게 하면 이벤트 모니터링 중에 시스템이 차단됩니다. 온라인 모니터는 시스템에서 실행이 분리되고 다른 컴퓨터에서 실행되는 경우 비동기식입니다. 그러나 저장된 실행 로그 파일이 필요합니다.

  • 오프라인에서는 이벤트가 발생한 후 생성된 프로세스 추적을 모니터링합니다.

    오프라인 런타임 확인에서는 일반적으로 영구 저장소에서 저장된 추적 로그 파일을 읽고 정보를 캡처합니다. 오프라인 모니터는 파일에 저장된 이벤트가 있는 경우에만 작동할 수 있습니다.

6.3. 사용자 인터페이스

사용자 인터페이스는 /sys/kernel/tracing/rv 에 있으며 추적 인터페이스와 유사합니다. 사용자 인터페이스에는 언급된 파일 및 폴더가 포함됩니다.

Expand
설정설명명령 예

available_monitors

한 줄에 하나씩 사용 가능한 모니터를 표시합니다.

# cat available_monitors

available_reactors

한 줄에 하나씩 사용 가능한 반응기를 표시합니다.

# cat available_reactors

enabled_monitors

한 줄에 하나씩 활성화된 모니터를 표시합니다. 두 개 이상의 모니터를 동시에 활성화할 수 있습니다.

'!' 접두사를 사용하여 모니터 이름을 작성하면 모니터가 비활성화되고 파일을 자르면 활성화된 모든 모니터가 비활성화됩니다.

# cat enabled_monitors

# Echo wip > enabled_monitors

# Echo '!wip'>> enabled_monitors

모니터/

모니터/ 디렉터리는 tracefs 파일 시스템의 events 디렉토리와 유사하며 각 모니터는 monitors/ 내에 자체 디렉터리가 있습니다.

# CD Monitor/wip/

모니터/MONITOR/reactors

"[]" 내의 특정 MONITOR에 대한 선택 반응과 함께 사용 가능한 반응기를 나열합니다. 기본값은 no operation (nop) reactor입니다.

반응자 이름을 작성하면 특정 MONITOR에 통합됩니다.

# cat monitors/wip/reactors

monitoring_on

추적 인터페이스에서 tracing_ontracing_off 전환기를 시작합니다.

0 을 작성하면 모니터링이 중지되고 1 은 모니터링을 계속합니다. 전환기에서는 활성화된 모니터를 비활성화하지 않지만 이벤트를 모니터링하지 못하도록 관련 모니터를 중지합니다.

 

reacting_on

reactors를 활성화합니다. 0 을 작성하면 응답이 비활성화되고 1 은 응답을 활성화합니다.

 

모니터/MONITOR/desc

모니터 설명 표시

 

모니터/MONITOR/enable

모니터의 현재 상태를 표시합니다. 0 을 작성하면 모니터가 비활성화되고 1 은 모니터를 활성화합니다.

 

7장. 하드웨어 및 펌웨어 대기 시간 테스트 실행 및 해석

hwlatdetect 프로그램을 사용하면 잠재적인 하드웨어 플랫폼이 실시간 작업을 사용하기에 적합한지 테스트하고 확인할 수 있습니다.

사전 요구 사항

  • RHEL-RT (RHEL for Real Time) 및 realtime-tests 패키지가 설치되어 있는지 확인합니다.
  • 대기 시간이 짧은 작업에 필요한 튜닝 단계는 벤더 설명서를 확인하십시오.

    벤더 문서는 시스템을SMM(System Management Mode)으로 전환하는SMI(System Management Interrupts)를 줄이거나 제거하는 지침을 제공할 수 있습니다. 시스템은 SMM에 있지만 운영 체제 코드가 아닌 펌웨어를 실행합니다. 즉, SMM에서 실행되는 모든 타이머는 시스템이 정상 작동으로 다시 전환될 때까지 대기합니다. 이는 Linux에서 SMI를 차단할 수 없기 때문에 설명되지 않은 대기 시간이 발생할 수 있으며, 실제로 SMI를 인수한 유일한 표시는 벤더별 성능 카운터 레지스터에서 확인할 수 있습니다.

    주의

    Red Hat은 심각한 하드웨어 장애가 발생할 수 있으므로 SMI를 완전히 비활성화하지 않는 것이 좋습니다.

7.1. 하드웨어 및 펌웨어 대기 시간 테스트 실행

이 테스트는 하드웨어 아키텍처 또는 BIOS 또는 EFI 펌웨어에 의해 도입된 대기 시간을 찾기 때문에 hwlatdetect 프로그램을 실행하는 동안 시스템에서 부하를 실행할 필요가 없습니다. hwlatdetect 의 기본값은 초당 0.5초 동안 폴링하고 연속 호출 간에 10마이크로초보다 큰 간격을 보고하여 시간을 가져옵니다. hwlatdetect 는 시스템에서 가능한 최상 의 대기 시간을 반환합니다. 따라서 10us 및 hwlatdetect 보다 적은 최대 대기 시간 값이 필요한 애플리케이션이 있는 경우 시스템은 20us의 대기 시간만 보장할 수 있습니다.

참고

hwlatdetect 가 애플리케이션의 대기 시간 요구 사항을 충족할 수 없음을 표시하는 경우 BIOS 설정을 변경하거나 시스템 공급 업체와 협력하여 애플리케이션의 대기 시간 요구 사항을 충족하는 새 펌웨어를 가져옵니다.

프로세스

  • 테스트 기간을 초 단위로 지정하여 hwlatdetect 를 실행합니다.

    hwlatdetect 는 클럭 소스를 폴링하고 설명되지 않은 격차를 확인하여 하드웨어 및 펌웨어의 대기 시간을 찾습니다.

    # hwlatdetect --duration=60s
    hwlatdetect:  test duration 60 seconds
    	detector: tracer
    	parameters:
    		Latency threshold:    10us
    		Sample window:        1000000us
    		Sample width:         500000us
    		Non-sampling period:  500000us
    		Output File:          None
    
    Starting test
    test finished
    Max Latency: Below threshold
    Samples recorded: 0
    Samples exceeding threshold: 0

7.2. 하드웨어 및 펌웨어 대기 시간 테스트 결과 해석

하드웨어 대기 시간 탐지기(hwlatdetect)는 추적기 메커니즘을 사용하여 하드웨어 아키텍처 또는 BIOS/EFI 펌웨어가 도입한 대기 시간을 감지합니다. hwlatdetect 에서 측정한 대기 시간을 확인하여 RHEL for Real Time 커널을 지원하는 데 잠재적인 하드웨어가 적합한지 확인할 수 있습니다.

  • 예제 결과는 펌웨어에서 시스템 중단을 최소화하도록 조정된 시스템을 나타냅니다. 이 경우 hwlatdetect 의 출력은 다음과 같습니다.

    # hwlatdetect --duration=60s
    hwlatdetect:  test duration 60 seconds
    	detector: tracer
    	parameters:
    		Latency threshold: 10us
    		Sample window:     1000000us
    		Sample width:      500000us
    		Non-sampling period:  500000us
    		Output File:       None
    
    Starting test
    test finished
    Max Latency: Below threshold
    Samples recorded: 0
    Samples exceeding threshold: 0
  • 예제 결과는 펌웨어에서 시스템 중단을 최소화하도록 조정할 수 없는 시스템을 나타냅니다. 이 경우 hwlatdetect 의 출력은 다음과 같습니다.

    # hwlatdetect --duration=10s
    hwlatdetect:  test duration 10 seconds
    	detector: tracer
    	parameters:
    		Latency threshold: 10us
    		Sample window:     1000000us
    		Sample width:      500000us
    		Non-sampling period:  500000us
    		Output File:       None
    
    Starting test
    test finished
    Max Latency: 18us
    Samples recorded: 10
    Samples exceeding threshold: 10
    SMIs during run: 0
    ts: 1519674281.220664736, inner:17, outer:15
    ts: 1519674282.721666674, inner:18, outer:17
    ts: 1519674283.722667966, inner:16, outer:17
    ts: 1519674284.723669259, inner:17, outer:18
    ts: 1519674285.724670551, inner:16, outer:17
    ts: 1519674286.725671843, inner:17, outer:17
    ts: 1519674287.726673136, inner:17, outer:16
    ts: 1519674288.727674428, inner:16, outer:18
    ts: 1519674289.728675721, inner:17, outer:17
    ts: 1519674290.729677013, inner:18, outer:17----

    출력은 시스템 클럭 소스 의 연속 읽기 중에 15-18 us 범위에 표시되는 10 지연이 있음을 보여줍니다.

    참고

    이전 버전에서는 ftrace 추적기 대신 커널 모듈을 사용했습니다.

결과 이해

테스트 방법, 매개변수 및 결과에 대한 정보는 hwlatdetect 유틸리티에서 감지한 대기 시간 매개변수 및 대기 시간 값을 이해하는 데 도움이 됩니다.

테스트 메서드, 매개변수 및 결과에 대한 표에는 hwlatdetect 유틸리티에서 감지한 매개변수 및 대기 시간 값이 나열됩니다.

Expand
표 7.1. 테스트 방법, 매개변수 및 결과
매개변수현재의설명

테스트 기간

10 초

테스트 기간(초)

Detector

Tracer

detect 스레드를 실행하는 유틸리티

매개변수

  

대기 시간 임계값

10us

허용되는 최대 대기 시간

샘플 창

1000000us

1초

샘플 너비

500000us

0.05초

비 샘플링 기간

500000us

0.05초

출력 파일

없음

출력이 저장되는 파일입니다.

결과

  

최대 대기 시간

18us

테스트 중 대기 시간 임계값을 초과하는 가장 높은 대기 시간입니다. 샘플이 Latency 임계값 을 초과하지 않으면 보고서가 낮은 임계값으로 표시됩니다.

기록된 샘플

10

테스트에서 기록한 샘플 수입니다.

임계값을 초과하는 샘플

10

대기 시간이 Latency 임계값 을 초과한 테스트로 기록된 샘플 수입니다.

실행 중 SMIS

0

테스트 실행 중에 발생한SMI(System Management Interrupts) 수입니다.

참고

내부 및 외부를 위해 hwlatdetect 유틸리티에서 출력하는 값은 최대 대기 시간 값입니다. 현재 시스템 클럭 소스의 연속 읽기(일반적으로 TSC 또는 TSC 레지스터)와 하드웨어-Firmware 조합에 의해 도입된 연속 읽기 사이의 지연과 HPET 또는 ACPI 전원 관리 클록 사이의 지연입니다.

적합한 하드웨어 피임약 조합을 찾은 후 다음 단계는 로드 중인 동안 시스템의 실시간 성능을 테스트하는 것입니다.

8장. 시스템 대기 시간 테스트 실행 및 해석

RHEL for Real Time은 로드 중인 시스템 실시간 성능을 테스트하는 rteval 유틸리티를 제공합니다.

8.1. 시스템 대기 시간 테스트 실행

rteval 유틸리티를 사용하면 로드 중인 시스템의 실시간 성능을 테스트할 수 있습니다.

사전 요구 사항

  • RHEL for Real Time 패키지 그룹이 설치되어 있습니다.
  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • rteval 유틸리티를 실행합니다.

    # rteval

    rteval 유틸리티는 많은 시스템 로드를 시작합니다. Cryo stat_OTHER 작업. 그런 다음 각 온라인 CPU에서 실시간 응답을 측정합니다. 로드는 루프에 있는 Linux 커널 트리와 해커치 합성 벤치마크의 병렬 제작 입니다.

    목표는 시스템을 각 코어에 항상 예약할 작업이 있는 상태로 가져오는 것입니다. 작업은 메모리 할당/free, 디스크 I/O, 계산 작업, 메모리 복사본 및 기타와 같은 다양한 작업을 수행합니다.

    로드가 시작되면 rtevalcyclictest 측정 프로그램을 시작합니다. 이 프로그램은 각 온라인 코어에서 Cryostat _FIFO 실시간 스레드를 시작합니다. 그런 다음 실시간 스케줄링 응답 시간을 측정합니다.

    각 측정 스레드는 타임스탬프를 사용하고 간격 동안 유휴 상태를 확인한 후 다시 시작한 후 다른 타임 스탬프를 사용합니다. 측정된 대기 시간은 t1 - (t0 + i) 입니다. t1은 t1 시간 t1 과 첫 번째 타임 스탬프 t0의 이론적 레이턴시 t0 + 절전 간격 i 의 이론적인 레이턴시입니다.

    rteval 실행의 세부 사항은 시스템의 부팅 로그와 함께 XML 파일에 작성됩니다. 이 보고서는 화면에 표시되고 압축 파일에 저장됩니다.

    파일 이름은 rteval- <date>-N -tar.bz2 형식으로 되어 있습니다. 여기서 < date >는 보고서가 생성된 날짜이며 N 은 < date >에서 Nth 실행에 대한 카운터입니다.

    다음은 rteval 보고서의 예입니다.

    System:
    Statistics:
    	Samples:           1440463955
    	Mean:              4.40624790712us
    	Median:            0.0us
    	Mode:              4us
    	Range:             54us
    	Min:               2us
    	Max:               56us
    	Mean Absolute Dev: 1.0776661507us
    	Std.dev:           1.81821060672us
    
    CPU core 0       Priority: 95
    Statistics:
    	Samples:           36011847
    	Mean:              5.46434910711us
    	Median:            4us
    	Mode:              4us
    	Range:             38us
    	Min:               2us
    	Max:               40us
    	Mean Absolute Dev: 2.13785341159us
    	Std.dev:           3.50155558554us

    이 보고서에는 시스템 하드웨어, 실행 길이, 사용된 옵션 및 타이밍 결과(cpu별 및 시스템 수준)에 대한 세부 정보가 포함되어 있습니다.

    참고

    생성된 파일에서 rteval 보고서를 다시 생성하려면 다음을 실행합니다.

    # rteval --summarize rteval-<date>-N.tar.bz2

9장. 실시간 작업 실행에 rteval 컨테이너 사용

Red Hat Enterprise Linux (RHEL) for Real Time의 rteval (실시간 평가) 컨테이너는 중요한 작업의 대기 시간이 짧은 실행을 보장합니다. 실시간 응답을 유지하고 적절한 작업 실행을 보장하기 위해 다양한 시스템 로드에서 타이머가 가동 시간을 측정합니다.

rteval 툴은 ( cyclictest 또는 rtla와 같은 툴을 사용하여) 측정 프로세스를 우선순위가 높은 작업으로 설정합니다. 이 측정 프로세스는 시스템에서 생성된 부하보다 우선 순위가 높습니다. 결과적으로 R teval 컨테이너는 서로 다른 부하에서 실시간 작업의 작동 시간을 측정하여 시스템이 실시간 워크로드를 효과적으로 처리할 수 있도록 합니다.

9.1. rteval 컨테이너의 호스트 테스트

대기 시간에 민감한 워크로드에서 rteval 컨테이너를 실행하려면 컨테이너 기술에 가상화 스택에 추가 커널이 필요하지 않으므로 호스트 시스템을 조정해야 합니다. 베어 메탈에 적용되는 대부분의 튜닝 전략은 컨테이너 환경에도 적용할 수 있습니다.

realtime -variables.conf 파일에 정의된 기본 매개변수를 사용하여 tuned-adm 로 실시간 프로필을 적용해야 합니다.

실시간 프로필은 다음 작업을 수행합니다.

  • 다양한 커널 명령줄 옵션을 설정합니다.
  • NUMA(Non-Uniform Memory Access) 토폴로지를 감지합니다.
  • NUMA 노드가 두 개 이상 있을 때 각 노드의 첫 번째 CPU를 isolcpus 세트에 할당하는 모든 CPU를 할당합니다.

rteval 컨테이너에 대한 호스트 시스템을 구성합니다.

사전 요구 사항

  • 호스트 시스템은 Red Hat Enterprise Linux 버전 9.6 이상에서 실행되고 있습니다.
  • tunedtuned-profiles-realtime 패키지가 설치됩니다.
  • tuned 서비스가 실행 중입니다.
  • podman 애플리케이션이 설치되어 실행 중입니다.

프로세스

  1. 필수 패키지를 설치합니다.

    $ sudo dnf install rteval kernel-rt podman -y
  2. 설치된 커널을 확인합니다.

    $ sudo grubby --info=ALL
    index=0
    kernel="/boot/vmlinuz-5.XX.0-XX.X.X.el9_6.x86_64+rt"
    args="ro crashkernel=2G-64G:256M,64G-:512M resume=UUID=3e14acf4-a359-4045-b8fc-990ff83743ec rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81 $tuned_params"
    root="/dev/mapper/rhel_rt--qe--11-root"
    initrd="/boot/initramfs-5.XX.0-XX.X.X.el9_6.x86_64+rt.img $tuned_initrd"
    title="Red Hat Enterprise Linux (5.XX.0-XX.X.X.el9_6.x86_64+rt) 9.6 (Plow)"
    id="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-5.XX.0-XX.X.X.el9_6.x86_64+rt"
    index=1
    kernel="/boot/vmlinuz-5.XX.0-XX.X.X.el9_6.x86_64"
    args="ro crashkernel=2G-64G:256M,64G-:512M resume=UUID=3e14acf4-a359-4045-b8fc-990ff83743ec rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81 $tuned_params"
    root="/dev/mapper/rhel_rt--qe--11-root"
    initrd="/boot/initramfs-5.XX.0-XX.X.X.el9_6.x86_64.img $tuned_initrd"
    title="Red Hat Enterprise Linux (5.XX.0-XX.X.X.el9_6.x86_64) 9.6 (Plow)"
    id="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-5.XX.0-XX.X.X.el9_6.x86_64"
    index=2
    kernel="/boot/vmlinuz-0-rescue-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    args="ro crashkernel=2G-64G:256M,64G-:512M resume=UUID=3e14acf4-a359-4045-b8fc-990ff83743ec rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81"
    root="/dev/mapper/rhel_rt--qe--11-root"
    initrd="/boot/initramfs-0-rescue-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.img"
    title="Red Hat Enterprise Linux (0-rescue-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX) 9.6 (Plow)"
    id="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-0-rescue"
  3. 실시간 커널을 기본 커널로 설정합니다.

    $ select a in /boot/vmlinuz-*rt*; do grubby --set-default=$a; break; done
  4. tuned-adm:을 사용하여 실시간 프로필을 적용합니다.

    $ sudo tuned-adm profile realtime
  5. 호스트 시스템을 재부팅합니다.

    $ sudo reboot

검증

  1. 커널 버전 및 튜닝 매개변수를 확인합니다.

    $ sudo uname -r
    5.XX.0-XX.X.X.el9_6.x86_64+rt
    $ sudo cat /proc/cmdline
    BOOT_IMAGE=(hd0,gpt2)/vmlinuz-5.XX.0-XX.X.X.el9_6.x86_64+rt root=/dev/mapper/rhel_rt--qe--11-root ro crashkernel=2G-64G:256M,64G-:512M resume=UUID=3e14acf4-a359-4045-b8fc-990ff83743ec rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81 skew_tick=1 tsc=reliable rcupdate.rcu_normal_after_boot=1 isolcpus=managed_irq,domain,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 intel_pstate=disable nosoftlockup

9.2. 기준 결과를 위해 베어 메탈 테스트

필수 운영 체제 및 rteval 컨테이너를 제외한 추가 소프트웨어 없이 베어 메탈에서 시스템을 실행합니다. 이렇게 하면 시스템이 대기 시간이 짧은 성능에 최적화되고 결과는 다른 소프트웨어 또는 프로세스의 영향을 받지 않습니다.

사전 요구 사항

프로세스

  • rteval 컨테이너를 실행하는 두 가지 시나리오가 있습니다.

    • 단일 NUMA 노드에서 다음을 수행합니다.

      $ rteval --duration 2h
    • 여러 NUMA 노드에서 rteval 컨테이너를 실행합니다.

      $ rteval --duration 2h --loads-cpulist 0,1 --measurement-cpulist 2-47

베어 메탈 테스트를 완료한 후 rteval 컨테이너를 기준으로 사용하여 애플리케이션 또는 서비스로 실제 시나리오를 구성합니다.

9.3. 컨테이너 배치를 사용하여 CPU 성능 최적화

실시간 프로필을 사용하여 호스트를 튜닝한 후 특정 CPU에 컨테이너를 선택적으로 배치하고 컨테이너 런타임 동작을 조정하여 성능을 추가로 최적화할 수 있습니다. 이러한 전략을 사용하면 CPU 격리 및 cgroup 구성이 컨테이너화된 워크로드의 대기 시간에 미치는 영향을 확인할 수 있습니다.

9.3.1. 모든 CPU에서 podman 실행

rteval 컨테이너로 podman 을 실행하려면 tuned realtime 프로필 또는 사용자 지정 시스템 튜닝을 사용하여 시스템을 조정합니다. 측정 중인 시나리오에 대해 CPU 분리가 필요한지 확인합니다. 특정 시나리오에서 컨테이너를 실행할 때 문제를 방지하려면 CPU 격리를 올바르게 설정해야 합니다.

/proc/cmdline 에서 isolcpus= 인수를 확인합니다. isolcpus 가 설정되지 않은 경우 시스템은 CPU를 분리하지 않으며 모든 CPU에서 컨테이너를 실행할 수 있습니다.

사전 요구 사항

  • /proc/cmdlineisolcpus= 인수는 모든 CPU에서 컨테이너를 실행하도록 설정되지 않습니다.
  • 호스트 시스템은 Red Hat Enterprise Linux 버전 9.6 이상에서 실행되고 있습니다.
  • podman 서비스가 실행 중입니다.
  • rteval 컨테이너가 설치되어 실행 중입니다.

프로세스

  1. podman 레지스트리에 로그인합니다.

    $ podman login registry.redhat.io
  2. rteval 컨테이너를 실행합니다. 컨테이너를 실행하는 다음 방법 중 하나를 선택합니다.

    • 단일 NUMA 노드 박스의 모든 CPU에서 다음을 수행합니다.

      $ podman run -it --rm --privileged --pids-limit=0 registry.redhat.io/rhel10/rteval \
      	/bin/bash -c 'rteval --duration 2h'
    • 다중 NUMA 노드 시스템에서 다음을 수행합니다.

      $ podman run -it --rm --privileged --pids-limit=0 registry.redhat.io/rhel10/rteval \
      	/bin/bash -c 'rteval --duration 2h --loads-cpulist 0,1 --measurement-cpulist 2-47
      --pids-limit=0

      kcompile 은 컨테이너 런타임의 기본 제한에 도달하지 않고 실행할 수 있습니다.

      kcompile 은 전체 커널을 다시 빌드할 필요 없이 현재 실행 중인 커널의 커널 모듈을 컴파일하는 데 사용되는 명령줄 유틸리티입니다.

      --privileged
      컨테이너는 호스트 시스템의 모든 장치에 액세스할 수 있습니다. rteval 을 올바르게 실행하려면 이 작업이 필요합니다.

이러한 명령은 사용 가능한 모든 노드에서 단일 컨테이너를 실행합니다. tuned 서비스는 호스트 튜닝을 관리하여 단일 CPU만 사용할 때 베어 메탈 성능을 평가할 수 있습니다.

검증

  • 새 터미널에서 rteval 컨테이너를 포함한 모든 컨테이너를 나열하여 올바르게 실행되고 있는지 확인합니다.

    $ podman ps -a

9.3.2. 분할 CPU 할당으로 podman 실행

로드 분리 및 측정을 테스트하기 위해 다른 CPU 세트에 다른 컨테이너를 할당할 수 있습니다. 예를 들어 NUMA 노드가 하나만 있고 로드와 측정값을 컨테이너로 분리하려는 경우 두 개의 서로 다른 컨테이너를 실행할 수 있습니다. 이 경우 두 컨테이너는 모든 CPU에서 실행되고 튜닝에 파티션이 사용되지 않습니다.

명령 예:

  • 컨테이너 로드:

    $ podman run -it --rm --privileged --pids-limit=0 registry.redhat.io/rhel10/rteval \
       	/bin/bash -c 'rteval --duration 2h --onlyload'
  • 측정 컨테이너:

    $ podman run -it --rm --privileged --pids-limit=0 registry.redhat.io/rhel10/rteval \
       	/bin/bash -c 'rteval --duration 2h --onlymeasure'

NUMA 노드가 두 개 이상 있거나 수동으로 분할된 시스템에서 박스를 분할하는 경우 예제 명령은 다음과 같습니다.

  • 컨테이너 로드:

    $ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 0,1 registry.redhat.io/rhel10/rteval \
    /bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 0,1'
  • 측정 컨테이너:

    $ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 2-47 registry.redhat.io/rhel10/rteval \
    /bin/bash -c 'rteval --duration 2h --noload --measurement-cpulist 2-47'

이러한 명령을 실행한 후 load 컨테이너는 isol_cpu 세트에서 작동하는 동안 하우스키핑 코어에 부하를 생성합니다.

파티셔닝이 구성되지 않은 경우 하나의 컨테이너가 시스템의 모든 CPU에 부하를 생성하고 다른 컨테이너는 모든 노드에서 대기 시간을 측정합니다.

두 시나리오 모두에서 로드와 측정이 두 컨테이너 간에 성공적으로 구분됩니다.

9.3.3. 실시간 프로필에서 NUMA당 하우스키핑 조정

실시간 프로필에서 NUMA 노드당 하우스키핑 CPU 세트를 조정할 수 있습니다. 이렇게 하면 하우스키핑 작업이 NUMA 노드에 균등하게 분배되도록 하여 시스템의 성능이 최적화됩니다.

이 기능은 여러 NUMA 노드가 있는 시스템에 특히 유용합니다. 경합을 줄이고 전반적인 성능을 개선하는 데 도움이 되기 때문입니다.

기본 실시간 tuned 프로필은 NUMA 노드당 하나의 하우스키핑 CPU를 예약합니다(hk_per_numa=1). 컨테이너 워크로드에 사용 가능한 CPU가 더 필요한 경우 이 동작을 수정할 수 있습니다.

사전 요구 사항

  • 호스트 시스템은 Red Hat Enterprise Linux 버전 9.6 이상에서 실행되고 있습니다.
  • tuned 서비스가 실행 중입니다.
  • rteval 컨테이너가 설치되어 실행 중입니다.
  • podman 서비스가 실행 중입니다.
  • tuned-profiles-realtime 패키지가 설치됩니다.

프로세스

  1. realtime-variables.conf 파일을 수정하여 NUMA 노드별로 하우스키핑 CPU 세트를 조정합니다.

    • 텍스트 편집기에서 /etc/tuned 에 있는 realtime-variables.conf 파일을 엽니다.

      $ sudo vi /etc/tuned/realtime-variables.conf
    • isolated_cores 변수를 찾습니다. 기본적으로 이 값은 1 로 설정됩니다. 즉, NUMA 노드당 하나의 코어가 격리된 또는 비하우스키핑 사용을 위해 예약되어 있습니다. 이 값을 늘릴 수 있지만 NUMA 노드당 총 CPU 수보다 작아야 합니다.

      다음 예제에서는 NUMA 노드당 24개의 코어가 있는 시스템에서 isolated_cores3 으로 설정합니다.

      isolated_cores=${f:calc_isolated_cores:3}
  2. 변경 사항을 저장하고 파일을 닫습니다.
  3. tuned 실시간 프로필을 다시 적용합니다.

    $ sudo tuned-adm profile realtime

이로 인해 테스트 중에 총 6개의 CPU( NUMA 노드당)가 생성되는 반면, 시스템은 isolcpus 세트의 나머지 코어를 예약합니다. 이 구성은 측정에 사용됩니다. 혼합된 우선 순위 구성은 isolcpus 세트 대신 사용자 정의 토폴로지에 컨테이너를 배포할 수 있습니다.

또는 자동 노드 수를 사용하는 대신 사용자 지정 CPU 범위를 수동으로 지정할 수 있습니다. 이렇게 하면 분리된 코어를 완벽하게 제어할 수 있으므로 비균형 토폴로지 또는 특수 CPU 레이아웃으로 시스템을 미세 조정할 수 있습니다.

검증

  1. realtime-variables.conf 파일의 변경 사항을 확인합니다.
  2. 시스템을 재부팅하여 변경 사항을 적용합니다.
  3. /proc/cmdline 파일을 보고 isolcpus 설정을 확인합니다.

    $ cat /proc/cmdline
    BOOT_IMAGE=(hd0,gpt2)/vmlinuz-5.XX.X-XX.X.X.el9_6.x86_64+rt root=/dev/mapper/rhel_rt--qe--11-root ro  crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=UUID=00cbf36d-ffaa-4285-a381-5c1d868eb3e3 rd.lvm.lv=rhel_rt-qe-11/root rd.lvm.lv=rhel_rt-qe-11/swap console=ttyS0,115200n81 skew_tick=1 tsc=reliable rcupdate.rcu_normal_after_boot=1 isolcpus=managed_irq,domain,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 intel_pstate=disable nosoftlockup

9.3.4. 분리된 CPU에서 여러 컨테이너 분배

분리된 CPU에서 여러 컨테이너를 실행하려면 --cpuset-cpus 옵션을 사용하여 각 컨테이너에서 사용할 CPU를 지정할 수 있습니다. 이렇게 하면 여러 개의 격리된 CPU에 걸쳐 부하를 분할하여 성능을 개선하고 경합을 줄일 수 있습니다.

여러 컨테이너에 설정된 isolcpus 세트를 시뮬레이션하여 다음 작업을 시뮬레이션할 수 있습니다.

  • 동시 대기 시간에 민감한 작업입니다.
  • 분할된 시스템 전반에 걸쳐 여러 로드가 발생합니다.
9.3.4.1. 동시 대기 시간에 민감한 작업 시뮬레이션

동시 대기 시간에 민감한 작업을 시뮬레이션하기 위해 각 컨테이너에 특정 격리된 CPU를 할당할 수 있습니다. 다음 예제에서는 다른 CPU 세트에서 컨테이너를 구성하고 실행하는 방법을 보여줍니다.

CPU 0-6, 다른 하나는 CPU 7-28, CPU 29-47에서 세 번째 컨테이너를 실행합니다. 다음 명령을 사용합니다.

$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 0-6 registry.redhat.io/rhel10/rteval \
    /bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 0-6'
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 7-28 registry.redhat.io/rhel10/rteval \
    /bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 7-28'
$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 29-47 registry.redhat.io/rhel10/rteval \
    /bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 29-47'
9.3.4.2. 분할된 시스템에서 여러 로드 시뮬레이션

격리되지 않은 CPU 세트에서 rteval 로드 생성기를 시작합니다. 다음으로 isolcpus 세트의 일부에서 고속 데이터베이스 컨테이너와 같은 처리량이 높은 애플리케이션을 시뮬레이션합니다. 이 예에서 CPU 7-28은 고속 데이터베이스 컨테이너를 나타내는 데 사용됩니다. 별도의 터미널 세션에서 다음 명령을 실행하여 부하를 시작합니다.

$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 0-6 registry.redhat.io/rhel10/rteval \
    /bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 0-6'

그런 다음 별도의 터미널에서 분리된 CPU의 하위 집합에서 일부 부하를 생성합니다.

$ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 20-30 registry.redhat.io/rhel10/rteval \
    /bin/bash -c 'rteval --duration 2h --onlyload --loads-cpulist 20-30'

이제 나머지 CPU에서 측정 스레드를 실행하려면 다음 두 가지 옵션이 있습니다. 분리된 CPU의 나머지 두 하위 집합을 배포하여 컨테이너를 분리하거나 나머지 CPU 하위 집합을 모두 활용하는 단일 측정 컨테이너를 실행할 수 있습니다.

  • 옵션 1: 두 개의 측정 컨테이너 배포

    $ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 7-19 registry.redhat.io/rhel10/rteval \
        /bin/bash -c 'rteval --duration 2h --noload --measurement-cpulist 7-19'
    $ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 31-47 registry.redhat.io/rhel10/rteval \
        /bin/bash -c 'rteval --duration 2h --noload --measurement-cpulist 31-47'
  • 옵션 2: 단일 측정 컨테이너 배포

    $ podman run -it --rm --privileged --pids-limit=0 --cpuset-cpus 7-19,31-47 registry.redhat.io/rhel10/rteval \
        /bin/bash -c 'rteval --duration 2h --noload --measurement-cpulist 7-19,31-47'

10장. cgroupfs를 사용하여 cgroup을 수동으로 관리

cgroup fs 가상 파일 시스템에 디렉터리를 생성하여 시스템에서 cgroup 계층 구조를 관리할 수 있습니다. 파일 시스템은 기본적으로 /sys/fs/cgroup/ 디렉터리에 마운트되며 전용 제어 파일에서 원하는 구성을 지정할 수 있습니다.

중요

일반적으로 Red Hat은 시스템 리소스 사용을 제어하는 데 systemd 를 사용하는 것이 좋습니다. 특별한 경우에만 cgroups 가상 파일 시스템을 수동으로 구성해야 합니다. 예를 들어 cgroup-v2 계층에 동등한 항목이 없는 cgroup-v1 컨트롤러를 사용해야 하는 경우입니다.

10.1. cgroup 생성 및 cgroups-v2 파일 시스템에서 컨트롤러 활성화

디렉터리를 생성하거나 제거하고cgroups가상 파일 시스템의 파일에 작성하여 제어 그룹 ( cgroup )을 관리할 수 있습니다. 파일 시스템은 기본적으로 /sys/fs/cgroup/ 디렉터리에 마운트됩니다. cgroup 컨트롤러의 설정을 사용하려면 하위 cgroup 에 필요한 컨트롤러도 활성화해야 합니다. 기본적으로 root cgroup 에는 하위 cgroup 에 대해 메모리 pid 컨트롤러가 활성화되어 있습니다. 따라서 /sys/fs/cgroup/ root cgroup 내에 하위 cgroup 의 두 개 이상을 생성해야 합니다. 이렇게 하면 선택적으로 하위 cgroup에서 메모리 pid 컨트롤러를 제거하고 cgroup 파일을 보다 명확하게 이해할 수 있습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. /sys/fs/cgroup/Example/ 디렉터리를 생성합니다.

    # mkdir /sys/fs/cgroup/Example/

    /sys/fs/cgroup/Example/ 디렉터리는 하위 그룹을 정의합니다. /sys/fs/cgroup/Example/ 디렉터리를 생성하면 일부 cgroups-v2 인터페이스 파일이 디렉터리에 자동으로 생성됩니다. /sys/fs/cgroup/Example/ 디렉터리에는 메모리 및 pid 컨트롤러에 대한 컨트롤러별 파일도 포함되어 있습니다.

  2. 선택 사항: 새로 생성된 하위 제어 그룹을 검사합니다.

    # ll /sys/fs/cgroup/Example/
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cgroup.controllers
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cgroup.events
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.freeze
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.procs
    …​
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.subtree_control
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 memory.events.local
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 memory.high
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 memory.low
    …​
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 pids.current
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 pids.events
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 pids.max

    예제 출력은 cgroup.procs 또는 cgroup.controllers 와 같은 일반적인 cgroup 제어 인터페이스 파일을 보여줍니다. 이러한 파일은 활성화된 컨트롤러에 관계없이 모든 제어 그룹에 공통입니다.

    memory.highpids.max 와 같은 파일은 루트 제어 그룹(/sys/fs/cgroup/)에 있는 메모리pids 컨트롤러와 관련이 있으며 systemd 에 의해 기본적으로 활성화됩니다.

    기본적으로 새로 생성된 하위 그룹은 상위 cgroup 의 모든 설정을 상속합니다. 이 경우 루트 cgroup 의 제한이 없습니다.

  3. 필요한 컨트롤러를 /sys/fs/cgroup/cgroup.controllers 파일에서 사용할 수 있는지 확인합니다.

    # cat /sys/fs/cgroup/cgroup.controllers
    cpuset cpu io memory hugetlb pids rdma
  4. 필요한 컨트롤러를 활성화합니다. 이 예에서는 cpucpuset 컨트롤러입니다.

    # echo "+cpu" >> /sys/fs/cgroup/cgroup.subtree_control
    # echo "+cpuset" >> /sys/fs/cgroup/cgroup.subtree_control

    이러한 명령은 /sys/fs/cgroup/ root 제어 그룹의 즉시 하위 그룹에 대해 cpucpuset 컨트롤러를 활성화합니다. 새로 생성된 예제 제어 그룹 포함. 하위 그룹은 기준을 기반으로 프로세스를 지정하고 각 프로세스에 제어 검사를 적용할 수 있는 위치입니다.

    사용자는 모든 수준에서 cgroup.subtree_control 파일의 내용을 읽고 즉시 하위 그룹에서 활성화에 사용할 수 있는 컨트롤러를 파악할 수 있습니다.

    참고

    기본적으로 루트 제어 그룹의 /sys/fs/cgroup/cgroup.subtree_control 파일에는 메모리pids 컨트롤러가 포함되어 있습니다.

  5. 예제 제어 그룹의 하위 cgroup 에 필요한 컨트롤러를 활성화합니다.

    # echo "+cpu +cpuset" >> /sys/fs/cgroup/Example/cgroup.subtree_control

    이 명령을 사용하면 즉시 하위 제어 그룹에 메모리 또는 pid 컨트롤러가 아닌 CPU 시간 분배를 규제하는 컨트롤러 사용할 있습니다.

  6. /sys/fs/cgroup/Example/tasks/ 디렉터리를 생성합니다.

    # mkdir /sys/fs/cgroup/Example/tasks/

    /sys/fs/cgroup/Example/tasks/ 디렉터리는 cpucpuset 컨트롤러와 순전히 관련된 파일이 있는 하위 그룹을 정의합니다. 이제 이 제어 그룹에 프로세스를 할당하고 프로세스에 cpucpuset 컨트롤러 옵션을 사용할 수 있습니다.

  7. 선택 사항: 하위 제어 그룹을 검사합니다.

    # ll /sys/fs/cgroup/Example/tasks
    -r—​r—​r--. 1 root root 0 Jun  1 11:45 cgroup.controllers
    -r—​r—​r--. 1 root root 0 Jun  1 11:45 cgroup.events
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cgroup.freeze
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cgroup.max.depth
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cgroup.max.descendants
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cgroup.procs
    -r—​r—​r--. 1 root root 0 Jun  1 11:45 cgroup.stat
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cgroup.subtree_control
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cgroup.threads
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cgroup.type
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cpu.max
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cpu.pressure
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cpuset.cpus
    -r—​r—​r--. 1 root root 0 Jun  1 11:45 cpuset.cpus.effective
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cpuset.cpus.partition
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cpuset.mems
    -r—​r—​r--. 1 root root 0 Jun  1 11:45 cpuset.mems.effective
    -r—​r—​r--. 1 root root 0 Jun  1 11:45 cpu.stat
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cpu.weight
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 cpu.weight.nice
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 io.pressure
    -rw-r—​r--. 1 root root 0 Jun  1 11:45 memory.pressure
중요

cpu 컨트롤러는 관련 하위 제어 그룹에 단일 CPU에서 시간 동안 경쟁하는 프로세스가 2개 이상인 경우에만 활성화됩니다.

검증

  • 선택 사항: 필요한 컨트롤러만 활성화된 새 cgroup 을 생성했는지 확인합니다.

    # cat /sys/fs/cgroup/Example/tasks/cgroup.controllers
    cpuset cpu

10.2. CPU 가중치를 조정하여 애플리케이션의 CPU 시간 분배 제어

cpu 컨트롤러의 관련 파일에 값을 할당하여 특정 cgroup 트리 아래의 애플리케이션에 CPU 시간 배포를 규제해야 합니다.

사전 요구 사항

  • root 권한이 있습니다.
  • CPU 시간 배포를 제어하려는 애플리케이션이 있습니다.
  • 다음 예제와 같이 /sys/fs/cgroup/ root 제어 그룹 내에 하위 제어 그룹의 두 수준 계층 구조를 생성했습니다.

    …​
      ├── Example
      │   ├── g1
      │   ├── g2
      │   └── g3
    …​

프로세스

  1. 제어 그룹 내에서 리소스 제한을 달성하도록 원하는 CPU 가중치를 구성합니다.

    # echo "150" > /sys/fs/cgroup/Example/g1/cpu.weight
    # echo "100" > /sys/fs/cgroup/Example/g2/cpu.weight
    # echo "50" > /sys/fs/cgroup/Example/g3/cpu.weight
  2. 애플리케이션의 PID를 g1,g2, g3 하위 그룹에 추가합니다.

    # echo "33373" > /sys/fs/cgroup/Example/g1/cgroup.procs
    # echo "33374" > /sys/fs/cgroup/Example/g2/cgroup.procs
    # echo "33377" > /sys/fs/cgroup/Example/g3/cgroup.procs

    예제 명령은 원하는 애플리케이션이 Example/g*/ 하위 cgroups의 멤버가 되도록 하며 해당 cgroup 구성에 따라 CPU 시간을 배포합니다.

    실행 중인 프로세스가 있는 하위 cgroup의 가중치(g1,g2,g3)는 상위 cgroup 수준()으로 요약됩니다. 그러면 CPU 리소스가 해당 가중치에 따라 비례적으로 배포됩니다.

    결과적으로 모든 프로세스가 동시에 실행되면 커널은 해당 cgroup의 cpu.weight 파일을 기반으로 비례 CPU 시간을 각각 할당합니다.

    Expand
    하위 cgroupcpu.weight 파일CPU 시간 할당

    g1

    150

    ~50% (150/300)

    g2

    100

    ~33% (100/300)

    g3

    50

    ~16% (50/300)

    cpu.weight 컨트롤러 파일의 값은 백분율이 아닙니다.

    하나의 프로세스가 실행을 중단하고 cgroup g2 를 실행 중인 프로세스 없이 그대로 두면 계산에서 cgroup g2 g 3 의 계정 가중치만 생략합니다.

    Expand
    하위 cgroupcpu.weight 파일CPU 시간 할당

    g1

    150

    ~75% (150/200)

    g3

    50

    ~25% (50/200)

    중요

    하위 cgroup에 실행 중인 프로세스가 여러 개 있는 경우 cgroup에 할당된 CPU 시간이 멤버 프로세스 간에 균등하게 배포됩니다.

검증

  1. 애플리케이션이 지정된 제어 그룹에서 실행되는지 확인합니다.

    # cat /proc/33373/cgroup /proc/33374/cgroup /proc/33377/cgroup
    0::/Example/g1
    0::/Example/g2
    0::/Example/g3

    명령 출력에는 Example/g*/ 하위 cgroup에서 실행되는 지정된 애플리케이션의 프로세스가 표시됩니다.

  2. 제한된 애플리케이션의 현재 CPU 사용을 검사합니다.

    # top
    top - 05:17:18 up 1 day, 18:25,  1 user,  load average: 3.03, 3.03, 3.00
    Tasks:  95 total,   4 running,  91 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 18.1 us, 81.6 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.3 hi,  0.0 si,  0.0 st
    MiB Mem :   3737.0 total,   3233.7 free,    132.8 used,    370.5 buff/cache
    MiB Swap:   4060.0 total,   4060.0 free,      0.0 used.   3373.1 avail Mem
    
        PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
      33373 root      20   0   18720   1748   1460 R  49.5   0.0 415:05.87 sha1sum
      33374 root      20   0   18720   1756   1464 R  32.9   0.0 412:58.33 sha1sum
      33377 root      20   0   18720   1860   1568 R  16.3   0.0 411:03.12 sha1sum
        760 root      20   0  416620  28540  15296 S   0.3   0.7   0:10.23 tuned
          1 root      20   0  186328  14108   9484 S   0.0   0.4   0:02.00 systemd
          2 root      20   0       0      0      0 S   0.0   0.0   0:00.01 kthread
    ...
    참고

    모든 프로세스는 명확한 설명을 위해 단일 CPU에서 실행됩니다. CPU weight는 여러 CPU에서 사용할 때 동일한 원칙을 적용합니다.

    PID 33373,PID 33374PID 33377 의 CPU 리소스가 해당 하위 cgroup에 할당한 150, 100 및 50 개의 가중치를 기반으로 할당되었습니다. 가중치는 각 애플리케이션에 대해 약 50%, 33%, CPU 시간 할당에 해당합니다.

10.3. cgroups-v1 마운트

부팅 프로세스 중에 RHEL 10은 기본적으로 cgroup-v2 가상 파일 시스템을 마운트합니다. cgroup-v1 기능을 사용하여 애플리케이션의 리소스를 제한하려면 시스템을 수동으로 구성합니다.

참고

커널에서 cgroup-v1cgroup-v2 모두 완전히 활성화됩니다. 커널 관점에서 기본 제어 그룹 버전이 없으며 시작 시 systemd 에 의해 마운트됩니다.

사전 요구 사항

  • root 권한이 있습니다.

프로세스

  1. 시스템 시스템 및 서비스 관리자가 시스템 부팅 중에 기본적으로 cgroups-v1마운트 하도록 시스템을 구성합니다.

    # grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"

    그러면 필요한 커널 명령줄 매개변수가 현재 부팅 항목에 추가됩니다.

    모든 커널 부팅 항목에 동일한 매개변수를 추가하려면 다음을 수행합니다.

    # grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"
  2. 변경 사항을 적용하려면 시스템을 재부팅합니다.

검증

  1. cgroups-v1 파일 시스템이 마운트되었는지 확인합니다.

    # mount -l | grep cgroup
    tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,seclabel,size=4096k,nr_inodes=1024,mode=755,inode64)
    cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
    cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event)
    cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpu,cpuacct)
    cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids)
    cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset)
    cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_cls,net_prio)
    cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb)
    cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory)
    cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio)
    cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices)
    cgroup on /sys/fs/cgroup/misc type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,misc)
    cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer)
    cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,rdma)

    다양한 cgroup-v1 컨트롤러에 해당하는 cgroups-v1 파일 시스템이 /sys/fs/cgroup/ 디렉터리에 성공적으로 마운트되었습니다.

  2. /sys/fs/cgroup/ 디렉터리의 콘텐츠를 검사합니다.

    # ll /sys/fs/cgroup/
    dr-xr-xr-x. 10 root root  0 Mar 16 09:34 blkio
    lrwxrwxrwx.  1 root root 11 Mar 16 09:34 cpu → cpu,cpuacct
    lrwxrwxrwx.  1 root root 11 Mar 16 09:34 cpuacct → cpu,cpuacct
    dr-xr-xr-x. 10 root root  0 Mar 16 09:34 cpu,cpuacct
    dr-xr-xr-x.  2 root root  0 Mar 16 09:34 cpuset
    dr-xr-xr-x. 10 root root  0 Mar 16 09:34 devices
    dr-xr-xr-x.  2 root root  0 Mar 16 09:34 freezer
    dr-xr-xr-x.  2 root root  0 Mar 16 09:34 hugetlb
    dr-xr-xr-x. 10 root root  0 Mar 16 09:34 memory
    dr-xr-xr-x.  2 root root  0 Mar 16 09:34 misc
    lrwxrwxrwx.  1 root root 16 Mar 16 09:34 net_cls → net_cls,net_prio
    dr-xr-xr-x.  2 root root  0 Mar 16 09:34 net_cls,net_prio
    lrwxrwxrwx.  1 root root 16 Mar 16 09:34 net_prio → net_cls,net_prio
    dr-xr-xr-x.  2 root root  0 Mar 16 09:34 perf_event
    dr-xr-xr-x. 10 root root  0 Mar 16 09:34 pids
    dr-xr-xr-x.  2 root root  0 Mar 16 09:34 rdma
    dr-xr-xr-x. 11 root root  0 Mar 16 09:34 systemd

    기본적으로 루트 제어 그룹이라고도 하는 /sys/fs/cgroup / 디렉터리에 cpuset 과 같은 컨트롤러별 디렉터리가 포함되어 있습니다. 또한 systemd 와 관련된 일부 디렉터리도 있습니다.

10.4. cgroups-v1을 사용하여 애플리케이션에 대한 CPU 제한 설정

제어 그룹 버전 1 (cgroups-v1)을 사용하여 애플리케이션에 대한 CPU 제한을 구성하려면 /sys/fs/ 가상 파일 시스템을 사용합니다.

사전 요구 사항

  • root 권한이 있습니다.
  • 시스템에 설치된 CPU 사용을 제한하는 애플리케이션이 있습니다.

프로세스

  1. CPU 소비에서 제한하려는 애플리케이션의 PID(프로세스 ID)를 식별합니다.

    # top
    top - 11:34:09 up 11 min,  1 user,  load average: 0.51, 0.27, 0.22
    Tasks: 267 total,   3 running, 264 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 49.0 us,  3.3 sy,  0.0 ni, 47.5 id,  0.0 wa,  0.2 hi,  0.0 si,  0.0 st
    MiB Mem :   1826.8 total,    303.4 free,   1046.8 used,    476.5 buff/cache
    MiB Swap:   1536.0 total,   1396.0 free,    140.0 used.    616.4 avail Mem
    
      PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     6955 root      20   0  228440   1752   1472 R  99.3   0.1   0:32.71 sha1sum
     5760 jdoe      20   0 3603868 205188  64196 S   3.7  11.0   0:17.19 gnome-shell
     6448 jdoe      20   0  743648  30640  19488 S   0.7   1.6   0:02.73 gnome-terminal-
        1 root      20   0  245300   6568   4116 S   0.3   0.4   0:01.87 systemd
      505 root      20   0       0      0      0 I   0.3   0.0   0:00.75 kworker/u4:4-events_unbound
    ...

    PID 6955 가 있는 sha1sum 예제 애플리케이션은 많은 양의 CPU 리소스를 사용합니다.

  2. cpu 리소스 컨트롤러 디렉터리에 하위 디렉터리를 생성합니다.

    # mkdir /sys/fs/cgroup/cpu/Example/

    이 디렉터리는 특정 프로세스를 배치하고 프로세스에 특정 CPU 제한을 적용할 수 있는 제어 그룹을 나타냅니다. 동시에 여러 cgroups-v1 인터페이스 파일과 cpu 컨트롤러별 파일이 디렉터리에 생성됩니다.

  3. 선택 사항: 새로 생성된 제어 그룹을 검사합니다.

    # ll /sys/fs/cgroup/cpu/Example/
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cgroup.clone_children
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cgroup.procs
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.stat
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_all
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu_sys
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu_user
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_sys
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_user
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.cfs_period_us
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.cfs_quota_us
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.rt_period_us
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.rt_runtime_us
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.shares
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpu.stat
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 notify_on_release
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 tasks

    cpuacct.usage,cpu.cfs._period_us 와 같은 파일은 예제 제어 그룹의 프로세스에 대해 설정할 수 있는 특정 구성 및/또는 제한을 나타냅니다. 파일 이름 앞에는 자신이 속한 제어 그룹 컨트롤러의 이름이 접두어 있습니다.

    기본적으로 새로 생성된 제어 그룹은 제한 없이 시스템의 전체 CPU 리소스에 대한 액세스를 상속합니다.

  4. 제어 그룹에 대한 CPU 제한을 구성합니다.

    # echo "1000000" > /sys/fs/cgroup/cpu/Example/cpu.cfs_period_us
    # echo "200000" > /sys/fs/cgroup/cpu/Example/cpu.cfs_quota_us
    • cpu.cfs_period_us 파일은 CPU 리소스에 대한 제어 그룹의 액세스를 다시 할당해야 하는 빈도를 나타냅니다. 기간은 마이크로초(microsecondss, "us")입니다. 상한은 1 000 000 마이크로초이며 더 낮은 제한은 1000 마이크로초입니다.
    • cpu.cfs_quota_us 파일은 cpu.cfs_period_us 에서 정의한 대로 제어 그룹의 모든 프로세스가 한 기간 동안 집합적으로 실행할 수 있는 마이크로초 단위로 총 시간을 나타냅니다. 제어 그룹의 프로세스에서 단일 기간 동안 할당량에 의해 지정된 모든 시간을 사용하는 경우 나머지 기간 동안 제한되며 다음 기간까지 실행할 수 없습니다. 낮은 제한은 1000 마이크로초입니다.

      위의 예제 명령은 CPU 시간 제한을 설정하여 Example 제어 그룹의 모든 프로세스가 1초( cpu.cfs_quota_us로 정의됨) 1초( cpu.cfs_period_us로 정의됨) 동안 0.2초 동안만 실행할 수 있도록 CPU 시간 제한을 설정합니다.

  5. 선택 사항: 제한 확인:

    # cat /sys/fs/cgroup/cpu/Example/cpu.cfs_period_us /sys/fs/cgroup/cpu/Example/cpu.cfs_quota_us
    1000000
    200000
  6. 애플리케이션의 PID를 Example 제어 그룹에 추가합니다.

    # echo "6955" > /sys/fs/cgroup/cpu/Example/cgroup.procs

    이 명령을 수행하면 특정 애플리케이션이 Example 제어 그룹의 멤버가 되고 Example 제어 그룹에 구성된 CPU 제한을 초과하지 않습니다. PID는 시스템의 기존 프로세스를 표현해야 합니다. 여기에 PID 6955sha1sum /dev/zero & amp; process에 할당되었으며 cpu 컨트롤러의 사용 사례를 설명합니다.

검증

  1. 애플리케이션이 지정된 제어 그룹에서 실행되는지 확인합니다.

    # cat /proc/6955/cgroup
    12:cpuset:/
    11:hugetlb:/
    10:net_cls,net_prio:/
    9:memory:/user.slice/user-1000.slice/user@1000.service
    8:devices:/user.slice
    7:blkio:/
    6:freezer:/
    5:rdma:/
    4:pids:/user.slice/user-1000.slice/user@1000.service
    3:perf_event:/
    2:cpu,cpuacct:/Example
    1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service

    애플리케이션의 프로세스는 애플리케이션의 프로세스에 CPU 제한을 적용하는 예제 제어 그룹에서 실행됩니다.

  2. 제한된 애플리케이션의 현재 CPU 사용을 확인합니다.

    # top
    top - 12:28:42 up  1:06,  1 user,  load average: 1.02, 1.02, 1.00
    Tasks: 266 total,   6 running, 260 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 11.0 us,  1.2 sy,  0.0 ni, 87.5 id,  0.0 wa,  0.2 hi,  0.0 si,  0.2 st
    MiB Mem :   1826.8 total,    287.1 free,   1054.4 used,    485.3 buff/cache
    MiB Swap:   1536.0 total,   1396.7 free,    139.2 used.    608.3 avail Mem
    
      PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     6955 root      20   0  228440   1752   1472 R  20.6   0.1  47:11.43 sha1sum
     5760 jdoe      20   0 3604956 208832  65316 R   2.3  11.2   0:43.50 gnome-shell
     6448 jdoe      20   0  743836  31736  19488 S   0.7   1.7   0:08.25 gnome-terminal-
      505 root      20   0       0      0      0 I   0.3   0.0   0:03.39 kworker/u4:4-events_unbound
     4217 root      20   0   74192   1612   1320 S   0.3   0.1   0:01.19 spice-vdagentd
    ...

    PID 6955 의 CPU 사용량이 99 %에서 20%로 감소했습니다.

참고

cpu.cfs_period_uscpu.cfs_quota_uscgroups-v2 카운터는 cpu.max 파일입니다. cpu.max 파일은 cpu 컨트롤러를 통해 사용할 수 있습니다.

제어 그룹(cgroup) 커널 기능을 사용하면 애플리케이션의 리소스 사용량을 제어하여 보다 효율적으로 사용할 수 있습니다.

다음 작업에 cgroup 을 사용할 수 있습니다.

  • 시스템 리소스 할당에 대한 제한 설정.
  • 특정 프로세스에 대한 하드웨어 리소스 할당 우선 순위를 지정합니다.
  • 특정 프로세스에서 하드웨어 리소스를 가져오지 못하도록 격리합니다.

10.5. 제어 그룹 소개

제어 그룹 Linux 커널 기능을 사용하여 프로세스를 계층적으로 정렬된 그룹인 cgroup 으로 구성할 수 있습니다. /sys/fs/cgroup/ 디렉터리에 기본적으로 마운트된 cgroups 가상 파일 시스템에 구조를 제공하여 계층 구조(제어 그룹 트리)를 정의합니다.

systemd 서비스 관리자는 cgroup 을 사용하여 관리하는 모든 장치 및 서비스를 구성합니다. 수동으로 /sys/fs/cgroup/ 디렉터리에 하위 디렉터리를 생성하고 제거하여 cgroup 의 계층 구조를 관리할 수 있습니다.

그런 다음 커널의 리소스 컨트롤러는 해당 프로세스의 시스템 리소스를 제한, 우선 지정 또는 할당하여 cgroup 의 프로세스 동작을 수정합니다. 이러한 리소스에는 다음이 포함됩니다.

  • CPU 시간
  • 메모리
  • 네트워크 대역폭
  • 이러한 리소스의 조합

cgroup 의 주요 사용 사례는 시스템 프로세스를 집계하고 애플리케이션 및 사용자 간에 하드웨어 리소스를 분할하는 것입니다. 이를 통해 환경의 효율성, 안정성 및 보안을 강화할 수 있습니다.

제어 그룹 버전 1

제어 그룹 버전 1 (cgroups-v1)은 리소스별 컨트롤러 계층 구조를 제공합니다. CPU, 메모리 또는 I/O와 같은 각 리소스에는 자체 제어 그룹 계층 구조가 있습니다. 하나의 컨트롤러에서 각각의 리소스를 관리할 때 다른 컨트롤러와 조정할 수 있는 방식으로 서로 다른 제어 그룹 계층 구조를 결합할 수 있습니다. 그러나 두 컨트롤러가 서로 다른 프로세스 계층에 속하는 경우 조정이 제한됩니다.

cgroups-v1 컨트롤러는 많은 기간 동안 개발되어 제어 파일의 동작과 이름이 일치하지 않습니다.

제어 그룹 버전 2

제어 그룹 버전 2 (cgroups-v2)는 모든 리소스 컨트롤러가 마운트된 단일 제어 그룹 계층 구조를 제공합니다.

제어 파일 동작 및 이름 지정은 서로 다른 컨트롤러 간에 일관되게 유지됩니다.

10.6. 커널 리소스 컨트롤러 소개

커널 리소스 컨트롤러를 사용하면 제어 그룹의 기능을 사용할 수 있습니다. RHEL 10에서는 제어 그룹 버전 1 (cgroups-v1) 및 제어 그룹 버전 2(cgroups-v2 )에 대한 다양한 컨트롤러를 지원합니다.

제어 그룹 하위 시스템이라고도 하는 리소스 컨트롤러는 CPU 시간, 메모리, 네트워크 대역폭 또는 디스크 I/O와 같은 단일 리소스를 나타내는 커널 하위 시스템입니다. Linux 커널은 systemd 서비스 관리자가 자동으로 마운트하는 다양한 리소스 컨트롤러를 제공합니다. 현재 마운트된 리소스 컨트롤러 목록은 /proc/cgroups 파일에서 찾을 수 있습니다.

cgroups-v1 에서 사용 가능한 컨트롤러:

blkio
블록 장치에 대한 입력/출력 액세스 제한을 설정합니다.
cpu
제어 그룹의 작업에 대한 CFS(Completely Fair Scheduler)의 매개변수를 조정합니다. cpu 컨트롤러는 동일한 마운트에 cpuacct 컨트롤러와 함께 마운트됩니다.
cpuacct
제어 그룹의 작업에서 사용하는 CPU 리소스에 대한 자동 보고서를 생성합니다. cpuacct 컨트롤러는 동일한 마운트에 cpu 컨트롤러와 함께 마운트됩니다.
cpuset
CPU의 지정된 하위 집합에서만 실행되도록 제어 그룹 작업을 제한하고 지정된 메모리 노드에서만 메모리를 사용하도록 작업에 지시합니다.
devices
제어 그룹의 작업에 대한 장치에 대한 액세스를 제어합니다.
freezer
제어 그룹에서 작업을 일시 중지하거나 재개합니다.
메모리
제어 그룹의 작업에서 메모리 사용량에 대한 제한을 설정하고 해당 작업에서 사용하는 메모리 리소스에 대한 자동 보고서를 생성합니다.
net_cls
Linux 트래픽 컨트롤러( tc 명령)를 활성화하여 특정 제어 그룹 작업에서 시작된 패킷을 식별하는 클래스 식별자(classid)가 있는 네트워크 패킷을 태그합니다. net_cls 의 하위 시스템인 net_filter (iptables)도 이 태그를 사용하여 이러한 패킷에 대한 작업을 수행할 수 있습니다. net_filter 는 Linux 방화벽에서 특정 제어 그룹 작업에서 시작된 패킷을 식별할 수 있는 방화벽 식별자(fwid)로 네트워크 소켓을 태그합니다( iptables 명령을 사용하여).
net_prio
네트워크 트래픽의 우선 순위를 설정합니다.
pids
컨트롤 그룹에서 여러 프로세스 및 해당 하위 항목에 대한 제한을 설정합니다.
perf_event
perf 성능 모니터링 및 보고 유틸리티를 통한 모니터링을 위한 작업을 그룹화합니다.
rdma
제어 그룹의 Remote Direct Memory Access/InfiniBand 특정 리소스에 대한 제한을 설정합니다.
hugetlb
컨트롤 그룹의 작업별 대규모 가상 메모리 페이지 사용을 제한합니다.

cgroups-v2 에서 사용 가능한 컨트롤러:

io
블록 장치에 대한 입력/출력 액세스 제한을 설정합니다.
메모리
제어 그룹의 작업에서 메모리 사용량에 대한 제한을 설정하고 해당 작업에서 사용하는 메모리 리소스에 대한 자동 보고서를 생성합니다.
pids
컨트롤 그룹에서 여러 프로세스 및 해당 하위 항목에 대한 제한을 설정합니다.
rdma
제어 그룹의 Remote Direct Memory Access/InfiniBand 특정 리소스에 대한 제한을 설정합니다.
cpu
제어 그룹의 작업에 대한 CFS(Completely Fair Scheduler) 매개변수를 조정하고 제어 그룹의 작업에서 사용하는 CPU 리소스에 대한 자동 보고서를 생성합니다.
cpuset
CPU의 지정된 하위 집합에서만 실행되도록 제어 그룹 작업을 제한하고 지정된 메모리 노드에서만 메모리를 사용하도록 작업에 지시합니다. 새 파티션 기능이 있는 코어 기능(cpus{,.effective}, mems{,.effective})만 지원합니다.
perf_event
perf 성능 모니터링 및 보고 유틸리티를 통한 모니터링을 위한 작업을 그룹화합니다. perf_event 는 v2 계층 구조에서 자동으로 활성화됩니다.
중요

리소스 컨트롤러는 cgroups-v1 계층 구조 또는 cgroups-v2 계층에서 동시에 사용할 수 있습니다.

10.7. 네임스페이스 소개

네임스페이스는 소프트웨어 오브젝트 구성 및 식별을 위한 별도의 공간을 생성합니다. 이는 서로 영향을 미치는 것을 방지합니다. 결과적으로 각 소프트웨어 오브젝트에는 동일한 시스템을 공유하더라도 마운트 지점, 네트워크 장치 또는 호스트 이름과 같은 자체 리소스 세트가 포함됩니다.

네임스페이스를 사용하는 가장 일반적인 기술 중 하나는 컨테이너입니다.

특정 글로벌 리소스에 대한 변경 사항은 해당 네임스페이스의 프로세스에만 표시되고 나머지 시스템 또는 기타 네임스페이스에는 영향을 미치지 않습니다.

프로세스가 멤버인 네임스페이스를 검사하려면 /proc/<PID>/ns/ 디렉토리에서 심볼릭 링크를 확인할 수 있습니다.

Expand
표 10.1. 격리할 수 있는 지원되는 네임스페이스 및 리소스:
네임스페이스격리

Mount

마운트 지점

UTS

호스트 이름 및 NIS 도메인 이름

IPC

System V IPC, POSIX 메시지 대기열

PID

프로세스 ID

네트워크

네트워크 장치, 스택, 포트 등

사용자

사용자 및 그룹 ID

제어 그룹

제어 그룹 루트 디렉터리

11장. RHEL for Real Time에서 CPU 선호도 설정

시스템의 모든 스레드 및 인터럽트 소스에는 프로세서 선호도 속성이 있습니다. 운영 체제 스케줄러는 이 정보를 사용하여 CPU에서 실행할 스레드 및 인터럽트를 결정합니다. 효율적인 정책 및 우선 순위 설정과 함께 프로세서 선호도를 설정하면 최대한의 성능을 얻을 수 있습니다. 애플리케이션은 항상 리소스, 특히 CPU 시간, 다른 프로세스와 경쟁합니다. 애플리케이션에 따라 관련 스레드는 종종 동일한 코어에서 실행됩니다. 또는 하나의 애플리케이션 스레드를 하나의 코어에 할당할 수 있습니다.

멀티 태스킹을 수행하는 시스템은 의심의 여지없이 결정적이지 않습니다. 우선 순위가 낮은 애플리케이션이 코드의 중요한 섹션에 있는 동안 우선 순위가 높은 애플리케이션도 실행되지 않을 수 있습니다. 낮은 우선 순위 애플리케이션이 중요 섹션을 종료하면 커널은 낮은 우선 순위 애플리케이션을 안전하게 선점하고 프로세서에서 높은 우선 순위 애플리케이션을 예약합니다. 또한 한 CPU에서 다른 CPU로 프로세스를 마이그레이션하는 것은 캐시 무효화로 인해 비용이 많이 들 수 있습니다. RHEL for Real Time에는 이러한 문제 중 일부를 해결하고 대기 시간을 보다 효과적으로 제어할 수 있는 툴이 포함되어 있습니다.

유사성은 비트 마스크로 표시되며 마스크의 각 비트는 CPU 코어를 나타냅니다. 비트가 1로 설정되면 스레드 또는 인터럽트가 해당 코어에서 실행됩니다. 0인 경우 스레드 또는 인터럽트가 코어에서 실행되지 않습니다. 선호도 비트 마스크의 기본값은 모두이므로 스레드 또는 인터럽트는 시스템의 모든 코어에서 실행될 수 있습니다.

기본적으로 프로세스는 모든 CPU에서 실행할 수 있습니다. 그러나 프로세스의 선호도를 변경하면 사전 결정된 CPU 세트에서 실행되도록 프로세스를 정의할 수 있습니다. 하위 프로세스는 상위 프로세스의 CPU 특성을 상속합니다.

다음과 같은 일반적인 선호도 설정을 설정하면 최대한의 성능을 얻을 수 있습니다.

  • 모든 시스템 프로세스에 단일 CPU 코어를 사용하고 나머지 코어에서 실행되도록 애플리케이션을 설정합니다.
  • 동일한 CPU에서 스레드 애플리케이션 및 네트워크 softirq 또는 드라이버 스레드와 같은 특정 커널 스레드 구성.
  • 각 CPU에서 producer-consumer 스레드를 페어링합니다. 생산자와 소비자는 두 개의 스레드 클래스로, 생산자가 버퍼에 데이터를 삽입하고 사용자가 버퍼에서 데이터를 제거합니다.

실시간 시스템에서 속성을 조정하는 일반적인 방법은 애플리케이션을 실행하는 데 필요한 코어 수를 확인한 다음 해당 코어를 분리하는 것입니다. Tuna 툴 또는 쉘 스크립트를 사용하여 taskset 명령과 같은 비트 마스크 값을 수정할 수 있습니다. taskset 명령은 프로세스의 선호도를 변경하고 /proc/ 파일 시스템 항목을 수정하면 인터럽트의 선호도가 변경됩니다.

11.1. taskset 명령을 사용하여 프로세서 선호도 튜닝

실시간으로 taskset 명령은 실행 중인 프로세스의 CPU 선호도를 설정하거나 검색하는 데 도움이 됩니다. taskset 명령은 -p-c 옵션을 사용합니다. -p 또는 --pid 옵션은 기존 프로세스를 작동하고 새 작업을 시작하지 않습니다. -c 또는 --cpu-list비트마스크 대신 숫자 프로세서 목록을 지정합니다. 목록에는 쉼표로 구분된 두 개 이상의 항목과 프로세서 범위가 포함될 수 있습니다. 예: 0,5,7,9-11.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 특정 프로세스의 프로세스 유사성을 확인하려면 다음을 수행합니다.

    # taskset -p -c 1000
    pid 1000’s current affinity list: 0,1

    이 명령은 PID 1000을 사용하여 프로세스의 선호도를 출력합니다. CPU 0 또는 CPU 1을 사용하도록 프로세스가 설정됩니다.

    • 선택 사항: 프로세스를 바인딩하도록 특정 CPU를 구성하려면 다음을 수행합니다.

      # taskset -p -c 1 1000
      pid 1000’s current affinity list: 0,1
      pid 1000’s new affinity list: 1
    • 선택 사항: 두 개 이상의 CPU 선호도를 정의하려면 다음을 수행합니다.

      # taskset -p -c 0,1 1000
      pid 1000’s current affinity list: 1
      pid 1000’s new affinity list: 0,1
    • 선택 사항: 특정 CPU에서 우선순위 수준 및 정책을 구성하려면 다음을 수행합니다.

      # taskset -c 5 chrt -f 78 /bin/my-app

      세분화를 위해 우선순위와 정책을 지정할 수도 있습니다. 이 예에서 명령은 Cryostat _FIFO 정책 및 우선 순위 값 78을 사용하여 CPU 5에서 /bin/my-app 애플리케이션을 실행합니다.

11.2. sched_setaffinity() 시스템 호출을 사용하여 프로세서 선호도 설정

실시간 sched_setaffinity() 시스템 호출을 사용하여 프로세서 선호도를 설정할 수도 있습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • sched_setaffinity() 를 사용하여 프로세서 선호도를 설정하려면 다음을 수행합니다.

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sched.h>
    
    int main(int argc, char **argv)
    {
      int i, online=0;
      ulong ncores = sysconf(_SC_NPROCESSORS_CONF);
      cpu_set_t *setp = CPU_ALLOC(ncores);
      ulong setsz = CPU_ALLOC_SIZE(ncores);
    
      CPU_ZERO_S(setsz, setp);
    
      if (sched_getaffinity(0, setsz, setp) == -1) {
        perror("sched_getaffinity(2) failed");
        exit(errno);
      }
    
      for (i=0; i < CPU_COUNT_S(setsz, setp); i) {
        if (CPU_ISSET_S(i, setsz, setp))
          online;
      }
    
      printf("%d cores configured, %d cpus allowed in affinity mask\n", ncores, online);
      CPU_FREE(setp);
    }

11.3. 사용량이 높은 작업을 실행하도록 단일 CPU 격리

cpusets 메커니즘을 사용하면 Cryostat _DEADLINE 작업에 대한 CPU 및 메모리 노드 집합을 할당할 수 있습니다. CPU 사용량이 높고 낮은 작업 집합에서 CPU를 격리하여 높은 사용률 작업을 실행하고 다른 CPU 세트에서 작은 사용률 작업을 예약하면 모든 작업이 할당된 런타임 을 충족할 수 있습니다. 'cpusets'에 대한 구성을 수동으로 추가해야 합니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. cluster 및 partition이라는 두 개의 제어 그룹을 생성합니다.

    # cd /sys/fs/cgroup
    # echo +cpuset > cgroup.subtree_control
    # mkdir cluster
    # mkdir partition
    # echo +cpuset | tee cluster/cgroup.subtree_control partition/cgroup.subtree_control
  2. 클러스터 제어 그룹에서 CPU 1에서 7까지 실행하도록 낮은 사용률 작업을 예약합니다. 메모리 크기 및 이름 제어 그룹을 독점적으로 확인합니다.

    # cd cluster
    # echo 1-7 | tee cpuset.cpus cpuset.cpus.exclusive
    # echo root > cpuset.cpus.partition
  3. 모든 낮은 사용률 작업을 클러스터 제어 그룹으로 이동합니다.

    # ps -eLo lwp | while read thread; do echo $thread > cgroup.procs ; done
  4. 파티션 제어 그룹에서 높은 사용률 작업을 할당합니다.

    # echo 0 | tee cpuset.cpus cpuset.cpus.exclusive
    # echo isolated > cpuset.cpus.partition
  5. 파티션 제어 그룹에 쉘을 추가하고 시작합니다.

    # echo $$ > cgroup.procs

    이 설정을 사용하면 파티션 제어 그룹의 작업이 클러스터 제어 그룹의 작업을 방해하지 않습니다. 이를 통해 모든 실시간 작업이 스케줄러 데드라인을 충족할 수 있습니다. 데드라인 스케줄러를 사용하는 경우 일반적으로 이 변경 없이 데드라인이 충족됩니다. 다른 작업에는 고유한 기한이 있습니다.

애플리케이션이 적절한 고정을 사용할 준비가 되면 cgroup을 조정하여 파티션 cgroup에 더 많은 cpus를 할당하고 모든 실시간 작업을 할당할 수 있습니다.

# cd ..
# echo 4-7 | tee cluster/{cpuset.cpus,cpuset.cpus.exclusive}
# echo 0-3 | tee partition/{cpuset.cpus,cpuset.cpus.exclusive}

11.4. CPU 성능 급증 감소

일반적인 대기 시간 급증 소스는 커널 타이머 틱 처리기의 공통 잠금에 여러 CPU가 충돌하는 경우입니다. 경합을 담당하는 일반적인 잠금은 xtime_lock 이며 시간 유지 시스템과 RCU(Read-Copy-Update) 구조 잠금에서 사용됩니다. skew_tick=1 을 사용하면 CPU당 타이머 눈금을 다른 시간에 시작하도록 오프셋하고 잠재적인 잠금 충돌을 방지할 수 있습니다.

skew_tick 커널 명령줄 매개 변수는 대규모 core-count가 있는 대규모 시스템에서 대규모 시스템에 대한 대기 시간이 변동되고 대기 시간에 민감한 워크로드가 있을 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

프로세스

  1. grubby 를 사용하여 skew_tick=1 매개변수를 활성화합니다.

    # grubby --update-kernel=ALL --args="skew_tick=1"
  2. 변경 사항을 적용하려면 재부팅하십시오.

    # reboot
참고

skew_tick=1 을 활성화하면 전력 소비가 크게 증가하므로 대기 시간에 민감한 실시간 워크로드를 실행하고 일관된 대기 시간이 전력 소비에 비해 중요한 고려 사항인 경우에만 skew 부팅 매개변수를 활성화해야 합니다.

검증

/proc/cmdline 파일을 표시하고 skew_tick=1 이 지정되었는지 확인합니다. /proc/cmdline 파일은 커널에 전달된 매개 변수를 표시합니다.

  • /proc/cmdline 파일에서 새 설정을 확인합니다.

    # cat /proc/cmdline

11.5. PC 카드 데몬을 비활성화하여 CPU 사용량 감소

pcscd 데몬은 병렬 통신(PC 또는 PCMCIA) 및 스마트 카드(SC) 리더에 대한 연결을 관리합니다. pcscd 는 일반적으로 우선순위가 낮은 작업이지만 다른 데몬보다 많은 CPU를 사용할 수 있습니다. 따라서, 추가 배경 노이즈는 더 높은 선점 비용을 실시간 작업 및 결정론에 대한 기타 바람직하지 않은 영향을 유발할 수 있습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. pcscd 데몬의 상태를 확인합니다.

    # systemctl status pcscd
    ● pcscd.service - PC/SC Smart Card Daemon
         Loaded: loaded (/usr/lib/systemd/system/pcscd.service; indirect; vendor preset: disabled)
         Active: active (running) since Mon 2021-03-01 17:15:06 IST; 4s ago
    TriggeredBy: ● pcscd.socket
           Docs: man:pcscd(8)
       Main PID: 2504609 (pcscd)
          Tasks: 3 (limit: 18732)
         Memory: 1.1M
            CPU: 24ms
         CGroup: /system.slice/pcscd.service
                 └─2504609 /usr/sbin/pcscd --foreground --auto-exit

    Active 매개변수는 pcsd 데몬의 상태를 표시합니다.

  2. pcsd 데몬이 실행 중인 경우 중지합니다.

    # systemctl stop pcscd
    Warning: Stopping pcscd.service, but it can still be activated by:
      pcscd.socket
  3. 시스템이 부팅될 때 pcsd 데몬이 재시작되지 않도록 시스템을 구성합니다.

    # systemctl disable pcscd
    Removed /etc/systemd/system/sockets.target.wants/pcscd.socket.

검증

  1. pcscd 데몬의 상태를 확인합니다.

    # systemctl status pcscd
    ● pcscd.service - PC/SC Smart Card Daemon
         Loaded: loaded (/usr/lib/systemd/system/pcscd.service; indirect; vendor preset: disabled)
         Active: inactive (dead) since Mon 2021-03-01 17:10:56 IST; 1min 22s ago
    TriggeredBy: ● pcscd.socket
           Docs: man:pcscd(8)
       Main PID: 4494 (code=exited, status=0/SUCCESS)
            CPU: 37ms
  2. Active 매개변수의 값이 비활성(dead) 인지 확인합니다.

12장. RHEL에서 실시간에 mlock() 시스템 호출 사용

RHEL for Real-Time 메모리 잠금(mlock()) 함수를 사용하면 실시간 호출 프로세스가 지정된 주소 공간 범위를 잠그거나 잠금 해제할 수 있습니다. 이 범위는 Linux가 메모리 공간을 스와핑할 때 잠긴 메모리를 페이징하지 못하도록 합니다. 페이지 테이블 항목에 실제 페이지를 할당하면 해당 페이지에 대한 참조가 빨라집니다. mlock() 시스템 호출에는 mlock()mlockall() 의 두 함수가 포함됩니다. 마찬가지로 munlock() 시스템 호출에는 munlock()munlockall() 함수가 포함됩니다.

12.1. mlock() 시스템 호출을 사용하여 페이지를 잠그기

실시간 mlock() 시스템 호출은 addr 매개변수를 사용하여 주소 범위의 시작을 지정하고 len 을 사용하여 주소 공간의 길이를 바이트 단위로 정의합니다. alloc_workbuf() 함수는 메모리 버퍼를 동적으로 할당하고 잠급니다. 메모리 할당은 posix_memalig() 함수에 의해 수행되어 메모리 영역을 페이지에 맞춥니다. function free_workbuf() 는 메모리 영역을 잠금 해제합니다.

사전 요구 사항

  • 큰 버퍼에서 mlockall() 또는 mlock() 을 사용할 수 있는 루트 권한 또는 CAP_IPC_LOCK 기능이 있습니다.

프로세스

  • 다음 코드는 mlock() 시스템 호출을 사용하여 페이지를 잠급니다.

    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/mman.h>
    
    void *alloc_workbuf(size_t size)
    {
      void *ptr;
      int retval;
    
      // alloc memory aligned to a page, to prevent two mlock() in the same page.
      retval = posix_memalign(&ptr, (size_t) sysconf(_SC_PAGESIZE), size);
    
      // return NULL on failure
      if (retval)
        return NULL;
    
      // lock this buffer into RAM
      if (mlock(ptr, size)) {
        free(ptr);
        return NULL;
      }
    
      return ptr;
    }
    
    void free_workbuf(void *ptr, size_t size) {
      // unlock the address range
      munlock(ptr, size);
    
      // free the memory
      free(ptr);
    }

검증

성공 시 실시간 mlock()munlock() 호출은 0을 반환합니다. 오류가 발생하면 -1을 반환하고 오류를 나타내기 위해 errno 를 설정합니다.

12.2. mlockall() 시스템 호출을 사용하여 매핑된 모든 페이지를 잠그기

mlockall() 및 munlockall() 시스템 호출을 사용하여 실시간 메모리를 잠금 및 잠금 해제하려면 플래그 인수를 0 또는 상수 중 하나( MCL_CURRENT 또는 MCL_FUTURE )로 설정합니다. MCL_FUTURE 를 사용하면 mmap(2), sbrk(2) 또는 malloc Cryostat와 같은 향후 시스템 호출이 실패할 수 있습니다. 이는 잠긴 바이트 수가 허용된 최대값을 초과할 수 있기 때문입니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • mlockall()munlockall() 실시간 시스템 호출을 사용하려면 다음을 수행합니다.

    • mlockall() 시스템 호출을 사용하여 매핑된 모든 페이지를 잠급니다.

      #include <sys/mman.h>
      int mlockall (int flags)
    • munlockall() 시스템 호출을 사용하여 매핑된 모든 페이지의 잠금을 해제합니다.

      #include <sys/mman.h>
      int munlockall (void)

12.3. mmap() 시스템 호출을 사용하여 파일 또는 장치를 메모리에 매핑

실시간 시스템에서 대규모 메모리 할당의 경우 메모리 할당(malloc) 메서드는 mmap() 시스템 호출을 사용하여 메모리 공간을 찾습니다. flags 매개변수에서 MAP_LOCKED 를 설정하여 메모리 영역을 할당하고 잠글 수 있습니다. mmap() 은 페이지에 메모리를 할당하므로 동일한 페이지에서 두 개의 잠금을 방지하여 이중 잠금 또는 단일 잠금 문제를 방지합니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 특정 프로세스 주소 공간을 매핑하려면 다음을 수행합니다.

    #include <sys/mman.h>
    #include <stdlib.h>
    
    void *alloc_workbuf(size_t size)
    {
     void *ptr;
    
     ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
                MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, -1, 0);
    
     if (ptr == MAP_FAILED)
      return NULL;
    
     return ptr;
    }
    
    void
    free_workbuf(void *ptr, size_t size)
    {
     munmap(ptr, size);
    }

검증

  • mmap() 함수가 성공적으로 완료되면 매핑된 영역에 대한 포인터를 반환합니다. 오류가 발생하면 MAP_FAILED 값을 반환하고 오류를 나타내는 errno 를 설정합니다.
  • munmap() 함수가 성공적으로 완료되면 0 을 반환합니다. 오류가 발생하면 -1 을 반환하고 오류를 나타내는 errno 를 설정합니다.

12.4. mlock() 시스템 호출 매개 변수

메모리 잠금 시스템 호출 및 수행하는 함수에 대한 매개 변수가 나열되고 mlock 매개변수 테이블에 설명되어 있습니다.

Expand
표 12.1. mlock 매개변수
매개변수설명

addr

잠금 또는 잠금 해제를 위한 프로세스 주소 공간을 지정합니다. NULL인 경우 커널은 메모리에서 페이지 정렬된 데이터 정렬을 선택합니다. addr 가 NULL이 아닌 경우 커널은 항상 위 또는 /proc/sys/vm/mmap_min_addr 파일에 지정된 값과 같은 가까운 페이지 경계를 선택합니다.

Len

매핑 길이는 0보다 커야 합니다.

fd

파일 설명자를 지정합니다.

Prot

mmapmunmap 호출은 이 매개 변수를 사용하여 원하는 메모리 보호를 정의합니다. ProtPROT_EXEC,PROT_READ,PROT_WRITE 또는 PROT_NONE 값의 조합을 사용합니다.

플래그

동일한 파일을 매핑하는 다른 프로세스에 매핑 가시성을 제어합니다. MAP_ANONYMOUS,MAP_LOCKED,MAP_PRIVATE 또는 MAP_SHARED 값 중 하나를 사용합니다.

MCL_CURRENT

현재 프로세스에 매핑된 모든 페이지를 잠급니다.

MCL_FUTURE

후속 메모리 할당을 잠그도록 모드를 설정합니다. 늘어나는 힙 및 스택, 새 메모리 매핑 파일 또는 공유 메모리 영역에 필요한 새 페이지일 수 있습니다.

13장. RHEL for Real Time의 타이머를 사용하여 스케줄링 대기 시간 측정

rtla- timerlat 툴은 타이머 추적기를 위한 인터페이스입니다. 타이머 모음 추적기는 실시간 스레드의 레이닝 대기 시간 소스를 찾습니다. 타이머 내역 추적기는 실시간 우선 순위를 사용하여 CPU당 커널 스레드를 생성하고 이러한 스레드는 주기적인 타이머를 설정하여 잠자기 상태로 돌아갑니다. 슬림에서 타이머는 정보를 찾아서 수집하며 운영 체제 타이머 대기 시간을 디버깅하는 데 유용합니다. timerlat 추적기에서는 출력을 생성하고 모든 활성화 시 다음 두 행을 출력합니다.

  • 타이머 내역 추적기 에서는 타이머 인터럽트 요청(IRQ) 처리기에서 표시되는 타이머 대기 시간을 주기적으로 출력합니다. 스레드 활성화 전에 hardirq 컨텍스트에 표시되는 첫 번째 출력입니다.
  • 두 번째 출력은 스레드의 타이머 대기 시간입니다. ACTIVATION ID 필드는 해당 스레드 실행에 대한 인터럽트 요청(IRQ) 성능을 표시합니다.

13.1. 스케줄링 대기 시간을 측정하도록 타이머lat 추적 프로그램 구성

추적 시스템의 curret_tracer 파일에 timerlat 을 추가하여 타이머 추적기를 구성할 수 있습니다. current_tracer 파일은 일반적으로 /sys/kernel/tracing 디렉터리에 마운트됩니다. 타이머 내역 추적기는 인터럽트 요청(IRQ)을 측정하고 스레드 대기 시간이 100 마이크로초를 초과하면 분석을 위해 추적 출력을 저장합니다.

프로세스

  1. 현재 추적기를 나열합니다.

    # cat /sys/kernel/tracing/current_tracer
    nop

    no operations (nop)는 기본 추적기입니다.

  2. 추적 시스템의 current_tracer 파일에 timerlat 추적기를 추가합니다.

    # cd /sys/kernel/tracing/
    # echo timerlat > current_tracer
  3. 추적 출력을 생성합니다.

    # cat trace
    # tracer: timerlat

검증

  • 다음 명령을 입력하여 타이머 가 현재 추적기로 활성화되어 있는지 확인합니다.

    # cat /sys/kernel/tracing/current_tracer
    timerlat

13.2. 타이머 추적기 옵션

timerlat 추적기는 osnoise tracer 위에 빌드됩니다. 따라서 /osnoise/config 디렉토리에서 옵션을 설정하여 스레드 스케줄링 대기 시간에 대한 정보를 추적하고 캡처할 수 있습니다.

타이머 수준 옵션

CPU
timerlat 스레드가 실행될 CPU를 설정합니다.
timerlat_period_us
timerlat 스레드의 기간 기간을 마이크로초 단위로 설정합니다.
stop_tracing_us
irq 컨텍스트에서 타이머 대기 시간이 구성된 값보다 크면 시스템 추적을 중지합니다. 0을 작성하면 이 옵션이 비활성화됩니다.
stop_tracing_total_us
총 노이즈가 구성된 값보다 큰 경우 시스템 추적을 중지합니다. 0을 작성하면 이 옵션이 비활성화됩니다.
print_stack
인터럽트 요청(IRQ) 발생 스택을 저장합니다. 스택은 스레드 컨텍스트 이벤트 후 또는 IRQs 처리기가 구성된 값보다 많은 경우 IRQs 발생을 저장합니다.

13.3. rtla-timerlat-top로 타이머 대기 시간 측정

rtla-timerlat-top 추적기에는 타이머 추적기 에서 주기적인 출력 요약이 표시됩니다. 추적기 출력은 또한 각 운영 체제의 노이즈 및 이벤트(예: osnoise ) 및 tracepoints 에 대한 정보를 제공합니다. 이 정보는 -t 옵션을 사용하여 볼 수 있습니다.

프로세스

  • 타이머 대기 시간을 측정하려면 다음을 수행합니다.

    # rtla timerlat top -s 30 -T 30 -t

13.4. rtla 타이머lat 최상위 추적기 옵션

rtla timerlat top --help 명령을 사용하면 rtla-timerlat-top 추적기 에 대한 옵션에 대한 도움말 사용법을 볼 수 있습니다.

timerlat-top-tracer 옵션

-p, --period us
timerlat 추적 기간을 마이크로초 단위로 설정합니다.
-i, --irq us
인터럽트 요청(IRQ) 대기 시간이 마이크로초의 인수보다 큰 경우 추적을 중지합니다.
-t, --thread us
스레드 대기 시간이 마이크로초의 인수보다 큰 경우 추적을 중지합니다.
-t, --trace
중지된 추적을 timerlat_trace.txt 파일에 저장합니다.
-s, --stack us
스레드 대기 시간이 인수보다 크면 인터럽트 요청(IRQ)에 스택 추적을 저장합니다.

14장. 실시간 RHEL에서 rtla-osnoise를 사용하여 스케줄링 대기 시간 측정

초고속 대기 시간은 지연에 대한 허용 오차가 낮은 대량의 데이터 패킷을 처리하기 위해 최적화된 환경입니다. CPU를 포함한 애플리케이션에 배타적 리소스를 제공하는 것은 매우 대기 시간이 짧은 환경에서 널리 사용되는 방법입니다. 예를 들어 NFV(네트워크 기능 가상화) 애플리케이션에서 고성능 네트워크 처리의 경우 단일 애플리케이션에는 작업을 지속적으로 실행하도록 CPU 전원 제한이 설정됩니다.

Linux 커널에는 운영 체제 노이즈(osnoise) 추적기에 대한 인터페이스를 제공하는 실시간 분석(rtla) 툴이 포함되어 있습니다. 운영 체제의 노이즈는 운영 체제 내부의 활동으로 인해 애플리케이션에서 발생하는 간섭입니다. Linux 시스템은 다음과 같은 이유로 노이즈가 발생할 수 있습니다.

  • 마스킹할 수 없는 인터럽트(NMI)
  • 인터럽트 요청(IRQs)
  • 소프트 인터럽트 요청(SoftIRQs)
  • 기타 시스템 스레드 활동
  • 마스크 불가능한 높은 우선 순위 시스템 관리 인터럽트(SMI)와 같은 하드웨어 관련 작업

14.1. rtla-osnoise 추적기

Linux 커널에는 운영 체제 노이즈(osnoise) 추적기에 대한 인터페이스를 제공하는 실시간 분석(rtla) 툴이 포함되어 있습니다. rtla-osnoise 추적기에서는 지정된 기간에 대해 주기적으로 실행되는 스레드를 생성합니다. 기간이 시작될 때 스레드는 인터럽트를 비활성화하고 샘플링을 시작하고 루프에서 시간을 캡처합니다.

rtla-osnoise 추적기에서는 다음과 같은 기능을 제공합니다.

  • CPU가 수신하는 작동 노이즈의 양을 측정합니다.
  • CPU에서 발생하는 운영 체제 노이즈 유형을 나타냅니다.
  • 예기치 않은 결과의 근본 원인을 정의하는 데 도움이 되는 최적화된 추적 보고서를 출력합니다.
  • 각 간섭의 소스에 대한 간섭 카운터를 저장합니다. 마스킹할 수 없는 인터럽트(NMI), 인터럽트 요청(IRQ), 소프트웨어 인터럽트 요청(SoftIRQ) 및 스레드에 대한 중단 카운터는 도구가 이러한 방해에 대한 입력 이벤트를 감지하면 증가합니다.

rtla-osnoise 추적기에서는 기간 종료 시 노이즈 소스에 대한 다음 정보가 포함된 실행 보고서를 출력합니다.

  • 총 노이즈량입니다.
  • 최대 노이즈 양입니다.
  • 스레드에 할당된 CPU의 백분율입니다.
  • 노이즈 소스에 대한 카운터입니다.

14.2. 스케줄링 대기 시간을 측정하도록 rtla-osnoise 추적 프로그램 구성

추적 시스템의 curret_tracer 파일에 osnoise 를 추가하여 rtla-osnoise 추적기를 구성할 수 있습니다. current_tracer 파일은 일반적으로 /sys/kernel/tracing/ 디렉터리에 마운트됩니다. rtla-osnoise 추적기에서는 인터럽트 요청(IRQ)을 측정하고 단일 노이즈 발생을 위해 스레드 대기 시간이 20 마이크로초 이상인 경우 분석을 위해 추적 출력을 저장합니다.

프로세스

  1. 현재 추적기를 나열합니다.

    # cat /sys/kernel/tracing/current_tracer
    nop

    no operations (nop)는 기본 추적기입니다.

  2. 추적 시스템의 current_tracer 파일에 timerlat 추적기를 추가합니다.

    # cd /sys/kernel/tracing/
    # echo osnoise > current_tracer
  3. 추적 출력을 생성합니다.

    # cat trace
    # tracer: osnoise

14.3. 구성에 대한 rtla-osnoise 옵션

rtla-osnoise 추적기에 대한 구성 옵션은 /sys/kernel/tracing/ 디렉터리에서 사용할 수 있습니다.

rtla-osnoise의 구성 옵션

osnoise/cpus
osnoise 스레드가 실행될 CPU를 구성합니다.
osnoise/period_us
osnoise 스레드 실행 기간을 구성합니다.
osnoise/runtime_us
osnoise 스레드의 실행 기간을 구성합니다.
osnoise/stop_tracing_us
단일 노이즈가 구성된 값보다 큰 경우 시스템 추적을 중지합니다. 0 을 설정하면 이 옵션이 비활성화됩니다.
osnoise/stop_tracing_total_us
총 노이즈가 구성된 값보다 큰 경우 시스템 추적을 중지합니다. 0 을 설정하면 이 옵션이 비활성화됩니다.
tracing_thresh
마이크로초 단위에서 두 번의 time() 호출 읽기 사이에 최소 delta를 어댑터로 간주하도록 설정합니다. 0 으로 설정하면tracing_thresh 는 기본값인 5마이크로초를 사용합니다.

14.4. rtla-osnoise 추적 지점

rtla-osnoise 에는 운영 체제 노이즈의 소스를 식별하는 일련의 추적 포인트 가 포함되어 있습니다(osnoise).

rtla-osnoise의 추적 포인트

osnoise:sample_threshold
어댑터가 구성된 임계값(tolerance_ns)보다 클 때 노이즈를 표시합니다.
osnoise:nmi_noise
마스킹할 수 없는 인터럽트(NMI)의 노이즈 및 노이즈 기간을 표시합니다.
osnoise:irq_noise
인터럽트 요청(IRQ)에서 노이즈 및 노이즈 기간을 표시합니다.
osnoise:softirq_noise
소프트 인터럽트 요청(SoftIRQ)에서 노이즈 및 노이즈 기간을 표시합니다.
osnoise:thread_noise
스레드에서 노이즈 및 노이즈 기간을 표시합니다.

14.5. rtla-osnoise 추적기 옵션

osnoise/options 파일에는 rtla-osnoise 추적기 대한 설정 옵션 세트가 포함되어 있습니다.

rtla-osnoise옵션

기본값
옵션을 기본값으로 재설정합니다.
OSNOISE_WORKLOAD
osnoise 워크로드 디스패치를 중지합니다.
PANIC_ON_STOP
tracer가 중지되면 panic() 호출을 설정합니다. 이 옵션은 vmcore 덤프 파일을 캡처합니다.
OSNOISE_PREEMPT_DISABLE
인터럽트 요청(IRQ) 및 하드웨어 관련 노이즈만 허용하는 osnoise 워크로드에 대한 선점을 비활성화합니다.
OSNOISE_IRQ_DISABLE
마스킹할 수 없는 인터럽트(NMI) 및 하드웨어 관련 노이즈만 허용하는 osnoise 워크로드에 대한 인터럽트 요청(IRQ)을 비활성화합니다.

14.6. rtla-osnoise-top 추적기를 사용하여 운영 체제 노이즈 측정

rtla osnoise-top tracer는 유해 소스의 발생 카운터에 대한 정보와 함께 osnoise 추적기의 주기적인 요약을 측정하고 출력합니다.

프로세스

  1. 시스템 노이즈 측정:

    # rtla osnoise top -P F:1 -c 0-3 -r 900000 -d 1M -q

    명령 출력은 실시간 우선 순위, 스레드를 실행하도록 할당된 CPU 및 실행 기간(마이크로초)에 대한 정보가 포함된 주기적인 요약을 표시합니다.

14.7. rtla-osnoise-top 추적기 옵션

rtla osnoise top --help 명령을 사용하면 rtla-osnoise-top 추적기에 사용 가능한 옵션에 대한 도움말 사용량을 볼 수 있습니다.

rtla-osnoise-top옵션

-a, --auto us
자동 추적 모드를 설정합니다. 이 모드는 시스템을 디버깅하는 동안 일반적으로 사용되는 몇 가지 옵션을 설정합니다. 이는 -s us -T 1-t 를 사용하는 것과 동일합니다.
-p, --period us
osnoise tracer 기간을 마이크로초 단위로 설정합니다.
-r, --runtime us
osnoise tracer 런타임을 마이크로초 단위로 설정합니다.
-s, --stop us
단일 샘플이 microseconds의 인수보다 큰 경우 추적을 중지합니다. -t 를 사용하면 명령은 추적을 출력에 저장합니다.
-s, --stop-total us
총 샘플이 microseconds의 인수보다 큰 경우 추적을 중지합니다. -T 를 사용하면 명령은 추적을 출력에 저장합니다.
-t, --threshold us
노이즈로 간주되는 두 시간 사이의 최소 delta를 지정합니다. 기본 임계값은 5입니다.
-q, --quiet
실행 끝에 요약만 출력합니다.
-c, --cpus cpu-list
할당된 cpu-list 에서 샘플 스레드를 실행하도록 osnoise 추적 프로그램을 설정합니다.
-d, --duration time[s|m|h|d]
실행 기간을 설정합니다.
-d, --debug
디버그 정보를 출력합니다.
-t, --trace[=file]
중지된 추적을 [file|osnoise_trace.txt] 파일에 저장합니다.
-e, --event sys:event
trace(-t) 세션에서 이벤트를 활성화합니다. 인수는 특정 이벤트(예: -e sched:sched_switch ) 또는 시스템 그룹의 모든 이벤트(예: -e sched 시스템 그룹)일 수 있습니다.
--filter <filter>
필터 표현식을 사용하여 이전 -e sys:event 시스템 이벤트를 필터링합니다.
--trigger <trigger>
이전 -e sys:event 시스템 이벤트에 대한 추적 이벤트 트리거를 활성화합니다.
-p, --priority o:prio|r:prio|f:prio|d:runtime:period
스케줄링 매개 변수를 osnoise 추적r 스레드로 설정합니다.
-h, --help
도움말 메뉴를 출력합니다.

15장. 저널링으로 인한 시스템 속도 저하 최소화 또는 방지

저널 변경 사항이 디스크에 기록되는 순서는 도착 순서와 다를 수 있습니다. 커널 I/O 시스템은 저널 변경 사항을 다시 정렬하여 사용 가능한 스토리지 공간 사용을 최적화할 수 있습니다. 저널 활동을 통해 저널 변경 사항을 다시 정렬하고 데이터 및 메타데이터를 커밋하여 시스템 대기 시간을 초래할 수 있습니다. 결과적으로 저널링 파일 시스템은 시스템의 속도가 느려질 수 있습니다.

XFS 는 RHEL 8에서 사용하는 기본 파일 시스템입니다. 저널링 파일 시스템입니다. ext2 라는 이전 파일 시스템은 저널링을 사용하지 않습니다. 특별히 저널링이 필요하지 않는 한 ext2 파일 시스템을 고려하십시오. Red Hat의 최상의 벤치마크 결과에는 ext2 파일 시스템이 사용됩니다. 이는 주요 초기 튜닝 권장 사항 중 하나입니다.

XFS 와 같은 저널링 파일 시스템은 파일에 마지막으로 액세스한 시간( atime 속성)을 기록합니다. 저널링 파일 시스템을 사용해야 하는 경우 시간 비활성화를 고려하십시오.

15.1. 시간 비활성화

atime 속성을 비활성화하면 성능이 향상되고 파일 시스템 저널에 대한 쓰기 수를 제한하여 전력 사용량이 줄어듭니다.

프로세스

  1. 선택한 텍스트 편집기를 사용하여 /etc/fstab 파일을 열고 루트 마운트 지점의 항목을 찾습니다.

    /dev/mapper/rhel-root       /       xfs    defaults…
  2. noatimenodiratime 용어를 포함하도록 options 섹션을 편집합니다. noatime 옵션은 파일을 읽을 때 액세스 타임스탬프가 업데이트되지 않도록 하고 nodiratime 옵션은 디렉터리 inode 액세스 시간이 업데이트됩니다.

    /dev/mapper/rhel-root       /       xfs    noatime,nodiratime…
중요

일부 애플리케이션은 atime 이 업데이트되는 데 의존합니다. 따라서 이 옵션은 이러한 애플리케이션이 사용되지 않는 시스템에서만 적합합니다.

또는 relatime 마운트 옵션을 사용하면 이전 액세스 시간이 현재 수정 시간보다 오래된 경우에만 액세스 시간이 업데이트되도록 할 수 있습니다.

커널은 시작하는 즉시 printk() 에 메시지를 전달하기 시작합니다. 커널은 로그 파일에 메시지를 전송하고 헤드리스 서버에 연결된 모니터가 없는 경우에도 그래픽 콘솔에 표시됩니다.

일부 시스템에서는 그래픽 콘솔로 전송되는 출력에 파이프라인이 중단될 수 있습니다. 이로 인해 데이터 전송을 기다리는 동안 작업 실행이 지연될 수 있습니다. 예를 들어 Teletype0 (/dev/tty0) 으로 전송된 출력은 일부 시스템에서 잠재적인 정지를 유발할 수 있습니다.

예기치 않은 정지를 방지하려면 다음을 통해 그래픽 콘솔로 전송되는 정보를 제한하거나 비활성화할 수 있습니다.

  • tty0 정의 제거.
  • 콘솔 정의 순서 변경.
  • 대부분의 printk() 함수를 끄고 ignore_loglevel 커널 매개변수를 구성되지 않았는지 확인합니다.

그래픽 콘솔 출력을 로깅에서 비활성화하고 그래픽 콘솔에서 출력하는 메시지를 제어하면 중요한 워크로드의 대기 시간을 개선할 수 있습니다.

16.1. 그래픽 콘솔 로깅을 그래픽 어댑터로 비활성화

Teletype (tty) 기본 커널 콘솔을 사용하면 입력 데이터를 시스템에 전달하고 그래픽 콘솔에 대한 출력 정보를 표시하여 시스템과 상호 작용할 수 있습니다.

그래픽 콘솔을 구성하지 않고 그래픽 어댑터에 로깅하지 못하도록 합니다. 이렇게 하면 시스템에서 tty0 을 사용할 수 없으며 그래픽 콘솔에서 인쇄 메시지를 비활성화할 수 있습니다.

참고

그래픽 콘솔 출력을 비활성화해도 정보는 삭제되지 않습니다. 정보는 시스템 로그에 출력되며 journalctl 또는 dmesg 유틸리티를 사용하여 액세스할 수 있습니다.

프로세스

  • 커널 구성에서 console=tty0 옵션을 제거합니다.

    # grubby --update-kernel=ALL --remove-args="console=tty0"

16.2. 그래픽 콘솔에서 출력할 수 없는 메시지 비활성화

/proc/sys/kernel/printk 파일에서 필요한 로그 수준을 구성하여 그래픽 콘솔에 전송되는 출력 메시지의 양을 제어할 수 있습니다.

프로세스

  1. 현재 콘솔 로그 수준을 표시합니다.

    $ cat /proc/sys/kernel/printk
      7    4    1    7

    명령은 시스템 로그 수준의 현재 설정을 출력합니다. 숫자는 시스템 로거의 현재, 기본값, 최소 및 부팅 기본값 값에 해당합니다.

  2. /proc/sys/kernel/printk 파일에서 원하는 로그 수준을 구성합니다.

    $ echo "1” > /proc/sys/kernel/printk

    명령은 현재 콘솔 로그 수준을 변경합니다. 예를 들어 로그 수준 1을 설정하면 경고 메시지만 출력하고 그래픽 콘솔에 다른 메시지가 표시되지 않습니다.

17장. 애플리케이션 요구 사항을 충족하기 위해 시스템 클럭 관리

NUMA 또는 SMP와 같은 다중 프로세서 시스템에는 하드웨어 클록의 여러 인스턴스가 있습니다. 부팅 시 커널은 사용 가능한 클럭 소스를 검색하고 사용할 클럭 소스를 선택합니다. 성능을 개선하기 위해 실시간 시스템의 최소 요구 사항을 충족하는 데 사용되는 클럭 소스를 변경할 수 있습니다.

17.1. 하드웨어 클럭

NUMA(Non-Uniform Memory Access) 및 SMP(Symmetric Multiprocessing)와 같은 다중 프로세서 시스템에서 발견된 클럭 소스의 여러 인스턴스는 CPU 빈도 스케일링 또는 에너지 경제 모드 입력과 같은 시스템 이벤트에 반응하는 방식을 상호 작용하며 실시간 커널에 적합한 클럭 소스인지 결정합니다.

기본 클록 소스는 TSC(Time Stamp Cryostat)입니다. TSC를 사용할 수 없는 경우 HPET(High Precision Event Timer)이 두 번째 최상의 옵션입니다. 그러나 모든 시스템에 HPET 시계가 있는 것은 아니며 일부 HPET 클록은 신뢰할 수 없습니다.

TSC 및 HPET가 없는 다른 옵션에는 ACPI_PM (ACPI_PM), Programmable Interval Timer (PIT) 및 Real Time Clock (RTC)이 포함됩니다. 마지막 두 옵션은 읽기에는 비용이 많이 들거나 낮은 해상도(시간 단위)가 있으므로 실시간 커널과 함께 사용할 수 있습니다.

17.2. 현재 사용 중인 클럭 소스 보기

시스템에서 현재 사용되는 클럭 소스는 /sys/devices/system/clocksource/clocksource0/current_clocksource 파일에 저장됩니다.

프로세스

  • current_clocksource 파일을 표시합니다.

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    tsc

    이 예에서 시스템의 현재 클럭 소스는 TSC입니다.

17.3. 일시적으로 사용할 클럭 소스 변경

경우에 따라 시스템의 주요 애플리케이션에 가장 적합한 시계가 시계의 알려진 문제로 인해 사용되지 않는 경우가 있습니다. 문제가 있는 모든 시계를 판단한 후 시스템은 실시간 시스템의 최소 요구 사항을 충족할 수 없는 하드웨어 클록으로 남을 수 있습니다.

중요한 애플리케이션의 요구 사항은 시스템마다 다릅니다. 따라서 각 애플리케이션에 가장 적합한 시계가 결과적으로 각 시스템도 다릅니다. 일부 애플리케이션은 클럭 해상도에 따라 다르며 안정적인 나노초 읽기를 제공하는 시계가 더 적합할 수 있습니다. 시계를 너무 자주 읽는 애플리케이션은 읽기 비용이 더 적은 시계의 이점을 얻을 수 있습니다(읽기 요청과 결과 사이의 시간).

이러한 경우 재정의의 부작용을 이해하고 지정된 하드웨어 클록의 알려진 단점을 트리거하지 않는 환경을 생성할 수 있는 경우 커널에서 선택한 시계를 재정의할 수 있습니다.

중요

커널은 사용 가능한 최상의 클럭 소스를 자동으로 선택합니다. 영향을 잘 이해하지 않는 한 선택한 클럭 소스를 재정의하는 것은 권장되지 않습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. 사용 가능한 클럭 소스를 확인합니다.

    # cat /sys/devices/system/clocksource/clocksource0/available_clocksource
    tsc hpet acpi_pm

    예를 들어 시스템에서 사용 가능한 클럭 소스는 TSC, HPET 및 ACPI_PM이라고 가정합니다.

  2. 사용할 클럭 소스의 이름을 /sys/devices/system/clocksource/clocksource0/current_clocksource 파일에 작성합니다.

    # echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource

검증

  • current_clocksource 파일을 표시하여 현재 클럭 소스가 지정된 클럭 소스인지 확인합니다.

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    hpet

    이 예제에서는 HPET를 시스템의 현재 클럭 소스로 사용합니다.

17.4. 하드웨어 클럭 소스 읽기 비용 비교

시스템의 클럭 속도를 비교할 수 있습니다. TSC에서 읽기는 프로세서에서 레지스터를 읽는 것과 관련이 있습니다. HPET 클록에서 읽기는 메모리 영역을 읽는 것입니다. TSC에서 읽는 것이 더 빠르기 때문에 초당 수만 개의 메시지를 타임스탬프할 때 상당한 성능 이점을 제공합니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.
  • clock_timing 프로그램이 시스템에 있어야 합니다. 자세한 내용은 clock_timing 프로그램을 참조하십시오.

프로세스

  1. clock_timing 프로그램이 저장되는 디렉터리로 변경합니다.

    # cd clock_test
  2. 시스템에서 사용 가능한 클럭 소스를 확인합니다.

    # cat /sys/devices/system/clocksource/clocksource0/available_clocksource
    tsc hpet acpi_pm

    이 예에서 시스템에서 사용 가능한 클럭 소스는 TSC,HPETACPI_PM 입니다.

  3. 현재 사용 중인 클럭 소스를 확인합니다.

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    tsc

    이 예에서 시스템의 현재 클럭 소스는 TSC 입니다.

  4. ./clock_timing 프로그램과 함께 time 유틸리티를 실행합니다. 출력에 클럭 소스를 10 만 번 읽는 데 필요한 기간이 표시됩니다.

    # time ./clock_timing
    
    	real	0m0.601s
    	user	0m0.592s
    	sys	0m0.002s

    이 예제에서는 다음 매개변수를 보여줍니다.

    • real - 프로세스가 종료될 때까지 프로그램 호출에서 시작하는 총 시간입니다. real 은 사용자와 커널 시간을 포함하며 일반적으로 후자 2의 합계보다 큽니다. 우선 순위가 높은 애플리케이션에 의해 또는 하드웨어 인터럽트(IRQ)와 같은 시스템 이벤트에 의해 이 프로세스가 중단되는 경우 대기 시간이 실제 상태에서도 계산됩니다.
    • user - 사용자가 커널 개입이 필요하지 않은 작업을 수행하는 데 소비한 시간입니다.
    • sys - 사용자 프로세스에 필요한 작업을 수행하는 동안 커널이 사용하는 시간입니다. 이러한 작업에는 파일 열기, 파일 읽기 및 I/O 포트, 메모리 할당, 스레드 생성 및 네트워크 관련 활동이 포함됩니다.
  5. 테스트할 다음 클럭 소스의 이름을 /sys/devices/system/clocksource/clocksource0/current_clocksource 파일에 작성합니다.

    # echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource

    이 예에서는 현재 클럭 소스가 HPET 로 변경되었습니다.

  6. 사용 가능한 모든 클럭 소스에 대해 4단계와 5단계를 반복합니다.
  7. 사용 가능한 모든 클럭 소스에 대해 4단계의 결과를 비교합니다.

17.5. Opteron CPU에서 TSC 타이머 동기화

AMD64 Opteron 프로세서의 현재 생성은 대규모의 gettimeofday skew에 취약해질 수 있습니다. 이 스큐는 cpufreq 및 TSC( Time Stamp Cryo stat)를 모두 사용 중인 경우 발생합니다. RHEL for Real Time은 모든 프로세서가 동일한 빈도로 동시에 변경되도록 강제하여 이러한 스큐를 방지할 수 있는 방법을 제공합니다. 결과적으로 단일 프로세서의 TSC는 다른 프로세서의 TSC와 다른 속도로 증가하지 않습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. clocksource=tscpowernow-k8.tscsync=1 커널 옵션을 활성화합니다.

    # grubby --update-kernel=ALL --args="clocksource=tsc powernow-k8.tscsync=1"

    이로 인해 TSC를 강제로 사용하고 동시 코어 프로세서 빈도 전환을 활성화합니다.

  2. 시스템을 다시 시작합니다.

17.6. clock_timing 프로그램

clock_timing 프로그램은 현재 클럭 소스를 10 만 번 읽습니다. 시간 유틸리티와 함께 이 작업을 수행하는 데 필요한 시간을 측정합니다.

프로세스

clock_timing 프로그램을 생성하려면 다음을 수행합니다.

  1. 프로그램 파일의 디렉터리를 만듭니다.

    $ mkdir clock_test
  2. 생성된 디렉터리로 변경합니다.

    $ cd clock_test
  3. 소스 파일을 생성하고 텍스트 편집기에서 엽니다.

    $ {EDITOR} clock_timing.c
  4. 파일에 다음을 입력합니다.

    #include <time.h>
    void main()
    {
      int rc;
      long i;
      struct timespec ts;
    
      for(i=0; i<10000000; i++) {
        rc = clock_gettime(CLOCK_MONOTONIC, &ts);
      }
    }
  5. 파일을 저장하고 편집기를 종료합니다.
  6. 파일을 컴파일합니다.

    $ gcc clock_timing.c -o clock_timing -lrt

    clock_timing 프로그램은 준비되었으며 저장된 디렉터리에서 실행할 수 있습니다.

18장. 전원 관리 전환 제어

전원 관리 전환을 제어하여 대기 시간을 개선할 수 있습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

18.1. 전원 저장 상태

최신 프로세서는 더 낮은 상태에서 더 높은 절전 상태(C 상태)로 적극적으로 전환됩니다. 안타깝게도 높은 전력 절감 상태에서 실행 상태로 다시 전환하면 실시간 애플리케이션에 최적의 시간보다 더 많은 시간이 걸릴 수 있습니다. 이러한 전환을 방지하기 위해 애플리케이션은 PM QoS(Power Management Quality of Service) 인터페이스를 사용할 수 있습니다.

PM QoS 인터페이스를 사용하면 시스템은 idle=pollprocessor.max_cstate=1 매개변수의 동작을 에뮬레이션할 수 있지만 전원 저장 상태를 보다 세밀하게 제어할 수 있습니다. idle=poll 을 사용하면 프로세서가 유휴 상태가 되지 않습니다. processor.max_cstate=1 은 프로세서가 더 깊은 C 상태(energy-serving 모드)를 입력하지 못하도록 합니다.

애플리케이션에 /dev/cpu_dma_latency 파일이 열려 있으면 PM QoS 인터페이스에서 프로세서가 깊은 절전 상태를 입력하지 못하도록 하여 종료될 때 예기치 않은 대기 시간이 발생합니다. 파일이 닫히면 시스템은 전원으로 돌아갑니다.

18.2. 전원 관리 상태 구성

다음 방법 중 하나로 전원 관리 상태를 구성하여 전원 관리 전환을 제어할 수 있습니다.

  • /dev/cpu_dma_latency 파일에 값을 작성하여 마이크로초 단위로 프로세스의 최대 응답 시간을 변경하고 짧은 대기 시간이 필요할 때까지 파일 설명자를 열어 둡니다.
  • 애플리케이션 또는 스크립트의 /dev/cpu_dma_latency 파일을 참조합니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

프로세스

  • /dev/cpu_dma_latency 에서 microseconds로 최대 응답 시간을 나타내는 32비트 수를 작성하고 대기 시간이 짧은 작업을 통해 파일 설명자를 열어서 대기 시간을 지정하여 대기 시간을 지정합니다. 값이 0 이면 C-state가 완전히 비활성화됩니다.

    예를 들면 다음과 같습니다.

    import os
    import signal
    import sys
    if not os.path.exists('/dev/cpu_dma_latency'):
        print("no PM QOS interface on this system!")
        sys.exit(1)
    try:
        fd = os.open('/dev/cpu_dma_latency', os.O_WRONLY)
        os.write(fd, b'\0\0\0\0')
        print("Press ^C to close /dev/cpu_dma_latency and exit")
        signal.pause()
    except KeyboardInterrupt:
        print("closing /dev/cpu_dma_latency")
        os.close(fd)
        sys.exit(0)
    참고

    Power Management Quality of Service 인터페이스(pm_qos) 인터페이스는 열려 있는 파일 설명자가 있는 경우에만 활성화됩니다. 따라서 /dev/cpu_dma_latency 에 액세스하는 데 사용하는 모든 스크립트 또는 프로그램은 power-state 전환이 허용될 때까지 파일을 열린 상태로 유지해야 합니다.

실시간 환경은 다양한 이벤트에 응답할 때 대기 시간을 최소화하거나 제거해야 합니다. 이렇게 하려면 다른 전용 CPU에서 사용자 프로세스에서 인터럽트(IRQ)를 분리할 수 있습니다.

19.1. 인터럽트 및 프로세스 바인딩

다른 전용 CPU의 사용자 프로세스에서 인터럽트(IRQ)를 격리하면 실시간 환경에서 대기 시간을 최소화하거나 제거할 수 있습니다.

인터럽트는 일반적으로 CPU 간에 균등하게 공유됩니다. 이는 CPU가 새 데이터 및 명령 캐시를 작성해야 할 때 인터럽트 처리를 지연할 수 있습니다. 이러한 인터럽트 지연으로 인해 다른 처리와 동일한 CPU에서 충돌이 발생할 수 있습니다.

특정 CPU(또는 다양한 CPU)에 시간 중요한 인터럽트 및 프로세스를 할당할 수 있습니다. 이러한 방식으로 이 인터럽트를 처리하기 위한 코드 및 데이터 구조는 프로세서 및 명령어 캐시에 있을 가능성이 높습니다. 결과적으로 전용 프로세스가 가능한 한 빨리 실행될 수 있지만 다른 모든 시간 외 프로세스는 다른 CPU에서 실행됩니다. 이는 관련된 속도가 메모리의 제한과 사용 가능한 주변 버스 대역폭에 있는 경우 특히 중요할 수 있습니다. 메모리가 프로세서 캐시로 가져올 때까지 대기하면 전체 처리 시간 및 결정성에 상당한 영향을 미칩니다.

실제로 최적의 성능은 전적으로 애플리케이션에 따라 다릅니다. 예를 들어 다른 회사에서 유사한 기능을 사용하여 애플리케이션을 튜닝하려면 완전히 다른 최적의 성능 튜닝이 필요합니다.

  • 한 회사는 운영 체제 기능 및 인터럽트 처리를 위해 CPU 2개를 4개에서 분리할 때 최적의 결과를 확인했습니다. 나머지 2개의 CPU는 애플리케이션 처리를 위해 전적으로 전용되었습니다.
  • 또 다른 회사는 네트워크 장치 드라이버 인터럽트를 처리하는 단일 CPU에 네트워크 관련 애플리케이션 프로세스를 바인딩할 때 최적의 결정성을 발견했습니다.
중요

프로세스를 CPU에 바인딩하려면 일반적으로 지정된 CPU 또는 CPU 범위의 CPU 마스크를 알아야 합니다. CPU 마스크는 일반적으로 사용 중인 명령에 따라 32비트 비트 마스크, 10진수 또는 16진수로 표시됩니다.

Expand
표 19.1. 지정된 CPU에 대한 CPU의 예

CPU

비트 마스크

10진수

Hexadecimal

0

00000000000000000000000000000001

1

0x00000001

0, 1

00000000000000000000000000000011

3

0x00000011

19.2. irqbalance 데몬 비활성화

irqbalance 데몬은 기본적으로 활성화되어 있으며 주기적으로 CPU에서 인터럽트를 처리하도록 강제 적용합니다. 그러나 애플리케이션이 일반적으로 특정 CPU에 바인딩되므로 실시간 배포에서는 irqbalance 가 필요하지 않습니다.

프로세스

  1. irqbalance 의 상태를 확인합니다.

    # systemctl status irqbalance
    irqbalance.service - irqbalance daemon
       Loaded: loaded (/usr/lib/systemd/system/irqbalance.service; enabled)
       Active: active (running) …
  2. irqbalance 가 실행 중인 경우 비활성화한 후 중지합니다.

    # systemctl disable irqbalance
    # systemctl stop irqbalance

검증

  • irqbalance 상태가 비활성화되었는지 확인합니다.

    # systemctl status irqbalance

19.3. IRQ 밸런싱에서 CPU 제외

IRQ 밸런싱 서비스를 사용하여 인터럽트(IRQ) 밸런싱을 위해 제외할 CPU를 지정할 수 있습니다. /etc/sysconfig/irqbalance 구성 파일의 IRQBALANCE_BANNED_CPUS 매개변수는 이러한 설정을 제어합니다. 매개 변수의 값은 64비트 16진수 비트 마스크로, 각 마스크는 CPU 코어를 나타냅니다.

프로세스

  1. 원하는 텍스트 편집기에서 /etc/sysconfig/irqbalance 를 열고 IRQBALANCE_BANNED_CPUS 라는 파일의 섹션을 찾습니다.

    # IRQBALANCE_BANNED_CPUS
    # 64 bit bitmask which allows you to indicate which cpu's should
    # be skipped when reblancing irqs. Cpu numbers which have their
    # corresponding bits set to one in this mask will not have any
    # irq's assigned to them on rebalance
    #
    #IRQBALANCE_BANNED_CPUS=
  2. IRQBALANCE_BANNED_CPUS 변수의 주석을 제거합니다.
  3. 적절한 비트마스크를 입력하여 IRQ 밸런싱 메커니즘에서 무시할 CPU를 지정합니다.
  4. 파일을 저장하고 닫습니다.
  5. 변경 사항을 적용하려면 irqbalance 서비스를 다시 시작하십시오.

    # systemctl restart irqbalance
참고

최대 64개의 CPU 코어가 있는 시스템을 실행하는 경우 8개의 16진수 그룹을 쉼표로 구분합니다. 예: IRQBALANCE_BANNED_CPUS=00000001,0000ff00

Expand
표 19.2. 예

CPU

비트 마스크

0

00000001

8 - 15

0000ff00

8 - 15, 33

00000002,0000ff00

참고

RHEL 7.2 이상에서는 IRQBALANCE_BANNED_CPUS/etc/sysconfig/irqbalance 에 설정되지 않은 경우 isolcpus 커널 매개변수를 통해 분리된 CPU 코어의 IRQ를 자동으로 방지합니다.

19.4. 개별 IRQ에 수동으로 CPU 선호도 할당

CPU 선호도를 할당하면 지정된 CPU 또는 CPU 범위에 바인딩 및 바인딩 해제 프로세스 및 스레드가 활성화됩니다. 이는 캐싱 문제를 줄일 수 있습니다.

프로세스

  1. /proc/interrupts 파일을 확인하여 각 장치에서 사용 중인 IRQ를 확인합니다.

    # cat /proc/interrupts

    각 행은 IRQ 번호, 각 CPU에서 발생한 인터럽트 수와 IRQ 유형 및 설명을 표시합니다.

             CPU0       CPU1
    0:   26575949         11         IO-APIC-edge  timer
    1:         14          7         IO-APIC-edge  i8042
  2. CPU 마스크를 특정 IRQ의 smp_affinity 항목에 작성합니다. CPU 마스크는 16진수로 표시되어야 합니다.

    예를 들어 다음 명령은 IRQ 번호 142가 CPU 0에서만 실행되도록 지시합니다.

    # echo 1 > /proc/irq/142/smp_affinity

    변경은 인터럽트가 발생할 때만 적용됩니다.

검증

  1. 지정된 인터럽트를 트리거하는 활동을 수행합니다.
  2. /proc/interrupts 에서 변경 사항을 확인합니다.

    구성된 IRQ에 대해 지정된 CPU의 인터럽트 수가 증가했으며 지정된 선호도 외부의 CPU에서 구성된 IRQ에 대한 인터럽트 수가 증가하지 않았습니다.

19.5. taskset 유틸리티를 사용하여 프로세스를 CPU에 바인딩

taskset 유틸리티는 작업의 PID(프로세스 ID)를 사용하여 CPU 선호도를 보거나 설정합니다. 유틸리티를 사용하여 선택한 CPU 선호도로 명령을 실행할 수 있습니다.

선호도를 설정하려면 CPU 마스크를 10진수 또는 16진수로 가져와야 합니다. mask 인수는 명령 또는 PID를 수정하는 데 적합한 CPU 코어를 지정하는 비트 마스크 입니다.

중요

taskset 유틸리티는 NUMA(Uniform Memory Access) 시스템에서 작동하지만 사용자가 스레드를 CPU 및 가장 가까운 NUMA 메모리 노드에 바인딩할 수 없습니다. 이러한 시스템에서 taskset은 기본 도구가 아니며 numactl 유틸리티 대신 고급 기능을 사용해야 합니다.

자세한 내용은 시스템의 numactl(8) 도움말 페이지를 참조하십시오.

프로세스

  • 필요한 옵션 및 인수를 사용하여 taskset 을 실행합니다.

    • CPU 마스크 대신 -c 매개변수를 사용하여 CPU 목록을 지정할 수 있습니다. 이 예에서 my_embedded_process 는 CPU 0,4,7-11에서만 실행되도록 지시합니다.

      # taskset -c 0,4,7-11 /usr/local/bin/my_embedded_process

      이 호출은 대부분의 경우 더 편리합니다.

    • 현재 실행되고 있지 않은 프로세스의 선호도를 설정하려면 taskset 을 사용하여 CPU 마스크 및 프로세스를 지정합니다.

      이 예에서 my_embedded_process 는 CPU 3만 사용하도록 지시합니다(CPU 마스크의 10진수 버전 사용).

      # taskset 8 /usr/local/bin/my_embedded_process
    • 비트마스크에서 두 개 이상의 CPU를 지정할 수 있습니다. 이 예에서 my_embedded_process 는 프로세서 4, 5, 6, 7에서 실행하라는 지시를 받습니다(CPU 마스크의 16진수 버전 사용).

      # taskset 0xF0 /usr/local/bin/my_embedded_process
    • CPU 마스크 및 변경하려는 프로세스의 PID와 함께 -p (--pid) 옵션을 사용하여 이미 실행 중인 프로세스의 CPU 선호도를 설정할 수 있습니다. 이 예에서 PID가 7013인 프로세스는 CPU 0에서만 실행되도록 지시됩니다.

      # taskset -p 1 7013
참고

나열된 옵션을 결합할 수 있습니다.

20장. 메모리 부족 상태 관리

OOM(메모리 부족)은 스왑 공간을 포함하여 사용 가능한 모든 메모리가 할당된 컴퓨팅 상태입니다. 일반적으로 이 경우 시스템이 패닉 상태가 되고 예상대로 작동을 중지합니다. 시스템에서 OOM 상태를 방지하는 데 사용되는 지침입니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

20.1. 메모리 부족 값 변경

/proc/sys/vm/panic_on_oom 파일에는 OOM(Out of Memory) 동작을 제어하는 스위치 값이 포함되어 있습니다. 파일에 1 이 포함된 경우 커널이 OOM에서 패닉 상태가 되고 예상대로 작동하지 않습니다.

기본값은 0 이며 시스템이 OOM 상태에 있을 때 커널에 oom_killer() 함수를 호출하도록 지시합니다. 일반적으로 oom_killer() 는 불필요한 프로세스를 종료하므로 시스템이 유지될 수 있습니다.

/proc/sys/vm/panic_on_oom 의 값을 변경할 수 있습니다.

프로세스

  1. /proc/sys/vm/panic_on_oom 의 현재 값을 표시합니다.

    # cat /proc/sys/vm/panic_on_oom
    0

    /proc/sys/vm/panic_on_oom 에서 값을 변경하려면 다음을 수행합니다.

  2. /proc/sys/vm/panic_on_oom 에 새 값을 에코합니다.

    # echo 1 > /proc/sys/vm/panic_on_oom
참고

OOM (1)에서 Real-Time 커널을 패닉시키는 것이 좋습니다. 그렇지 않으면 시스템이 OOM 상태가 되면 더 이상 결정적이지 않습니다.

검증

  1. /proc/sys/vm/panic_on_oom 의 값을 표시합니다.

    # cat /proc/sys/vm/panic_on_oom
    1
  2. 표시된 값이 지정된 값과 일치하는지 확인합니다.

20.2. 메모리 부족 상태에서 종료할 프로세스 우선 순위 지정

oom_killer() 함수로 종료되는 프로세스의 우선 순위를 지정할 수 있습니다. 이렇게 하면 우선 순위가 높은 프로세스가 OOM 상태에서 계속 실행될 수 있습니다. 각 프로세스에는 /proc/PID 가 있습니다. 각 디렉터리에는 다음 파일이 포함됩니다.

  • oom_score_adj ' - 'oom_score_adj의 유효한 점수는 -16에서 +15 사이입니다. 이 값은 프로세스의 성능 풋프린트를 계산하는 데 사용되며, 다른 요인 중에서 프로세스 실행 기간을 고려해야 하는 알고리즘을 사용합니다.
  • oom_score - oom_score_adj의 값을 사용하여 계산된 알고리즘의 결과를 포함합니다.

메모리 부족 상태에서 oom_killer() 함수는 oom_score 가 가장 높은 프로세스를 종료합니다.

프로세스의 'oom_score_adj ' 파일을 편집하여 프로세스가 종료되도록 우선순위를 지정할 수 있습니다.

사전 요구 사항

  • 우선순위를 지정할 프로세스의 PID(프로세스 ID)를 확인합니다.

프로세스

  1. 프로세스의 현재 oom_score 를 표시합니다.

    # cat /proc/12465/oom_score
    79872
  2. 프로세스의 oom_score_adj 콘텐츠를 표시합니다.

    # *cat /proc/12465/oom_score_adj *
    13
  3. oom_score_adj 의 값을 편집합니다.

    # *echo -5 > /proc/12465/oom_score_adj *

검증

  1. 프로세스의 현재 oom_score 를 표시합니다.

    # cat /proc/12465/oom_score
    78
  2. 표시된 값이 이전 값보다 낮은지 확인합니다.

20.3. 프로세스에 대한 메모리 부족 킬러 비활성화

oom_score_adj' 를 예약된 -17 값으로 설정하여 프로세스에 대해 oom_killer() 함수를 비활성화할 수 있습니다. 이렇게 하면 OOM 상태에서도 프로세스가 활성 상태가 됩니다.

프로세스

  • oom_score_adj 의 값을 -17 로 설정합니다.

    # echo -17 > /proc/12465/oom_score_adj

검증

  1. 프로세스의 현재 oom_score 를 표시합니다.

    # cat /proc/12465/oom_score
    0
  2. 표시된 값이 0 인지 확인합니다.

21장. tuna CLI를 사용하여 대기 시간 개선

tuna CLI를 사용하여 시스템의 대기 시간을 개선할 수 있습니다. RHEL 10용 tuna CLI에는 argparse 구문 분석 모듈을 기반으로 하는 명령줄이 포함되어 있습니다. 인터페이스는 다음과 같은 기능을 제공합니다.

  • 보다 표준화된 명령 및 옵션 메뉴
  • 인터페이스에서 사전 정의된 입력 및 tuna 를 사용하면 입력이 올바른 유형인지 확인할 수 있습니다.
  • 매개변수를 사용하는 방법에 대해 자동으로 사용법 도움말 메시지를 생성하고 잘못된 인수가 있는 오류 메시지를 제공합니다.

21.1. 사전 요구 사항

  • tunapython-linux-procfs 패키지가 설치됩니다.
  • 시스템에 대한 root 권한이 있습니다.

21.2. tuna CLI

tuna CLI(명령줄 인터페이스)는 시스템을 조정하는 데 도움이 되는 툴입니다.

tuna 툴은 실행 중인 시스템에서 사용하도록 설계되었으며 변경 사항이 즉시 수행됩니다. 이를 통해 모든 애플리케이션별 측정 툴에서 변경 후 즉시 시스템 성능을 확인하고 분석할 수 있습니다.

이제 tuna CLI에는 이전에 작업 옵션이 있는 명령 세트가 있습니다. 이러한 명령은 다음과 같습니다.

격리
CPU-LIST 로부터 모든 스레드와 IRQ를 이동합니다.
포함
CPU-LIST 에서 실행되도록 모든 스레드를 구성합니다.
이동
특정 엔터티를 CPU-LIST 로 이동합니다.
스프레드
선택한 엔터티를 CPU-LIST 에 분배합니다.
priority
스레드 스케줄러 튜닝 가능 항목(예: POLICY 및 Cryostat RIO ) 을 설정합니다.
run
새 프로세스를 분기하고 명령을 실행합니다.
저장
kthreads 스케줄링 튜닝 가능 항목을 FILENAME 에 저장합니다.
apply
프로필에 정의된 변경 사항을 적용합니다.
show_threads
스레드 목록을 표시합니다.
show_irqs
IRQ 목록을 표시합니다.
show_configs
기존 프로필 목록을 표시합니다.
what_is
선택한 엔터티에 대한 도움말을 제공합니다.
gui
GUI(그래픽 사용자 인터페이스)를 시작합니다.

tuna -h 명령을 사용하여 명령을 볼 수 있습니다. 각 명령에는 tuna <command> -h 명령으로 볼 수 있는 선택적 인수가 있습니다. 예를 들어 tuna isolate -h 명령을 사용하면 격리 옵션을 볼 수 있습니다.

21.3. tuna CLI를 사용하여 CPU 분리

tuna CLI를 사용하여 서로 다른 전용 CPU의 사용자 프로세스에서 인터럽트(IRQ)를 분리하여 실시간 환경에서 대기 시간을 최소화할 수 있습니다. CPU 격리에 대한 자세한 내용은 Interrupt 및 process binding 을 참조하십시오.

사전 요구 사항

  • tunapython-linux-procfs 패키지가 설치됩니다.
  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 하나 이상의 CPU를 분리합니다.

    # tuna isolate --cpus=<cpu_list>

    cpu_list 는 쉼표로 구분된 목록 또는 격리할 CPU 범위입니다.

    예를 들면 다음과 같습니다.

    # tuna isolate --cpus=0,1

    또는

    # tuna isolate --cpus=0-5

21.4. tuna CLI를 사용하여 인터럽트를 지정된 CPU로 이동

tuna CLI를 사용하여 인터럽트(IRQ)를 전용 CPU로 이동하여 실시간 환경에서 대기 시간을 최소화하거나 제거할 수 있습니다. IRQ 이동에 대한 자세한 내용은 Interrupt 및 process binding 을 참조하십시오.

사전 요구 사항

  • tunapython-linux-procfs 패키지가 설치됩니다.
  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. IRQ 목록이 연결된 CPU를 나열합니다.

    # tuna show_irqs --irqs=<irq_list>

    irq_list 는 연결된 CPU를 나열하려는 IRQ의 쉼표로 구분된 목록입니다.

    예를 들면 다음과 같습니다.

    # tuna show_irqs --irqs=128
  2. IRQ 목록을 CPU 목록에 연결합니다.

    # tuna move --irqs=irq_list --cpus=<cpu_list>

    irq_list 는 연결하려는 IRQ의 쉼표로 구분된 목록입니다. cpu_list 는 연결할 CPU 또는 CPU의 쉼표로 구분된 목록입니다.

    예를 들면 다음과 같습니다.

    # tuna move --irqs=128 --cpus=3

검증

  • IRQ를 지정된 CPU로 이동하기 전후에 선택한 IRQ의 상태를 비교합니다.

    # tuna show_irqs --irqs=128

21.5. tuna CLI를 사용하여 프로세스 스케줄링 정책 및 우선순위 변경

tuna CLI를 사용하여 프로세스 스케줄링 정책 및 우선 순위를 변경할 수 있습니다.

사전 요구 사항

  • tunapython-linux-procfs 패키지가 설치됩니다.
  • 시스템에 대한 root 권한이 있습니다.

    참고

    OTHERBATCH 스케줄링 정책을 할당하려면 루트 권한이 필요하지 않습니다.

프로세스

  1. 스레드에 대한 정보를 확인합니다.

    # tuna show_threads --threads=<thread_list>

    thread_list 는 표시할 프로세스의 쉼표로 구분된 목록입니다.

    예를 들면 다음과 같습니다.

    # tuna show_threads --threads=42369,42416,43859
  2. 프로세스 스케줄링 정책 및 스레드의 우선 순위를 수정합니다.

    # tuna priority scheduling_policy:priority_number --threads=<thread_list>
    • thread_list 는 표시하려는 스케줄링 정책 및 우선 순위가 있는 프로세스의 쉼표로 구분된 목록입니다.
    • scheduling_policy 는 다음 중 하나입니다.

      • 기타
      • BATCH
      • FIFO - 첫 번째 아웃
      • RR - Round Robin
    • priority_number 는 0에서 99 사이의 우선 순위 번호입니다. 여기서 0 은 우선순위가 아니며 99 가 가장 높은 우선 순위입니다.

      참고

      OTHERBATCH 스케줄링 정책에는 우선순위를 지정할 필요가 없습니다. 또한 유일하게 유효한 우선순위(지정된 경우)는 0 입니다. FIFORR 스케줄링 정책에는 우선순위가 1 개 이상 있어야 합니다.

      예를 들면 다음과 같습니다.

# tuna priority FIFO:1 --threads=42369,42416,43859

검증

  • 스레드 정보를 보고 정보가 변경되는지 확인합니다.
# tuna show_threads --threads=42369,42416,43859

22장. 스케줄러 우선순위 설정

Red Hat Enterprise Linux for Real Time 커널을 사용하면 스케줄러 우선 순위를 세밀하게 제어할 수 있습니다. 또한 커널 스레드보다 우선 순위가 높은 애플리케이션 수준 프로그램을 예약할 수 있습니다.

주의

스케줄러 우선순위를 설정하면 결과가 발생할 수 있으며 중요한 커널 프로세스가 필요에 따라 실행되지 않으면 시스템이 응답하지 않거나 예기치 않게 작동할 수 있습니다. 궁극적으로 올바른 설정은 워크로드에 따라 다릅니다.

22.1. 스레드 스케줄링 우선순위 보기

스레드 우선순위는 0 (최저 우선 순위)에서 99 (최고 우선 순위) 사이의 일련의 수준을 사용하여 설정됩니다. 커널 부팅 후 systemd 서비스 관리자를 사용하여 스레드의 기본 우선순위를 변경할 수 있습니다.

프로세스

  • 실행 중인 스레드의 스케줄링 우선순위를 보려면 tuna 유틸리티를 사용합니다.

    # tuna --show_threads
                          thread       ctxt_switches
        pid SCHED_ rtpri affinity voluntary nonvoluntary             cmd
      2      OTHER     0    0xfff       451            3        kthreadd
      3       FIFO     1        0     46395            2     ksoftirqd/0
      5      OTHER     0        0        11            1    kworker/0:0H
      7       FIFO    99        0         9            1   posixcputmr/0
      ...[output truncated]...

22.2. 부팅 중 서비스의 우선 순위 변경

systemd 를 사용하면 부팅 프로세스 중에 시작된 서비스의 실시간 우선 순위를 설정할 수 있습니다.

단위 구성 지시문은 부팅 프로세스 중에 서비스의 우선 순위를 변경하는 데 사용됩니다. 부팅 프로세스 우선 순위 변경은 /etc/systemd/system/ 서비스 .service.d/priority.conf의 service 섹션에서 다음 지시문을 사용하여 수행됩니다.

CPUSchedulingPolicy=

실행된 프로세스의 CPU 스케줄링 정책을 설정합니다. Linux에서 사용할 수 있는 스케줄링 클래스 중 하나를 가져옵니다.

  • 기타
  • batch
  • idle
  • fifo
  • rr

CPUSchedulingPriority=

실행된 프로세스의 CPU 스케줄링 우선 순위를 설정합니다. 사용 가능한 우선순위 범위는 선택한 CPU 스케줄링 정책에 따라 다릅니다. 실시간 스케줄링 정책의 경우 1 (최저 우선 순위)에서 99 (최고 우선 순위) 사이의 정수를 사용할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.
  • 부팅 시 실행되는 서비스입니다.

프로세스

기존 서비스의 경우:

  1. 서비스에 대한 보조 서비스 구성 디렉터리 파일을 생성합니다.

    # cat <<-EOF > /etc/systemd/system/mcelog.service.d/priority.conf
  2. [Service] 섹션의 파일에 스케줄링 정책 및 우선 순위를 추가합니다.

    예를 들면 다음과 같습니다.

    [Service]
    CPUSchedulingPolicy=fifo
    CPUSchedulingPriority=20
    EOF
  3. systemd 스크립트 구성을 다시 로드합니다.

    # systemctl daemon-reload
  4. 서비스를 다시 시작합니다.

    # systemctl restart mcelog

검증

  • 서비스의 우선 순위를 표시합니다.

    $ tuna -t mcelog -P

    출력에는 서비스의 구성된 우선 순위가 표시됩니다.

    예를 들면 다음과 같습니다.

                        thread       ctxt_switches
      pid SCHED_ rtpri affinity voluntary nonvoluntary             cmd
    826     FIFO    20  0,1,2,3        13            0          mcelog

22.3. 서비스의 CPU 사용량 구성

systemd 를 사용하여 서비스를 실행할 수 있는 CPU를 지정할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

프로세스

  1. 서비스에 대한 보조 서비스 구성 디렉터리 파일을 생성합니다.

    # md sscd
  2. [Service] 섹션의 CPUAffinity 특성을 사용하여 서비스에 사용할 CPU를 파일에 추가합니다.

    예를 들면 다음과 같습니다.

    [Service]
    CPUAffinity=0,1
    EOF
  3. systemd 스크립트 구성을 다시 로드합니다.

    # systemctl daemon-reload
  4. 서비스를 다시 시작합니다.

    # systemctl restart service

검증

  • 지정된 서비스가 제한된 CPU를 표시합니다.

    $ tuna -t mcelog -P

    여기서 service 는 지정된 서비스입니다.

    다음 출력에서는 mcelog 서비스가 CPU 0 및 1로 제한되었음을 보여줍니다.

                        thread       ctxt_switches
      pid SCHED_ rtpri affinity voluntary nonvoluntary             cmd
    12954   FIFO    20      0,1         2            1          mcelog

22.4. 우선순위 맵

우선순위는 그룹에 정의되어 있으며, 일부 그룹은 특정 커널 함수를 전용으로 사용합니다. 실시간 스케줄링 정책의 경우 1 (최저 우선 순위)에서 99 (최고 우선 순위) 사이의 정수를 사용할 수 있습니다.

다음 표에서는 프로세스의 스케줄링 정책을 설정하는 동안 사용할 수 있는 우선 순위 범위를 설명합니다.

Expand
표 22.1. 우선순위 범위에 대한 설명
우선 순위스레드설명

1

우선 순위가 낮은 커널 스레드

이 우선순위는 일반적으로 just above _OTHER 여야 하는 작업에 대해 예약되어 있습니다.

2 - 49

사용 가능

일반적인 애플리케이션 우선 순위에 사용되는 범위입니다.

50

기본 hard-IRQ 값

 

51 - 98

높은 우선순위 스레드

주기적으로 실행되고 빠른 응답 시간이 있어야 하는 스레드에 이 범위를 사용합니다. 인터럽트를 중단하므로 CPU 바인딩된 스레드에는 이 범위를 사용하지 마십시오.

99

워치독 및 마이그레이션

가장 높은 우선 순위로 실행해야 하는 시스템 스레드입니다.

23장. 네트워크 결정성 팁

TCP는 대기 시간에 큰 영향을 미칠 수 있습니다. TCP는 효율성을 확보하고, 혼잡을 제어하고, 안정적인 제공을 보장하기 위해 대기 시간을 추가합니다. 튜닝할 때 다음 사항을 고려하십시오.

  • 주문 배송이 필요하십니까?
  • 패킷 손실을 방지해야합니까?

    패킷을 두 번 이상 전송하면 지연이 발생할 수 있습니다.

  • TCP를 사용해야 합니까?

    소켓에서 TCP_NODELAY 를 사용하여 나글 버퍼링 알고리즘을 비활성화하는 것이 좋습니다. 나글 알고리즘은 모두 한 번에 보낼 작은 발신 패킷을 수집하고 대기 시간에 부정적인 영향을 미칠 수 있습니다.

23.1. 대기 시간 또는 처리량에 민감한 서비스를 위해 RHEL 최적화

병합 튜닝의 목표는 지정된 워크로드에 필요한 인터럽트 수를 최소화하는 것입니다. 처리량이 높은 상황에서 목표는 높은 데이터 속도를 유지하면서 가능한 한 적은 수의 인터럽트를 보유하는 것입니다. 대기 시간이 짧은 상황에서는 더 많은 인터럽트를 사용하여 트래픽을 신속하게 처리할 수 있습니다.

네트워크 카드의 설정을 조정하여 단일 인터럽트로 결합된 패킷 수를 늘리거나 줄일 수 있습니다. 결과적으로 트래픽의 처리량 또는 대기 시간을 개선할 수 있습니다.

프로세스

  1. 병목 현상이 발생하는 네트워크 인터페이스를 식별합니다.

    # ethtool -S enp1s0
    NIC statistics:
         rx_packets: 1234
         tx_packets: 5678
         rx_bytes: 12345678
         tx_bytes: 87654321
         rx_errors: 0
         tx_errors: 0
         rx_missed: 0
         tx_dropped: 0
         coalesced_pkts: 0
         coalesced_events: 0
         coalesced_aborts: 0

    이름에서 드롭 삭제, 삭제 또는 오류가 포함된 패킷 카운터를 식별합니다. 이러한 특정 통계는 NIC(네트워크 인터페이스 카드) 패킷 버퍼에서 실제 패킷 손실을 측정하며, NIC 병합으로 인해 발생할 수 있습니다.

  2. 이전 단계에서 확인한 패킷 카운터 값을 모니터링합니다.

    네트워크에 대해 예상되는 값과 비교하여 특정 인터페이스에 병목 현상이 발생하는지 확인합니다. 네트워크 병목 현상의 몇 가지 일반적인 표시에는 다음이 포함되지만 이에 국한되지는 않습니다.

    • 네트워크 인터페이스에 많은 오류
    • 높은 패킷 손실
    • 네트워크 인터페이스의 사용량이 많이 있음

      참고

      다른 중요한 요인은 네트워크 병목 현상을 식별할 때 CPU 사용량, 메모리 사용량, 디스크 I/O 등의 중요한 요소입니다.

  3. 현재 인터럽트 병합 설정을 확인합니다.

    # ethtool -c enp1s0
    Coalesce parameters for enp1s0:
            Adaptive RX: off
            Adaptive TX: off
            RX usecs: 100
            RX frames: 8
            RX usecs irq: 100
            RX frames irq: 8
            TX usecs: 100
            TX frames: 8
            TX usecs irq: 100
            TX frames irq: 8
    • usecs 값은 인터럽트를 생성하기 전에 수신자 또는 송신기가 대기하는 마이크로초의 수를 나타냅니다.
    • 프레임 값은 인터럽트를 생성하기 전에 수신자 또는 송신기가 대기하는 프레임 수를 나타냅니다.
    • irq 값은 네트워크 인터페이스에서 인터럽트를 이미 처리하고 있을 때 인터럽트 모드를 구성하는 데 사용됩니다.

      참고

      모든 네트워크 인터페이스 카드에서 예제 출력의 모든 값을 보고하고 변경하는 데 지원되지는 않습니다.

    • Adaptive RX/TX 값은 인터럽트 병합 설정을 동적으로 조정하는 Adaptive 인터럽트 병합 메커니즘을 나타냅니다. 패킷 상태에 따라 Adaptive RX/TX 가 활성화된 경우 NIC 드라이버에서 병합 값을 자동으로 계산합니다(각 NIC 드라이버마다 알고리즘이 다릅니다).
  4. 필요에 따라 병합 설정을 수정합니다. 예를 들면 다음과 같습니다.

    • ethtool.coalesce-adaptive-rx 는 비활성화되지만 RX 패킷에 대해 인터럽트 를 100 마이크로초로 생성하기 전에 지연을 설정하도록 ethtool.coalesce-rx 를 구성합니다.

      # nmcli connection modify enp1s0 ethtool.coalesce-rx-usecs 100
    • ethtool.coalesce-rx-usecs 가 기본값으로 설정된 동안 ethtool.coalesce-adaptive-rx -rx를 활성화합니다.

      # nmcli connection modify enp1s0 ethtool.coalesce-adaptive-rx on

      다음과 같이 Adaptive-RX 설정을 수정합니다.

      • 짧은 대기 시간(sub-50us)에 관련된 사용자는 Adaptive-RX 를 활성화해서는 안 됩니다.
      • 처리량에 관련된 사용자는 손상 없이 Adaptive-RX 를 활성화할 수 있습니다. Adaptive 인터럽트 병합 메커니즘을 사용하지 않으려면 100us와 같은 큰 값을 설정하거나 ethtool.coalesce-rx-usecs 로 250us를 설정할 수 있습니다.
      • 사용자가 문제가 발생할 때까지 요구 사항에 대해 잘 모르는 경우 이 설정을 수정해서는 안 됩니다.
  5. 연결을 다시 활성화합니다.

    # nmcli connection up enp1s0

검증

  • 네트워크 성능을 모니터링하고 삭제된 패킷을 확인합니다.

    # ethtool -S enp1s0
    NIC statistics:
         rx_packets: 1234
         tx_packets: 5678
         rx_bytes: 12345678
         tx_bytes: 87654321
         rx_errors: 0
         tx_errors: 0
         rx_missed: 0
         tx_dropped: 0
         coalesced_pkts: 12
         coalesced_events: 34
         coalesced_aborts: 56
    ...

    rx_errors,rx_dropped,tx_errors, tx_dropped 필드의 값은 0이어야 합니다(네트워크 트래픽 및 시스템 리소스에 따라 최대 수백 개까지). 이러한 필드의 높은 값은 네트워크 문제를 나타냅니다. 카운터는 다른 이름을 가질 수 있습니다. 이름에 "drop", "discard" 또는 "error"가 포함된 패킷 카운터를 밀접하게 모니터링합니다.

    rx_packets,tx_packets,rx_bytes, tx_bytes 의 값은 시간이 지남에 따라 증가해야 합니다. 값이 증가하지 않으면 네트워크에 문제가 있을 수 있습니다. NIC 드라이버에 따라 패킷 카운터의 이름이 다를 수 있습니다.

    중요

    ethtool 명령 출력은 사용 중인 NIC 및 드라이버에 따라 다를 수 있습니다.

    대기 시간이 매우 짧은 사용자는 모니터링 목적으로 애플리케이션 수준 메트릭 또는 커널 패킷 시간 샘플링 API를 사용할 수 있습니다.

23.2. 이더넷 네트워크의 흐름 제어

이더넷 링크에서 네트워크 인터페이스와 스위치 포트 간의 지속적인 데이터 전송으로 인해 전체 버퍼 용량이 발생할 수 있습니다. 전체 버퍼 용량으로 인해 네트워크 정체가 발생합니다. 이 경우, 발신자가 수신기의 처리 용량보다 더 높은 속도로 데이터를 전송할 때, 패킷 손실은 링크의 다른 쪽 끝에 있는 네트워크 인터페이스의 데이터 처리 용량으로 인해 발생할 수 있습니다.

흐름 제어 메커니즘은 각 발신자와 수신자가 다른 전송 및 수신 용량을 갖는 이더넷 링크를 통한 데이터 전송을 관리합니다. 패킷 손실을 방지하기 위해 이더넷 흐름 제어 메커니즘은 스위치 포트에서 더 높은 전송 속도를 관리하기 위해 패킷 전송을 일시적으로 중단합니다. 스위치는 스위치 포트 이외의 일시 중지 프레임을 전달하지 않습니다.

수신(RX) 버퍼가 가득 차면 수신자는 일시 중지 프레임을 송신기에 보냅니다. 그런 다음 송신기는 이 일시 중지 기간 동안 들어오는 데이터를 버퍼링하는 동안 짧은 하위 시간 프레임에 대한 데이터 전송을 중지합니다. 이 기간은 수신자가 해당 인터페이스 버퍼를 비우고 버퍼 오버플로를 방지할 수 있는 충분한 시간을 제공합니다.

참고

이더넷 링크의 끝은 일시 중지 프레임을 다른 끝으로 보낼 수 있습니다. 네트워크 인터페이스의 수신 버퍼가 가득 차면 네트워크 인터페이스에서 일시 중지 프레임을 스위치 포트로 보냅니다. 마찬가지로, 스위치 포트의 수신 버퍼가 가득 차면 스위치 포트는 일시 중지 프레임을 네트워크 인터페이스로 보냅니다.

기본적으로 Red Hat Enterprise Linux의 대부분의 네트워크 드라이버에는 일시 중지 프레임 지원이 활성화되어 있습니다. 네트워크 인터페이스의 현재 설정을 표시하려면 다음을 입력합니다.

# ethtool --show-pause enp1s0
Pause parameters for enp1s0:
...
RX:     on
TX:     on
...

스위치 공급 업체에 문의하여 스위치가 일시 중지 프레임을 지원하는지 확인합니다.

24장. trace-cmd를 사용하여 대기 시간 추적

trace-cmd 유틸리티는 ftrace 유틸리티의 프런트 엔드입니다. trace-cmd 를 사용하면 /sys/kernel/debug/tracing/ 디렉터리에 쓸 필요 없이 ftrace 작업을 활성화할 수 있습니다. trace-cmd 는 설치에 오버헤드를 추가하지 않습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

24.1. trace-cmd 설치

trace-cmd 유틸리티는 ftrace 유틸리티에 프론트 엔드를 제공합니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

프로세스

  • trace-cmd 유틸리티를 설치합니다.

    # dnf install trace-cmd

24.2. trace-cmd 실행

trace-cmd 유틸리티를 사용하여 모든 ftrace 기능에 액세스할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

프로세스

  • trace-cmd 명령입력

    여기서 commandftrace 옵션입니다.

    참고

    명령 및 옵션의 전체 목록은 trace-cmd(1) 도움말 페이지를 참조하십시오. 대부분의 개별 명령에는 자체 도움말 페이지인 trace-cmd-명령 도 있습니다.

24.3. trace-cmd 예

명령 예제에서는 trace-cmd 유틸리티를 사용하여 커널 기능을 추적하는 방법을 보여줍니다.

  • myapp 이 실행되는 동안 커널 내에서 실행되는 레코딩 기능을 활성화하고 시작합니다.

    # trace-cmd record -p function myapp

    이는 myapp 과 관련이 없는 모든 CPU 및 모든 작업의 기능을 기록합니다.

  • 결과를 표시합니다.

    # trace-cmd report
  • myapp 이 실행되는 동안 sched 로 시작하는 함수만 기록합니다.

    # trace-cmd record -p function -l 'sched*' myapp
  • 모든 IRQ 이벤트를 활성화합니다.

    # trace-cmd start -e irq
  • wakeup_rt 추적기를 시작합니다.

    # trace-cmd start -p wakeup_rt
  • 함수 추적을 비활성화하는 동안 선점irqsoff 추적을 시작합니다.

    # trace-cmd start -p preemptirqsoff -d
    참고

    RHEL 8의 trace-cmd 버전은 function-trace 옵션을 사용하는 대신 ftrace_enabled 를 끕니다. trace-cmd start -p 함수를 사용하여 ftrace 를 다시 활성화할 수 있습니다.

  • trace-cmd 가 수정되기 전의 상태를 복원합니다.

    # trace-cmd start -p nop

    trace-cmd 를 사용한 후 시스템을 다시 시작했는지 여부에 관계없이 debugfs 파일 시스템을 사용하려는 경우 중요합니다.

  • 단일 추적 지점을 추적합니다.

    # trace-cmd record -e sched_wakeup ls /bin
  • 추적을 중지합니다.

    # trace-cmd record stop

25장. tuned-profiles-real-time을 사용하여 CPU 격리

애플리케이션 스레드에 가능한 가장 많은 실행 시간을 제공하기 위해 CPU를 분리할 수 있습니다. 따라서 CPU에서 가능한 한 많은 불필요한 작업을 제거하십시오. CPU 격리에는 일반적으로 다음이 포함됩니다.

  • 모든 사용자 공간 스레드 제거.
  • 바인딩되지 않은 커널 스레드 제거. 커널 관련 바인딩된 스레드는 특정 CPU에 연결되어 있으며 이동할 수 없습니다.
  • 시스템의 각 IRQ(interrupt Request) 번호 N/proc/irq/N/smp_affinity 속성을 수정하여 인터럽트를 제거합니다.

tuned-profiles-realtime 패키지의 isolated_cores=cpulist 구성 옵션을 사용하면 작업을 자동화하여 CPU를 격리할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

25.1. 분리할 CPU 선택

격리할 CPU를 선택하려면 시스템의 CPU 토폴로지를 신중하게 고려해야 합니다. 사용 사례마다 다른 구성이 필요합니다.

  • 캐시를 공유하여 스레드가 서로 통신해야 하는 다중 스레드 애플리케이션이 있는 경우 동일한 NUMA 노드 또는 물리적 소켓에 보관해야 합니다.
  • 관련이 없는 여러 실시간 애플리케이션을 실행하는 경우 CPU를 NUMA 노드 또는 소켓으로 분리하는 것이 적합할 수 있습니다.

hwloc 패키지는 lstopo-no-graphicsnumactl 을 포함하여 CPU에 대한 정보를 가져오는 데 유용한 유틸리티를 제공합니다.

사전 요구 사항

  • hwloc 패키지가 설치되어 있습니다.

프로세스

  1. 물리적 패키지에서 사용 가능한 CPU의 레이아웃을 확인합니다.

    # lstopo-no-graphics --no-io --no-legend --of txt

    그림 25.1. lstopo-no-graphics를 사용하여 CPU 레이아웃 표시

    lstopo 그래픽 출력 없음

    이 명령은 사용 가능한 코어 및 소켓 수와 NUMA 노드의 논리 거리를 표시하므로 다중 스레드 애플리케이션에 유용합니다.

    또한 hwloc-gui 패키지는 그래픽 출력을 생성하는 lstopo 유틸리티를 제공합니다.

  2. 노드 간 거리와 같은 CPU에 대한 자세한 정보를 확인합니다.

    # numactl --hardware
    available: 2 nodes (0-1)
    node 0 cpus: 0 1 2 3
    node 0 size: 16159 MB
    node 0 free: 6323 MB
    node 1 cpus: 4 5 6 7
    node 1 size: 16384 MB
    node 1 free: 10289 MB
    node distances:
    node   0   1
      0:  10  21
      1:  21  10

25.2. TuneD의 isolated_cores 옵션을 사용하여 CPU 격리

CPU 격리를 위한 초기 메커니즘은 커널 부팅 명령줄에 boot 매개변수 isolcpus=cpulist 를 지정하는 것입니다. RHEL for Real Time에 대해 이 작업을 수행하는 권장 방법은 TuneD 데몬과 tuned-profiles-realtime 패키지를 사용하는 것입니다.

참고

tuned-profiles-realtime 버전 2.19 이상에서 기본 제공 함수 calc_isolated_cores 는 초기 CPU 설정을 자동으로 적용합니다. /etc/tuned/realtime-variables.conf 구성 파일에는 기본 변수 콘텐츠가 isolated_cores=$f:calc_isolated_cores:2} 로 포함됩니다.

기본적으로 calc_isolated_cores 는 하우스키핑을 위해 소켓당 하나의 코어를 예약하고 나머지 항목을 격리합니다. 기본 구성을 변경해야 하는 경우 /etc/tuned/realtime-variables.conf 구성 파일에서 isolated_cores=${f:calc_isolated_cores:2} 행을 주석 처리하고 TuneD의 isolated_cores 옵션을 사용하여 CPU를 격리하는 절차 단계를 따릅니다.

사전 요구 사항

  • TuneDtuned-profiles-realtime 패키지가 설치됩니다.
  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. root 사용자로 텍스트 편집기에서 /etc/tuned/realtime-variables.conf 를 엽니다.
  2. isolated_cores=cpulist 를 설정하여 분리할 CPU를 지정합니다. CPU 번호와 범위를 사용할 수 있습니다.

    예:

    isolated_cores=0-3,5,7

    이는 코어 0, 1, 2, 3, 5 및 7을 격리합니다.

    8개의 코어가 있는 두 개의 소켓 시스템에서 NUMA 노드 0-3에 코어가 있고 NUMA 노드 1에는 코어 4-8이 있어 멀티 스레드 애플리케이션에 두 개의 코어를 할당합니다.

    isolated_cores=4,5

    이렇게 하면 사용자 공간 스레드가 CPU 4 및 5에 할당되지 않습니다.

    관련이 없는 애플리케이션의 다른 NUMA 노드에서 CPU를 선택하려면 다음을 지정합니다.

    isolated_cores=0,4

    이렇게 하면 사용자 공간 스레드가 CPU 0 및 4에 할당되지 않습니다.

  3. tuned-adm 유틸리티를 사용하여 실시간 TuneD 프로필을 활성화합니다.

    # tuned-adm profile realtime
  4. 변경 사항을 적용하려면 시스템을 재부팅합니다.

검증

  • 커널 명령줄에서 isolcpus 매개변수를 검색합니다.

    $ cat /proc/cmdline | grep isolcpus
    BOOT_IMAGE=/vmlinuz-4.18.0-305.rt7.72.el8.x86_64 root=/dev/mapper/rhel_foo-root ro crashkernel=auto rd.lvm.lv=rhel_foo/root rd.lvm.lv=rhel_foo/swap console=ttyS0,115200n81 isolcpus=0,4

25.3. nohz 및 nohz_full 매개변수를 사용하여 CPU 격리

nohznohz_full 매개변수는 지정된 CPU의 활동을 수정합니다. 이러한 커널 부팅 매개변수를 활성화하려면 realtime-virtual-host,realtime-virtual-guest 또는 cpu-partitioning 중 하나를 사용해야 합니다.

nohz=on

특정 CPU 세트에서 타이머 활동을 줄입니다.

nohz 매개변수는 주로 유휴 CPU의 타이머 인터럽트를 줄이는 데 사용됩니다. 이렇게 하면 유휴 CPU가 전원 모드에서 실행되도록 허용하여 배터리 수명을 줄일 수 있습니다. 실시간 응답 시간에 직접 유용한 것은 아니지만, nohz 매개변수는 실시간 응답 시간에 부정적인 영향을 미치지 않습니다. 그러나 실시간 성능에 긍정적인 영향을 미치는 nohz _full 매개변수를 활성화하려면 nohz 매개변수가 필요합니다.

nohz_full=cpulist
nohz_full 매개 변수는 지정된 CPU 목록의 타이머 눈금을 다르게 처리합니다. CPU가 nohz_full CPU로 지정되고 CPU에 실행 가능한 작업이 하나만 있는 경우 커널은 해당 CPU에 타이머 전송을 중지합니다. 결과적으로 애플리케이션을 실행하는 데 더 많은 시간이 소요되고 인터럽트 및 컨텍스트 전환에 소요되는 시간이 줄어들 수 있습니다.

26장. Limit_OTHER 작업 마이그레이션 제한

sched_nr _migrate 변수 를 사용하여 다른 CPU로 마이그레이션하는 작업을 제한할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

26.1. 작업 마이그레이션

Cryo stat_OTHER 작업이 많은 수의 다른 작업을 생성하는 경우 모두 동일한 CPU에서 실행됩니다. 마이그레이션 작업 또는 softirq 는 유휴 CPU에서 실행할 수 있도록 이러한 작업의 균형을 맞추려고 합니다.

sched_nr_migrate 옵션은 한 번에 이동할 작업 수를 지정하도록 조정할 수 있습니다. 실시간 작업에는 마이그레이션 방법이 다르기 때문에 이 작업의 직접적인 영향을 받지 않습니다. 그러나 softirq 가 작업을 이동할 때 실행 큐 스핀 잠금을 잠그므로 인터럽트를 비활성화합니다.

이동해야 하는 많은 작업이 있는 경우 인터럽트가 비활성화된 동안 발생합니다. 따라서 타이머 이벤트 또는 운동이 동시에 발생하지 않습니다. 이 경우 sched_nr_migrate 가 큰 값으로 설정된 경우 실시간 작업에 대한 심각한 대기 시간이 발생할 수 있습니다.

sched_nr_migrate 변수를 늘리면 실시간 대기 시간을 희생하는 많은 작업을 생성하는 Cryostat _OTHER 스레드에서 고성능을 제공합니다.

Cryostat _OTHER 작업 성능이 저하되는 경우 실시간 작업 대기 시간이 짧은 경우 값을 줄여야 합니다. 기본값은 8 입니다.

프로세스

  • sched_nr_migrate 변수의 값을 조정하려면 값을 /proc/sys/kernel/sched_nr_migrate 에 직접 에코합니다.

    # echo 2 > /proc/sys/kernel/sched_nr_migrate

검증

  • /proc/sys/kernel/sched_nr_migrate 의 내용을 봅니다.

    # cat > /proc/sys/kernel/sched_nr_migrate
    2

27장. TCP 성능 급증 감소

TCP 타임스탬프를 생성하면 TCP 성능이 저하될 수 있습니다. sysctl 명령은 TCP 관련 항목의 값을 제어하여 /proc/sys/net/ipv4/tcp_timestamps 에 있는 timestamps 커널 매개변수를 설정합니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

27.1. TCP 타임스탬프 끄기

TCP 타임스탬프를 끄면 TCP 성능 급증을 줄일 수 있습니다.

프로세스

  • TCP 타임 스탬프를 끕니다.

    # sysctl -w net.ipv4.tcp_timestamps=0
    net.ipv4.tcp_timestamps = 0

    출력에는 net.ip4.tcp_timestamps 옵션 값이 0 이라는 내용이 표시됩니다. 즉, TCP 타임스탬프가 비활성화됩니다.

27.2. TCP 타임 스탬프 사용

타임스탬프를 생성하면 TCP 성능 급증이 발생할 수 있습니다. TCP 타임스탬프를 비활성화하여 TCP 성능 급증을 줄일 수 있습니다. TCP 타임스탬프를 생성하는 것이 TCP 성능 급증을 유발하지 않는 경우 활성화할 수 있습니다.

프로세스

  • TCP 타임스탬프를 활성화합니다.

    # sysctl -w net.ipv4.tcp_timestamps=1
    net.ipv4.tcp_timestamps = 1

    출력은 net.ip4.tcp_timestamps 값이 1 임을 보여줍니다. 즉, TCP 타임스탬프가 활성화됩니다.

27.3. TCP 타임스탬프 상태 표시

TCP 타임 스탬프 생성 상태를 볼 수 있습니다.

프로세스

  • TCP 타임 스탬프 생성 상태를 표시합니다.

    # sysctl net.ipv4.tcp_timestamps
    net.ipv4.tcp_timestamps = 0

    1 은 타임스탬프가 생성됨을 나타냅니다. 값 0 은 타임스탬프가 생성되지 않음을 나타냅니다.

28장. RCU 콜백을 사용하여 CPU 성능 개선

RCU( Read-Copy-Update ) 시스템은 커널 내부의 스레드를 상호 제외하기 위한 잠금 메커니즘입니다. RCU 작업을 수행한 결과 메모리 제거 시 나중에 수행할 CPU에 호출이 대기열에 추가되는 경우가 있습니다.

RCU 콜백을 사용하여 CPU 성능을 개선하려면 다음을 수행합니다.

  • CPU 콜백 실행 후보가 되는 CPU를 제거할 수 있습니다.
  • 모든 RCU 콜백을 처리하기 위해 CPU를 할당할 수 있습니다. 이 CPU를 하우스키핑 CPU라고 합니다.
  • RCU 오프로드 스레드의 담당 CPU를 완화할 수 있습니다.

이 조합은 사용자 워크로드에 전용 CPU의 간섭을 줄입니다.

사전 요구 사항

  • 관리자 권한이 있습니다.
  • tuna 패키지가 설치되어 있어야 합니다.

28.1. RCU 콜백 오프로드

rcu_nocbsrcu_nocb_poll 커널 매개 변수를 사용하여 RCU 콜백을 오프로드할 수 있습니다.

프로세스

  • RCU 콜백 실행을 위한 후보에서 하나 이상의 CPU를 제거하려면 rcu_nocbs 커널 매개변수에 CPU 목록을 지정합니다.

    rcu_nocbs=1,4-6

    또는

    rcu_nocbs=3

    두 번째 예는 CPU 3이 호출되지 않은 CPU임을 커널에 지시합니다. 즉 RCU 콜백은 CPU 3에 고정된 rcuc/$CPU 스레드에서 수행되지 않지만 rcuo/$CPU 스레드에서 수행됩니다. 이 트래 헤드를 하우스키핑 CPU로 이동하여 CPU 3이 RCU 콜백 작업이 할당되지 않도록 할 수 있습니다.

28.2. RCU 콜백 이동

하우스키핑 CPU를 할당하여 모든 RCU 콜백 스레드를 처리할 수 있습니다. 이렇게 하려면 tuna 명령을 사용하여 모든 RCU 콜백을 하우스키핑 CPU로 이동합니다.

프로세스

  • RCU 콜백 스레드를 하우스키핑 CPU로 이동합니다.

    # tuna --threads=rcu --cpus=x --move

    여기서 x 는 하우스키핑 CPU의 CPU 번호입니다.

이 작업은 CPU X 이외의 모든 CPU가 RCU 콜백 스레드를 처리하지 못하도록 합니다.

28.3. RCU 오프로드 스레드에서 CPU 신뢰

RCU 오프로드 스레드가 다른 CPU에서 RCU 콜백을 수행할 수 있지만 각 CPU는 해당 RCU 오프로드 스레드를 고를 수 있습니다. 이 경우 CPU를 제거할 수 있습니다.

프로세스

  • rcu_nocb_poll 커널 매개 변수를 설정합니다.

    이 명령을 실행하면 타이머에서 주기적으로 RCU 오프로드 스레드를 발생시켜 콜백이 실행되는지 확인합니다.

29장. ftrace를 사용하여 대기 시간 추적

ftrace 유틸리티는 RHEL for Real Time 커널과 함께 제공되는 진단 기능 중 하나입니다. 개발자가 ftrace 를 사용하여 사용자 공간 외부에서 발생하는 대기 시간 및 성능 문제를 분석하고 디버깅할 수 있습니다. ftrace 유틸리티에는 다양한 방법으로 유틸리티를 사용할 수 있는 다양한 옵션이 있습니다. 컨텍스트 전환을 추적하거나 우선순위가 높은 작업이 발생하는 데 걸리는 시간을 측정하거나, 인터럽트 길이를 비활성화하거나, 지정된 기간 동안 실행되는 모든 커널 함수를 나열하는 데 사용할 수 있습니다.

함수 추적기와 같은 일부 ftrace 추적기에서는 과도하게 많은 양의 데이터를 생성할 수 있으므로 추적 로그 분석을 시간 소모적인 작업으로 전환할 수 있습니다. 그러나 애플리케이션이 중요한 코드 경로에 도달하면 추적자를 시작하고 종료하도록 지시할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

29.1. ftrace 유틸리티를 사용하여 대기 시간 추적

ftrace 유틸리티를 사용하여 대기 시간을 추적할 수 있습니다.

프로세스

  1. 시스템에서 사용 가능한 추적기를 확인합니다.

    # cat /sys/kernel/debug/tracing/available_tracers
    function_graph wakeup_rt wakeup preemptirqsoff preemptoff irqsoff function nop

    ftrace 의 사용자 인터페이스는 debugfs 내의 일련의 파일입니다.

    ftrace 파일은 /sys/kernel/debug/tracing/ 디렉터리에도 있습니다.

  2. /sys/kernel/debug/tracing/ 디렉터리로 이동합니다.

    # cd /sys/kernel/debug/tracing

    추적을 활성화하면 시스템 성능에 영향을 줄 수 있으므로 이 디렉터리의 파일은 root 사용자만 수정할 수 있습니다.

  3. 추적 세션을 시작하려면 다음을 수행합니다.

    1. /sys/kernel/debug/tracing/available_tracers 의 사용 가능한 추적기 목록에서 사용할 추적기를 선택합니다.
    2. 선택기 이름을 /sys/kernel/debug/tracing/current_tracer 에 삽입합니다.

      # echo preemptoff > /sys/kernel/debug/tracing/current_tracer
      참고

      echo 명령과 함께 단일 '>'를 사용하면 파일의 기존 값을 재정의합니다. 파일에 값을 추가하려면 대신 '>>'를 사용합니다.

  4. function-trace 옵션은 wakeup_rt,preemptirqsoff 와의 대기 시간을 추적하므로 자동으로 함수 추적을 활성화하여 오버헤드를 과장할 수 있기 때문에 유용합니다.

    functionfunction_graph 추적이 활성화되어 있는지 확인합니다.

    # cat /sys/kernel/debug/tracing/options/function-trace
    1
    • 1functionfunction_graph 추적이 활성화되었음을 나타냅니다.
    • 값이 0 이면 functionfunction_graph 추적이 비활성화됩니다.
  5. 기본적으로 functionfunction_graph 추적이 활성화됩니다. functionfunction_graph 추적을 켜거나 해제하려면 적절한 값을 /sys/kernel/debug/tracing/options/function-trace 파일에 에코합니다.

    # echo 0 > /sys/kernel/debug/tracing/options/function-trace
    # echo 1 > /sys/kernel/debug/tracing/options/function-trace
    중요

    echo 명령을 사용할 때 값과 > 문자 사이에 공백 문자를 배치해야 합니다. 쉘 프롬프트에서 0 >, 1 > , 1> 및 2 >를 사용하는 것은 표준 입력, 표준 출력 및 표준 오류를 나타냅니다. 실수로 사용하면 예기치 않은 추적 출력이 발생할 수 있습니다.

  6. /debugfs/tracing/ 디렉터리에 있는 다양한 파일의 값을 변경하여 추적기의 세부 정보 및 매개 변수를 조정합니다.

    예를 들면 다음과 같습니다.

    irqsoff,preemptoff,preempirqsoffwakeup 추적기에서는 대기 시간을 지속적으로 모니터링합니다. tracing_max_latency 에 기록된 대기 시간보다 큰 대기 시간을 기록하면 해당 대기 시간이 기록되고 tracing_max_latency 가 새 최대 시간으로 업데이트됩니다. 이러한 방식으로 tracing_max_latency 는 항상 마지막으로 재설정되었기 때문에 기록된 가장 높은 대기 시간을 표시합니다.

    • 최대 대기 시간을 재설정하려면 tracing_max_latency 파일에 0 을 에코합니다.

      # echo 0 > /sys/kernel/debug/tracing/tracing_max_latency
    • 설정된 양보다 큰 대기 시간만 보려면 마이크로초 단위로 값을 에코합니다.

      # echo 200 > /sys/kernel/debug/tracing/tracing_max_latency

      추적 임계값이 설정되면 최대 대기 시간 설정을 덮어씁니다. 대기 시간이 임계값보다 크면 최대 대기 시간에 관계없이 기록됩니다. 추적 파일을 검토할 때 마지막으로 기록된 대기 시간만 표시됩니다.

    • 임계값을 설정하려면 기록해야 하는 microseconds 수를 에코합니다.

      # echo 200 > /sys/kernel/debug/tracing/tracing_thresh
  7. 추적 로그를 확인합니다.

    # cat /sys/kernel/debug/tracing/trace
  8. 추적 로그를 저장하려면 다른 파일에 복사합니다.

    # cat /sys/kernel/debug/tracing/trace > /tmp/lat_trace_log
  9. 추적 중인 함수 보기:

    # cat /sys/kernel/debug/tracing/set_ftrace_filter
  10. /sys/kernel/debug/tracing/set_ftrace_filter 의 설정을 편집하여 추적되는 함수를 필터링합니다. 파일에 필터를 지정하지 않으면 모든 기능이 추적됩니다.
  11. 필터 설정을 변경하려면 추적할 함수의 이름을 에코합니다. 이 필터를 사용하면 검색어의 시작 또는 끝에 '*' 와일드카드를 사용할 수 있습니다.

    예를 들어 ftrace 예제 를 참조하십시오.

29.2. ftrace 파일

다음은 /sys/kernel/debug/tracing/ 디렉터리의 기본 파일입니다.

ftrace 파일

trace
ftrace 추적의 출력을 표시하는 파일입니다. 이 파일을 읽을 때 추적이 중지되고 이벤트 읽기를 사용하지 않기 때문에 이는 실제로 추적의 스냅샷입니다. 즉, 사용자가 추적을 비활성화하고 이 파일을 읽는 경우 읽을 때마다 동일한 항목을 보고합니다.
trace_pipe
ftrace 추적의 출력을 표시하는 파일은 추적을 라이브로 읽을 때 사용합니다. 프로듀서/소유자 추적입니다. 즉, 각 읽기는 읽은 이벤트를 사용합니다. 이를 사용하여 추적을 읽지 않고 활성 추적을 읽을 수 있습니다.
available_tracers
커널에 컴파일된 ftrace 추적기 목록입니다.
current_tracer
ftrace 추적기를 활성화하거나 비활성화합니다.
이벤트
추적할 이벤트가 포함된 디렉터리이며 이벤트를 활성화 또는 비활성화하는 데 사용할 수 있으며 이벤트에 대한 필터를 설정할 수 있습니다.
tracing_on
ftrace 버퍼에 레코딩을 비활성화하고 활성화합니다. tracing_on 파일을 통해 추적을 비활성화해도 커널 내에서 발생하는 실제 추적이 비활성화됩니다. 버퍼에 대한 쓰기만 비활성화합니다. 추적을 수행하는 작업은 여전히 발생하지만 데이터는 아무데도 이동하지 않습니다.

29.3. ftrace 추적기

커널 구성 방법에 따라 지정된 커널에서 모든 추적기를 사용할 수 있는 것은 아닙니다. RHEL for Real Time 커널의 경우 추적 및 디버그 커널은 프로덕션 커널과 다른 추적기를 갖습니다. 이는 추적기가 커널에 구성되었지만 활성화되지 않은 경우 일부 추적기에서 눈에 띄는 오버헤드가 있기 때문입니다. 이러한 추적기는 추적디버그 커널에만 활성화됩니다.

추적기

function
가장 널리 사용되는 추적기 중 하나입니다. 커널 내에서 함수 호출을 추적합니다. 이로 인해 추적된 함수 수에 따라 눈에 띄는 오버헤드가 발생할 수 있습니다. 활성화하지 않으면 오버헤드가 거의 발생하지 않습니다.
function_graph

function_graph 추적기는 결과를 보다 시각적으로 최적의 형식으로 표시하도록 설계되었습니다. 이 추적기에서는 함수 종료도 추적하여 커널에서 함수 호출 흐름을 표시합니다.

참고

이 추적기 사용 시 함수 추적기보다 많은 오버헤드가 있지만 비활성화 시 낮은 오버헤드가 동일합니다.

wakeup
모든 CPU에서 발생하는 활동을 보고하는 전체 CPU 추적기입니다. 해당 작업이 실시간 작업인지 여부에 관계없이 시스템에서 가장 높은 우선 순위의 작업을 복구하는 데 걸리는 시간을 기록합니다. 비실시간 작업이 발생하지 않는 데 걸리는 최대 시간을 기록하면 실시간 작업을 복구하는 데 걸리는 시간을 숨깁니다.
wakeup_rt
모든 CPU에서 발생하는 활동을 보고하는 전체 CPU 추적기입니다. 현재 가장 높은 우선 순위 작업에서 걸리는 시간을 예약할 때까지 기록합니다. 이 추적기에서는 실시간 작업의 시간만 기록합니다.
preemptirqsoff
선점 또는 인터럽트를 비활성화하는 영역을 추적하고 선점 또는 인터럽트가 비활성화된 최대 시간을 기록합니다.
preemptoff
선점qsoff 추적기와 유사하지만 사전 선점이 비활성화된 최대 간격만 추적합니다.
irqsoff
선점irqsoff 추적기와 유사하지만 인터럽트가 비활성화된 최대 간격만 추적합니다.
NOP
기본 추적기입니다. 추적 기능 자체를 제공하지 않지만 이벤트가 모든 추적기에 상호 작용할 수 있으므로 nop 추적기가 이벤트 추적에 사용됩니다.

29.4. ftrace 예제

다음은 추적 중인 함수 필터링을 변경하는 여러 예제를 제공합니다. 단어의 시작과 끝 모두에서 * 와일드카드를 사용할 수 있습니다. 예를 들어 *irq\* 는 이름에 irq 가 포함된 모든 함수를 선택합니다. 그러나 와일드카드는 단어 내에서 사용할 수 없습니다.

검색 용어와 와일드카드 문자를 큰따옴표로 연결하면 쉘이 현재 작업 디렉터리에 대한 검색을 확장하지 않습니다.

필터 예

  • schedule 함수만 추적합니다.

    # echo schedule > /sys/kernel/debug/tracing/set_ftrace_filter
  • lock 으로 끝나는 모든 함수 추적:

    # echo "*lock" > /sys/kernel/debug/tracing/set_ftrace_filter
  • spin_ 로 시작하는 모든 함수를 추적합니다.

    # echo "spin_*" > /sys/kernel/debug/tracing/set_ftrace_filter
  • 이름에 cpu 를 사용하여 모든 함수를 추적합니다.

    # echo "cpu" > /sys/kernel/debug/tracing/set_ftrace_filter

30장. 애플리케이션 타임스탬프

빈번한 타임 스탬프를 수행하는 애플리케이션은 시계를 읽는 CPU 비용의 영향을 받습니다. 클럭을 읽는 데 사용되는 높은 비용과 시간은 애플리케이션의 성능에 부정적인 영향을 미칠 수 있습니다.

기본 클록보다 읽기 메커니즘이 있는 하드웨어 시계를 선택하여 시계를 읽는 비용을 줄일 수 있습니다.

RHEL for Real Time에서는 clock_gettime() 함수와 POSIX 클록을 사용하여 가능한 CPU 비용이 가장 낮은 클럭 읽기를 생성하여 추가 성능 이점을 얻을 수 있습니다.

이러한 이점은 높은 읽기 비용으로 하드웨어 클록을 사용하는 시스템에 대해 더 명확합니다.

30.1. POSIX 클록

POSIX는 시간 소스를 구현하고 나타내는 표준입니다. 시스템의 다른 애플리케이션에 영향을 주지 않고 애플리케이션에 POSIX 시계를 할당할 수 있습니다. 이는 커널에서 선택하고 시스템 전체에서 구현되는 하드웨어 클록과 대조적입니다.

지정된 POSIX 시계를 읽는 데 사용되는 함수는 <time .h>에 정의된 clock_gettime() 입니다. clock_gettime() 과 반대되는 커널은 시스템 호출입니다. 사용자 프로세스가 clock_gettime() 을 호출할 때:

  1. 해당 C 라이브러리(glibc)는 sys_clock_gettime() 시스템 호출을 호출합니다.
  2. sys_clock_gettime() 은 요청된 작업을 수행합니다.
  3. sys_clock_gettime() 은 사용자 프로그램에 결과를 반환합니다.

그러나 사용자 애플리케이션에서 커널로의 컨텍스트 전환에는 CPU 비용이 있습니다. 이러한 비용은 매우 낮지만 작업이 수천 번 반복되면 누적된 비용이 애플리케이션의 전체 성능에 영향을 미칠 수 있습니다. 커널로 컨텍스트 전환을 방지하기 위해 더 빠르게 클럭을 읽을 수 있도록 CLOCK_MONOTONIC_COARSECLOCK_REALTIME_COARSE POSIX 클록에 대한 지원이 VDSO(가상 동적 공유 오브젝트) 라이브러리 함수 형태로 추가되었습니다.

_COARSE 클럭 변형 중 하나를 사용하여 clock_gettime() 에 의해 수행되는 시간 읽기는 커널 개입이 필요하지 않으며 사용자 공간에서 완전히 실행됩니다. 이는 상당한 성능 이점을 제공합니다. _COARSE 클록에 대한 시간 읽기에는 밀리 초(ms) 해상도가 있으므로 1ms보다 작은 시간 간격은 기록되지 않습니다. POSIX 클록의 _COARSE 변형은 밀리 초 클록 해상도를 수용할 수 있는 모든 애플리케이션에 적합합니다.

30.2. clock_gettime의 _COARSE 클럭 변형

예제 코드 출력은 CLOCK_MONOTONIC_COARSE POSIX 클록과 함께 clock_gettime 함수 사용을 보여줍니다.

#include <time.h>

main()
{
	int rc;
	long i;
	struct timespec ts;

	for(i=0; i<10000000; i++) {
		rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
	}
}

위 예제에서는 clock_gettime() 의 반환 코드를 확인하기 위해 검사를 추가하거나, rc 변수의 값을 확인하거나, ts 구조의 내용을 신뢰할 수 있도록 하여 개선할 수 있습니다.

참고

clock_gettime() 도움말 페이지는 보다 안정적인 애플리케이션을 작성하는 방법에 대한 자세한 정보를 제공합니다.

중요

clock_gettime() 함수를 사용하는 프로그램은 gcc 명령줄에 -lrt 를 추가하여 rt 라이브러리와 연결해야 합니다.

$ gcc clock_timing.c -o clock_timing -lrt

31장. TCP_NODELAY를 사용하여 네트워크 대기 시간 개선

기본적으로 TCP 는 나글의 알고리즘을 사용하여 한 번에 모두 보낼 작은 발신 패킷을 수집합니다. 이로 인해 대기 시간이 증가할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

31.1. TCP_NODELAY 사용의 영향

전송된 모든 패킷에서 대기 시간이 짧은 애플리케이션은 TCP_NODELAY 옵션을 활성화한 소켓에서 실행해야 합니다. 이렇게 하면 이벤트가 발생하는 즉시 커널에 버퍼 쓰기가 전송됩니다.

참고
TCP_NODELAY 가 효과적이기 위해서는 애플리케이션이 논리적으로 작은 버퍼 쓰기를 수행하지 않도록 해야 합니다. 그렇지 않으면 이러한 작은 쓰기로 인해 TCP 가 이러한 여러 버퍼를 개별 패킷으로 보내 전체 성능이 저하됩니다.

애플리케이션에 논리적으로 연결된 버퍼가 여러 개 있고 하나의 패킷으로 전송해야 하는 경우 다음 해결 방법 중 하나를 적용하여 성능이 저하되지 않도록 합니다.

  • 메모리에 연속된 패킷을 빌드한 다음 TCP _NODELAY 로 구성된 소켓의 TCP로 논리 패킷을 보냅니다.
  • I/O 벡터를 만들고 TCP_NODELAY 로 구성된 소켓에서 writev 명령을 사용하여 커널에 전달합니다.
  • TCP_CORK 옵션을 사용합니다. TCP_CORKTCP 에 애플리케이션이 패킷을 전송하기 전에 코크를 제거할 때까지 기다립니다. 이 명령은 수신한 버퍼가 기존 버퍼에 추가되도록 합니다. 이를 통해 애플리케이션은 커널 공간에 패킷을 빌드할 수 있으며, 계층에 대한 추상화를 제공하는 다양한 라이브러리를 사용할 때 필요할 수 있습니다.

애플리케이션의 다양한 구성 요소에 의해 커널에 논리 패킷이 빌드되면 소켓을 분리하여 TCP 가 누적된 논리 패킷을 즉시 보낼 수 있어야 합니다.

31.2. TCP_NODELAY 활성화

TCP_NODELAY 옵션은 이벤트가 발생할 때 지연 없이 커널에 버퍼 쓰기를 보냅니다. setsockopt() 함수를 사용하여 TCP_NODELAY 를 활성화합니다.

프로세스

  1. TCP 애플리케이션의 .c 파일에 다음 행을 추가합니다.

    int one = 1;
    setsockopt(descriptor, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
  2. 파일을 저장하고 편집기를 종료합니다.
  3. 성능이 저하되지 않도록 다음 해결 방법 중 하나를 적용합니다.

    • 메모리에 연속된 패킷을 빌드한 다음 TCP _NODELAY 로 구성된 소켓의 TCP로 논리 패킷을 보냅니다.
    • I/O 벡터를 만들고 TCP_NODELAY 로 구성된 소켓에서 writev 를 사용하여 커널에 전달합니다.

31.3. TCP_CORK 활성화

TCP_CORK 옵션은 소켓이 "알려진" 때까지 TCP 가 패킷을 전송하지 못하도록 합니다.

프로세스

  1. TCP 애플리케이션의 .c 파일에 다음 행을 추가합니다.

    int one = 1;
    setsockopt(descriptor, SOL_TCP, TCP_CORK, &one, sizeof(one));
  2. 파일을 저장하고 편집기를 종료합니다.
  3. 애플리케이션의 다양한 구성 요소에 의해 커널에 논리 패킷이 빌드되면 TCP_CORK 를 비활성화합니다.

    int zero = 0;
    setsockopt(descriptor, SOL_TCP, TCP_CORK, &zero, sizeof(zero));

    TCP 는 누적된 논리 패킷을 애플리케이션에서 추가 패킷을 기다리지 않고 즉시 전송합니다.

32장. 뮤지션을 사용하여 리소스 초과 방지

상호 제외(mutex) 알고리즘은 공통 리소스의 과도한 사용을 방지하는 데 사용됩니다.

32.1. Mutex 옵션

상호 제외(mutex) 알고리즘은 공통 리소스를 동시에 사용하는 프로세스를 방지하는 데 사용됩니다. 빠른 사용자 공간 뮤지션(futex)은 사용자 공간 스레드가 커널 공간으로 컨텍스트 전환이 필요하지 않고 뮤지션을 클레임할 수 있도록 하는 도구입니다.A fast user-space mutex (futex) is a tool that allows a user-space thread to claim a mutex without requiring a context switch to kernel space, provided the mutex is not already held by another thread.

표준 특성을 사용하여 pthread_mutex_t 개체를 초기화하면 개인, 비재귀, 비robust 및 비 우선순위 상속 가능 뮤지션이 생성됩니다. 이 오브젝트는 pthreads API 및 RHEL for Real Time 커널에서 제공하는 벤싱을 제공하지 않습니다.

pthreads API 및 RHEL for Real Time 커널의 이점을 활용하려면 pthread_mutexattr_t 오브젝트를 생성합니다. 이 오브젝트는 futex에 대해 정의된 속성을 저장합니다.

참고

futexMutex 라는 용어는 POSIX 스레드(pthread) 뮤지스트 구문을 설명하는 데 사용됩니다.

32.2. Mutex 특성 개체 생성

뮤지션에 대한 추가 기능을 정의하려면 pthread_mutexattr_t 오브젝트를 만듭니다. 이 오브젝트는 futex에 대해 정의된 속성을 저장합니다. 이는 항상 수행해야 하는 기본 안전 절차입니다.

프로세스

  • 다음 중 하나를 사용하여 Mutex 특성 개체를 만듭니다.Create the mutex attribute object using one of the following:

    • pthread_mutex_t(my_mutex);
    • pthread_mutexattr_t(&my_mutex_attr);
    • pthread_mutexattr_init(&my_mutex_attr);

고급 뮤지션 속성에 대한 자세한 내용은 고급 뮤지션 특성을 참조하십시오.

32.3. 표준 특성을 사용하여 뮤지션 생성

표준 특성을 사용하여 pthread_mutex_t 개체를 초기화하면 개인, 비재귀, 비robust 및 비 우선순위 상속 가능 뮤지션이 생성됩니다.

프로세스

  • 다음 중 하나를 사용하여 pthreads 아래에 Mutex 개체를 만듭니다.

    • pthread_mutex_t(my_mutex);
    • pthread_mutex_init(&my_mutex, &my_mutex_attr);

      여기서 &my_mutex_attr; 은 뮤지션 특성 오브젝트입니다.

32.4. 고급 뮤추스 속성

다음과 같은 고급 뮤지션 특성을 뮤텍스 특성 개체에 저장할 수 있습니다.The following advanced mutex attributes can be stored in a mutex attribute object:

뮤추스 특성

공유 및 개인 뮤지션

공유 Mutex는 프로세스 간에 사용할 수 있지만 훨씬 더 많은 오버헤드를 생성할 수 있습니다.

pthread_mutexattr_setpshared(&my_mutex_attr, PTHREAD_PROCESS_SHARED);

실시간 우선 순위 상속

우선 순위 상속을 사용하여 우선 순위 내 버전 문제를 방지할 수 있습니다.

pthread_mutexattr_setprotocol(&my_mutex_attr, PTHREAD_PRIO_INHERIT);

강력한 뮤추스

pthread가 종료되면 pthread 아래의 강력한 뮤지션이 릴리스됩니다. 그러나 이로 인해 높은 오버헤드 비용이 발생합니다. 이 문자열의 _NP 는 이 옵션이 POSIX가 아니거나 이식할 수 없음을 나타냅니다.

pthread_mutexattr_setrobust_np(&my_mutex_attr, PTHREAD_MUTEX_ROBUST_NP);

뮤지션 초기화

공유 Mutex는 프로세스 간에 사용할 수 있지만 훨씬 더 많은 오버헤드를 생성할 수 있습니다.

pthread_mutex_init(&my_mutex_attr, &my_mutex);

32.5. 뮤지션 특성 개체 정리

Mutex 특성 개체를 사용하여 Mutex를 만든 후에는 특성 개체를 유지하여 동일한 형식의 더 많은 뮤지션을 초기화하거나 정리할 수 있습니다.After the mutex has been created using the mutex attribute object, you can keep the attribute object to initialize more mutexes of the same type, or you can clean it up. 뮤지컬은 두 경우 모두 영향을 받지 않습니다.

프로세스

  • pthread_mutexattr_destroy() 함수를 사용하여 특성 오브젝트를 정리합니다.

    pthread_mutexattr_destroy(&my_mutex_attr);

    뮤지션은 이제 일반 pthread_mutex 로 작동하며 정상적으로 잠금 해제, 잠금 해제 및 삭제할 수 있습니다.

33장. 애플리케이션 성능 분석

perf 는 성능 분석 도구입니다. 간단한 명령줄 인터페이스를 제공하고 Linux 성능 측정의 CPU 하드웨어 차이를 추상화합니다. perf 는 커널이 내보낸 perf_events 인터페이스를 기반으로 합니다.

perf 의 한 가지 장점은 커널과 아키텍처 중립적이라는 것입니다. 특정 시스템 구성 없이도 분석 데이터를 검토할 수 있습니다.

사전 요구 사항

  • perf 패키지가 시스템에 설치되어 있어야 합니다.
  • 관리자 권한이 있습니다.

33.1. 시스템 전체 통계 수집

perf record 명령은 시스템 전체 통계를 수집하는 데 사용됩니다. 모든 프로세서에서 사용할 수 있습니다.

프로세스

  • 시스템 전체 성능 통계를 수집합니다.

    # perf record -a
    ^C[ perf record: Woken up 1 times to write data ]
    [ perf record: Captured and wrote 0.725 MB perf.data (~31655 samples) ]

    이 예제에서는 모든 CPU가 -a 옵션으로 표시되고 프로세스는 몇 초 후에 종료되었습니다. 결과에 따르면 25MB의 데이터를 수집하여 새로 생성된 perf.data 파일에 저장했습니다.

검증

  • 결과 파일이 생성되었는지 확인합니다.

    # ls
    perf.data

33.2. 성능 분석 결과 아카이브

perf archive 명령을 사용하여 다른 시스템에서 perf 의 결과를 분석할 수 있습니다. 다음과 같은 경우 필요하지 않을 수 있습니다.

  • 바이너리 및 라이브러리와 같은 동적 공유 오브젝트(DSO)는 ~/.debug/ 캐시와 같은 분석 시스템에 이미 존재합니다.
  • 두 시스템에는 모두 동일한 바이너리 세트가 있습니다.

프로세스

  1. perf 명령에서 결과 아카이브를 생성합니다.

    # perf archive
  2. 아카이브에서 tarball을 만듭니다.

    # tar cvf perf.data.tar.bz2 -C ~/.debug

33.3. 성능 분석 결과 분석

이제 perf 레코드 기능의 데이터를 perf report 명령을 사용하여 직접 조사할 수 있습니다.

프로세스

  • perf.data 파일 또는 보관된 tarball에서 결과를 직접 분석합니다.

    # perf report

    보고서의 출력은 애플리케이션별로 최대 CPU 사용량(%)에 따라 정렬됩니다. 샘플이 프로세스의 커널 또는 사용자 영역에서 발생했는지 여부를 나타냅니다.

    이 보고서에는 샘플이 사용된 모듈에 대한 정보가 표시됩니다.

    • 커널 모듈에서 실행되지 않은 커널 샘플은 [kernel.kallsyms] 표기법으로 표시됩니다.
    • 커널 모듈에서 발생한 커널 샘플은 ', '[ext4] 로 표시됩니다.
    • 사용자 공간의 프로세스에서 결과에 해당 프로세스와 연결된 공유 라이브러리가 표시될 수 있습니다.

      이 보고서는 프로세스가 커널 또는 사용자 공간에서도 발생하는지 여부를 나타냅니다.

    • 결과 [.] 는 사용자 공간을 나타냅니다.
    • 결과 ''는 커널 공간을 나타냅니다.

    숙련된 perf 개발자에게 적합한 데이터를 포함하여 검토를 위해 세분화된 세부 정보를 사용할 수 있습니다.

33.4. 사전 정의된 이벤트 나열

하드웨어 추적 활동을 가져오는 데 사용할 수 있는 다양한 옵션이 있습니다.

프로세스

  • 사전 정의된 하드웨어 및 소프트웨어 이벤트를 나열합니다.

    # perf list
    List of pre-defined events (to be used in -e):
      cpu-cycles OR cycles                               [Hardware event]
      stalled-cycles-frontend OR idle-cycles-frontend    [Hardware event]
      stalled-cycles-backend OR idle-cycles-backend      [Hardware event]
      instructions                                       [Hardware event]
      cache-references                                   [Hardware event]
      cache-misses                                       [Hardware event]
      branch-instructions OR branches                    [Hardware event]
      branch-misses                                      [Hardware event]
      bus-cycles                                         [Hardware event]
    
      cpu-clock                                          [Software event]
      task-clock                                         [Software event]
      page-faults OR faults                              [Software event]
      minor-faults                                       [Software event]
      major-faults                                       [Software event]
      context-switches OR cs                             [Software event]
      cpu-migrations OR migrations                       [Software event]
      alignment-faults                                   [Software event]
      emulation-faults                                   [Software event]
      ...[output truncated]...

33.5. 지정된 이벤트에 대한 통계 가져오기

perf stat 명령을 사용하여 특정 이벤트를 볼 수 있습니다.

프로세스

  1. perf stat 기능을 사용하여 컨텍스트 전환 수를 확인합니다.

    # perf stat -e context-switches -a sleep 5
    Performance counter stats for 'sleep 5':
    
                15,619 context-switches
    
           5.002060064 seconds time elapsed

    결과에 따르면 5초 동안 15619 컨텍스트 전환이 발생했습니다.

  2. 스크립트를 실행하여 파일 시스템 활동을 확인합니다. 다음은 예제 스크립트를 보여줍니다.

    # for i in {1..100}; do touch /tmp/$i; sleep 1; done
  3. 다른 터미널에서 perf stat 명령을 실행합니다.

    # perf stat -e ext4:ext4_request_inode -a sleep 5
     Performance counter stats for 'sleep 5':
    
                     5 ext4:ext4_request_inode
    
           5.002253620 seconds time elapsed

    결과에는 5개의 파일을 만들도록 요청한 스크립트가 5초 후에 inode 요청이 있음을 나타냅니다.

Hidden -ng 툴은 치명적이지 않은 조건에서 효율성의 좋은 수준을 유지하기 위해 시스템의 기능을 측정합니다. stress-ng 툴은 모든 커널 인터페이스를 로드하고 강조하기 위해 워크로드 생성기입니다. 여기에는 학회로 알려진 다양한 학계 메커니즘이 포함됩니다. 부하 테스트는 머신 작업을 어렵게 만들고 시스템이 과도하게 작동할 때 발생하는 열 오버런 및 운영 체제 버그와 같은 하드웨어 문제를 트립합니다.

Cryostat 이상의 다양한 테스트가 있습니다. 여기에는 부동 소수점, 정수, 비트 조작, 제어 흐름 및 가상 메모리 테스트를 수행하는 CPU별 테스트가 포함됩니다.

참고

일부 테스트는 제대로 설계되지 않은 하드웨어에서 시스템의 열 영역 트립 지점에 영향을 미칠 수 있으므로 주의해서 가중한 툴을 사용하십시오. 이는 시스템 성능에 영향을 미칠 수 있으며 과도한 시스템 충돌로 인해 중지하기 어려울 수 있습니다.

34.1. CPU 부동 소수점 단위 및 프로세서 데이터 캐시 테스트

부동 소수점 단위는 부동 소수점 연산을 수행하는 프로세서의 기능 부분입니다.A floating point unit is the functional part of the processor that performs floating point arithmetic operations. 부동 소수점 단위는 수학적 작업을 처리하고 부동 숫자 또는 10진수 계산을 더 간단하게 만듭니다.

--matrix-method 옵션을 사용하면 CPU 부동 소수점 작업 및 프로세서 데이터 캐시 테스트를 과부하시킬 수 있습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 60초 동안 하나의 CPU에서 부동 지점을 테스트하려면 --matrix 옵션을 사용합니다.

    # stress-ng --matrix 1 -t 1m
  • 60초 동안 두 개 이상의 CPU에서 여러 과부하를 실행하려면 --times 또는 -t 옵션을 사용합니다.

    # stress-ng --matrix 0 -t 1m
    
    stress-ng --matrix 0 -t 1m --times
    stress-ng: info:  [16783] dispatching hogs: 4 matrix
    stress-ng: info:  [16783] successful run completed in 60.00s (1 min, 0.00 secs)
    stress-ng: info:  [16783] for a 60.00s run time:
    stress-ng: info:  [16783] 240.00s available CPU time
    stress-ng: info:  [16783] 205.21s user time   ( 85.50%)
    stress-ng: info:  [16783] 0.32s system time (  0.13%)
    stress-ng: info:  [16783] 205.53s total time  ( 85.64%)
    stress-ng: info:  [16783] load average: 3.20 1.25 1.40

    CPU 번호가 0인 특수 모드에서 실행 가능한 CPU를 쿼리하여 CPU 번호를 지정할 필요가 없습니다.

    필요한 총 CPU 시간은 4x 60초(240초)이며, 0.13%가 커널에 있고, 85.50%는 사용자 시간이며, stress-ng 는 모든 CPU의 85.64%를 실행합니다.

  • POSIX 메시지 큐를 사용하여 프로세스 간에 전달되는 메시지를 테스트하려면 -mq 옵션을 사용합니다.

    # stress-ng --mq 0 -t 30s --times --perf

    mq 옵션은 POSIX 메시지 큐를 사용하여 컨텍스트 전환을 강제하도록 특정 수의 프로세스를 구성합니다. 이 부하 테스트는 낮은 데이터 캐시 누락을 목표로 합니다.

34.2. 여러 과부하 메커니즘을 사용하여 CPU 테스트

stress-ng 툴은 여러 번의 과부하 테스트를 실행합니다. 기본 모드에서는 지정된 과부하 메커니즘을 병렬로 실행합니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 다음과 같이 여러 CPU 스포저 인스턴스를 실행합니다.

    # stress-ng --cpu 2 --matrix 1 --mq 3 -t 5m

    이 예에서 stress-ng 는 CPU 스포터의 두 인스턴스, 매트릭스 과부하 인스턴스 중 하나 인스턴스와 5분 동안 테스트하기 위한 메시지 큐 과부하의 인스턴스 3개를 실행합니다.

  • 모든 stress 테스트를 병렬로 실행하려면 -all 옵션을 사용합니다.

    # stress-ng --all 2

    이 예에서 stress-ng 는 모든 과부하 테스트의 두 인스턴스를 병렬로 실행합니다.

  • 특정 순서로 각각의 다른 강조자를 실행하려면 --seq 옵션을 사용합니다.

    # stress-ng --seq 4 -t 20

    이 예에서 stress-ng 는 온라인 CPU 수와 일치하는 각 과부하의 인스턴스 수와 함께 20분 동안 하나씩 모든 과부하를 실행합니다.

  • 테스트 실행에서 특정 강조자를 제외하려면 -x 옵션을 사용합니다.

    # stress-ng --seq 1 -x numa,matrix,hdd

    이 예에서 stress-ngnuma,hddkey stressors 메커니즘을 제외하고 각 강조자를 실행합니다.

34.3. CPU heat 생성 측정

CPU heat 생성을 측정하기 위해 지정된 과부하는 최대 heat 생성에서 시스템의 난관 신뢰성 및 안정성을 테스트하기 위해 짧은 기간 동안 높은 온도를 생성합니다. --matrix-size 옵션을 사용하면 짧은 기간 동안 Celsius 수준의 CPU 온도를 측정할 수 있습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. 지정된 기간 동안 높은 온도에서 CPU 동작을 테스트하려면 다음 명령을 실행합니다.

    # stress-ng --matrix 0 --matrix-size 64 --tz -t 60
    
      stress-ng: info:  [18351] dispatching hogs: 4 matrix
      stress-ng: info:  [18351] successful run completed in 60.00s (1 min, 0.00 secs)
      stress-ng: info:  [18351] matrix:
      stress-ng: info:  [18351] x86_pkg_temp   88.00 °C
      stress-ng: info:  [18351] acpitz   87.00 °C

    이 예에서 stress-ng 는 60초 동안 elsius에 도달하도록 프로세서 패키지 열 영역을 구성합니다.

  2. 선택 사항: 실행 종료 시 보고서를 인쇄하려면 --tz 옵션을 사용합니다.

    # stress-ng --cpu 0 --tz -t 60
    
      stress-ng: info:  [18065] dispatching hogs: 4 cpu
      stress-ng: info:  [18065] successful run completed in 60.07s (1 min, 0.07 secs)
      stress-ng: info:  [18065] cpu:
      stress-ng: info:  [18065] x86_pkg_temp   88.75 °C
      stress-ng: info:  [18065] acpitz   88.38 °C

34.4. bogo 작업을 사용하여 테스트 결과 측정

stress-ng 툴은 초당 bogo 작업을 측정하여 과부하 테스트 처리량을 측정할 수 있습니다. bogo 작업 크기는 실행 중인 과부하에 따라 달라집니다. 테스트 결과는 정확하지 않지만 대략적인 성능 추정치를 제공합니다.

이 측정을 정확한 벤치마크 메트릭으로 사용해서는 안 됩니다. 이러한 추정치는 과부하를 구축하는 데 사용되는 다양한 커널 버전 또는 다양한 컴파일러 버전에서 시스템 성능 변경을 이해하는 데 도움이 됩니다. --metrics-brief 옵션을 사용하여 시스템에서 사용 가능한 총 bogo 작업 및 매트릭스 과부하 성능을 표시합니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • bogo 작업을 사용하여 테스트 결과를 측정하려면 --metrics-brief 옵션과 함께 를 사용합니다.

    # stress-ng --matrix 0 -t 60s --metrics-brief
    
    stress-ng: info: [17579] dispatching hogs: 4 matrix
    stress-ng: info: [17579] successful run completed in 60.01s (1 min, 0.01 secs)
    stress-ng: info: [17579] stressor bogo ops real time usr time sys time   bogo ops/s bogo ops/s
    stress-ng: info:  [17579]                  (secs)   (secs)  (secs)  (real time) (usr+sys time)
    stress-ng: info:  [17579] matrix  349322   60.00    203.23   0.19      5822.03      1717.25

    --metrics-brief 옵션은 테스트 결과와 매트릭스 과부하에 의해 60초 동안 실행되는 총 실시간 bogo 작업을 표시합니다.

34.5. 가상 메모리 부족 생성

메모리 부족 상태에 있으면 커널이 스왑에 페이지 쓰기를 시작합니다. --page-in 옵션을 사용하여 non-resident 페이지가 가상 메모리로 다시 스왑되도록 하여 가상 메모리를 과부하시킬 수 있습니다. 이로 인해 가상 머신이 크게 수행됩니다. --page-in 옵션을 사용하면 bigheap,mmapvm(가상 시스템) 과부하에 이 모드를 활성화할 수 있습니다. --page-in 옵션은 코어가 아닌 할당된 페이지를 터치하여 페이지로 강제 적용합니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 가상 메모리 테스트를 강조하려면 --page-in 옵션을 사용합니다.

    # stress-ng --vm 2 --vm-bytes 2G --mmap 2 --mmap-bytes 2G --page-in

    이 예에서는 할당된 버퍼 크기보다 낮은 4GB 메모리, 2x 2GB의 vm stressor 및 --page-in 이 활성화된 2x 2GB의 mmap 스포터가 활성화된 시스템에서 메모리 부족을 테스트합니다.

34.6. 장치에서 대규모 인터럽트 로드 테스트

고주파에서 타이머를 실행하면 큰 인터럽트 로드를 생성할 수 있습니다. 적절하게 선택된 타이머 빈도를 가진 -timer 다운 로더는 초당 많은 인터럽트를 강제할 수 있습니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 인터럽트 로드를 생성하려면 --timer 옵션을 사용합니다.

    # stress-ng --timer 32 --timer-freq 1000000

    이 예에서 stress-ng 는 1#159에서 32개의 인스턴스를 테스트합니다.

34.7. 프로그램에서 주요 페이지 폴트 생성

stress-ng 를 사용하면 메모리에 로드되지 않은 페이지에 주요 페이지 폴트를 생성하여 페이지 폴트 속도를 테스트하고 분석할 수 있습니다. 새 커널 버전에서 userfaultfd 메커니즘은 프로세스의 가상 메모리 레이아웃에서 페이지 폴트에 대한 스레드를 찾는 오류를 알립니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 초기 커널 버전에서 주요 페이지 폴트를 생성하려면 다음을 사용합니다.

    # stress-ng --fault 0 --perf -t 1m
  • 새 커널 버전에서 주요 페이지 폴트를 생성하려면 다음을 사용합니다.

    # stress-ng --userfaultfd 0 --perf -t 1m

34.8. CPU 과부하 테스트 메커니즘 보기

CPU 스포크 테스트에는 CPU를 실행하는 방법이 포함되어 있습니다. 어떤 옵션을 사용하여 모든 메서드를 볼 수 있도록 출력을 출력할 수 있습니다.

기본적으로 테스트 방법을 지정하지 않으면 강조자가 라운드 로빈 방식으로 모든 강조자를 확인하여 각 스포터를 테스트합니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  1. 사용 가능한 모든 과부하 메커니즘을 출력하고 다음 옵션을 사용합니다.

    # stress-ng --cpu-method which
    
    cpu-method must be one of: all ackermann bitops callfunc cdouble cfloat clongdouble correlate crc16 decimal32 decimal64 decimal128 dither djb2a double euler explog fft fibonacci float fnv1a gamma gcd gray hamming hanoi hyperbolic idct int128 int64 int32
  2. --cpu-method 옵션을 사용하여 특정 CPU stress 방법을 지정합니다.

    # stress-ng --cpu 1 --cpu-method fft -t 1m

34.9. 확인 모드 사용

테스트가 활성화되면 확인 모드는 결과를 검증합니다. 이는 테스트 실행에서 메모리 콘텐츠를 확인하고 예기치 않은 오류를 보고합니다.

모든 과부하에는 확인 모드가 없으며 이를 활성화하면 이 모드에서 추가 검증 단계가 실행되기 때문에 bogo 작업 통계가 줄어듭니다.

사전 요구 사항

  • 시스템에 대한 root 권한이 있습니다.

프로세스

  • 과부하 테스트 결과를 검증하려면 --verify 옵션을 사용합니다.

    # stress-ng --vm 1 --vm-bytes 2G --verify -v

    이 예에서 stress-ng--verify 모드로 구성된 vm stressor를 사용하여 사실상 매핑된 메모리에 대한 전체 메모리 검사 출력을 출력합니다. 정상은 메모리에 대한 읽기 및 쓰기 결과를 확인합니다.

35장. 컨테이너 생성 및 실행

이 섹션에서는 실시간 커널로 컨테이너 생성 및 실행에 대한 정보를 제공합니다.

사전 요구 사항

  • podman 및 기타 컨테이너 관련 유틸리티를 설치합니다.
  • RHEL에서 Linux 컨테이너의 관리 및 관리에 대해 알아봅니다.
  • kernel-rt 패키지 및 기타 실시간 관련 패키지를 설치합니다.

35.1. 컨테이너 생성

실시간 커널과 기본 RHEL 커널 모두에서 다음 옵션을 모두 사용할 수 있습니다. kernel-rt 패키지는 잠재적인 결정성을 개선하고 일반적인 문제 해결을 허용합니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

프로세스

다음 절차에서는 실시간 커널과 관련하여 Linux 컨테이너를 구성하는 방법을 설명합니다.

  1. 컨테이너에 사용할 디렉터리를 만듭니다. 예를 들면 다음과 같습니다.

    # mkdir cyclictest
  2. 해당 디렉터리로 변경합니다.

    # cd cyclictest
  3. 컨테이너 레지스트리 서비스를 제공하는 호스트에 로그인합니다.

    # podman login registry.redhat.io
    Username: my_customer_portal_login
    Password: ***
    Login Succeeded!
  4. 컨테이너 파일을 생성합니다.
  5. 사용자 지정 Containerfile에서 빌드하는 경우 Containerfile을 수정하고 빌드합니다. 다음은 cyclisttest의 예입니다. 자체 이미지를 생성하지 않으면 realtime-tests-container 이미지를 가져와서 cyclictest를 실행할 수도 있습니다.

    # podman build -t cyclictest .

35.2. 컨테이너 실행

Containerfile으로 빌드된 컨테이너를 실행할 수 있습니다.

프로세스

  1. podman run 명령을 사용하여 컨테이너를 실행합니다.

    # podman run --device=/dev/cpu_dma_latency --cap-add ipc_lock --cap-add sys_nice --cap-add sys_rawio --rm -ti cyclictest
    
    /dev/cpu_dma_latency set to 0us
    policy: fifo: loadavg: 0.08 0.10 0.09 2/947 15
    
    T: 0 ( 8) P:95 I:1000 C: 3209 Min: 1 Act: 1 Avg: 1 Max:  14
    
    T: 1 ( 9) P:95 I:1500 C: 2137 Min: 1 Act: 2 Avg: 1 Max:  23
    
    T: 2 (10) P:95 I:2000 C: 1601 Min: 1 Act: 2 Avg: 2 Max:   7
    
    T: 3 (11) P:95 I:2500 C: 1280 Min: 1 Act: 2 Avg: 2 Max:  72
    
    T: 4 (12) P:95 I:3000 C: 1066 Min: 1 Act: 1 Avg: 1 Max:   7
    
    T: 5 (13) P:95 I:3500 C:  913 Min: 1 Act: 2 Avg: 2 Max:  87
    
    T: 6 (14) P:95 I:4000 C:  798 Min: 1 Act: 1 Avg: 2 Max:   7
    
    T: 7 (15) P:95 I:4500 C:  709 Min: 1 Act: 2 Avg: 2 Max:  29

이 예에서는 필요한 실시간별 옵션과 함께 podman run 명령을 보여줍니다. 예를 들면 다음과 같습니다.

  • 첫 번째 단계(FIFO) 스케줄러 정책은 --cap-add=sys_nice 옵션을 통해 컨테이너 내에서 실행되는 워크로드에 사용할 수 있습니다. 이 옵션을 사용하면 실시간 워크로드를 조정할 때 스레드의 CPU 선호도, 또 다른 중요한 구성 차원을 설정할 수 있습니다.
  • --device=/dev/cpu_dma_latency 옵션은 컨테이너 내에서 호스트 장치를 사용할 수 있도록 합니다(Subsequently used by the cyclictest workload to configure the CPU idle time management). 지정된 장치를 사용할 수 없는 경우 아래 메시지와 유사한 오류가 표시됩니다.

    WARN: stat /dev/cpu_dma_latency 실패: 이러한 파일 또는 디렉터리 없음

    이와 같은 오류 메시지가 있는 경우 podman-run(1) 매뉴얼 페이지를 참조하십시오. 컨테이너 내에서 특정 워크로드를 실행하려면 다른 podman-run 옵션이 유용할 수 있습니다.

    경우에 따라 --device=/dev/cpu 옵션을 추가하여 /dev/cpu/*/msr 와 같은 CPU당 장치 파일 매핑인 디렉터리 계층 구조를 추가해야 합니다.

36장. 프로세스의 우선 순위 표시

sched_getattr 특성을 사용하여 프로세스의 스케줄링 정책에 대한 정보와 프로세스의 우선 순위에 대한 정보를 표시할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

36.1. chrt 유틸리티

chrt 유틸리티는 스케줄러 정책 및 우선 순위를 확인하고 조정합니다. 원하는 속성으로 새 프로세스를 시작하거나 실행 중인 프로세스의 속성을 변경할 수 있습니다.

36.2. chrt 유틸리티를 사용하여 프로세스 우선 순위 표시

지정된 프로세스의 현재 스케줄링 정책 및 스케줄링 우선 순위를 표시할 수 있습니다.

프로세스

  • -p 옵션을 사용하여 chrt 유틸리티를 실행하여 실행 중인 프로세스를 지정합니다.

    # chrt -p 468
    pid 468's current scheduling policy: SCHED_FIFO
    pid 468's current scheduling priority: 85
    
    # chrt -p 476
    pid 476's current scheduling policy: SCHED_OTHER
    pid 476's current scheduling priority: 0

36.3. sched_getscheduler()를 사용하여 프로세스 우선 순위 표시

실시간 프로세스는 일련의 함수를 사용하여 정책 및 우선 순위를 제어합니다. sched_getscheduler() 함수를 사용하여 지정된 프로세스의 스케줄러 정책을 표시할 수 있습니다.

프로세스

  1. get_sched.c 소스 파일을 생성하고 텍스트 편집기에서 엽니다.

    $ {EDITOR} get_sched.c
  2. 파일에 다음 행을 추가합니다.

    #include <sched.h>
    #include <unistd.h>
    #include <stdio.h>
    
    int main()
    {
      int policy;
      pid_t pid = getpid();
    
      policy = sched_getscheduler(pid);
      printf("Policy for pid %ld is %i.\n", (long) pid, policy);
      return 0;
    }

    정책 변수에는 지정된 프로세스에 대한 스케줄러 정책이 포함되어 있습니다.

  3. 프로그램을 컴파일합니다.

    $ gcc get_sched.c -o get_sched
  4. 다양한 정책으로 프로그램을 실행합니다.

    $ chrt -o 0 ./get_sched
    Policy for pid 27240 is 0.
    $ chrt -r 10 ./get_sched
    Policy for pid 27243 is 2.
    $ chrt -f 10 ./get_sched
    Policy for pid 27245 is 1.

36.4. 스케줄러 정책에 유효한 범위 표시

sched_get_priority_min()sched_get_priority_max() 함수를 사용하여 지정된 스케줄러 정책에 유효한 우선순위 범위를 확인할 수 있습니다.

프로세스

  1. sched_get.c 소스 파일을 생성하여 텍스트 편집기에서 엽니다.

    $ {EDITOR} sched_get.c
  2. 파일에 다음을 입력합니다.

    #include <stdio.h>
    #include <unistd.h>
    #include <sched.h>
    
    int main()
    {
    
      printf("Valid priority range for SCHED_OTHER: %d - %d\n",
             sched_get_priority_min(SCHED_OTHER),
             sched_get_priority_max(SCHED_OTHER));
    
      printf("Valid priority range for SCHED_FIFO: %d - %d\n",
             sched_get_priority_min(SCHED_FIFO),
             sched_get_priority_max(SCHED_FIFO));
    
      printf("Valid priority range for SCHED_RR: %d - %d\n",
             sched_get_priority_min(SCHED_RR),
             sched_get_priority_max(SCHED_RR));
      return 0;
    }
    참고

    지정된 스케줄러 정책을 시스템에서 알 수 없는 경우 함수는 -1 을 반환하고 errnoEINVAL 로 설정됩니다.

    참고

    Cryo stat_FIFO 및 Cryo stat_RR 모두 1 에서 99 사이의 범위 내의 임의의 숫자일 수 있습니다. 그러나 POSIX는 이 범위를 준수하는 것은 보장되지 않으며 이식 가능한 프로그램은 이러한 기능을 사용해야 합니다.

  3. 파일을 저장하고 편집기를 종료합니다.
  4. 프로그램을 컴파일합니다.

    $ gcc sched_get.c -o msched_get

sched_get 프로그램이 준비되었으며 저장된 디렉터리에서 실행할 수 있습니다.

36.5. 프로세스의 timeslice 표시

Cryo stat_RR (round-robin) 정책은 Cryostat _FIFO (first-in, first-out) 정책과 약간 다릅니다. Cryostat_RR 은 라운드 로빈 순환에서 우선순위가 동일한 동시 프로세스를 할당합니다. 이렇게 하면 각 프로세스에 timeslice가 할당됩니다. sched_rr_get_interval() 함수는 각 프로세스에 할당된 timeslice를 보고합니다.

참고

POSIX에서는 이 함수가 Cryostat _RR 스케줄러 정책으로 실행되도록 구성된 프로세스에서만 작동해야 하지만 sched_ rr_get_interval() 함수는 Linux에서 모든 프로세스의 timeslice 길이를 검색할 수 있습니다.

timespec 은 timeslice 정보를 반환합니다. 1970년 1월 1일 기준 00:00:00-01T 이후의 초 및 나노초 수입니다.

struct timespec {
  time_t tv_sec;  /* seconds */
  long tv_nsec;   /* nanoseconds */
}

프로세스

  1. sched_timeslice.c 소스 파일을 생성하여 텍스트 편집기에서 엽니다.

    $ {EDITOR} sched_timeslice.c
  2. sched_timeslice.c 파일에 다음 행을 추가합니다.

    #include <stdio.h>
    #include <sched.h>
    
    int main()
    {
       struct timespec ts;
       int ret;
    
       /* real apps must check return values */
       ret = sched_rr_get_interval(0, &ts);
    
       printf("Timeslice: %lu.%lu\n", ts.tv_sec, ts.tv_nsec);
    
       return 0;
    }
  3. 파일을 저장하고 편집기를 종료합니다.
  4. 프로그램을 컴파일합니다.

    $ gcc sched_timeslice.c -o sched_timeslice
  5. 다양한 정책과 우선 순위로 프로그램을 실행합니다.

    $ chrt -o 0 ./sched_timeslice
    Timeslice: 0.38994072
    $ chrt -r 10 ./sched_timeslice
    Timeslice: 0.99984800
    $ chrt -f 10 ./sched_timeslice
    Timeslice: 0.0

36.6. 프로세스의 스케줄링 정책 및 관련 속성 표시

sched_getattr() 함수는 PID로 식별되는 지정된 프로세스에 현재 적용된 스케줄링 정책을 쿼리합니다. PID가 0이면 호출 프로세스의 정책이 검색됩니다.

size 인수는 userspace에 알려진 sched_attr 구조의 크기를 반영해야 합니다. 커널은 sched_attr::sizesched_attr 구조의 크기로 작성합니다.

입력 구조가 작으면 커널은 제공된 공간 이외의 값을 반환합니다. 결과적으로 E2BIG 오류로 인해 시스템 호출이 실패합니다. 다른 sched_attr 필드는 sched_attr 구조에 설명된 대로 채워집니다.

프로세스

  1. sched_timeslice.c 소스 파일을 생성하여 텍스트 편집기에서 엽니다.

    $ {EDITOR} sched_timeslice.c
  2. sched_timeslice.c 파일에 다음 행을 추가합니다.

    #define _GNU_SOURCE
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <linux/unistd.h>
    #include <linux/kernel.h>
    #include <linux/types.h>
    #include <sys/syscall.h>
    #include <pthread.h>
    
    #define gettid() syscall(__NR_gettid)
    
    #define SCHED_DEADLINE    6
    
    /* XXX use the proper syscall numbers */
    #ifdef __x86_64__
    #define __NR_sched_setattr        314
    #define __NR_sched_getattr        315
    #endif
    
    struct sched_attr {
         __u32 size;
         __u32 sched_policy;
         __u64 sched_flags;
    
         /* SCHED_NORMAL, SCHED_BATCH */
         __s32 sched_nice;
    
         /* SCHED_FIFO, SCHED_RR */
         __u32 sched_priority;
    
         /* SCHED_DEADLINE (nsec) */
         __u64 sched_runtime;
         __u64 sched_deadline;
         __u64 sched_period;
    };
    
    int sched_getattr(pid_t pid,
               struct sched_attr *attr,
               unsigned int size,
               unsigned int flags)
    {
         return syscall(__NR_sched_getattr, pid, attr, size, flags);
    }
    
    int main (int argc, char **argv)
    {
         struct sched_attr attr;
         unsigned int flags = 0;
         int ret;
    
         ret = sched_getattr(0, &attr, sizeof(attr), flags);
         if (ret < 0) {
             perror("sched_getattr");
             exit(-1);
         }
    
         printf("main thread pid=%ld\n", gettid());
         printf("main thread policy=%ld\n", attr.sched_policy);
         printf("main thread nice=%ld\n", attr.sched_nice);
         printf("main thread priority=%ld\n", attr.sched_priority);
         printf("main thread runtime=%ld\n", attr.sched_runtime);
         printf("main thread deadline=%ld\n", attr.sched_deadline);
         printf("main thread period=%ld\n", attr.sched_period);
    
         return 0;
    }
  3. sched_timeslice.c 파일을 컴파일합니다.

    $ gcc sched_timeslice.c -o sched_timeslice
  4. sched_timeslice 프로그램의 출력을 확인합니다.

    $ ./sched_timeslice
    main thread pid=321716
    main thread policy=6
    main thread nice=0
    main thread priority=0
    main thread runtime=1000000
    main thread deadline=9000000
    main thread period=10000000

36.7. sched_attr 구조

sched_attr 구조에는 스케줄링 정책 및 지정된 스레드에 대한 관련 속성이 포함되어 있습니다. sched_attr 구조는 다음과 같습니다.

struct sched_attr {
  u32 size;
  u32 sched_policy;
  u64 sched_flags;
  s32 sched_nice;
  u32 sched_priority;

  /* SCHED_DEADLINE fields */
  u64 sched_runtime;
  u64 sched_deadline;
  u64 sched_period;
};

sched_attr data structure

size

스레드 크기(바이트)입니다. 구조의 크기가 커널 구조보다 작으면 추가 필드가 0 으로 간주됩니다. 크기가 커널 구조보다 크면 커널에서 모든 추가 필드를 0 으로 확인합니다.

참고

sched_attr 구조가 커널 구조보다 크고 커널 구조 크기를 포함하는 업데이트 크기가 있는 경우 sched_setattr() 함수는 E2BIG 오류로 실패합니다.

sched_policy
스케줄링 정책
sched_flags

fork() 함수를 사용하여 프로세스 포크가 발생할 때 스케줄링 동작을 제어하는 데 도움이 됩니다. 호출 프로세스를 상위 프로세스라고 하며 새 프로세스를 하위 프로세스라고 합니다. 유효한 값은 다음과 같습니다.

  • 0: 하위 프로세스는 상위 프로세스의 스케줄링 정책을 상속합니다.
  • Cryostat_FLAG_RESET_ON_FORK: fork(): 하위 프로세스는 상위 프로세스의 스케줄링 정책을 상속하지 않습니다. 대신 기본 스케줄링 정책 (struct sched_attr){ .sched_policy = Cryostat_OTHER, } 로 설정됩니다.
sched_nice
Cryostat _OTHER 또는 Cryostat _ BATCH 스케줄링 정책을 사용할 때 설정할 nice 값을 지정합니다. nice 값은 -20 (최고 우선 순위) ~ +19 (낮은 우선 순위) 범위의 숫자입니다.
sched_priority
Cryostat _FIFO 또는 Cryostat _RR 을 예약 할 때 설정할 정적 우선 순위를 지정합니다. 다른 정책의 경우 priority를 0 으로 지정합니다.

Cryostat_DEADLINE 필드는 데드라인 예약을 위해서만 지정해야 합니다.

  • sched_runtime: 데드라인 스케줄링을 위한 런타임 매개변수를 지정합니다. 값은 나노초 단위로 표시됩니다.
  • Cryostat_DEADLINE: 데드라인 예약의 데드라인 매개변수를 지정합니다. 값은 나노초 단위로 표시됩니다.
  • sched_period: 데드라인 예약에 대한 period 매개변수를 지정합니다. 값은 나노초 단위로 표시됩니다.

37장. 선점 상태 보기

CPU를 사용하는 프로세스에서는 사용 중인 CPU를 포기할 수 있습니다.

37.1. 선점

프로세스는 완료되었거나 디스크의 데이터, 키 누를 또는 네트워크 패킷과 같은 이벤트를 대기하고 있기 때문에 CPU를 산출할 수 있습니다.

프로세스는 일반적으로 CPU를 실수로 생성할 수 있습니다. 이를 선점이라고 하며 더 높은 우선 순위 프로세스가 CPU를 사용하려는 경우 발생합니다.

선점은 시스템 성능에 특히 부정적인 영향을 미칠 수 있으며 지속적인 선점은 충돌이라는 상태로 이어질 수 있습니다. 이 문제는 프로세스가 지속적으로 선점되고 프로세스가 완료되지 않을 때 발생합니다.

작업의 우선 순위를 변경하면 비자발적 선점을 줄이는 데 도움이 될 수 있습니다.

37.2. 프로세스의 선점 상태 확인

지정된 프로세스에 대한 개인적이고 비압적 선점 상태를 확인할 수 있습니다. 상태는 /proc/PID/status 에 저장됩니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

프로세스

  • /proc/PID/status 의 내용을 표시합니다. 여기서 PID 는 프로세스의 ID입니다. 다음은 PID 1000이 있는 프로세스의 선점 상태를 표시합니다.

    # grep voluntary /proc/1000/status
    voluntary_ctxt_switches: 194529
    nonvoluntary_ctxt_switches: 195338

38장. chrt 유틸리티를 사용하여 프로세스의 우선 순위 설정

chrt 유틸리티를 사용하여 프로세스의 우선 순위를 설정할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

38.1. chrt 유틸리티를 사용하여 프로세스 우선 순위 설정

chrt 유틸리티는 스케줄러 정책 및 우선 순위를 확인하고 조정합니다. 원하는 속성으로 새 프로세스를 시작하거나 실행 중인 프로세스의 속성을 변경할 수 있습니다.

프로세스

  • 프로세스의 스케줄링 정책을 설정하려면 적절한 명령 옵션 및 매개 변수를 사용하여 chrt 명령을 실행합니다. 다음 예에서 명령의 영향을 받는 프로세스 ID는 1000 이며 우선 순위(-p)는 50 입니다.

    # chrt -f -p 50 1000

    지정된 스케줄링 정책 및 우선 순위로 애플리케이션을 시작하려면 애플리케이션 이름 및 필요한 경우 속성과 함께 해당 경로를 추가합니다.

    # chrt -r -p 50 /bin/my-app

    chrt 유틸리티 옵션에 대한 자세한 내용은 chrt 유틸리티 옵션을 참조하십시오.

38.2. chrt 유틸리티 옵션

chrt 유틸리티 옵션에는 명령의 프로세스 및 우선 순위를 지정하는 명령 옵션 및 매개 변수가 포함됩니다.

정책 옵션

-f
스케줄러 정책을 Cryostat _FIFO 로 설정합니다.
-o
스케줄러 정책을 Cryostat _OTHER 로 설정합니다.
-r
스케줄러 정책을 Cryostat _RR (round robin)으로 설정합니다.
-d
스케줄러 정책을 Cryostat _DEADLINE 으로 설정합니다.
-p n

프로세스의 우선 순위를 n 으로 설정합니다.

프로세스를 Cryostat_DEADLINE으로 설정하는 경우 런타임,데드라인period 매개변수를 지정해야 합니다.

예를 들면 다음과 같습니다.

# chrt -d --sched-runtime 5000000 --sched-deadline 10000000 --sched-period 16666666 0 video_processing_tool

다음과 같습니다.

  • --sched-runtime 5000000 은 나노초 단위의 런타임입니다.
  • --sched-deadline 10000000 은 나노초 단위의 상대 데드라인입니다.
  • --sched-period 16666666 은 나노초 단위의 기간입니다.
  • 0chrt 명령에 필요한 사용되지 않는 우선 순위의 자리 표시자입니다.

39장. 라이브러리 호출을 사용하여 프로세스의 우선 순위 설정

chrt 유틸리티를 사용하여 프로세스의 우선 순위를 설정할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있습니다.

39.1. 우선순위 설정을 위한 라이브러리 호출

실시간 프로세스는 다른 라이브러리 호출 세트를 사용하여 정책 및 우선 순위를 제어합니다. 다음 라이브러리 호출은 비실시간 프로세스의 우선 순위를 설정하는 데 사용됩니다.

  • nice
  • setpriority

이러한 함수는 비실시간 프로세스의 nice 값을 조정합니다. nice 값은 프로세서에서 실행할 즉시 실행 가능한 프로세스 목록을 정렬하는 방법에 대해 스케줄러에 대한 제안 역할을 합니다. 목록의 헤드에 있는 프로세스는 목록의 추가 단계보다 먼저 실행됩니다.

중요

함수에는 sched.h 헤더 파일이 포함되어야 합니다. 함수에서 반환 코드를 항상 확인하십시오.

39.2. 라이브러리 호출을 사용하여 프로세스 우선 순위 설정

스케줄러 정책 및 기타 매개변수는 sched_setscheduler() 함수를 사용하여 설정할 수 있습니다. 현재 실시간 정책에는 하나의 매개변수인 sched_priority 가 있습니다. 이 매개변수는 프로세스의 우선 순위를 조정하는 데 사용됩니다.

sched_setscheduler() 함수에는 sched_setscheduler(pid_t pid, int policy, const struct sched_param *sp) 의 세 가지 매개변수가 필요합니다.

참고

sched_setscheduler(2) 도움말 페이지에는 오류 코드를 포함하여 sched_setscheduler() 의 가능한 모든 반환 값이 나열됩니다.

프로세스 ID가 0이면 sched_setscheduler() 함수가 호출 프로세스에서 작동합니다.

다음 코드 발췌에서는 현재 프로세스의 스케줄러 정책을 Cryostat _FIFO 스케줄러 정책 및 우선 순위는 50 으로 설정합니다.

struct sched_param sp = { .sched_priority = 50 };
int ret;

ret = sched_setscheduler(0, SCHED_FIFO, &sp);
if (ret == -1) {
  perror("sched_setscheduler");
  return 1;
}

39.3. 라이브러리 호출을 사용하여 프로세스 우선순위 매개변수 설정

sched_setparam() 함수는 특정 프로세스의 스케줄링 매개변수를 설정하는 데 사용됩니다. 그런 다음 sched_getparam() 함수를 사용하여 확인할 수 있습니다.

스케줄링 정책만 반환하는 sched_getscheduler() 함수와 달리 sched_getparam() 함수는 지정된 프로세스에 대한 모든 스케줄링 매개변수를 반환합니다.

프로세스

지정된 실시간 프로세스의 우선 순위를 읽고 이를 두 개씩 늘리는 다음 코드 발췌를 사용합니다.

struct sched_param sp;
int ret;

ret = sched_getparam(0, &sp);
sp.sched_priority += 2;
ret = sched_setparam(0, &sp);

이 코드가 실제 애플리케이션에서 사용된 경우 함수에서 반환 값을 확인하고 오류를 적절하게 처리해야 합니다.

중요

우선 순위 증가에 주의하십시오. 이 예에서와 같이 스케줄러 우선 순위에 2를 지속적으로 추가하면 결국 잘못된 우선 순위가 발생할 수 있습니다.

39.4. 프로세스의 스케줄링 정책 및 관련 속성 설정

sched_setattr() 함수는 PID에 지정된 인스턴스 ID의 스케줄링 정책 및 관련 속성을 설정합니다. pid=0인 경우 sched_setattr() 은 호출 스레드의 프로세스 및 속성에서 작동합니다.

프로세스

  • sched_setattr() 호출은 호출이 작동하는 프로세스 ID와 다음 실시간 스케줄링 정책 중 하나를 지정합니다.

실시간 스케줄링 정책

SCHED_FIFO
First-in 및 first-out 정책을 예약합니다.
SCHED_RR
라운드 로빈 정책을 예약합니다.
SCHED_DEADLINE
데드라인 스케줄링 정책을 예약합니다.

Linux는 다음과 같은 비실시간 스케줄링 정책도 지원합니다.

비실시간 스케줄링 정책

SCHED_OTHER
표준 라운드 로빈 시간 공유 정책을 예약합니다.
SCHED_BATCH
프로세스의 "배치" 스타일 실행을 예약합니다.
SCHED_IDLE

우선 순위가 낮은 백그라운드 작업을 예약합니다. Cryostat_IDLE 은 정적 우선 순위 0 에서만 사용할 수 있으며, nice 값은 이 정책에 영향을 미치지 않습니다.

이 정책은 매우 낮은 우선 순위로 작업을 실행하기 위한 것입니다(+19보다 낮은 +19 nice 값 using Cryostat _OTHER 또는 BATCH 정책).

40장. 실시간 커널 및 솔루션 예약

실시간 커널에서의 예약은 경우에 따라 발생할 수 있습니다. 제공된 정보를 사용하면 실시간 커널에서 스케줄링 정책, 스케줄러 제한 및 스레드 중단 상태에 대한 문제와 잠재적인 솔루션을 파악할 수 있습니다.

40.1. 실시간 커널의 스케줄링 정책

실시간 스케줄링 정책은 하나의 주요 특성을 공유합니다. 높은 우선 순위 스레드가 스레드 또는 스레드가 I/O를 잠급거나 수행하여 대기할 때까지 실행됩니다.

Cryostat _RR 의 경우 운영 체제는 실행 중인 스레드를 중단하여 동일한 Cryostat _RR 우선순위의 다른 스레드를 실행할 수 있도록 합니다. 이러한 경우 중 하나에서 더 낮은 우선 순위 스레드가 CPU 시간을 얻을 수 있도록 정책을 정의하는 POSIX 사양에 의해 프로비저닝이 이루어지지 않습니다. 실시간 스레드의 이러한 특성은 지정된 CPU의 100%를 단조하는 애플리케이션을 쉽게 작성할 수 있음을 의미합니다. 그러나 이로 인해 운영 체제에 문제가 발생합니다. 예를 들어, 운영 체제는 시스템 전체 및 CPU당 리소스를 모두 관리해야 하며 이러한 리소스를 설명하는 데이터 구조를 주기적으로 검사하고 하우스키핑 활동을 수행해야 합니다. 그러나 코어가 Cryostat _FIFO 스레드에 의해 단조되는 경우 하우스키핑 작업을 수행할 수 없습니다. 결국 전체 시스템이 불안정해지고 잠재적으로 충돌할 수 있습니다.

RHEL for Real Time 커널에서 인터럽트 처리기는 Cryostat _FIFO 우선 순위로 스레드로 실행됩니다. 기본 우선순위는 50입니다. 인터럽트 처리기 스레드보다 높은 Cryostat _FIFO 또는 Cryostat _RR 정책이 있는 cpu-hog 스레드는 인터럽트 처리기가 실행되지 않도록 할 수 있습니다. 이로 인해 프로그램이 인터럽트에 의해 전달되는 데이터 신호를 대기하고 실패하게 됩니다.

40.2. 실시간 커널의 스케줄러 제한

실시간 커널에는 실시간 작업에서 사용할 대역폭을 할당할 수 있는 보호 메커니즘이 포함되어 있습니다. 보호 메커니즘을 실시간 스케줄러 제한이라고 합니다.

실시간 제한 메커니즘의 기본값은 실시간 작업에서 CPU 시간의 95%를 사용할 수 있음을 정의합니다. 나머지 5%는 Cryostat _OTHER 및 유사한 스케줄링 정책에서 실행되는 작업과 같이 실시간이 아닌 작업에 사용됩니다. 단일 실시간 작업이 95% CPU 시간 슬롯을 사용하는 경우 해당 CPU의 나머지 실시간 작업이 실행되지 않습니다. 실시간이 아닌 작업만 나머지 5%의 CPU 시간을 사용합니다. 기본값은 다음과 같은 성능에 영향을 미칠 수 있습니다.

  • 실시간 작업에는 사용 가능한 최대 95%의 CPU 시간이 있으며 이는 성능에 영향을 미칠 수 있습니다.
  • 실시간 작업은 실시간이 아닌 작업을 실행할 수 없으므로 시스템을 잠그지 않습니다.

실시간 스케줄러 제한은 /proc 파일 시스템의 다음 매개변수에 의해 제어됩니다.

/proc/sys/kernel/sched_rt_period_us 매개변수
CPU 대역폭의 100% 인 Cryo stat(마이크로초)의 기간을 정의합니다. 기본값은 1,000,000 Cryostats이며 1 초입니다. 마침표 값의 변경 사항은 매우 낮거나 낮으면 문제가 발생할 수 있으므로 신중하게 고려해야 합니다.
/proc/sys/kernel/sched_rt_runtime_us 매개변수
모든 실시간 작업에 사용할 수 있는 총 대역폭을 정의합니다. 기본값은 950,000 Cryostats (0.95 s)이며 이는 CPU 대역폭의 95%입니다. 값을 -1 로 설정하면 최대 100%의 CPU 시간을 사용하도록 실시간 작업이 구성됩니다. 이는 실시간 작업이 잘 엔지니어링되어 바인딩되지 않은 폴링 루프와 같은 명확한 경고 사항이 없는 경우에만 적합합니다.

40.3. 실시간 커널에서 스레드 중단

스레드 중단은 스레드가 별표 임계값보다 오래 CPU 실행 대기열에 있고 진행되지 않을 때 발생합니다. 스레드 중단의 일반적인 원인은 CPU에 바인딩된 Cryostat _FIFO 또는 Cryostat _ RR 과 같은 고정 우선 순위의 폴링 애플리케이션을 실행하는 것입니다. 폴링 애플리케이션은 I/O를 차단하지 않으므로 kworkers 와 같은 다른 스레드가 해당 CPU에서 실행되지 않도록 할 수 있습니다.

스레드 중단을 줄이기 위한 초기 시도는 실시간 제한이라고 합니다. 실시간 제한에서 각 CPU에는 실시간이 아닌 작업 전용 실행 시간의 일부가 있습니다. 제한의 기본 설정은 실시간 작업에 대해 CPU의 95%를 사용하고 5%는 비실시간 작업을 위해 예약되어 있습니다. 이 작업은 단일 실시간 작업으로 인해 중단을 유발하지만 CPU에 할당된 실시간 작업이 여러 개 있는 경우 작동하지 않습니다. 다음을 사용하여 문제를 해결할 수 있습니다.

stalld 메커니즘

stalld 메커니즘은 실시간 제한에 대한 대안이며 제한적인 단점을 방지합니다. stalld 는 시스템에서 각 스레드의 상태를 정기적으로 모니터링하고 실행 대기열에 있는 스레드를 실행하지 않고 지정된 시간 동안 찾는 데몬입니다. stalld 는 thread가 Cryostat _DEADLINE 정책을 사용하도록 일시적으로 변경되고 지정된 CPU에서 스레드에 작은 시간을 할당합니다. 그런 다음 스레드가 실행되고 시간 슬라이스를 사용하면 스레드가 원래 스케줄링 정책으로 반환되고 stalld 는 스레드 상태를 계속 모니터링합니다.

하우스키핑 CPU는 모든 데몬, 쉘 프로세스, 커널 스레드, 인터럽트 처리기 및 분리된 CPU에서 디스패치할 수 있는 모든 작업을 실행하는 CPU입니다. 실시간 제한이 비활성화된 하우스키핑 CPU의 경우 stalld 는 기본 워크로드를 실행하는 CPU를 모니터링하고 Cryostat _FIFO 사용량 루프로 CPU를 할당하므로 이전에 정의된 허용 가능한 추가 노이즈에서 필요에 따라 stalled 스레드를 감지하고 스레드 우선 순위를 개선하는 데 도움이 됩니다. 실시간 제한 메커니즘으로 인해 주요 워크로드에서 불합리한 노이즈가 발생하는 경우 stalld 가 선호될 수 있습니다.

stalld 를 사용하면 겨운 스레드를 강화하여 도입 된 노이즈를 더 정확하게 제어할 수 있습니다. stalld 가 실행될 때 쉘 스크립트 /usr/bin/throttlectl 은 실시간 제한을 자동으로 비활성화합니다. /usr/bin/throttlectl show 스크립트를 사용하여 현재 제한 값을 나열할 수 있습니다.

실시간 제한 비활성화

/proc 파일 시스템의 다음 매개변수는 실시간 제한을 제어합니다.

  • /proc/sys/kernel/sched_rt_period_us 매개 변수는 마침표의 마이크로초 수를 지정하고 기본값은 1초입니다.
  • /proc/sys/kernel/sched_rt_runtime_us 매개 변수는 제한되기 전에 실시간 작업에서 사용할 수 있는 마이크로초 단위 수를 지정하고 기본값은 사용 가능한 CPU 주기의 950,000 또는 95%입니다. echo -1 > /proc/sys/kernel/sched_rt_runtime_us 명령을 사용하여 -1 값을 sched_rt_runtime_us 파일에 전달하여 제한을 비활성화할 수 있습니다.

법적 공지

Copyright © 2025 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Red Hat logoGithubredditYoutubeTwitter

자세한 정보

평가판, 구매 및 판매

커뮤니티

Red Hat 문서 정보

Red Hat을 사용하는 고객은 신뢰할 수 있는 콘텐츠가 포함된 제품과 서비스를 통해 혁신하고 목표를 달성할 수 있습니다. 최신 업데이트를 확인하세요.

보다 포괄적 수용을 위한 오픈 소스 용어 교체

Red Hat은 코드, 문서, 웹 속성에서 문제가 있는 언어를 교체하기 위해 최선을 다하고 있습니다. 자세한 내용은 다음을 참조하세요.Red Hat 블로그.

Red Hat 소개

Red Hat은 기업이 핵심 데이터 센터에서 네트워크 에지에 이르기까지 플랫폼과 환경 전반에서 더 쉽게 작업할 수 있도록 강화된 솔루션을 제공합니다.

Theme

© 2026 Red Hat
맨 위로 이동