검색

짧은 대기 시간 작업을 위해 RHEL 8 for Real Time 최적화

download PDF
Red Hat Enterprise Linux for Real Time 8

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

Red Hat Customer Content Services

초록

RHEL for Real Time 커널에서 워크스테이션을 조정하여 대기 시간에 민감한 애플리케이션에서 대기 시간을 지속적으로 줄이고 예측 가능한 응답 시간을 확보합니다. 시스템 리소스를 관리하고, 이벤트 간 대기 시간을 측정하고, 엄격한 결정적 요구 사항이 있는 애플리케이션에 대한 분석을 위해 대기 시간을 기록하여 실시간 커널 튜닝을 수행합니다.

보다 포괄적 수용을 위한 오픈 소스 용어 교체

Red Hat은 코드, 문서 및 웹 속성에서 문제가 있는 언어를 교체하기 위해 최선을 다하고 있습니다. 먼저 마스터(master), 슬레이브(slave), 블랙리스트(blacklist), 화이트리스트(whitelist) 등 네 가지 용어를 교체하고 있습니다. 이러한 변경 작업은 작업 범위가 크므로 향후 여러 릴리스에 걸쳐 점차 구현할 예정입니다. 자세한 내용은 CTO Chris Wright의 메시지를 참조하십시오.

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

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

Jira를 통해 피드백 제출 (등록 필요)

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

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

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

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

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

주의

이러한 작업을 수행하지 않으면 RHEL for Real Time 배포에서 일관된 성능을 방지할 수 있습니다.

1.1. 튜닝 지침

  • 실시간 튜닝은 반복 프로세스입니다. 몇 가지 변수를 조정하지 못하고 변경 사항이 달성 가능한 최상의지 알 수 있습니다. 며칠 또는 몇 주 동안 시스템에 가장 적합한 튜닝 구성 세트를 줄일 수 있도록 준비하십시오.

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

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

1.2. 로깅 매개변수 밸런싱

syslog 서버는 네트워크를 통해 프로그램에서 로그 메시지를 전달합니다. 이 경우가 작을수록 보류 중인 트랜잭션이 클 수 있습니다. 트랜잭션이 매우 크면 I/O 급증을 유발할 수 있습니다. 이를 방지하기 위해 간격을 적절히 작게 유지하십시오.

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

절차

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

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

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

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

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

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

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

추가 리소스

  • syslog(3) man page
  • rsyslog.conf(5) man page
  • rsyslogd(8) man page

1.3. 불필요한 애플리케이션을 실행하지 않도록 하여 성능 향상

실행 중인 모든 애플리케이션은 시스템 리소스를 사용합니다. 시스템에서 실행되는 불필요한 애플리케이션이 없도록 하면 성능이 크게 향상됩니다.

사전 요구 사항

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

절차

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

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

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

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

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

    중요

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

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

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

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

    # crontab -l

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

  6. 시스템에서 외부 하드웨어 공급업체가 추가한 타사 애플리케이션과 구성 요소를 확인하고 불필요한 구성 요소를 제거하십시오.

추가 리소스

  • cron(8) 매뉴얼 페이지

1.4. NUMA(Non-Uniform Memory) 액세스

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

NUMA API에 대한 자세한 내용은 Andi Kleen의 백서 Linux용 NUMA API를 참조하십시오.

추가 리소스

  • numactl(8) man page

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

debugfs 파일 시스템은 디버깅 및 사용자가 정보를 사용할 수 있도록 특별히 설계되었습니다. RHEL 8에서 /sys/kernel/debug/ 디렉토리에 자동으로 마운트됩니다.

참고

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

절차

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

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

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

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

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

1.6. RHEL의 InfiniBand 실시간

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

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

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

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

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

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

추가 리소스

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

기본 RHEL 커널은 기본적으로 실시간 그룹 스케줄링 기능인 CONFIG_RT_GROUP_SCHED 를 활성화합니다. 그러나 실시간 커널의 경우 이 기능은 비활성화되어 있습니다.

CONFIG_RT_GROUP_SCHED 기능은 kernel-rt 패키지에 사용된 PREEMPT_RT 패치 세트와 독립적으로 개발되었으며 기본 RHEL 커널의 실시간 프로세스에서 작동하도록 설계되었습니다. CONFIG_RT_GROUP_SCHED 기능은 대기 시간 급증을 유발할 수 있으므로 PREEMPT_RT 사용 커널에서 비활성화됩니다. 따라서 기본 RHEL 커널에서 실행되는 컨테이너에서 워크로드를 테스트할 때 컨테이너 내에서 Cryostat _FIFO 또는 Cryostat _ RR 작업을 실행할 수 있도록 일부 실시간 대역폭을 컨테이너에 할당해야 합니다.

절차

  1. podman의 --cpu-rt-runtime 명령줄 옵션을 사용하기 전에 다음 글로벌 설정을 구성합니다.

    # echo 950000 > /sys/fs/cgroup/cpu,cpuacct/machine.slice/cpu.rt_runtime_us

  2. CPU 분리의 경우 기존 권장 사항을 사용하여 RT 워크로드에 대한 코어 세트를 별도로 설정합니다.
  3. 사용할 격리된 CPU 코어 목록을 사용하여 podman run --cpuset-cpus 를 실행합니다.
  4. 사용할 NUMA(Non-Uniform Memory Access) 메모리 노드를 지정합니다.

    *podman run --cpuset-mems=number-of-memory-nodes

    이렇게 하면 노드 간 메모리 액세스가 방지됩니다.

  5. 컨테이너에서 실행되는 실시간 워크로드에 필요한 최소 메모리 양을 컨테이너 시작 시 사용할 수 있는지 확인하려면 *podman run --memory-reservation=limit 명령을 사용합니다.

추가 리소스

  • podman-run(1) 도움말 페이지

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 작업은 마침표,런타임데드라인 매개 변수로 지정됩니다. 이러한 매개변수의 값은 나노초의 정수입니다.

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

기간

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

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

runtime

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

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

데드라인

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

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

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 신호는 특히 오류 처리를 위해 사용되지만 실시간 애플리케이션에서 이벤트 전달 메커니즘으로 적합하지 않습니다. 이는 현재 Linux 커널 신호 처리 코드가 매우 복잡하기 때문에 주로 레거시 동작과 지원되는 많은 API로 인해 발생합니다. 이러한 복잡성은 신호를 전달할 때 걸리는 코드 경로가 항상 최적의 것은 아니며 애플리케이션에서 긴 대기 시간을 경험할 수 있음을 의미합니다.

UNIX 신호의 원래 어려움은 실행의 서로 다른 "스레드" 사이에 여러 개의 제어 스레드 (프로세스)에 있습니다. 신호는 운영 체제 인터럽트와 동일하게 작동합니다. 즉, 신호가 애플리케이션에 전달되면 애플리케이션의 컨텍스트가 저장되고 이전에 등록된 신호 처리기 실행을 시작합니다. 신호 처리기가 완료되면 애플리케이션이 신호가 전달된 시점의 실행으로 돌아갑니다. 이것은 실제로 복잡해질 수 있습니다.

신호는 실시간 애플리케이션에서 신뢰할 수 없을 만큼 결정적이지 않습니다. 더 나은 옵션은 POSIX 스레드(pthreads)를 사용하여 워크로드를 배포하고 다양한 구성 요소 간에 통신하는 것입니다. pthreads 메커니즘, 조건 변수 및 장벽을 사용하여 스레드 그룹을 조정할 수 있습니다. 이러한 비교적 새로운 구성을 통한 코드 경로는 신호의 기존 처리 코드보다 훨씬 더 명확합니다.

4.2. 스레드 동기화

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

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

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

스케줄러는 실제로 실행을 기다리는 다른 스레드가 있는 시기를 더 잘 확인할 수 있습니다. 모든 실시간 작업에 sched_yield() 를 사용하지 않도록 합니다.

절차

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

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

    10.0.0.1 _DEADLINE 작업은 다음 기간(다음 루프 시작)까지 충돌 기반 검색(CBS) 알고리즘에 의해 제한됩니다.

추가 리소스

  • pthread.h(P) 매뉴얼 페이지
  • sched_yield(2) man page
  • sched_yield(3p) man page

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 변수를 ld.so 로 설정하여 애플리케이션 시작 시 동적 라이브러리가 로드되도록 지시할 수 있습니다.

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

#!/bin/sh

LD_BIND_NOW=1
export LD_BIND_NOW

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

추가 리소스

  • ld.so(8) man page

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

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

참고

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

5.1. 전원 관리 비활성화로 응답 시간 개선

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

응답 시간을 개선하기 위해 BIOS에서 모든 전원 관리 옵션을 비활성화합니다.

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

EDAC(Error Detection and Correction) 장치는 ECC(Error Correcting Code) 메모리에서 신호된 오류를 탐지하고 수정하는 장치입니다. 일반적으로 EDAC 옵션 범위는 ECC가 없는 경우 모든 메모리 노드의 주기적으로 검사에서 오류를 검사합니다. EDAC 수준이 높을수록 BIOS에서 사용하는 시간이 늘어납니다. 이로 인해 중요한 이벤트 기한이 누락될 수 있습니다.

응답 시간을 개선하기 위해 EDAC를 끄십시오. 이 작업을 수행할 수 없는 경우 EDAC를 가장 낮은 기능 수준으로 구성합니다.

5.3. 시스템 관리 Interrupts를 구성하여 응답 시간 개선

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

BIOS에 SMI 옵션이 포함되어 있는 경우 공급 업체 및 관련 문서를 확인하여 비활성화가 안전한 정도를 확인합니다.

주의

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

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

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

사전 요구 사항

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

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

    주의

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

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

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

참고

시스템이 애플리케이션의 대기 시간 요구 사항을 충족하지 못하는 것으로 표시되면 BIOS 설정을 변경하거나 시스템 공급 업체와 협력하여 애플리케이션의 대기 시간 요구 사항을 충족하는 새 펌웨어를 가져오십시오.

사전 요구 사항

  • RHEL-RTrt-tests 패키지가 설치되어 있는지 확인합니다.

절차

  • 테스트 기간을 초 단위로 지정하여 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

추가 리소스

6.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 tracer 대신 kernel 모듈을 사용했습니다.

결과 이해

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

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

표 6.1. 메서드, 매개변수 및 결과 테스트
매개변수현재의설명

테스트 기간

10초

테스트 기간(초)

Detector

Tracer

탐지기 스레드를 실행하는 유틸리티

매개변수

  

대기 시간 임계값

10us

허용되는 최대 대기 시간

샘플 창

1000000us

1초

샘플 너비

500000us

0.05초

샘플링되지 않는 기간

500000us

0.05초

출력 파일

없음

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

결과

  

최대 대기 시간

18us

Latency 임계값을 초과하는 테스트 중 가장 높은 대기 시간입니다. 대기 시간 임계값 을 초과하는 샘플이 없는 경우 보고서에 낮은 임계값이 표시됩니다.

기록된 샘플

10

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

임계값을 초과하는 샘플

10

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

실행 중 SMI

0

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

참고

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

적합한 hardware-firmware 조합을 찾은 후 다음 단계는 로드 중에 시스템의 실시간 성능을 테스트하는 것입니다.

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

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

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

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

사전 요구 사항

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

절차

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

    # rteval

    rteval 유틸리티는 시스템 로드가 많은 system load of 3-4_OTHER 작업을 시작합니다. 그런 다음 각 온라인 CPU에 대한 실시간 응답을 측정합니다. 로드는 루프의 Linux 커널 트리와 hackbench 합성 벤치마크의 병렬 구성 요소입니다.

    목표는 시스템을 각 코어에 항상 스케줄링할 작업이 있는 상태로 가져오는 것입니다. 이 작업은 메모리 할당/무료, 디스크 I/O, 전산 작업, 메모리 복사본 등과 같은 다양한 작업을 수행합니다.

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

    각 측정 스레드는 타임스탬프를 사용하여 간격 동안 유휴 상태인 다음, 다시 시작한 후 다른 타임 스탬프를 사용합니다. 측정된 대기 시간은 t1 - (t0 + i) 입니다. 이는 실제 워킹 시간 t1 과 첫 번째 타임스탬프 t0 의 발생 시간 차이 및 절전 간격 i 입니다.

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

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

    다음은 R teval 보고서의 예입니다.

    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

8장. 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/ 파일 시스템 항목을 수정하면 인터럽트의 선호도가 변경됩니다.

8.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

      추가 세분성을 위해 우선순위 및 정책을 지정할 수도 있습니다. 이 예에서 명령은 CPU 5에서 10.0.0.1 _FIFO 정책 및 우선 순위 값 78에서 /bin/my-app 애플리케이션을 실행합니다.

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

real-time 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);
    }

8.3. 높은 사용률 작업을 실행하도록 단일 CPU 격리

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

사전 요구 사항

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

절차

  1. cpuset 라는 두 디렉터리를 생성합니다.

    # cd /sys/fs/cgroup/cpuset/
    # mkdir cluster
    # mkdir partition
  2. root cpuset 의 부하 분산을 비활성화하여 cpuset 디렉터리에 두 개의 새 루트 도메인을 생성합니다.

    # echo 0 > cpuset.sched_load_balance
  3. cpuset 클러스터에서 CPU 1~7에서 실행되도록 낮은 사용률 작업을 예약하고 메모리 크기를 확인하고 CPU 이름을 exclusive로 지정합니다.

    # cd cluster/
    # echo 1-7 > cpuset.cpus
    # echo 0 > cpuset.mems
    # echo 1 > cpuset.cpu_exclusive
  4. 모든 낮은 사용률 작업을 cpuset 디렉터리로 이동합니다.

    # ps -eLo lwp | while read thread; do echo $thread > tasks ; done
  5. cpuset 이라는 파티션을 생성하고 high utilization 작업을 할당합니다.

    # cd ../partition/
    # echo 1 > cpuset.cpu_exclusive
    # echo 0 > cpuset.mems
    # echo 0 > cpuset.cpus
  6. 쉘을 cpuset로 설정하고 데드라인 워크로드를 시작합니다.

    # echo $$ > tasks
    # /root/d &

    이 설정에서는 분할된 cpuset 디렉터리에 격리된 작업이 클러스터 cpuset 디렉터리의 작업을 방해하지 않습니다. 이를 통해 모든 실시간 작업이 스케줄러 데드라인을 충족할 수 있습니다.

8.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

8.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 매개변수의 값이 inactive(dead) 인지 확인합니다.

9장. RHEL for Real Time에서 mlock() 시스템 호출 사용

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

9.1. mlock() 및 munlock() 시스템 호출

mlock()mlockall() 시스템 호출은 지정된 메모리 범위를 잠그고 이 메모리를 페이징하지 않습니다. 다음은 mlock() 시스템 호출 그룹입니다.

  • mlock() 시스템 호출: 지정된 주소 범위를 잠급니다.
  • munlock() 시스템 호출: 지정된 주소 범위를 잠금 해제합니다.

mlock() 시스템 호출, 주소 범위의 페이지 잠금은 addr 에서 시작하여 len 바이트를 계속합니다. 호출이 성공적으로 반환되면 지정된 주소 범위의 일부가 포함된 모든 페이지는 나중에 잠금 해제할 때까지 메모리에 유지됩니다.

mlockall() 시스템 호출을 사용하면 매핑된 모든 페이지를 지정된 주소 범위로 잠글 수 있습니다. 메모리 잠금은 스택이 아닙니다. 여러 호출에 의해 잠긴 모든 페이지는 지정된 주소 범위 또는 단일 munlock() 시스템 호출을 사용하여 전체 영역의 잠금을 해제합니다. munlockall() 시스템 호출을 사용하면 전체 프로그램 공간을 잠금 해제할 수 있습니다.

특정 범위에 포함된 페이지의 상태는 플래그 인수의 값에 따라 다릅니다. flags 인수는 0 또는 MLOCK_ONFAULT 일 수 있습니다.

메모리 잠금은 포크를 통해 하위 프로세스에서 상속되지 않으며 프로세스가 종료될 때 자동으로 제거됩니다.

주의

mlock() 시스템 호출을 주의해서 사용하십시오. 과도하게 사용하면 OOM(메모리 부족) 오류가 발생할 수 있습니다. 애플리케이션이 크거나 큰 데이터 도메인이 있는 경우 mlock() 호출은 시스템이 다른 작업에 메모리를 할당할 수 없는 경우 제한될 수 있습니다.

실시간 프로세스에 대한 mlockall() 호출을 사용하는 경우 충분한 스택 페이지를 예약해야 합니다.

9.2. mlock() 시스템 호출을 사용하여 페이지 잠금

실시간 mlock() 시스템 호출은 addr 매개변수를 사용하여 주소 범위의 시작을 지정하고 len 을 사용하여 주소 공간의 길이를 바이트 단위로 정의합니다. alloc_workbuf() 함수는 메모리 버퍼를 동적으로 할당하고 잠급니다. 메모리 할당은 메모리 영역을 페이지에 정렬하기 위해 posix_memalig() 함수에 의해 수행됩니다. 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 를 설정합니다.

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

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

사전 요구 사항

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

절차

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

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

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

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

추가 리소스

  • capabilities>-& lt; 매뉴얼 페이지
  • mlock(2) 매뉴얼 페이지
  • mlock(3) 매뉴얼 페이지
  • move_pages(2) man page
  • posix_memalign(3) man page
  • posix_memalign(3p) man page

9.4. 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() 함수가 성공적으로 완료되면 매핑된 영역에 포인터를 반환합니다. error에서 MAP_FAILED 값을 반환하고 오류를 나타내는 errno 를 설정합니다.
  • munmap() 함수가 성공적으로 완료되면 0 을 반환합니다. error에서 -1 을 반환하고 errno 를 설정하여 오류를 나타냅니다.

추가 리소스

  • mmap(2) 매뉴얼 페이지
  • mlockall(2) 매뉴얼 페이지

9.5. mlock() 시스템 호출에 대한 매개변수

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

표 9.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

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

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

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

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

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

10.1. atime 비활성화

atime 특성을 비활성화하면 성능이 향상되고 파일 시스템 저널에 대한 쓰기 횟수를 제한하여 전원 사용량이 감소합니다.

절차

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

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

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

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

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

10.2. 추가 리소스

  • mkfs.ext2(8) man page
  • mkfs.xfs(8) man page
  • mount(8) 매뉴얼 페이지

11장. 대기 시간에 민감한 워크로드에 대한 그래픽 콘솔 출력 비활성화

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

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

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

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

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

11.1. 그래픽 어댑터에 대한 그래픽 콘솔 로깅 비활성화

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

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

참고

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

절차

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

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

11.2. 그래픽 콘솔에 인쇄에서 메시지 비활성화

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

절차

  1. 현재 콘솔 로그 수준을 확인합니다.

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

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

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

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

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

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

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

12.1. 하드웨어 클럭

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

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

TSC 및 HPET가 없는 경우 다른 옵션에는 ACPI Power Management Timer(ACPI_PM), PIT(Programmable Interval Timer) 및 RTC(Real Time Clock)가 포함됩니다. 마지막 두 가지 옵션은 읽기 비용이 많이 들거나 낮은 해상도(시간 세분성)이므로 실시간 커널과 함께 사용할 수 있는 하위 선택 사항입니다.

12.2. 시스템에서 사용 가능한 클럭 소스 보기

시스템에서 사용 가능한 클럭 소스 목록은 /sys/devices/system/clocksource/clocksource0/available_clocksource 파일에 있습니다.

절차

  • available_clocksource 파일을 표시합니다.

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

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

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

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

절차

  • current_clocksource 파일을 표시합니다.

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

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

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

때때로 시계의 알려진 문제로 인해 시스템의 주요 애플리케이션에 대한 최상의 시계가 사용되지 않는 경우가 있습니다. 문제가 있는 모든 시계를 제거한 후 실시간 시스템의 최소 요구사항을 충족할 수 없는 하드웨어 시계를 사용할 수 있습니다.

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

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

중요

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

사전 요구 사항

  • 시스템에 대한 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를 시스템의 현재 클럭 소스로 사용합니다.

12.5. 하드웨어 클럭 소스를 읽는 비용 비교

시스템의 시계 속도를 비교할 수 있습니다. 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 프로그램과 함께 시간 유틸리티를 실행합니다. 출력에는 클럭 소스를 10만 번 읽는 데 필요한 기간이 표시됩니다.

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

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

    • Real - 프로세스가 종료될 때까지 프로그램 호출부터 시작된 총 시간입니다. 실제 에는 사용자 및 커널 시간이 포함되며 일반적으로 마지막 두 시간의 합계보다 큽니다. 이 프로세스가 우선 순위가 높은 애플리케이션 또는 하드웨어 인터럽트(IRQ)와 같은 시스템 이벤트에 의해 중단되는 경우 이 시간도 실제 대기에서 계산됩니다.
    • 사용자 - 프로세스에서 커널 개입이 필요하지 않은 작업을 수행하는 데 소비된 시간입니다.
    • 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의 결과를 비교합니다.

추가 리소스

  • time(1) 매뉴얼 페이지

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

현재 AMD64 Opteron 프로세서의 현재 생성은 대규모 gettimeofday skew에 취약할 수 있습니다. 이 스큐는 cpufreq 및 TSC( Time Stamp Forwarded)를 모두 사용할 때 발생합니다. 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. 컴퓨터를 다시 시작합니다.

추가 리소스

  • gettimeofday(2) 매뉴얼 페이지

12.7. 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 프로그램이 준비되었으며 저장된 디렉터리에서 실행할 수 있습니다.

13장. 전원 관리 전환 제어

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

사전 요구 사항

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

13.1. 절전 상태

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

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

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

13.2. 전원 관리 상태 구성

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

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

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

절차

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

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

    import os
    import os.path
    import signal
    import sys
    if not os.path.exists('/dev/cpu_dma_latency'):
     	print("no PM QOS interface on this system!")
     	sys.exit(1)
    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 전환이 허용될 때까지 파일을 열린 상태로 유지해야 합니다.

14장. 인터럽트 및 사용자 프로세스를 격리하여 시스템 대기 시간 최소화

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

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

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

인터럽트는 일반적으로 CPU 간에 균등하게 공유됩니다. 이렇게 하면 CPU가 새 데이터 및 명령 캐시를 작성해야 하는 경우 인터럽트 처리가 지연될 수 있습니다. 이러한 인터럽트 지연으로 인해 동일한 CPU에서 다른 처리가 실행될 수 있습니다.

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

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

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

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

표 14.1. 지정된 CPU에 대한 CPU의 예

CPU

Bitmask

10진수

Hexadecimal

0

00000000000000000000000000000001

1

0x00000001

0, 1

00000000000000000000000000000011

3

0x00000011

14.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 상태가 inactive인지 확인합니다.

    # systemctl status irqbalance

14.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 코어가 있는 시스템을 실행하는 경우 각 16진수 그룹을 쉼표로 구분합니다. 예: IRQBALANCE_BANNED_CPUS=00000001,0000ff00

표 14.2. 예

CPU

Bitmask

0

00000001

8 - 15

0000ff00

8 - 15, 33

00000002,0000ff00

참고

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

14.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. 특정 IRQ의 smp_affinity 항목에 CPU 마스크를 작성합니다. CPU 마스크는 16진수로 표시되어야 합니다.

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

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

    변경 사항은 인터럽트가 발생했을 때만 적용됩니다.

검증 단계

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

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

14.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) 매뉴얼 페이지를 참조하십시오.

절차

  • 필요한 옵션 및 인수를 사용하여 작업 세트를 실행합니다.

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

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

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

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

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

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

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

      # taskset -p 1 7013
참고

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

추가 리소스

  • taskset(1) man page
  • numactl(8) man page

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

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

사전 요구 사항

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

15.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(OOM 1)에서 Real-Time 커널 패닉을 생성하는 것이 좋습니다. 그렇지 않으면 시스템이 OOM 상태가 되면 더 이상 결정적이지 않습니다.

검증 단계

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

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

15.2. 메모리 부족 상태의 경우 종료할 프로세스 우선 순위 지정

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

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

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

프로세스에 대한 oom_adj 파일을 편집하여 종료할 프로세스의 우선 순위를 지정할 수 있습니다.

사전 요구 사항

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

절차

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

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

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

    # echo -5 > /proc/12465/oom_adj

검증 단계

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

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

15.3. 프로세스에 대한 메모리 부족 종료 비활성화

oom_killer() 를 예약된 값 -17 로 설정하여 프로세스에 대해 oom_ killer() 함수를 비활성화할 수 있습니다. 이렇게 하면 프로세스가 OOM 상태인 경우에도 계속 유지됩니다.

절차

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

    # echo -17 > /proc/12465/oom_adj

검증 단계

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

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

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

tuna CLI를 사용하여 시스템의 대기 시간을 개선할 수 있습니다. tuna 명령에 사용되는 옵션은 대기 시간을 개선하기 위해 호출된 방법을 결정합니다. tuna CLI를 사용하면 다음 기능을 수행합니다.

  • 스케줄러 튜닝 가능 항목 수정
  • IRQ 처리기 및 스레드 우선 순위 조정
  • CPU 코어 및 소켓 분리
  • 작업 튜닝에 대한 복잡성 감소

16.1. 사전 요구 사항

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

16.2. tuna CLI

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

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

tuna CLI에는 작업 옵션과 수정자 옵션이 모두 있습니다. 수정하려는 작업보다 먼저 명령줄에 수정하기 위한 수정자 옵션을 지정해야 합니다. 모든 수정자 옵션은 수정자 옵션을 재정의할 때까지 이어지는 작업에 적용됩니다.

16.3. tuna CLI를 사용하여 CPU 격리

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

사전 요구 사항

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

절차

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

    # tuna --cpus=<cpu_list> --isolate

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

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

    # tuna --cpus=0,1 --isolate

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

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

사전 요구 사항

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

절차

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

    # tuna --irqs=<irq_list> --show_irqs

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

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

    # tuna --irqs=128 --show_irqs
       # users         affinity
     128 iwlwifi          0,1,2,3
  2. IRQ 목록을 CPU 목록에 연결합니다.

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

    irq_list 는 쉼표로 구분된 IRQ 목록입니다. cpu_list 는 쉼표로 구분된 CPU 목록이며, cpu_list는 해당 CPU가 연결될 CPU의 쉼표로 구분된 목록입니다.

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

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

검증

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

    # tuna --irqs=128 --show_irqs
       # users         affinity
     128 iwlwifi          3

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

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

사전 요구 사항

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

    참고

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

절차

  1. 스레드에 대한 정보를 봅니다.

    # tuna --threads=<thread_list> --show_threads

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

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

    # tuna --threads=rngd --show_threads
                          thread       ctxt_switches
        pid SCHED_ rtpri affinity voluntary nonvoluntary             cmd
      3571   OTHER     0  0,1,2,3    167697          134            rngd
  2. 프로세스 스케줄링 정책 및 스레드의 우선 순위를 수정합니다.

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

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

      참고

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

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

      # tuna --threads=rngd --priority FIFO:1

검증

  • 스레드의 정보를 보고 정보가 변경되는지 확인합니다.
# *tuna --threads=rngd --show_threads*
                      thread       ctxt_switches
    pid SCHED_ rtpri affinity voluntary nonvoluntary           cmd
  3571   FIFO     1  0,1,2,3    167697          134            rngd

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

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

주의

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

17.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]...

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

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

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

CPUSchedulingPolicy=

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

  • 기타
  • 일괄 처리
  • 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

17.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

17.4. 우선순위 맵

스케줄러 우선순위는 그룹에 정의되며, 일부 그룹은 특정 커널 함수로 전용됩니다.

표 17.1. 스레드 우선 순위 테이블
우선 순위스레드설명

1

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

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

2 - 49

사용 가능

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

50

기본 hard-IRQ 값

이 우선순위는 하드웨어 기반 인터럽트의 기본값입니다.

51 - 98

우선순위가 높은 스레드

주기적으로 실행되고 빠른 응답 시간이 필요한 스레드에는 이 범위를 사용합니다. 낮은 수준의 인터럽트에 대한 응답을 방지하기 때문에 CPU 바인딩 스레드에는 이 범위를 사용하지 마십시오.

99

워치독 및 마이그레이션

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

17.5. 추가 리소스

18장. 네트워크 결정성 팁

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

  • Do you need ordered delivery?
  • 패킷 손실을 방지할 필요가 있습니까?

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

  • TCP를 사용해야 합니까?

    소켓에서 TCP_NODELAY 를 사용하여 Nagle 버퍼링 알고리즘을 비활성화하는 것이 좋습니다. Nagle 알고리즘은 작은 발신 패킷을 수집하여 한 번에 모두 전송하며 대기 시간에 심각한 영향을 미칠 수 있습니다.

18.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

    이름에 "drop", "discard" 또는 "error"가 포함된 패킷 카운터를 식별합니다. 이러한 특정 통계는 NIC(네트워크 인터페이스 카드) 패킷 버퍼에서 실제 패킷 손실을 측정하며, NIC 병합으로 인해 발생할 수 있습니다.

  2. 이전 단계에서 확인한 패킷 카운터 값을 모니터링합니다.

    네트워크에 대해 예상되는 값과 비교하여 특정 인터페이스에 병목 현상이 발생하는지 확인합니다. 네트워크 병목 현상의 몇 가지 일반적인 표시에는 다음이 포함되지만 이에 국한되지는 않습니다.

    • 네트워크 인터페이스에 많은 오류
    • 높은 패킷 손실
    • 네트워크 인터페이스의 사용량이 많이 있음

      참고

      다른 중요한 요인은 네트워크 병목 현상을 식별할 때 CPU 사용량, 메모리 사용량, 디스크 I/O 등의 중요한 요소입니다.

  3. 현재 병합 설정을 확인합니다.

    # ethtool enp1s0
    Settings for enp1s0:
            Supported ports: [ TP ]
            Supported link modes:   10baseT/Half 10baseT/Full
                                    100baseT/Half 100baseT/Full
                                    1000baseT/Full
            Supported pause frame use: No
            Supports auto-negotiation: Yes
            Advertised link modes:  10baseT/Half 10baseT/Full
                                    100baseT/Half 100baseT/Full
                                    1000baseT/Full
            Advertised pause frame use: No
            Advertised auto-negotiation: Yes
            Speed: 1000Mb/s
            Duplex: Full
            Port: Twisted Pair
            PHYAD: 0
            Transceiver: internal
            Auto-negotiation: on
            MDI-X: Unknown
            Supports Wake-on: g
            Wake-on: g
            Current message level: 0x00000033 (51)
                                   drv probe link
            Link detected: yes

    이 출력에서 SpeedDuplex 필드를 모니터링합니다. 이러한 필드에는 네트워크 인터페이스 작업과 예상된 값으로 실행 중인지에 대한 정보가 표시됩니다.

  4. 현재 인터럽트 병합 설정을 확인합니다.

    # 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 드라이버마다 알고리즘이 다릅니다).
  5. 필요에 따라 병합 설정을 수정합니다. 예를 들면 다음과 같습니다.

    • 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를 설정할 수 있습니다.
      • 사용자가 문제가 발생할 때까지 요구 사항에 대해 잘 모르는 경우 이 설정을 수정해서는 안 됩니다.
  6. 연결을 다시 활성화합니다.

    # 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를 사용할 수 있습니다.

18.2. 이더넷 네트워크의 흐름 제어

이더넷 링크에서 네트워크 인터페이스와 스위치 포트 간의 지속적인 데이터 전송으로 인해 전체 버퍼 용량이 발생할 수 있습니다. 전체 버퍼 용량으로 인해 네트워크 정체가 발생합니다. 이 경우, 발신자가 수신기의 처리 용량보다 더 높은 속도로 데이터를 전송할 때, 패킷 손실은 링크의 다른 쪽 끝에 있는 네트워크 인터페이스의 데이터 처리 용량으로 인해 발생할 수 있습니다.

흐름 제어 메커니즘은 각 발신자와 수신자가 다른 전송 및 수신 용량을 갖는 이더넷 링크를 통한 데이터 전송을 관리합니다. 패킷 손실을 방지하기 위해 이더넷 흐름 제어 메커니즘은 스위치 포트에서 더 높은 전송 속도를 관리하기 위해 패킷 전송을 일시적으로 중단합니다. 라우터는 스위치 포트 이외의 일시 중지 프레임을 전달하지 않습니다.

수신(RX) 버퍼가 가득 차면 수신자는 일시 중지 프레임을 송신기에 보냅니다. 그런 다음 송신기는 이 일시 중지 기간 동안 들어오는 데이터를 버퍼링하는 동안 짧은 하위 시간 프레임에 대한 데이터 전송을 중지합니다. 이 기간은 수신자가 해당 인터페이스 버퍼를 비우고 버퍼 오버플로를 방지할 수 있는 충분한 시간을 제공합니다.

참고

이더넷 링크의 끝은 일시 중지 프레임을 다른 끝으로 보낼 수 있습니다. 네트워크 인터페이스의 수신 버퍼가 가득 차면 네트워크 인터페이스에서 일시 중지 프레임을 스위치 포트로 보냅니다. 마찬가지로, 스위치 포트의 수신 버퍼가 가득 차면 스위치 포트는 일시 중지 프레임을 네트워크 인터페이스로 보냅니다.

기본적으로 Red Hat Enterprise Linux의 대부분의 네트워크 드라이버에는 일시 중지 프레임 지원이 활성화되어 있습니다. 네트워크 인터페이스의 현재 설정을 표시하려면 다음을 입력합니다.

# ethtool --show-pause enp1s0
Pause parameters for enp1s0:
...
RX:     on
TX:     on
...

스위치 공급 업체에 문의하여 스위치가 일시 중지 프레임을 지원하는지 확인합니다.

18.3. 추가 리소스

  • ethtool(8) 매뉴얼 페이지
  • netstat(8) 매뉴얼 페이지

19장. trace-cmd를 사용하여 대기 시간 추적

trace-cmd 유틸리티는 ftrace 유틸리티의 프런트 엔드입니다. trace-cmd 를 사용하면 /sys/kernel/debug/tracing/ 디렉토리에 쓸 필요 없이 ftrace 작업을 활성화할 수 있습니다. trace-cmd 는 설치에 오버헤드를 추가하지 않습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

19.1. trace-cmd 설치

trace-cmd 유틸리티는 ftrace 유틸리티에 프런트 엔드를 제공합니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

절차

  • trace-cmd 유틸리티를 설치합니다.

    # yum install trace-cmd

19.2. trace-cmd 실행

trace-cmd 유틸리티를 사용하여 모든 ftrace 기능에 액세스할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

절차

  • trace-cmd 명령을입력합니다.

    여기서 명령은 ftrace 옵션입니다.

    참고

    전체 명령 및 옵션 목록은 trace-cmd(1) 매뉴얼 페이지를 참조하십시오. 대부분의 개별 명령에는 자체 도움말 페이지인 trace-cmd-명령도 있습니다.

19.3. trace-cmd 예제

명령 예제에서는 trace-cmd 유틸리티를 사용하여 커널 기능을 추적하는 방법을 보여줍니다.

  • myapp 이 실행되는 동안 커널 내에서 실행 중인 레코딩 기능을 활성화하고 시작합니다.

    # trace-cmd record -p function myapp

    이 레코드는 모든 CPU 및 모든 작업의 기능, 심지어 myapp 과 관련이 없는 작업을 기록합니다.

  • 결과를 표시합니다.

    # trace-cmd report
  • myapp 이 실행되는 동안 sched 로 시작하는 함수만 기록합니다.

    # trace-cmd record -p function -l 'sched*' myapp
  • 모든 IRQ 이벤트를 활성화합니다.

    # trace-cmd start -e irq
  • wakeup_rt tracer를 시작합니다.

    # trace-cmd start -p wakeup_rt
  • 함수 추적을 비활성화하면서 preemptirqsoff 추적기를 시작합니다.

    # 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

19.4. 추가 리소스

  • trace-cmd(1) man page

20장. tuned-profiles-real-time을 사용하여 CPU 격리

애플리케이션 스레드에 가능한 가장 많은 실행 시간을 제공하려면 CPU를 격리할 수 있습니다. 따라서 CPU에서 관련 없는 작업을 최대한 많이 제거합니다. CPU 격리는 일반적으로 다음과 같습니다.

  • 모든 사용자 공간 스레드 제거.
  • 바인딩되지 않은 커널 스레드 제거. 커널 관련 바인딩된 스레드는 특정 CPU에 연결되어 있으며 이동할 수 없습니다.
  • 시스템에서 각 Interrupt Request(IRQ) 번호 N/proc/irq/N/smp_affinity 속성을 수정하여 인터럽트 제거

tuned-profiles-realtime 패키지의 isolated_cores=cpulist 구성 옵션을 사용하면 작업을 자동화하여 CPU를 격리할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

20.1. 격리할 CPU 선택

격리할 CPU를 선택하려면 시스템의 CPU 토폴로지를 신중하게 고려해야 합니다. 다른 사용 사례에는 다른 구성이 필요합니다.

  • 스레드가 캐시를 공유하여 서로 통신해야 하는 다중 스레드 애플리케이션이 있는 경우 동일한 NUMA 노드 또는 물리적 소켓에 보관해야 합니다.
  • 관련이 없는 여러 실시간 애플리케이션을 실행하는 경우 CPU를 NUMA 노드 또는 소켓으로 분리하는 것이 적합할 수 있습니다.

hwloc 패키지는 lstopo-no-graphicsnumactl 을 포함하여 CPU에 대한 정보를 얻는 데 유용한 유틸리티를 제공합니다.

사전 요구 사항

  • hwloc 패키지가 설치됩니다.

절차

  1. 물리적 패키지에서 사용 가능한 CPU의 레이아웃을 확인합니다.

    # lstopo-no-graphics --no-io --no-legend --of txt

    그림 20.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

추가 리소스

  • hwloc>-&lt; 매뉴얼 페이지

20.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->-<s.conf 구성 파일에는 기본 변수 콘텐츠가 isolated_cores=${f:calc_isolated_cores:2} 로 포함됩니다.

기본적으로 calc_isolated_cores 는 하우스키핑을 위해 소켓당 하나의 코어를 예약하고 나머지는 격리합니다. 기본 구성을 변경해야 하는 경우 /etc/tuned/realtime-anchors.conf 구성 파일의 isolated_cores=${f:calc_isolated_cores:2} 행을 주석 처리하고 TuneD의 isolated_cores 옵션을 사용하여 Isolating CPU의 절차 단계를 따릅니다.

사전 요구 사항

  • TuneDtuned-profiles-realtime 패키지가 설치됩니다.
  • 시스템에 대한 root 권한이 있습니다.

절차

  1. 루트 사용자로 텍스트 편집기에서 /etc/tuned/realtime->-<s.conf를 엽니다.
  2. isolated_cores=cpulist 를 설정하여 분리할 CPU를 지정합니다. CPU 번호와 범위를 사용할 수 있습니다.

    예:

    isolated_cores=0-3,5,7

    이는 코어 0, 1, 2, 3, 5, 7을 분리합니다.

    NUMA 노드 0에 코어가 8개인 두 개의 소켓 시스템에서 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

20.3. nohz 및 nohz_full 매개변수를 사용하여 CPU 격리

nohznohz_full 매개 변수는 지정된 CPU의 활동을 수정합니다. 이러한 커널 부팅 매개변수를 활성화하려면 realtime-virtual-host,realtime-virtual-guest 또는 cpu-partitioning 의 다음 TuneD 프로필 중 하나를 사용해야 합니다.

nohz=on

특정 CPU 세트의 타이머 활동을 줄입니다.

nohz 매개변수는 주로 유휴 CPU의 타이머 인터럽트를 줄이는 데 사용됩니다. 이를 통해 유휴 CPU를 감소 모드로 실행할 수 있으므로 건전지 수명을 유지할 수 있습니다. 실시간 응답 시간에 직접 유용하지는 않지만 nohz 매개변수는 실시간 응답 시간에 부정적인 영향을 미치지 않습니다. 그러나 nohz 매개변수는 실시간 성능에 긍정적인 영향을 미치는 nohz_full 매개변수를 활성화하는 데 필요합니다.

nohz_full=cpulist
nohz_full 매개 변수는 지정된 CPU 목록의 타이머 눈금을 다르게 처리합니다. CPU가 nohz_full CPU로 지정되어 있고 CPU에 실행 가능한 작업이 하나만 있는 경우 커널은 해당 CPU로 타이머 컷 전송을 중지합니다. 결과적으로 애플리케이션을 실행하는 데 더 많은 시간을 할애하고 인터럽트 및 컨텍스트 전환에 소요되는 시간을 줄일 수 있습니다.

추가 리소스

21장. ScanSetting_OTHER 작업 마이그레이션 제한

sched_nr_migrate 변수를 사용하여 gRPC_OTHER 가 다른 CPU로 마이그레이션하는 작업을 제한할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

21.1. 작업 마이그레이션

a ECDHE_OTHER 작업이 다른 많은 작업을 생성하는 경우 모두 동일한 CPU에서 실행됩니다. 마이그레이션 작업 또는 softirq 는 유휴 상태의 CPU에서 실행할 수 있도록 이러한 작업의 균형을 맞추려고 합니다.

sched_nr_migrate 옵션을 조정하여 한 번에 이동할 작업 수를 지정할 수 있습니다. 실시간 작업은 마이그레이션 방법이 다르기 때문에 이 문제의 직접적인 영향을 받지 않습니다. 그러나 softirq 가 작업을 이동할 때 실행 대기열 회전이 잠기므로 인터럽트를 비활성화합니다.

이동해야 하는 작업이 많이 있는 경우 인터럽트가 비활성화된 동안 발생하므로 타이머 이벤트 또는 발생 시 동시에 발생할 수 있습니다. 이로 인해 sched_nr_migrate 가 큰 값으로 설정된 경우 실시간 작업에 심각한 대기 시간이 발생할 수 있습니다.

21.2. sched_nr_migrate 변수를 사용하여 CloudEvent_OTHER 작업 마이그레이션 제한

sched_nr_migrate 변수를 늘리면 실시간 대기 시간을 고려하여 많은 작업을 생성하는 gRPC _OTHER 스레드의 고성능이 제공됩니다.

low real-time task latency at the cost of ECDHE_OTHER task performance, value must be lowered. 기본값은 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

22장. TCP 성능 급증 감소

TCP 타임스탬프를 생성하면 TCP 성능이 급증할 수 있습니다. sysctl 명령은 TCP 관련 항목의 값을 제어하고, /proc/sys/net/ipv4/tcp_timestamps 에 있는 timestamps 커널 매개 변수를 설정합니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

22.1. TCP 타임스탬프 비활성화

TCP 타임스탬프를 끄면 TCP 성능이 저하될 수 있습니다.

절차

  • TCP 타임스탬프를 끄십시오.

    # sysctl -w net.ipv4.tcp_timestamps=0
    net.ipv4.tcp_timestamps = 0

    출력은 net.ip4.tcp_timestamps 옵션 값이 0 임을 보여줍니다. 즉, TCP 타임스탬프는 비활성화되어 있습니다.

22.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 타임스탬프가 활성화됩니다.

22.3. TCP 타임스탬프 상태 표시

TCP 타임스탬프 생성 상태를 볼 수 있습니다.

절차

  • TCP 타임스탬프 생성 상태를 표시합니다.

    # sysctl net.ipv4.tcp_timestamps
    net.ipv4.tcp_timestamps = 0

    1 은 타임스탬프가 생성 중임을 나타냅니다. 값 0 은 타임스탬프가 생성되지 않음을 나타냅니다.

23장. R CloudEvent 콜백을 사용하여 CPU 성능 향상

Read-Copy-Update (RECDHE ) 시스템은 커널 내부의 스레드를 상호 제외하기 위한 잠금 해제 메커니즘입니다. RECDHE 작업을 수행하면 메모리가 안전해질 때 호출이 CPU에 대기되는 경우가 있습니다.

R CloudEvent 콜백을 사용하여 CPU 성능을 개선하려면 다음을 수행합니다.

  • CPU 콜백 실행의 후보가 되는 CPU를 제거할 수 있습니다.
  • 모든 Ranchor 콜백을 처리하도록 CPU를 할당할 수 있습니다. 이 CPU를 하우스키핑 CPU라고 합니다.
  • CPU는 R ScanSetting 오프로드 스레드를 유발하는 책임에서 벗어날 수 있습니다.

이 조합은 사용자 워크로드에 전용된 CPU에 대한 간섭을 줄입니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.
  • tuna 패키지가 설치됨

23.1. RLoadBalancer 콜백 오프로드

rcu_nocbsrcu_nocb_poll 커널 매개변수를 사용하여 RLoadBalancer 콜백을 오프로드할 수 있습니다.

절차

  • R SSDT 콜백 실행 후보에서 하나 이상의 CPU를 제거하려면 rcu_nocbs 커널 매개변수의 CPU 목록을 지정합니다. 예를 들면 다음과 같습니다.

    rcu_nocbs=1,4-6

    또는

    rcu_nocbs=3

    두 번째 예는 커널에 CPU 3이 호출되지 않음 CPU임을 지시합니다. 즉, R CloudEvent 콜백은 CPU 3에 고정된 rcuc/$CPU 스레드에서 실행되지 않지만 rcuo/$CPU 스레드에서 수행됩니다. 이 trhead를 하우스키핑 CPU로 이동하여 CPU 3이 RECDHE 콜백 작업이 할당되지 않도록 할 수 있습니다.

23.2. Ranchor 콜백

하우스키핑 CPU를 할당하여 모든 RECDHE 콜백 스레드를 처리할 수 있습니다. 이렇게 하려면 tuna 명령을 사용하고 모든 RECDHE 콜백을 하우스키핑 CPU로 이동합니다.

절차

  • RECDHE 콜백 스레드를 하우스키핑 CPU로 이동합니다.

    # tuna --threads=rcu --cpus=x --move

    여기서 x 는 하우스키핑 CPU의 CPU 번호입니다.

이 작업은 CPU X 이외의 모든 CPU가 RECDHE 콜백 스레드를 처리하지 못하도록 합니다.

23.3. RECDHE 오프로드 스레드를 축소하지 못하도록 CPU 조정

Ranchor 오프로드 스레드는 다른 CPU에서 RECDHE 콜백을 수행할 수 있지만 각 CPU는 해당 R ScanSetting 오프로드 스레드를 재지정해야 합니다. 이 책임에서 CPU를 줄일 수 있습니다.

절차

  • rcu_nocb_poll 커널 매개변수를 설정합니다.

    이 명령을 실행하면 타이머가 주기적으로 Ranchor 오프로드 스레드를 발생시켜 실행할 콜백이 있는지 확인합니다.

23.4. 추가 리소스

24장. ftrace를 사용하여 대기 시간 추적

ftrace 유틸리티는 RHEL for Real Time 커널과 함께 제공되는 진단 기능 중 하나입니다. ftrace 는 개발자가 사용자 공간 외부에서 발생하는 대기 시간 및 성능 문제를 분석하고 디버깅하는 데 사용할 수 있습니다. ftrace 유틸리티에는 다양한 방법으로 유틸리티를 사용할 수 있는 다양한 옵션이 있습니다. 컨텍스트 스위치를 추적하거나, 우선 순위가 높은 작업이 발생하는 시간, 인터럽트 길이가 비활성화되거나 지정된 기간 동안 실행되는 모든 커널 함수를 나열하는 데 사용할 수 있습니다.

함수 추적기와 같은 ftrace 추적기 중 일부는 과도하게 많은 양의 데이터를 생성할 수 있으므로 추적 로그 분석을 시간이 많이 소요되는 작업으로 변환할 수 있습니다. 그러나 애플리케이션이 중요한 코드 경로에 도달할 때만 추적기를 시작하고 종료하도록 지시할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

24.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_tracer의 사용 가능한 추적기 목록에서 사용할 추적기를 선택합니다.
    2. 선택기 이름을 /sys/kernel/debug/tracing/current_tracer 에 삽입합니다.

      # echo preemptoff > /sys/kernel/debug/tracing/current_tracer
      참고

      echo 명령과 함께 단일 '>'를 사용하면 파일의 기존 값을 덮어씁니다. 파일에 값을 추가하려면 대신 '>>'을 사용합니다.

  4. function-trace 옵션은 wakeup_rt,preemptirqsoff 로 대기 시간을 추적하기 때문에 유용합니다. preemptirqsoff는 오버헤드를 초과할 수 있는 함수 추적을 자동으로 활성화합니다.

    functionfunction_graph tracing이 활성화되어 있는지 확인합니다.

    # cat /sys/kernel/debug/tracing/options/function-trace
    1
    • 값이 1 이면 함수 및 function _graph 추적이 활성화되었음을 나타냅니다.
    • 값이 0 이면 함수function_graph 추적이 비활성화됩니다.
  5. 기본적으로 함수 및 function _graph 추적은 활성화되어 있습니다. function _graph tracing을 설정하거나 끄려면 적절한 값을 /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, Preempirqsoff,preempirqsoffwakeup 추적기는 지속적으로 대기 시간을 모니터링합니다. tracing_max_latency 에 기록된 것보다 더 큰 대기 시간을 기록하는 경우 해당 대기 시간의 추적이 기록되고 tracing_max_latency 가 새 최대 시간으로 업데이트됩니다. 이러한 방식으로 tracing_max_latency 는 마지막 재설정 이후 항상 가장 높은 대기 시간을 표시합니다.

    • 최대 대기 시간을 재설정하려면 0tracing_max_latency 파일로 에코합니다.

      # echo 0 > /sys/kernel/debug/tracing/tracing_max_latency
    • 설정된 양보다 대기 시간만 표시하려면 마이크로초 단위로 양을 에코합니다.

      # echo 200 > /sys/kernel/debug/tracing/tracing_max_latency

      추적 임계값이 설정되면 최대 대기 시간 설정을 덮어씁니다. 임계값보다 큰 대기 시간이 기록되면 최대 대기 시간에 관계없이 기록됩니다. 추적 파일을 검토할 때 마지막으로 기록된 대기 시간만 표시됩니다.

    • 임계값을 설정하려면 대기 시간을 기록해야 하는 마이크로초 수를 에코합니다.

      # 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 예제 를 참조하십시오.

24.2. ftrace 파일

다음은 /sys/kernel/debug/tracing/ 디렉토리의 기본 파일입니다.

ftrace 파일

Trace
ftrace 추적의 출력을 보여주는 파일입니다. 이 파일을 읽을 때 추적이 중지되고 읽은 이벤트를 사용하지 않기 때문에 실제로 추적의 스냅샷입니다. 즉, 사용자가 추적을 비활성화하고 이 파일을 읽으면 읽힐 때마다 동일한 항목을 보고합니다.
trace_pipe
추적을 읽을 때 ftrace 추적의 출력을 보여주는 파일은 실시간으로 표시됩니다. 생산자/소유자 추적입니다. 즉, 각 읽기는 읽은 이벤트를 사용합니다. 이는 읽은 대로 추적을 중지하지 않고 활성 추적을 읽는 데 사용할 수 있습니다.
available_tracers
커널로 컴파일된 ftrace 추적기 목록입니다.
current_tracer
ftrace 추적기를 활성화하거나 비활성화합니다.
이벤트
추적할 이벤트가 포함되어 있고 이벤트를 활성화 또는 비활성화하고 이벤트에 대한 필터를 설정하는 데 사용할 수 있는 디렉터리입니다.
tracing_on
ftrace 버퍼에 대한 레코딩을 비활성화하고 활성화합니다. tracing_on 파일을 통해 추적을 비활성화해도 커널 내부에서 발생하는 실제 추적은 비활성화되지 않습니다. 버퍼 쓰기만 비활성화합니다. 추적을 수행하는 작업은 계속 발생하지만 데이터는 아무데도 이동하지 않습니다.

24.3. ftrace 추적기

커널 구성 방법에 따라 지정된 커널에서 일부 추적기를 사용할 수 있는 것은 아닙니다. RHEL for Real Time 커널의 경우 추적 및 디버그 커널에는 프로덕션 커널과 다른 추적기가 있습니다. 이는 추적기가 커널에 구성되어 있지만 활성 상태가 아닌 경우 일부 추적기에서 눈에 띄는 오버헤드가 있기 때문입니다. 이러한 추적자는 tracedebug 커널에만 활성화됩니다.

Tracers

function
가장 널리 적용할 수 있는 추적기 중 하나입니다. 커널 내에서 함수 호출을 추적합니다. 이로 인해 추적된 함수 수에 따라 눈에 띄는 오버헤드가 발생할 수 있습니다. 활성화되지 않으면 약간의 오버헤드가 발생합니다.
function_graph

function_graph tracer는 시각적으로 원하는 결과를 제공하도록 설계되었습니다. 또한 이 추적기에서는 함수의 종료를 추적하여 커널의 함수 호출 흐름을 표시합니다.

참고

이 추적기에는 활성화된 경우 함수 추적기보다 많은 오버헤드가 있지만 비활성화되면 동일한 낮은 오버헤드가 발생합니다.

wakeup
모든 CPU에서 발생하는 활동을 보고하는 전체 CPU 추적기입니다. 해당 작업이 실시간 작업인지 여부에 관계없이 시스템에서 가장 높은 우선 순위 작업을 시작하는 데 걸리는 시간을 기록합니다. 비실시간 작업을 시작하는 데 걸리는 최대 시간을 기록하면 실시간 작업을 시작하는 데 걸리는 시간이 숨겨집니다.
wakeup_rt
모든 CPU에서 발생하는 활동을 보고하는 전체 CPU 추적기입니다. 이는 예약된 시간까지 현재 가장 높은 우선 순위 작업에서 걸리는 시간을 기록합니다. 이 추적기에서는 실시간 작업의 시간만 기록합니다.
preemptirqsoff
선점 또는 인터럽트를 비활성화하는 영역을 추적하고 선점 또는 인터럽트가 비활성화된 최대 시간을 기록합니다.
preemptoff
preemptirqsoff 추적기와 유사하지만 사전 교환이 비활성화된 최대 간격만 추적합니다.
irqsoff
preemptirqsoff 추적기와 유사하지만 인터럽트가 비활성화된 최대 간격만 추적할 수 있습니다.
NOP
기본 추적기입니다. 이는 추적 기능을 제공하지 않지만, 이벤트가 모든 추적기와 인터리어링할 수 있으므로 nop tracer는 이벤트 추적에 대한 특정 관심에 사용됩니다.

24.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

25장. 애플리케이션 타임스탬프

타임스탬프를 자주 수행하는 애플리케이션은 시계를 읽는 CPU 비용의 영향을 받습니다. 클럭을 읽는 데 사용된 높은 비용과 시간은 애플리케이션 성능에 부정적인 영향을 미칠 수 있습니다.

기본 시계보다 빠르고 읽기 메커니즘이 있는 하드웨어 시계를 선택하여 클럭을 읽는 비용을 줄일 수 있습니다.

RHEL for Real Time에서는 clock_gettime() 함수와 함께 POSIX 시계를 사용하여 가능한 가장 낮은 CPU 비용으로 클럭 읽기를 생성함으로써 추가 성능 향상을 얻을 수 있습니다.

이러한 이점은 높은 읽기 비용으로 하드웨어 시계를 사용하는 시스템에 더 큰 이점이 있습니다.

25.1. POSIX 클럭

POSIX는 시간 소스를 구현하고 표시하기 위한 표준입니다. 시스템의 다른 애플리케이션에 영향을 주지 않고 애플리케이션에 POSIX 시계를 할당할 수 있습니다. 이는 커널에 의해 선택되고 시스템 전체에 구현된 하드웨어 시계와 대조됩니다.

지정된 POSIX 시계를 읽는 데 사용되는 함수는 clock_gettime() 이며 < time.h>에서 정의됩니다. 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 변형은 밀리 초 시계 해상도를 수용할 수 있는 모든 애플리케이션에 적합합니다.

참고

_COARSE 접두사와 없이 POSIX 시계를 읽는 비용과 해결 방법을 비교하려면 RHEL for Real Time Reference 가이드를 참조하십시오.

25.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

25.3. 추가 리소스

  • clock_gettime() man page

26장. TCP_NODELAY를 사용하여 네트워크 대기 시간 개선

기본적으로 TCP 는 Nagle의 알고리즘을 사용하여 작은 발신 패킷을 수집하여 모두 한 번에 보냅니다. 이로 인해 대기 시간이 증가할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

26.1. TCP_NODELAY 사용의 영향

전송되는 모든 패킷에 대해 대기 시간이 짧은 애플리케이션은 TCP_NODELAY 옵션이 활성화된 소켓에서 실행되어야 합니다. 이렇게 하면 이벤트가 발생하는 즉시 커널에 버퍼 쓰기를 보냅니다.

참고
TCP_NODELAY 가 효과적이려면 애플리케이션은 작고 논리적으로 관련된 버퍼 쓰기를 피해야 합니다. 그렇지 않으면 이러한 작은 쓰기로 인해 TCP 가 이러한 여러 버퍼를 개별 패킷으로 보내 전체 성능이 저하됩니다.

애플리케이션에 논리적으로 관련된 여러 버퍼가 있고 하나의 패킷으로 전송되어야 하는 경우 다음 해결 방법 중 하나를 적용하여 성능이 저하되지 않도록 합니다.

  • 메모리에 연속된 패킷을 빌드한 다음 TCP _NODELAY 로 구성된 소켓의 논리 패킷을 TCP로 전송합니다.
  • I/O 벡터를 만들고 TCP_NODELAY 로 구성된 소켓에서 writev 명령을 사용하여 커널에 전달합니다.
  • TCP_CORK 옵션을 사용합니다. TCP_CORKTCP 가 패킷을 전송하기 전에 애플리케이션이 코스크를 제거할 때까지 대기하도록 지시합니다. 이 명령을 실행하면 수신하는 버퍼가 기존 버퍼에 추가됩니다. 이렇게 하면 애플리케이션이 커널 공간에 패킷을 빌드할 수 있으므로 계층에 추상화를 제공하는 다른 라이브러리를 사용할 때 필요할 수 있습니다.

애플리케이션의 다양한 구성 요소에 의해 논리 패킷이 커널에 빌드된 경우 소켓을 분리하여 TCP 가 즉시 누적된 논리 패킷을 보낼 수 있어야 합니다.

26.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 를 사용하여 커널에 전달합니다.

26.3. TCP_CORK 활성화

TCP_CORK 옵션은 소켓이 "cocorked"될 때까지 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 는 애플리케이션에서 추가 패킷을 기다리지 않고 누적된 논리적 패킷을 즉시 전송합니다.

26.4. 추가 리소스

  • TCP>-& lt; 매뉴얼 페이지
  • setsockopt(3p) man page
  • setsockopt(2) man page

27장. CloudEvent를 사용하여 리소스 초과 방지

상호 제외(mutex) 알고리즘은 공통 리소스의 과다 사용을 방지하는 데 사용됩니다.

27.1. trigger options

상호 제외(mutex) 알고리즘은 공통 리소스를 사용하여 프로세스를 동시에 방지하는 데 사용됩니다. 빠른 사용자 공간 10.0.0.1(futex)은 커널 공간으로 컨텍스트 전환을 요구하지 않고 사용자 공간 스레드가 이미 다른 스레드에 의해 보유되지 않은 경우 사용자 공간 스레드를 클레임할 수 있는 툴입니다.

표준 속성, 비공개, 비재귀, 비로버스 및 우선순위가 없는 inherited-enabled로 pthread_mutex_t 오브젝트를 초기화하면 우선순위가 적용되지 않습니다. 이 오브젝트는 pthreads API 및 RHEL for Real Time 커널에서 제공하는 ben fits를 제공하지 않습니다.

pthreads API 및 RHEL for Real Time 커널의 이점을 얻으려면 pthread_mutexattr_t 오브젝트를 만듭니다. 이 개체는 futex에 대해 정의된 특성을 저장합니다.

참고

용어는 POSIX 스레드(pthread) constructs를 설명하는 데 사용됩니다.

27.2. attributes 특성 오브젝트 생성

CloudEvent에 대한 추가 기능을 정의하려면 pthread_mutexattr_t 오브젝트를 만듭니다. 이 개체는 futex에 대해 정의된 특성을 저장합니다. 이는 항상 수행해야 하는 기본적인 안전 절차입니다.

절차

  • 다음 중 하나를 사용하여 CloudEvent 특성 오브젝트를 생성합니다.

    • pthread_mutex_t(my_mutex);
    • pthread_mutexattr_t(&my_mutex_attr);
    • pthread_mutexattr_init(&my_mutex_attr);

고급 attributes에 대한 자세한 내용은 고급 attributes를 참조하십시오.

27.3. 표준 속성을 사용하여 태그 생성

표준 속성, 비공개, 비재귀, 비로버스 및 우선순위가 없는 inherited-enabled로 pthread_mutex_t 오브젝트를 초기화하면 우선순위가 적용되지 않습니다.

절차

  • 다음 중 하나를 사용하여 pthreads 아래에>-< 오브젝트를 생성합니다.

    • pthread_mutex_t(my_mutex);
    • pthread_mutex_init(&my_mutex, &my_mutex_attr);

      여기서 &my_mutex_attr; 은 attribute 객체입니다.

27.4. 고급 attributes

다음 고급 속성을 태그 특성 개체에 저장할 수 있습니다.

triggerbinding 특성

공유 및 개인 태그

공유는 프로세스 간에 사용할 수 있지만 더 많은 오버헤드를 생성할 수 있습니다.

pthread_mutexattr_setpshared(&my_mutex_attr, PTHREAD_PROCESS_SHARED);

실시간 우선순위 상속

우선순위 상속을 사용하여 우선 순위 버전 문제를 방지할 수 있습니다.

pthread_mutexattr_setprotocol(&my_mutex_attr, PTHREAD_PRIO_INHERIT);

강력한 경우

pthread가 종료되면 pthread 아래의 강력한 prethreades가 해제됩니다. 그러나 이는 높은 오버헤드 비용이 발생합니다. 이 문자열의 _NP 는 이 옵션이 POSIX가 아니거나 이식 가능하지 않음을 나타냅니다.

pthread_mutexattr_setrobust_np(&my_mutex_attr, PTHREAD_MUTEX_ROBUST_NP);

triggerinitinitialization

그러나 공유는 프로세스 간에 사용할 수 있지만 더 많은 오버헤드를 만들 수 있습니다.

pthread_mutex_init(&my_mutex_attr, &my_mutex);

27.5. CloudEvent 특성 오브젝트 정리

10.0.0.1 특성 개체를 사용하여 만든 후에는 특성 개체를 유지하여 동일한 형식의 더 많은 device를 초기화하거나 정리할 수 있습니다.After theECDHE has been created using theECDHE attribute object, you can keep the attribute object to initialize more of the same type, or you can clean it up. 두 경우 모두 영향을 받지 않습니다.

절차

  • _destroy 명령을 사용하여 속성 오브젝트를 정리합니다.

    pthread_mutexattr_destroy(&my_mutex_attr);

    이제 CloudEvent는 일반 pthread_mutex 로 작동하며 정상적으로 잠기고 잠금 해제 및 삭제할 수 있습니다.

27.6. 추가 리소스

  • futex(7) man page
  • pthread_mutex_destroy(P) 매뉴얼 페이지
  • pthread_mutexattr_setprotocol(3p) man page
  • pthread_mutexattr_setprioceiling(3p) man page

28장. 애플리케이션 성능 분석

per f는 성능 분석 도구입니다. 간단한 명령줄 인터페이스를 제공하며 Linux 성능 측정에서 CPU 하드웨어 차이를 추상화합니다. per f는 커널이 내보낸 perf_events 인터페이스를 기반으로 합니다.

perf 의 한 가지 장점은 커널과 아키텍처 둘 다라는 것입니다. 분석 데이터는 특정 시스템 구성 없이도 검토할 수 있습니다.

사전 요구 사항

  • perf 패키지가 시스템에 설치되어 있어야 합니다.
  • 관리자 권한이 있어야 합니다.

28.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 옵션으로 표시되고 프로세스는 몇 초 후에 종료되었습니다. 결과는 0.725MB의 데이터를 수집하여 새로 생성된 perf.data 파일에 저장했습니다.

검증

  • 결과 파일이 생성되었는지 확인합니다.

    # ls
    perf.data

28.2. 성능 분석 결과 보관

perf archive 명령을 사용하여 다른 시스템에서 perf 의 perf 결과를 분석할 수 있습니다. 다음의 경우 필요하지 않을 수 있습니다.

  • 바이너리 및 라이브러리와 같은 동적 공유 오브젝트(DSO)는 이미 ~/.debug/ 캐시와 같은 분석 시스템에 있습니다.
  • 두 시스템에는 동일한 바이너리 세트가 있습니다.

절차

  1. perf 명령의 결과 아카이브를 만듭니다.

    # perf archive
  2. 아카이브에서 tarball을 만듭니다.

    # tar cvf perf.data.tar.bz2 -C ~/.debug

28.3. 성능 분석 결과 분석

이제 perf 레코드 기능의 데이터를 perf report 명령을 사용하여 직접 조사할 수 있습니다.

절차

  • 결과를 perf.data 파일 또는 아카이브된 tarball에서 직접 분석합니다.

    # perf report

    보고서의 출력은 애플리케이션의 최대 CPU 사용량에 따라 정렬됩니다. 이는 프로세스의 커널 또는 사용자 공간에서 샘플이 발생했는지를 나타냅니다.

    이 보고서는 샘플이 가져온 모듈에 대한 정보를 보여줍니다.

    • 커널 모듈에서 발생하지 않은 커널 샘플은 표기법 [kernel.kallsyms] 으로 표시됩니다.
    • 커널 모듈에서 발생한 커널 샘플은 [module], [ext4] 로 표시됩니다.
    • 사용자 공간의 프로세스의 경우 결과에 해당 프로세스와 연결된 공유 라이브러리가 표시될 수 있습니다.

      보고서는 프로세스가 커널 또는 사용자 공간에서도 발생하는지 여부를 나타냅니다.

    • 결과 [.] 는 사용자 공간을 나타냅니다.
    • 결과 [k] 는 커널 공간을 나타냅니다.

    숙련된 perf 개발자에게 적합한 데이터를 포함하여 보다 세분화된 세부 정보를 검토할 수 있습니다.

28.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]...

28.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 요청이 있음을 나타내는 메시지를 표시한 것으로 표시됩니다.

28.6. 추가 리소스

  • Perf helpCOMM AND
  • perf(1) 매뉴얼 페이지

29장. stress-ng를 사용하여 실시간 시스템을 테스트하는 응력 테스트

강조 표시는 시스템의 기능을 측정하여 불합리한 조건에서 적절한 수준의 효율성을 유지합니다. stress-ng 툴은 모든 커널 인터페이스를 로드하고 과부하할 수 있는 stress 워크로드 생성기입니다. 여기에는 스트레스 요인으로 알려진 광범위한 응력 메커니즘이 포함되어 있습니다. 과부하 테스트는 시스템이 과도하게 작동할 때 발생하는 열 오버런 및 운영 체제 버그와 같은 머신 작업 및 트립 하드웨어 문제를 만듭니다.

1000개 이상의 다양한 테스트가 있습니다. 여기에는 부동 소수점, 정수, 비트 조작, 제어 흐름 및 가상 메모리 테스트를 실행하는 CPU 특정 테스트가 포함됩니다.

참고

테스트 중 일부가 잘못 설계 된 하드웨어에서 시스템의 열 영역 이동 지점에 영향을 줄 수 있으므로 강조 표시 된 도구를 사용하십시오. 이로 인해 시스템 성능에 영향을 미치고 과도한 시스템 제한으로 인해 중단하기 어려울 수 있습니다.

29.1. CPU 부동 소수점 단위 및 프로세서 데이터 캐시 테스트

부동 소수점 단위는 부동 소수점 연산을 수행하는 프로세서의 기능 부분입니다.A floating-point unit is the functional part of the processor that performs floating-point arithmetic operations. 부동 소수점 단위는 수치화 작업을 처리하고 부동 숫자 또는 10진수 계산을 더 간단하게 만듭니다.

--matrix-method 옵션을 사용하면 CPU 부동 소수점 작업 및 프로세서 데이터 캐시를 테스트하는 데 어려움을 겪을 수 있습니다.

사전 요구 사항

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

절차

  • 한 CPU에서 60초 동안 부동 소수점을 테스트하려면 --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

    stressors가 0인 특수 모드에서는 실행할 사용 가능한 CPU를 쿼리하여 CPU 번호를 지정할 필요가 없습니다.

    필요한 총 CPU 시간은 4 x 60 초 (240 초)입니다.이 중 0.13 %는 사용자 시간에 85.50%이며, stress-ng 는 모든 CPU의 85.64 %를 실행합니다.

  • POSIX 메시지 큐를 사용하여 프로세스 간 메시지 전달을 테스트하려면 -mq 옵션을 사용합니다.

    # stress-ng --mq 0 -t 30s --times --perf

    mq 옵션은 POSIX 메시지 큐를 사용하여 컨텍스트 전환을 강제 적용하도록 특정 수의 프로세스를 구성합니다. 이 워크로드 테스트는 낮은 데이터 캐시 누락을 목표로 합니다.

29.2. 여러 강조 메커니즘으로 CPU 테스트

stress-ng 툴은 여러 개의 stress 테스트를 실행합니다. 기본 모드에서는 지정된 stressor 메커니즘을 병렬로 실행합니다.

사전 요구 사항

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

절차

  • 다음과 같이 CPU 강조 표시기 인스턴스를 여러 개 실행합니다.

    # stress-ng --cpu 2 --matrix 1 --mq 3 -t 5m

    예를 들어, stress-ng 는 CPU 강조기의 두 개의 인스턴스, 즉 매트릭스 강조기 인스턴스 한 개와 메시지 대기열 강조기의 인스턴스 3개로 5분 동안 테스트할 수 있습니다.

  • 모든 stress 테스트를 병렬로 실행하려면 -all 옵션을 사용합니다.

    # stress-ng --all 2

    이 예에서 stress-ng 는 모든 과부하 테스트의 두 인스턴스를 병렬로 실행합니다.

  • 특정 순서로 서로 다른 각 강조표를 실행하려면 --seq 옵션을 사용합니다.

    # stress-ng --seq 4 -t 20

    이 예에서, stress-ng 는 모든 스트레스를 1분 20분 동안 실행하며, 각 강조기의 인스턴스 수는 온라인 CPU 수와 일치합니다.

  • 테스트 실행에서 특정 과부하를 제외하려면 -x 옵션을 사용합니다.

    # stress-ng --seq 1 -x numa,matrix,hdd

    이 예에서 stress-ngnuma,hdd주요 과부하 메커니즘을 제외하고 각각의 한 인스턴스인 모든 스트레스를 실행합니다.

29.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초 동안 88도에 도달하도록 구성합니다.

  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

29.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 작업을 표시합니다.

29.5. 가상 메모리 부족 생성

메모리 부족이 있을 때 커널은 스왑에 페이지 쓰기를 시작합니다. --page-in 옵션을 사용하여 가상 메모리를 과부하시켜 비동시 페이지가 가상 메모리로 다시 스왑되도록 강제할 수 있습니다. 이로 인해 가상 시스템이 크게 실행됩니다. --page-in 옵션을 사용하면 bigheap,mmap 및 가상 머신(vm) 과부하 요인에 대해 이 모드를 활성화할 수 있습니다. --page-in 옵션, 코어가 아닌 할당된 페이지를 눌러 의 페이지로 강제 적용합니다.

사전 요구 사항

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

절차

  • 가상 메모리를 테스트하도록 하려면 --page-in 옵션을 사용합니다.

    # stress-ng --vm 2 --vm-bytes 2G --mmap 2 --mmap-bytes 2G --page-in

    이 예에서는 할당된 버퍼 크기, 2 x 2GB의 vm stressor 및 --page -in 이 활성화된 2 x 2GB의 mmap 강조 기보다 작은 메모리가 4GB인 시스템에서 메모리 부족을 테스트합니다.

29.6. 장치에서 대규모 인터럽트 로드 테스트

높은 빈도에서 타이머 실행은 대규모 인터럽트 로드를 생성할 수 있습니다. 적절하게 선택된 타이머 주파수를 가진 -timer stressor는 초당 많은 인터럽트를 강제할 수 있습니다.

사전 요구 사항

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

절차

  • 인터럽트 로드를 생성하려면 --timer 옵션을 사용합니다.

    # stress-ng --timer 32 --timer-freq 1000000

    이 예에서는 stress-ng 테스트 32개의 인스턴스 1ECDHE를 테스트합니다.

29.7. 프로그램에서 주요 페이지 폴트 생성

stress-ng 를 사용하면 메모리에 로드되지 않은 주요 페이지 폴트를 생성하여 페이지 폴트 속도를 테스트하고 분석할 수 있습니다. 새 커널 버전에서 userfaultfd 메커니즘은 프로세스의 가상 메모리 레이아웃에서 페이지 폴트에 대한 스레드를 찾는 오류를 알립니다.

사전 요구 사항

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

절차

  • 초기 커널 버전에서 주요 페이지 폴트를 생성하려면 다음을 사용합니다.

    # stress-ng --fault 0 --perf -t 1m
  • 새 커널 버전에서 주요 페이지 폴트를 생성하려면 다음을 사용합니다.

    # stress-ng --userfaultfd 0 --perf -t 1m

29.8. CPU 과부하 테스트 메커니즘 보기

CPU 강조 표시 테스트에는 CPU를 실행하는 방법이 포함되어 있습니다. which 옵션을 사용하여 모든 방법을 볼 수 있도록 출력을 출력할 수 있습니다.

기본적으로 테스트 방법을 지정하지 않으면 stressor는 라운드 로빈 방식으로 모든 과부하를 확인하여 각 부하에 대해 CPU를 테스트합니다.

사전 요구 사항

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

절차

  1. 사용 가능한 모든 stressor 메커니즘을 출력하고 다음 옵션을 사용합니다.

    # 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-ng --cpu 1 --cpu-method fft -t 1m

29.9. 확인 모드 사용

검증 모드는 테스트가 활성화될 때 결과를 검증합니다. 테스트 실행의 메모리 콘텐츠를 확인하고 예기치 않은 오류를 보고합니다.

모든 오버로드는 확인 모드가 없으며 활성화로 인해 이 모드에서 추가 확인 단계가 실행되므로 bogo 작업 통계를 줄일 수 있습니다.

사전 요구 사항

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

절차

  • stress 테스트 결과를 확인하려면 --verify 옵션을 사용합니다.

    # stress-ng --vm 1 --vm-bytes 2G --verify -v

    이 예에서 stress-ng--verify 모드로 구성된 vm stressor를 사용하여 실질적으로 매핑된 메모리에 대한 완전한 메모리 검사 출력을 출력합니다. 메모리의 읽기 및 쓰기 결과를 확인합니다.Checks the read and write results on the memory.

30장. 컨테이너 생성 및 실행

이 섹션에서는 실시간 커널로 컨테이너 생성 및 실행에 대한 정보를 제공합니다.

사전 요구 사항

  • podman 및 기타 컨테이너 관련 유틸리티를 설치합니다.
  • RHEL에서 Linux 컨테이너의 관리 및 관리에 대해 알아봅니다.
  • kernel-rt 패키지 및 기타 실시간 관련 패키지를 설치합니다.

30.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. 다음 Dockerfile 을 생성합니다.

    # vim Dockerfile
    FROM rhel8
    RUN subscription-manager repos --enable=rhel-8-for-x86_64-rt-rpm
    RUN dnf -y install rt-tests
    ENTRYPOINT cyclictest --smp -p95
  5. Dockerfile이 포함된 디렉터리에서 컨테이너 이미지를 빌드합니다.

    # podman build -t cyclictest .

30.2. 컨테이너 실행

Dockerfile로 빌드된 컨테이너를 실행할 수 있습니다.

절차

  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 옵션은 컨테이너 내에서 호스트 장치를 사용할 수 있도록 합니다(하위적으로 CPU 유휴 시간 관리를 구성하기 위해cyclictest 워크로드에서 사용). 지정된 장치를 사용할 수 없는 경우 아래 메시지와 유사한 오류가 표시됩니다.

    WARN: stat /dev/cpu_dma_latency failed: No such file or directory

    이와 같은 오류 메시지로 인해 문제가 발생하는 경우 podman-run(1) 매뉴얼 페이지를 참조하십시오. 컨테이너 내에서 특정 워크로드를 실행하려면 다른 podman-run 옵션이 유용할 수 있습니다.

    /dev/cpu/*/msr 와 같은 CPU 장치 파일을 매핑하려면 --device=/dev/cpu 옵션을 추가하여 디렉터리 계층 구조를 추가해야 하는 경우도 있습니다.

30.3. 추가 리소스

31장. 프로세스의 우선 순위 표시

sched_getattr 특성을 사용하여 프로세스의 스케줄링 정책에 대한 정보와 프로세스의 우선 순위에 대한 정보를 표시할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

31.1. chrt 유틸리티

chrt 유틸리티는 스케줄러 정책 및 우선순위를 확인하고 조정합니다. 원하는 속성을 사용하여 새 프로세스를 시작하거나 실행 중인 프로세스의 속성을 변경할 수 있습니다.

추가 리소스

  • chrt(1) 매뉴얼 페이지

31.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

31.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.

추가 리소스

  • sched_getscheduler(2) man page

31.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 로 설정됩니다.

    참고

    ScanSetting _FIFO 및 10.0.0.1 _RR 모두 1 에서 99 사이의 범위 내의 숫자일 수 있습니다. POSIX는 이 범위를 충족하기 위해 보장되지 않으며 이식 가능한 프로그램은 이러한 기능을 사용해야 합니다.

  3. 파일을 저장하고 편집기를 종료합니다.
  4. 프로그램을 컴파일합니다.

    $ gcc sched_get.c -o msched_get

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

추가 리소스

  • sched_get_priority_min(2) man page
  • sched_get_priority_max(2) man page

31.5. 프로세스의 timeslice 표시

ScanSetting _RR (round-robin) 정책은 10.0.0.1 _FIFO (first-in, first-out) 정책과 약간 다릅니다. gRPC_RR 은 라운드 로빈 회전에서 우선 순위가 동일한 동시 프로세스를 할당합니다. 이러한 방식으로 각 프로세스에 timeslice가 할당됩니다. sched_rr_get_interval() 함수는 각 프로세스에 할당된 timeslice를 보고합니다.

참고

POSIX를 사용하려면 이 함수가 10.0.0.1 _RR 스케줄러 정책으로 실행되도록 구성된 프로세스에서만 작동해야 하지만 sched_ rr_get_get_interval() 함수는 Linux의 모든 프로세스의 timeslice 길이를 검색할 수 있습니다.

timeslice 정보는 timespec 으로 반환됩니다. 이것은 00:00:00 GMT의 기본 시간, 1970년 1월 1일 이후의 초 및 나노초 수입니다.

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

추가 리소스

  • nice(2) man page
  • getpriority(2) man page
  • setpriority(2) 매뉴얼 페이지

31.6. 프로세스의 스케줄링 정책 및 관련 속성 표시

sched_getattr() 함수는 PID로 식별되는 지정된 프로세스에 현재 적용되는 스케줄링 정책을 쿼리합니다. PID가 0이면 호출 프로세스의 정책이 검색됩니다.

size 인수는 사용자 공간에 알려진 sched_attr 구조의 크기를 반영해야 합니다. 커널은 sched_attr::sizesched_attr 구조의 크기로 채웁니다.

입력 구조가 작은 경우 커널은 제공된 공간 외부의 값을 반환합니다. 그 결과 시스템 호출이 E2BIG 오류와 함께 실패합니다. 다른 sched_attr 필드는 The 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

31.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 데이터 구조

크기

스레드 크기(바이트)입니다. 구조의 크기가 커널 구조보다 작으면 추가 필드가 0 으로 가정합니다. 크기가 커널 구조보다 크면 커널은 모든 추가 필드를 0 으로 확인합니다.

참고

sched_setattr() 함수가 커널 구조보다 크고 커널 구조의 크기를 업데이트하는 경우 E2BIG 오류와 함께 실패합니다.

sched_policy
스케줄링 정책
sched_flags

fork() 함수를 사용하여 프로세스 포크가 시작될 때 스케줄링 동작을 제어할 수 있습니다. 호출 프로세스를 상위 프로세스라고 하며 새 프로세스를 하위 프로세스라고 합니다. 유효한 값은 다음과 같습니다.

  • 0: 하위 프로세스는 상위 프로세스의 스케줄링 정책을 상속합니다.
  • gRPC_FLAG_RESET_ON_FORK: fork (): 하위 프로세스는 상위 프로세스에서 스케줄링 정책을 상속하지 않습니다. 대신 기본 스케줄링 정책 (struct sched_attr){ .sched_policy =ECDHE_OTHER, } 로 설정됩니다.
sched_nice
CloudEvent _OTHER 또는 ScanSetting _ BATCH 스케줄링 정책을 사용할 때 설정할 좋은 값을 지정합니다. nice 값은 -20 (High priority)에서 +19 (Low priority) 사이의 범위 범위입니다.
sched_priority
10.0.0.1 _FIFO 또는 10.0.0.1 _RR 을 예약할 때 설정할 정적 우선 순위를 지정합니다. 다른 정책의 경우 priority를 0 으로 지정합니다.

deadline _DEADLINE 필드는 데드라인 예약에만 지정해야 합니다.

  • sched_runtime: 데드라인 스케줄링에 대한 런타임 매개변수를 지정합니다. 값은 나노초 단위로 표시됩니다.
  • gRPC_DEADLINE: 데드라인 스케줄링에 대한 데드라인 매개변수를 지정합니다. 값은 나노초 단위로 표시됩니다.
  • sched_period: 데드라인 스케줄링의 period 매개변수를 지정합니다. 값은 나노초 단위로 표시됩니다.

32장. 선점 상태 보기

CPU를 사용하는 프로세스는 사용 중인 CPU를 자발적으로 또는 자발적으로 포기할 수 있습니다.

32.1. 선점

프로세스는 완료되면 또는 디스크의 데이터, 키 누름 또는 네트워크 패킷과 같은 이벤트를 대기 중이므로 CPU를 자발적으로 산출할 수 있습니다.

또한 프로세스는 자발적으로 CPU를 산출할 수 있습니다. 이를 선점이라고 하며 더 높은 우선 순위 프로세스에서 CPU를 사용하려는 경우 발생합니다.

선점은 시스템 성능에 특히 부정적인 영향을 미칠 수 있으며 지속적인 선점으로 인해 스래싱으로 알려진 상태가 발생할 수 있습니다. 이 문제는 프로세스가 지속적으로 선점되고 완료까지 프로세스가 실행되지 않을 때 발생합니다.

작업의 우선 순위를 변경하면 일시적인 선점을 줄이는 데 도움이 될 수 있습니다.

32.2. 프로세스의 선점 상태 확인

지정된 프로세스에 대해 자발적으로 및 자발적으로 제공하는 선점 상태를 확인할 수 있습니다. 상태는 /proc/PID/status 에 저장됩니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

절차

  • /proc/PID/status 의 내용을 표시합니다. 여기서 PID 는 프로세스의 ID입니다. 다음은 PID 1000이 있는 프로세스의 선점 상태를 표시합니다.

    # grep voluntary /proc/1000/status
    voluntary_ctxt_switches: 194529
    nonvoluntary_ctxt_switches: 195338

33장. chrt 유틸리티를 사용하여 프로세스의 우선 순위 설정

chrt 유틸리티를 사용하여 프로세스의 우선 순위를 설정할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

33.1. chrt 유틸리티를 사용하여 프로세스 우선 순위 설정

chrt 유틸리티는 스케줄러 정책 및 우선순위를 확인하고 조정합니다. 원하는 속성을 사용하여 새 프로세스를 시작하거나 실행 중인 프로세스의 속성을 변경할 수 있습니다.

절차

  • 프로세스의 스케줄링 정책을 설정하려면 적절한 명령 옵션 및 매개변수를 사용하여 chrt 명령을 실행합니다. 다음 예에서 명령에 영향을 받는 프로세스 ID는 1000 개이며 우선순위(-p)는 50 입니다.

    # chrt -f -p 50 1000

    지정된 스케줄링 정책 및 우선 순위로 애플리케이션을 시작하려면 애플리케이션 이름과 필요한 경우 속성과 함께 애플리케이션을 추가합니다.

    # chrt -r -p 50 /bin/my-app

    chrt 유틸리티 옵션에 대한 자세한 내용은 chrt 유틸리티 옵션을 참조하십시오.

33.2. chrt 유틸리티 옵션

chrt 유틸리티 옵션에는 명령의 프로세스 및 우선 순위를 지정하는 명령 옵션 및 매개변수가 포함되어 있습니다.

정책 옵션

-f
스케줄러 정책을 10.0.0.1 _FIFO 로 설정합니다.
-o
스케줄러 정책을 ScanSetting _OTHER 로 설정합니다.
-r
스케줄러 정책을 10.0.0.1 _RR (round robin)으로 설정합니다.
-d
스케줄러 정책을 ScanSetting _DEADLINE 으로 설정합니다.
-p n

프로세스의 우선 순위를 n 으로 설정합니다.

프로세스를 10.0.0.1_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 16666 은 나노초 단위의 기간입니다.
  • 0chrt 명령에 필요한 사용되지 않는 우선 순위의 자리 표시자입니다.

33.3. 추가 리소스

  • chrt(1) 매뉴얼 페이지

34장. 라이브러리 호출을 사용하여 프로세스의 우선 순위 설정

chrt 유틸리티를 사용하여 프로세스의 우선 순위를 설정할 수 있습니다.

사전 요구 사항

  • 관리자 권한이 있어야 합니다.

34.1. 우선순위 설정 라이브러리 호출

실시간 프로세스는 정책 및 우선 순위를 제어하기 위해 다른 라이브러리 호출 세트를 사용합니다. 다음 라이브러리 호출은 비실시간 프로세스의 우선 순위를 설정하는 데 사용됩니다.

  • nice
  • setpriority

이 함수는 비실시간 프로세스의 좋은 값을 조정합니다. nice 값은 프로세서에서 실행할 준비가 된 비실시간 프로세스 목록을 정렬하는 방법에 대한 스케줄러 제안의 역할을 합니다. 목록의 헤드에 있는 프로세스는 목록의 추가 감소 전에 실행됩니다.

중요

함수를 사용하려면 sched.h 헤더 파일을 포함해야 합니다. 함수의 반환 코드를 항상 확인하십시오.

34.2. 라이브러리 호출을 사용하여 프로세스 우선 순위 설정

스케줄러 정책 및 기타 매개변수는 sched_setscheduler() 함수를 사용하여 설정할 수 있습니다. 현재 실시간 정책에는 하나의 매개변수 sched_priority 가 있습니다. 이 매개변수는 프로세스의 우선 순위를 조정하는 데 사용됩니다.

sched_setscheduler() 함수에는 sched_setscheduler (sched_setscheduler,pid_t pid, int 정책, const struct sched_param *sp) 형식의 매개변수가 필요합니다.

참고

sched_setscheduler(2) 매뉴얼 페이지에는 오류 코드를 포함하여 sched_setscheduler() 의 가능한 모든 반환 값이 나열됩니다.

프로세스 ID가 0이면 sched_setscheduler() 함수가 호출 프로세스에 대해 작동합니다.

다음 코드 발췌에서는 현재 프로세스의 스케줄러 정책을 10.0.0.1 _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;
}

34.3. 라이브러리 호출을 사용하여 프로세스 우선순위 매개변수 설정

sched_setparam() 함수는 특정 프로세스의 스케줄링 매개변수를 설정하는 데 사용됩니다. 그런 다음 sched_getparam() 함수를 사용하여 확인할 수 있습니다.

스케줄링 정책만 반환하는 sched_getscheduler() 함수와 달리 sched_getparam() 함수는 지정된 프로세스에 대한 모든 스케줄링 매개변수를 반환합니다.

절차

지정된 실시간 프로세스의 우선 순위를 읽고 다음 코드 발췌를 두 단계로 증가시킵니다.Use the following code excerpt that reads the priority of a given real-time process and increments it by two:

struct sched_param sp;
int ret;

ret = sched_getparam(0, &sp);
sp.sched_priority += 2;
ret = sched_setparam(0, &sp);

이 코드가 실제 애플리케이션에서 사용된 경우 함수에서 반환 값을 확인하고 오류를 적절하게 처리해야 합니다.

중요

우선순위 증가에 유의하십시오. 이 예에서와 같이 스케줄러 우선 순위에 2를 지속적으로 추가하면 잘못된 우선순위가 발생할 수 있습니다.

34.4. 프로세스의 스케줄링 정책 및 관련 속성 설정

sched_setattr() 함수는 PID에 지정된 인스턴스 ID에 대한 스케줄링 정책 및 관련 속성을 설정합니다. pid=0인 경우 sched_setattr() 은 호출 스레드의 프로세스 및 속성에서 작동합니다.

절차

  • 호출이 작동하는 프로세스 ID와 다음 실시간 스케줄링 정책 중 하나를 지정하여 sched_setattr() 을 호출합니다.

실시간 스케줄링 정책

SCHED_FIFO
first-in 및 first-out 정책을 예약합니다.
SCHED_RR
라운드 로빈 정책을 예약합니다.
SCHED_DEADLINE
데드라인 스케줄링 정책을 예약합니다.

Linux는 다음과 같은 비실시간 스케줄링 정책도 지원합니다.

비실시간 스케줄링 정책

SCHED_OTHER
표준 라운드 로빈 시간 할당 정책을 예약합니다.
SCHED_BATCH
프로세스의 "배치" 스타일 실행을 예약합니다.
SCHED_IDLE

우선 순위가 매우 낮은 백그라운드 작업을 예약합니다. gRPC_IDLE 은 정적 우선 순위 0 에서만 사용할 수 있으며 nice 값은 이 정책에 영향을 미치지 않습니다.

이 정책은 매우 낮은 우선 순위로 작업을 실행하기 위한 것입니다. (+19 nice 값보다 낮음 +19 또는 gRPC _ BATCH 정책을 사용하여 값).

34.5. 추가 리소스

35장. 실시간 커널 및 솔루션 예약

실시간 커널에서의 예약은 경우에 따라 발생할 수 있습니다. 제공된 정보를 사용하면 실시간 커널에서 스케줄링 정책, 스케줄러 제한 및 스레드 중단 상태에 대한 문제와 잠재적인 솔루션을 파악할 수 있습니다.

35.1. 실시간 커널의 스케줄링 정책

실시간 스케줄링 정책은 하나의 주요 특성을 공유합니다. 높은 우선 순위 스레드가 스레드 또는 스레드가 I/O를 잠급거나 수행하여 대기할 때까지 실행됩니다.

Cryostat _RR 의 경우 운영 체제는 실행 중인 스레드를 중단하여 동일한 Cryostat _RR 우선순위의 다른 스레드를 실행할 수 있도록 합니다. 이러한 경우 중 하나에서 더 낮은 우선 순위 스레드가 CPU 시간을 얻을 수 있도록 정책을 정의하는 POSIX 사양에 의해 프로비저닝이 이루어지지 않습니다. 실시간 스레드의 이러한 특성은 지정된 CPU의 100%를 단조하는 애플리케이션을 쉽게 작성할 수 있음을 의미합니다. 그러나 이로 인해 운영 체제에 문제가 발생합니다. 예를 들어 운영 체제는 시스템 전체 및 CPU별 리소스를 모두 관리하는 역할을 하며 주기적으로 이러한 리소스를 설명하는 데이터 구조를 검사하고 해당 리소스를 사용하는 하우스키핑 활동을 수행해야 합니다. 그러나 코어가 Cryostat _FIFO 스레드에 의해 단조되는 경우 하우스키핑 작업을 수행할 수 없습니다. 결국 전체 시스템이 불안정해지고 잠재적으로 충돌할 수 있습니다.

RHEL for Real Time 커널에서 인터럽트 핸들러는 hieradata _FIFO 우선 순위가 있는 스레드로 실행됩니다. 기본 우선순위는 50입니다. 인터럽트 처리기 스레드보다 높은 Cryostat _FIFO 또는 Cryostat _RR 정책이 있는 cpu-hog 스레드는 인터럽트 처리기가 실행되지 않도록 할 수 있습니다. 이로 인해 프로그램이 인터럽트에 의해 전달되는 데이터 신호를 대기하고 실패하게 됩니다.

35.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 시간을 사용하도록 실시간 작업이 구성됩니다. 이는 실시간 작업이 잘 엔지니어링되어 바인딩되지 않은 폴링 루프와 같은 명확한 경고 사항이 없는 경우에만 적합합니다.

35.3. 실시간 커널에서 스레드 중단

스레드가 고가용성 임계값보다 긴 CPU 실행 큐에 있고 진행하지 않는 경우 발생합니다. 스레드 중단의 일반적인 원인은 CPU에 바인딩된 Cryostat _FIFO 또는 Cryostat _ RR 과 같은 고정 우선 순위의 폴링 애플리케이션을 실행하는 것입니다. 폴링 애플리케이션은 I/O를 차단하지 않으므로 kworkers 와 같은 다른 스레드가 해당 CPU에서 실행되지 않도록 할 수 있습니다.

스레드 래핑을 줄이기 위한 초기 시도는 실시간 제한으로 호출됩니다. 실시간 제한에서 각 CPU는 비 실시간 작업에 전용 실행 시간의 일부를 갖습니다. 제한의 기본 설정은 실시간 작업에 대해 CPU의 95%를 사용하고 5%는 비실시간 작업을 위해 예약되어 있습니다. 단일 실시간 작업이 있는 경우 결함이 발생하지만 CPU에 할당된 실시간 작업이 여러 개 있는 경우 작동하지 않습니다. 다음을 사용하여 문제를 해결할 수 있습니다.

stalld 메커니즘

stalld 메커니즘은 실시간 제한의 대안이며 일부 제한 결함을 피할 수 있습니다. stalld 는 시스템의 각 스레드 상태를 주기적으로 모니터링하는 데몬이며 실행 큐에 있는 스레드를 실행하지 않고 지정된 시간 동안 실행되는 스레드를 찾습니다. stalld 는 thread가 Cryostat _DEADLINE 정책을 사용하도록 일시적으로 변경되고 지정된 CPU에서 스레드에 작은 시간을 할당합니다. 그런 다음 스레드가 실행되고 time 슬라이스를 사용하면 스레드가 원래 스케줄링 정책으로 돌아가 스레드 상태를 계속 모니터링합니다.

하우스키핑 CPU는 모든 데몬, 쉘 프로세스, 커널 스레드, 인터럽트 처리기 및 분리된 CPU에서 디스패치할 수 있는 모든 작업을 실행하는 CPU입니다. 실시간 제한이 비활성화된 하우스키핑 CPU의 경우 stalld 는 기본 워크로드를 실행하는 CPU를 모니터링하고 Cryostat _FIFO 사용량 루프로 CPU를 할당하므로 이전에 정의된 허용 가능한 추가 노이즈에서 필요에 따라 stalled 스레드를 감지하고 스레드 우선 순위를 개선하는 데 도움이 됩니다. 실시간 제한 메커니즘으로 인해 기본 워크로드에서 복구할 수 없는 노이즈가 발생하는 경우 stalld 가 선호될 수 있습니다.

stalld 를 사용하면 starved 스레드를 강화하여 도입되는 노이즈를 보다 정확하게 제어할 수 있습니다. 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 © 2024 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은 기업이 핵심 데이터 센터에서 네트워크 에지에 이르기까지 플랫폼과 환경 전반에서 더 쉽게 작업할 수 있도록 강화된 솔루션을 제공합니다.

© 2024 Red Hat, Inc.