Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

개발자 가이드

Red Hat Enterprise Linux 7

RHEL 7의 애플리케이션 개발 툴 소개

초록

이 문서에서는 Red Hat Enterprise Linux 7을 애플리케이션 개발을 위한 이상적인 엔터프라이즈 플랫폼으로 만드는 다양한 기능 및 유틸리티에 대해 설명합니다.

접두부

이 문서에서는 Red Hat Enterprise Linux 7을 애플리케이션 개발을 위한 이상적인 엔터프라이즈 플랫폼으로 만드는 다양한 기능 및 유틸리티에 대해 설명합니다.

Red Hat Enterprise Linux 7은 RHEL 7.9 릴리스 후 업데이트될 예정입니다. RHEL 7 제품의 현재 상태에 대한 정보는 Red Hat Enterprise Linux 7에 대한 Red Hat Software Collections의 제품 라이프 사이클 을 확인하십시오.

I 부. 개발 워크스테이션 설정

Red Hat Enterprise Linux 7은 사용자 지정 애플리케이션 개발을 지원합니다. 개발자가 이를 수행할 수 있도록 하려면 필요한 툴과 유틸리티를 사용하여 시스템을 설정해야 합니다. 이 장에서는 개발 및 설치할 항목의 가장 일반적인 사용 사례를 나열합니다.

1장. 운영 체제 설치

특정 개발 요구 사항에 맞게 설정하기 전에 기본 시스템을 설정해야 합니다.

  1. 워크스테이션 변형에 Red Hat Enterprise Linux를 설치합니다. Red Hat Enterprise Linux 설치 가이드 의 지침을 따르십시오.
  2. 설치하는 동안, 소프트웨어 선택에 주의를 기울이십시오. Development 및 Creative Workstation 시스템 프로파일을 선택하고 개발 요구에 적합한 애드온을 설치할 수 있습니다. 관련 추가 기능은 다양한 개발 유형에 중점을 둔 다음 각 섹션에 나열되어 있습니다.
  3. 드라이버와 같은 Linux 커널과 긴밀하게 협력하는 애플리케이션을 개발하려면 설치 중에 kdump 를 자동으로 덤프할 수 있습니다.
  4. 시스템 자체를 설치한 후 이를 등록하고 필요한 서브스크립션을 첨부합니다. Red Hat Enterprise Linux 시스템 관리자 가이드의 지침에 따라 7장, 시스템 등록 및 서브스크립션 관리 .

    다음 섹션에서는 각 개발 유형에 대해 연결해야 하는 특정 서브스크립션을 나열합니다.

  5. 개발 도구 및 유틸리티의 최신 버전은 Red Hat Software Collections로 제공됩니다. Red Hat Software Collections에 대한 자세한 내용은 Red Hat Software Collections 릴리스 노트, 2장, 설치 장을 참조하십시오.

추가 리소스

2장. 애플리케이션 버전 관리 설정

효과적인 버전 제어는 모든 다중 개발자 프로젝트에 필수적입니다. Red Hat Enterprise Linux는 분산 버전 제어 시스템인 Git 와 함께 배포됩니다.

  1. 시스템을 설치하는 동안 Development Tools Add-on을 선택하여 Git 을 설치합니다.
  2. 또는 시스템을 설치한 후 Red Hat Enterprise Linux 리포지토리에서 git 패키지를 설치합니다.

    # yum install git
  3. Red Hat에서 지원하는 Git 의 최신 버전을 얻으려면 Red Hat Software Collections에서 rh-git227 구성 요소를 설치하십시오.

    # yum install rh-git227
  4. Git 커밋과 관련된 전체 이름 및 이메일 주소를 설정합니다.

    $ git config --global user.name "full name"
    $ git config --global user.email "email_address"

    전체 이름email_address 를 실제 이름 및 이메일 주소로 바꿉니다.

  5. Git 에서 시작한 기본 텍스트 편집기를 변경하려면 core.editor 구성 옵션의 값을 설정합니다.

    $ git config --global core.editor command

    선택한 텍스트 편집기 시작하는 데 사용할 명령으로 명령을 바꿉니다.

추가 리소스

3장. C 및 C++를 사용하여 애플리케이션 개발 설정

Red Hat Enterprise Linux는 완전히 컴파일된 C 및 C++ 프로그래밍 언어를 사용하여 개발을 가장 잘 지원합니다.

  1. 시스템 설치 중에 Development Tools and Debugging Tools Add-ons를 선택하여 GNU 컴파일러 컬렉션(GCC)GNU Debugger(GDB) 및 기타 개발 툴을 설치합니다.
  2. GCC, GDB 및 관련 툴의 최신 버전은 Red Hat Developer Toolset 툴체인 구성 요소의 일부로 사용할 수 있습니다.

    # yum install devtoolset-9-toolchain

    알림: Red Hat Developer Toolset은 소프트웨어 컬렉션으로 제공됩니다. scl 유틸리티를 사용하면 Red Hat Enterprise Linux 시스템에 해당하는 기본 설정에 사용되는 Red Hat Developer Toolset 바이너리를 사용하여 명령을 실행할 수 있습니다.

  3. Red Hat Enterprise Linux 리포지토리에는 C 및 C++ 애플리케이션 개발에 널리 사용되는 많은 라이브러리가 포함되어 있습니다. yum 패키지 관리자를 사용하여 애플리케이션에 필요한 라이브러리의 개발 패키지를 설치합니다.
  4. 그래픽 기반 개발의 경우 Eclipse 통합 개발 환경을 설치합니다. C 및 C++ 언어도 직접 지원됩니다. Eclipse 는 Red Hat Developer Tools의 일부로 제공됩니다. 실제 설치 절차는 Eclipse 사용을 참조하십시오.

추가 리소스

4장. 디버그 애플리케이션 설정

Red Hat Enterprise Linux는 여러 디버깅 및 계측 툴을 제공하여 내부 애플리케이션 동작을 분석하고 문제를 해결합니다.

  1. 시스템 설치 중에 디버깅 도구 및 성능 도구 애드온을 선택하여 GNU Debugger(GDB), Valgrind , SystemTap, ltrace, strace 및 기타 툴을 설치합니다.
  2. GDB, Valgrind, SystemTap, straceltrace 의 최신 버전은 Red Hat Developer Toolset 을 설치합니다. 이것은 또한 memstomp 를 설치합니다.

    # yum install devtoolset-9

    알림: Red Hat Developer Toolset은 소프트웨어 컬렉션으로 제공됩니다. scl 유틸리티를 사용하면 Red Hat Enterprise Linux 시스템에 해당하는 기본 설정에 사용되는 Red Hat Developer Toolset 바이너리를 사용하여 명령을 실행할 수 있습니다.

  3. memstomp 유틸리티는 Red Hat Developer Toolset의 일부로만 사용할 수 있습니다. 전체 Developer Toolset을 설치하는 것이 바람직하지 않고 memstomp 가 필요한 경우 Red Hat Developer Toolset에서 해당 구성 요소만 설치합니다.

    # yum install devtoolset-9-memstomp
  4. debuginfo-install 툴을 사용하려면 yum-utils 패키지를 설치합니다.

    # yum install yum-utils
  5. Red Hat Enterprise Linux의 일부로 사용 가능한 애플리케이션 및 라이브러리를 디버깅하려면 debuginfo-install 툴을 사용하여 Red Hat Enterprise Linux 리포지토리에서 해당 debuginfo 및 source 패키지를 설치합니다. 이는 코어 덤프 파일 분석에도 적용됩니다.
  6. SystemTap 애플리케이션에 필요한 커널 debuginfo 및 소스 패키지를 설치합니다. SystemTap Beginners 가이드, 2.1.1., SystemTap 설치를 참조하십시오.
  7. 커널 덤프를 캡처하려면 kdump 를 설치하고 구성하십시오. Kernel Crash Dump Guide, 7.2., Installing and Configuring kdump 에 있는 지침을 따르십시오.
  8. SELinux 정책을 통해 관련 애플리케이션을 정상적으로 실행할 수 있을 뿐만 아니라 디버깅 상황에서도 실행할 수 있습니다. SELinux 사용자 및 관리자 가이드, 섹션 11.3. 를 참조하십시오.

추가 리소스

5장. 애플리케이션의 성능 측정 설정

Red Hat Enterprise Linux에는 개발자가 애플리케이션 성능 손실의 원인을 파악하는 데 도움이 되는 여러 애플리케이션이 포함되어 있습니다.

  1. 시스템 설치 중에 디버깅도구, 개발 툴 , 성능 도구 추가 기능을 선택하여 OProfile, perfpcp 를 설치합니다.
  2. 성능 측정 모듈을 포함하는 일부 유형의 성능 분석을 허용하는 SystemTapValgrind 를 설치합니다.

    # yum install valgrind systemtap systemtap-runtime

    알림: Red Hat Developer Toolset은 소프트웨어 컬렉션으로 제공됩니다. scl 유틸리티를 사용하면 Red Hat Enterprise Linux 시스템에 해당하는 기본 설정에 사용되는 Red Hat Developer Toolset 바이너리를 사용하여 명령을 실행할 수 있습니다.

  3. SystemTap 환경을 설정하려면 SystemTap 도우미 스크립트를 실행합니다.

    # stap-prep
    참고

    이 스크립트를 실행하면 매우 큰 kernel debuginfo 패키지가 설치됩니다.

  4. SystemTap, OProfile, Valgrind 의 더 자주 업데이트된 버전은 Red Hat Developer Toolset 패키지 perftools 를 설치합니다.

    # yum install devtoolset-9-perftools

추가 리소스

6장. Java를 사용하여 애플리케이션 개발 설정

Red Hat Enterprise Linux는 Java에서 애플리케이션 개발을 지원합니다.

  1. 시스템 설치 중에 Java Platform 애드온을 선택하여 OpenJDK를 기본 Java 버전으로 설치합니다.

    또는 Red Hat CodeReady Studio 설치 가이드의 지침에 따라 2.2장, RHEL에 OpenJDK 1.8.0 을 설치하여 OpenJDK를 별도로 설치합니다.

  2. 통합 그래픽 개발 환경의 경우 Eclipse 기반 Red Hat CodeReady Studio 를 설치하여 Java 개발을 위한 광범위한 지원을 제공합니다. Red Hat CodeReady Studio 에 대한 설치 가이드 의 지침을 따르십시오.

7장. Python을 사용하여 애플리케이션 개발 설정

Python 언어 버전 2.7.5는 Red Hat Enterprise Linux의 일부로 제공됩니다.

  • 최신 버전의 Python 인터프리터 및 라이브러리(최신 버전의 Python 2.7 포함)는 Red Hat Software Collections 패키지로 사용할 수 있습니다. 아래 표에 따라 원하는 버전으로 패키지를 설치합니다.

    # yum install package

    Red Hat Software Collections 패키지에 해당하는 Python 버전

    버전패키지

    Python 2.7

    python27

    Python 3.6

    rh-python36

    Python 3.8

    rh-python38

    python27 소프트웨어 컬렉션은 RHEL 7에서 업데이트된 Python 2 패키지 버전입니다.

  1. Python 언어로 개발을 지원하는 Eclipse 통합 개발 환경을 설치합니다. Eclipse 는 Red Hat Developer Tools의 일부로 제공됩니다. 실제 설치 절차는 Eclipse 사용을 참조하십시오.

추가 리소스

8장. C# 및 .NET Core를 사용하여 애플리케이션 개발 설정

Red Hat은 .NET Core를 대상으로 하는 애플리케이션 개발을 지원합니다.

  • 런타임, 컴파일러 및 추가 툴이 포함된 Red Hat Enterprise Linux용 .NET Core 를 설치합니다. .NET Core용 시작하기 가이드의 지침을 따릅니다.Follow the instructions in the Getting Started Guide for .NET Core.

추가 리소스

9장. 컨테이너화된 애플리케이션 개발 설정

Red Hat은 Red Hat Enterprise Linux, Red Hat OpenShift 및 기타 여러 Red Hat 제품을 기반으로 하는 컨테이너화된 애플리케이션 개발을 지원합니다.

  • Red Hat Container Development Kit (CDK)는 단일 노드 Red Hat OpenShift 3 클러스터를 실행하는 Red Hat Enterprise Linux 가상 머신을 제공합니다. OpenShift 4는 지원하지 않습니다. Red Hat Container Development Kit 시작하기 가이드의 지침에 따라 1.4., CDK 설치.
  • Red Hat CodeReady Containers (CRC)는 로컬 컴퓨터에 최소한의 OpenShift 4 클러스터를 제공하여 개발 및 테스트 목적으로 최소한의 환경을 제공합니다. CodeReady Containers는 주로 개발자의 데스크탑을 실행하는 것을 목표로 합니다.
  • Red Hat Development Suite 는 Java, C 및 C++에서 컨테이너화된 애플리케이션을 개발하기 위한 Red Hat 툴을 제공합니다. Red Hat JBoss Developer Studio, OpenJDK, Red Hat Container Development Kit 및 기타 마이너 구성 요소로 구성됩니다. DevSuite 를 설치하려면 Red Hat Development Suite 설치 가이드 의 지침을 따르십시오.
  • .NET Core 3.1 은 OpenShift Container Platform 버전 3.3 이상에서 실행되는 고급 애플리케이션을 구축하기 위한 범용 개발 플랫폼입니다. 설치 및 사용 방법은 .NET Core 시작하기 가이드 2.(Red Hat OpenShift Container Platform에서 .NET Core 3.1 사용 )를 참조하십시오.

추가 리소스

10장. 웹 애플리케이션 개발 설정

Red Hat Enterprise Linux는 배포하기 위한 플랫폼이 되어 웹 애플리케이션 개발을 지원합니다.

웹 개발 주제가 너무 커서 몇 가지 간단한 지침으로 캡처할 수 있습니다. 이 섹션에서는 Red Hat Enterprise Linux에서 웹 애플리케이션 개발에 가장 적합한 경로만 제공합니다.

  • 기존 웹 애플리케이션을 개발하기 위한 환경을 설정하려면 Apache 웹 서버, PHP 런타임 및 MariaDB 데이터베이스 서버 및 툴을 설치하십시오.

    # yum install httpd mariadb-server php-mysql php

    또는 이러한 애플리케이션의 최신 버전을 Red Hat Software Collections의 구성 요소로 사용할 수 있습니다.

    # yum install httpd24 rh-mariadb102 rh-php73

추가 리소스

II 부. 다른 개발자와 애플리케이션 협업

이 문서 부분에서는 버전 제어 시스템인 Git을 간략하게 소개합니다.

11장. Git 사용

효과적인 버전 제어는 모든 다중 개발자 프로젝트에 중요합니다. 이를 통해 팀의 모든 개발자가 체계적이고 순서대로 코드를 생성, 검토, 수정 및 문서화할 수 있습니다. Red Hat Enterprise Linux 7은 오픈 소스 버전 관리 시스템인 Git 와 함께 배포됩니다.

Git 및 해당 기능에 대한 자세한 설명은 이 문서의 범위를 벗어납니다. 이 버전 제어 시스템에 대한 자세한 내용은 아래 나열된 리소스를 참조하십시오.

설치된 문서

  • Git 및 튜토리얼을 위한 Linux 도움말 페이지:

    $ man git
    $ man gittutorial
    $ man gittutorial-2

    많은 Git 명령에는 자체 도움말 페이지가 있습니다.

  • Git 사용자 설명서 - Git 에 대한 HTML 문서는 /usr/share/doc/git-1.8.3/user-manual.html.에 있습니다.

온라인 문서

  • Pro Git 책의 온라인 버전은 Git, 개념 및 사용법 - Pro Git Book에 대한 자세한 설명을 제공합니다.
  • Git - Git용 Linux 설명서 페이지의 온라인 버전 - Git 참조

III 부. 사용자가 애플리케이션을 사용할 수 있도록 설정

사용자가 애플리케이션을 사용할 수 있도록 하는 방법에는 여러 가지가 있습니다. 이 가이드에서는 가장 일반적인 방법을 설명합니다.

  • 애플리케이션을 RPM 패키지로 패키징
  • 애플리케이션을 소프트웨어 컬렉션으로 패키징
  • 애플리케이션을 컨테이너로 패키징

12장. 배포 옵션

Red Hat Enterprise Linux는 타사 애플리케이션을 위한 세 가지 배포 방법을 제공합니다.

RPM 패키지

RPM 패키지는 소프트웨어를 배포하고 설치하는 일반적인 방법입니다.

  • RPM 패키지는 여러 도구가 있는 완성도 높은 기술이며 널리 배포되는 지식입니다.
  • 애플리케이션은 시스템의 일부로 설치됩니다.
  • 설치 도구는 종속성을 해결하는 데 큰 도움이 됩니다.
참고

하나의 패키지 버전만 설치하여 여러 애플리케이션 버전을 설치하기가 어렵습니다.

RPM 패키지를 만들려면 RPM 패키징 가이드의 지침에 따라 소프트웨어 패키징 을 참조하십시오.

Software Collections

소프트웨어 컬렉션은 다른 버전의 애플리케이션을 위한 특수 준비된 RPM 패키지입니다.

  • 소프트웨어 컬렉션은 Red Hat에서 사용하고 지원하는 패키징 방법입니다.
  • RPM 패키지 메커니즘을 기반으로 구축됩니다.
  • 여러 버전의 애플리케이션을 한 번에 설치할 수 있습니다.

자세한 내용은 Red Hat Software Collections Packaging Guide, What Are Software Collections를 참조하십시오.

소프트웨어 컬렉션 패키지를 만들려면 Red Hat Software Collections 패키징 가이드, 소프트웨어 컬렉션 패키징 가이드의 지침에 따릅니다. https://access.redhat.com/documentation/en-us/red_hat_software_collections/3/html/packaging_guide/chap-packaging_software_collections

컨테이너

Docker 형식의 컨테이너는 경량의 가상화 방법입니다.

  • 애플리케이션은 여러 독립 버전 및 인스턴스에 존재할 수 있습니다.
  • RPM 패키지 또는 소프트웨어 컬렉션을 통해 쉽게 준비할 수 있습니다.
  • 시스템과의 상호 작용을 정확하게 제어 할 수 있습니다.
  • 애플리케이션 격리를 통해 보안이 향상됩니다.
  • 애플리케이션 또는 해당 구성 요소를 컨테이너화하면 여러 인스턴스를 오케스트레이션할 수 있습니다.

추가 리소스

13장. 애플리케이션을 사용하여 컨테이너 생성

이 섹션에서는 로컬에서 빌드된 애플리케이션에서 docker 형식 컨테이너 이미지를 생성하는 방법을 설명합니다. 배포에 오케스트레이션을 사용하려는 경우 컨테이너로 애플리케이션을 사용할 수 있도록 하는 것이 좋습니다. 또는 종속 항목의 충돌을 효과적으로 컨테이너화합니다.

사전 요구 사항

  • 컨테이너 이해
  • 소스에서 로컬로 빌드된 애플리케이션

절차

  1. 사용할 기본 이미지를 결정합니다.

    참고

    Red Hat Enterprise Linux를 기반으로 사용하는 기본 이미지로 시작하는 것이 좋습니다. 자세한 내용은 Red Hat Container Catalog의 기본 이미지를 참조하십시오.

  2. 작업 공간 디렉터리를 생성합니다.
  3. 애플리케이션의 모든 필수 파일이 포함된 디렉터리로 애플리케이션을 준비합니다. 이 디렉터리를 작업 공간 디렉터리에 배치합니다.
  4. 컨테이너를 생성하는 데 필요한 단계를 설명하는 Dockerfile을 작성합니다.

    콘텐츠가 포함된 Dockerfile을 생성하는 방법에 대한 자세한 내용은 Dockerfile 참조를 참조하고, 실행할 기본 명령을 설정하며, 필요한 포트 및 기타 기능을 엽니다.

    이 예에서는 my-program/ 디렉터리가 포함된 최소 Dockerfile을 보여줍니다.

    FROM registry.access.redhat.com/rhel7
    USER root
    ADD my-program/ .

    이 Dockerfile을 작업 공간 디렉터리에 배치합니다.

  5. Dockerfile에서 컨테이너 이미지를 빌드합니다.

    # docker build .
    (...)
    Successfully built container-id

    이 단계에서 새로 생성된 컨테이너 이미지의 container-id 를 기록해 둡니다.

  6. 이미지에 태그를 추가하여 컨테이너 이미지를 저장할 레지스트리를 식별합니다. 컨테이너 시작하기 - 이미지 태그 지정을 참조하십시오.

    # docker tag container-id registry:port/name

    container-id 를 이전 단계의 출력에 표시된 값으로 교체합니다.

    이미지를 푸시할 레지스트리의 주소, 포트 를 레지스트리의 포트(필요하지 않은 경우)로 바꾸고 이미지 이름으로 이름을 바꿉니다.

    예를 들어, myimage 라는 이미지가 있는 로컬 시스템에서 docker-distribution 서비스를 사용하여 레지스트리를 실행하는 경우 localhost:5000/myimage 태그를 사용하면 해당 이미지를 레지스트리로 내보낼 수 있습니다.

  7. 나중에 해당 레지스트리에서 이미지를 가져올 수 있도록 이미지를 레지스트리로 푸시합니다.

    # docker push registry:port/name

    태그 부분을 이전 단계에서 사용한 것과 동일한 값으로 바꿉니다.

    자체 Docker 레지스트리를 실행하려면 컨테이너 시작하기 - Docker 레지스트리 작업을 참조하십시오.

추가 리소스

14장. 패키지에서 애플리케이션 컨테이너화

여러 가지 이유로 RPM 패키지에 패키지된 애플리케이션을 컨테이너로 배포하는 것이 유용할 수 있습니다.

사전 요구 사항

  • 컨테이너 이해
  • 하나 이상의 RPM 패키지로 패키지된 애플리케이션

절차

RPM 패키지에서 애플리케이션을 컨테이너화하려면 컨테이너 시작하기 - Docker 이미지 생성 을 참조하십시오.

추가 정보

IV 부. C 또는 C++ 애플리케이션 생성

Red Hat은 C 및 C++ 언어를 사용하여 애플리케이션을 만들기 위한 다양한 툴을 제공합니다. 이 문서에는 가장 일반적인 개발 작업 일부가 나열되어 있습니다.

15장. GCC를 사용하여 코드 빌드

이 장에서는 소스 코드를 실행 코드로 변환해야 하는 상황을 설명합니다.

15.1. 코드 양식 간의 관계

사전 요구 사항

  • 컴파일 및 연결의 개념 이해

가능한 코드 양식

C 및 C++ 언어를 사용하는 경우 다음 세 가지 형식의 코드가 있습니다.

  • C 또는 C++ 언어로 작성된 소스 코드는 일반 텍스트 파일로 표시됩니다.

    일반적으로 파일은 .c,. cc,. cpp,. h,. hpp,. i,. inc 등의 확장 프로그램을 사용합니다. 지원되는 확장 기능 및 해석의 전체 목록은 gcc 도움말 페이지를 참조하십시오.

    $ man gcc
  • 컴파일러 로 소스 코드를 컴파일 하여 생성된 개체 코드입니다. 이는 중간 형식입니다.

    오브젝트 코드 파일은 .o 확장자를 사용합니다.

  • 개체 코드를 링커연결하여 만든 실행 코드.

    Linux 애플리케이션 실행 파일은 파일 이름 확장자를 사용하지 않습니다. 공유 오브젝트(library) 실행 파일은 .so 파일 이름 확장자를 사용합니다.

참고

정적 연결을 위한 라이브러리 아카이브 파일도 존재합니다. 이는 .a 파일 이름 확장자를 사용하는 오브젝트 코드의 변형입니다. 정적 연결은 권장되지 않습니다. 16.2절. “정적 및 동적 연결”을 참조하십시오.

GCC에서 코드 양식 처리

소스 코드에서 실행 가능한 코드를 생성하려면 서로 다른 애플리케이션 또는 도구가 필요한 두 단계가 필요합니다. GCC는 컴파일러와 링커 모두에 대한 지능형 드라이버로 사용할 수 있습니다. 이를 통해 필요한 작업에 단일 명령 gcc 를 사용할 수 있습니다. GCC는 필요한 조치(compiling and linking) 및 해당 시퀀스를 자동으로 선택합니다.

  1. 소스 파일은 오브젝트 파일로 컴파일됩니다.
  2. 오브젝트 파일과 라이브러리가 연결되어 있습니다(이전 컴파일된 소스 포함).

1단계만 발생하거나, 2단계만 발생하거나, 1단계와 2단계 모두 발생하도록 GCC를 실행할 수 있습니다. 이는 입력 유형 및 요청된 출력 유형에 따라 결정됩니다.

대규모 프로젝트에는 일반적으로 GCC를 각 작업에 대해 별도로 실행하는 빌드 시스템이 필요하므로 GCC를 한 번에 모두 수행할 수 있더라도 컴파일 및 두 가지 작업으로 연결하는 것이 좋습니다.

추가 리소스

15.2. 오브젝트 코드에 소스 파일 컴파일

소스 파일에서 개체 코드 파일을 즉시 생성하고 실행 파일이 아닌 경우 GCC는 출력으로 개체 코드 파일만 생성하도록 지시해야 합니다. 이 작업은 대규모 프로젝트에 대한 빌드 프로세스의 기본 작업을 나타냅니다.

사전 요구 사항

절차

  1. 소스 코드 파일이 포함된 디렉터리로 변경합니다.
  2. c 옵션을 사용하여 gcc 를 실행합니다.

    $ gcc -c source.c another_source.c

    개체 파일은 원본 소스 코드 파일을 반영하는 파일 이름을 사용하여 생성됩니다 . source.csource.o 가 됩니다.

    참고

    C++ 소스 코드로 gcc 명령을 g++로 교체하여 C++ 표준 라이브러리 종속성을 편리하게 처리하십시오.

추가 리소스

15.3. GCC를 사용하여 C 및 C++ 애플리케이션 디버깅 활성화

디버깅 정보는 크기 때문에 기본적으로 실행 파일에 포함되지 않습니다. C 및 C++ 애플리케이션을 사용하여 디버깅할 수 있도록 하려면 컴파일러에 디버깅 정보를 작성하도록 명시적으로 지정해야 합니다.To enable debugging of your C and C++ applications with it, you must explicitly instruct the compiler to create debugging information.

GCC를 사용하여 디버깅 정보 생성 활성화

코드를 컴파일 및 연결할 때 GCC 로 디버깅 정보를 생성할 수 있도록 하려면 -g 옵션을 사용합니다.

$ gcc ... -g ...
  • 컴파일러 및 링커에서 수행하는 최적화로 인해 원래 소스 코드와 관련되기 어려운 실행 코드가 발생할 수 있습니다. 변수는 롤백되지 않고 주변 항목에 병합된 작업을 최적화할 수 있습니다. 이는 디버깅에 부정적인 영향을 미칩니다. 디버깅 환경을 개선하려면 -Og 옵션으로 최적화를 설정하는 것이 좋습니다. 그러나 최적화 수준을 변경하면 실행 코드가 변경되고 일부 버그를 제거하기 위해 실제 동작이 변경될 수 있습니다.
  • f compare-debug GCC 옵션은 디버그 정보와 디버그 정보 없이 GCC에서 컴파일한 코드를 테스트합니다. 결과 두 바이너리 파일이 동일한 경우 테스트가 통과합니다. 이 테스트를 사용하면 디버깅 옵션의 영향을 받지 않으므로 디버그 코드에 숨겨진 버그가 없습니다. f compare-debug 옵션을 사용하면 컴파일 시간이 크게 증가합니다. 이 옵션에 대한 자세한 내용은 GCC 도움말 페이지를 참조하십시오.

추가 리소스

15.4. GCC를 통한 코드 최적화

단일 프로그램은 2개 이상의 머신 명령어로 변환될 수 있습니다. 컴파일 중 코드 분석을 위해 더 많은 리소스가 할당된 경우 최적의 결과를 얻을 수 있습니다.

GCC를 통한 코드 최적화

GCC를 사용하면 -O 수준 옵션을 사용하여 최적화 수준을 설정할 수있습니다. 이 옵션은 수준 대신 값 집합을 허용합니다.

level설명

0

컴파일 속도 최적화(기본값) 없음

1, 2, 3

코드 실행 속도를 위한 최적화 작업 증가

결과 파일 크기에 최적화

fast

추가 최적화를 허용하기 위해 레벨 3 및 엄격한 표준 준수에 대해 무시됨

g

디버깅 환경에 최적화

릴리스 빌드의 경우 최적화 옵션 -O2 가 권장됩니다.

개발 중에 -Og 옵션은 일부 상황에서 프로그램 또는 라이브러리를 디버깅하는 데 더 유용합니다. 일부 버그는 특정 최적화 수준에서만 표시되므로 릴리스 최적화 수준을 사용하여 프로그램 또는 라이브러리를 테스트하십시오.

GCC는 개별 최적화를 가능하게 하는 다양한 옵션을 제공합니다. 자세한 내용은 다음 추가 리소스를 참조하십시오.

추가 리소스

  • GNU 컴파일러 컬렉션 사용 - 3.11 옵션 관리
  • GCC의 Linux 도움말 페이지:

    $ man gcc

15.5. GCC를 사용하여 코드 강화

컴파일러가 소스 코드를 개체 코드로 변환할 때 일반적으로 악용되는 상황을 방지하기 위해 다양한 검사를 추가하여 보안을 강화할 수 있습니다. 올바른 컴파일러 옵션 세트를 선택하면 소스 코드를 변경하지 않고도 보다 안전한 프로그램 및 라이브러리를 생성하는 데 도움이 될 수 있습니다.

릴리스 버전 옵션

다음은 Red Hat Enterprise Linux를 대상으로 하는 개발자에게 최소 권장 옵션 목록입니다.

$ gcc ... -O2 -g -Wall -Wl,-z,now,-z,relro -fstack-protector-strong -D_FORTIFY_SOURCE=2 ...
  • 프로그램의 경우 -fPIE-pie Position Independent Executable 옵션을 추가합니다.
  • 동적으로 연결된 라이브러리의 경우 필수 -fPIC (Position Independent Code) 옵션은 간접적으로 보안을 강화합니다.

개발 옵션

다음 옵션을 사용하여 개발 중 보안 결함을 탐지하는 것이 좋습니다. 릴리스 버전 옵션과 함께 다음 옵션을 사용합니다.

$ gcc ... -Walloc-zero -Walloca-larger-than -Wextra -Wformat-security -Wvla-larger-than ...

추가 리소스

15.6. 실행 가능한 파일 만들기에 코드 연결

C 또는 C++ 애플리케이션을 빌드할 때의 마지막 단계는 연결입니다. 연결은 모든 개체 파일과 라이브러리를 실행 파일로 결합합니다.

사전 요구 사항

절차

  1. 오브젝트 코드 파일이 포함된 디렉터리로 변경합니다.
  2. gcc 실행 :

    $ gcc ... objectfile.o another_object.o ... -o executable-file

    executable-file이라는 실행 가능한 파일은 제공된 오브젝트 파일 및 라이브러리에서 생성됩니다.

    추가 라이브러리를 연결하려면 오브젝트 파일 목록 앞에 필요한 옵션을 추가합니다. 16장. GCC와 함께 라이브러리 사용을 참조하십시오.

    참고

    C++ 소스 코드로 gcc 명령을 g++로 교체하여 C++ 표준 라이브러리 종속성을 편리하게 처리하십시오.

추가 리소스

15.7. C++ 다양한 Red Hat 제품의 호환성

Red Hat 에코시스템에는 Red Hat Enterprise Linux 및 Red Hat Developer Toolset에서 제공되는 GCC 컴파일러 및 링커의 여러 버전이 포함되어 있습니다. 이러한 C++ ABI 호환성은 다음과 같습니다.

  • GCC 4.8을 기반으로 하며 Red Hat Enterprise Linux 7의 일부로 직접 제공되는 시스템 컴파일러 는 C ++98 표준 (C++03이라고도 함) 및 GNU 확장과 변형 만 컴파일하고 연결할 수 있습니다.
  • C++98 호환 바이너리 또는 라이브러리 -std=c++98 또는 -std=gnu++98 옵션을 사용하여 명시적으로 빌드된 모든 라이브러리를 사용하는 컴파일러 버전에 관계없이 자유롭게 혼합할 수 있습니다.
  • C++11 및 C++14 언어 버전을 혼합하는 것은 Red Hat Developer Toolset에서 컴파일러를 사용하는 경우에만 지원되며 해당 플래그로 컴파일된 모든 C++ 개체가 GCC의 동일한 주요 버전을 사용하여 빌드된 경우에만 지원됩니다.
  • Red Hat Developer Toolset 및 Red Hat Enterprise Linux 툴체인으로 빌드된 C++ 파일을 연결하는 경우 컴파일러 및 링커의 Red Hat Developer Toolset 버전을 선호합니다.
  • Red Hat Enterprise Linux 6 및 7 및 Red Hat Developer Toolset의 컴파일러에 대한 기본 설정은 4.1까지 -std=gnu++98 입니다. 즉, GNU 확장이 포함된 C++98입니다.
  • Red Hat Developer Toolset 6, 6.1, 7, 7.1, 8.0, 8.1, 9.0, 9.1, 10의 컴파일러에 대한 기본 설정은 -std=gnu++14 입니다. 즉, GNU 확장 기능이 있는 C++14입니다.

추가 리소스

15.8. 예제: GCC를 사용하여 C 프로그램 구축

이 예에서는 샘플 최소 C 프로그램을 빌드하는 정확한 단계를 보여줍니다.

사전 요구 사항

  • GCC 사용 이해

단계

  1. hello-c 디렉터리를 생성하고 해당 위치로 변경합니다.

    $ mkdir hello-c
    $ cd hello-c
  2. 다음 콘텐츠를 사용하여 hello.c 파일을 생성합니다.

    #include <stdio.h>
    
    int main() {
      printf("Hello, World!\n");
      return 0;
    }
  3. GCC를 사용하여 코드를 컴파일하십시오.

    $ gcc -c hello.c

    오브젝트 파일 hello.o 가 생성됩니다.

  4. 오브젝트 파일에서 실행 가능한 파일 helloworld 를 연결합니다.

    $ gcc hello.o -o helloworld
  5. 결과 실행 파일을 실행합니다.

    $ ./helloworld
    Hello, World!

추가 리소스

15.9. 예제: GCC를 사용하여 C++ 프로그램 구축

이 예에서는 샘플 최소 C++ 프로그램을 빌드하는 정확한 단계를 보여줍니다.

사전 요구 사항

  • GCC 사용 이해
  • gccg++의 차이점 이해

절차

  1. hello-cpp 디렉토리를 생성하고 해당 위치로 변경합니다.

    $ mkdir hello-cpp
    $ cd hello-cpp
  2. 다음 콘텐츠를 사용하여 hello.cpp 파일을 생성합니다.

    #include <iostream>
    
    int main() {
      std::cout << "Hello, World!\n";
      return 0;
    }
  3. g++ 로 코드를 컴파일하십시오.

    $ g++ -c hello.cpp

    오브젝트 파일 hello.o 가 생성됩니다.

  4. 오브젝트 파일에서 실행 가능한 파일 helloworld 를 연결합니다.

    $ g++ hello.o -o helloworld
  5. 결과 실행 파일을 실행합니다.

    $ ./helloworld
    Hello, World!

16장. GCC와 함께 라이브러리 사용

이 장에서는 코드에서 라이브러리를 사용하는 방법을 설명합니다.

16.1. 라이브러리 이름 지정

특수 파일 이름 규칙은 라이브러리에 사용됩니다. foo라는 라이브러리는 lib foo. so 또는 libfoo .a .a 로 존재할 것으로 예상됩니다. 이 규칙은 gcc 의 입력 옵션을 연결함으로써 자동으로 이해되지만 출력 옵션은 지원하지 않습니다.

  • 라이브러리에 대해 연결할 때 라이브러리는 -l 옵션을 -l foo : 로 사용하여 foo 이름으로만 지정할 수 있습니다.

    $ gcc ... -lfoo ...
  • 라이브러리를 생성할 때 전체 파일 이름 libfoo.so 또는 libfoo.a 를 지정해야 합니다.

추가 리소스

16.2. 정적 및 동적 연결

개발자는 완전히 컴파일된 언어로 애플리케이션을 빌드할 때 정적 또는 동적 연결을 사용할 수 있습니다. 이 섹션에는 특히 Red Hat Enterprise Linux에서 C 및 C++ 언어 사용의 차이점이 설명되어 있습니다. 요약하자면, Red Hat은 Red Hat Enterprise Linux의 애플리케이션에서 정적 링크 사용을 권장하지 않습니다.

정적 및 동적 연결 비교

정적 연결은 라이브러리가 결과 실행 파일의 일부로 만듭니다. 동적 연결은 이러한 라이브러리를 별도의 파일로 유지합니다.

동적 및 정적 연결은 다음과 같은 여러 방법으로 비교할 수 있습니다.

리소스 사용

정적 연결로 더 많은 코드가 포함된 실행 파일이 더 커집니다. 라이브러리에서 제공하는 이 추가 코드는 시스템의 여러 프로그램에서 공유할 수 없으므로 런타임에 파일 시스템 사용과 메모리 사용량이 증가합니다. 정적으로 연결된 동일한 프로그램을 실행하는 여러 프로세스가 여전히 코드를 공유합니다.

반면, 정적 애플리케이션에는 더 적은 가동 시간 재배치가 필요하므로 시작 시간이 줄어들고RSS(개인 상주 설정 크기) 메모리가 줄어듭니다. 정적 연결을 위한 생성된 코드는 PoC(위치 종속 코드)에서 도입한 오버헤드로 인해 동적 연결보다 효율적일 수 있습니다.

보안

ABI 호환성을 제공하는 동적으로 연결된 라이브러리는 이러한 라이브러리에 따라 실행 파일을 변경하지 않고 업데이트할 수 있습니다. 이는 Red Hat이 보안 업데이트를 제공하는 Red Hat Enterprise Linux의 일부로 Red Hat에서 제공하는 라이브러리에 특히 중요합니다. 이러한 라이브러리에 대한 정적 연결은 권장되지 않습니다.

또한 로드 주소 임의화와 같은 보안 조치를 정적으로 연결된 실행 파일과 함께 사용할 수 없습니다. 이렇게 하면 결과 애플리케이션의 보안이 더욱 감소합니다.

호환성

정적 연결은 운영 체제에서 제공하는 라이브러리 버전과 관계없이 실행 파일을 제공하는 것으로 나타납니다. 그러나 대부분의 라이브러리는 다른 라이브러리에 의존합니다. 정적 연결을 사용하면 이 종속성이 유연해지므로 정방향 및 이전 버전과의 호환성이 모두 손실됩니다. 정적 연결은 실행 파일이 빌드된 시스템에서만 작동하도록 보장됩니다.

주의

GNU C 라이브러리(glibc)에서 정적 라이브러리를 연결하는 애플리케이션에는 여전히 시스템에 glibc 가 동적 라이브러리로 있어야 합니다. 또한 애플리케이션의 런타임에 사용 가능한 glibc 의 동적 라이브러리 변형은 애플리케이션을 연결하는 동안 존재하는 것과 약간 동일한 버전이어야 합니다. 따라서 정적 연결은 실행 파일이 빌드된 시스템에서만 작동할 수 있습니다.

지원 범위
Red Hat에서 제공하는 대부분의 정적 라이브러리는 선택적 채널에 있으며 Red Hat에서 지원하지 않습니다.
기능

일부 라이브러리, 특히 GNU C 라이브러리(glibc)는 정적으로 연결될 때 축소된 기능을 제공합니다.

예를 들어, 정적으로 연결된 경우 glibc 는 스레드를 지원하지 않으며 동일한 프로그램에서 dlopen() 함수에 대한 호출 형식을 지원합니다.

나열된 단점으로 인해 특히 전체 애플리케이션 및 glibclibstdc++ 라이브러리의 경우 정적 연결을 피할 수 있습니다.

참고

compat-glibc 패키지는 Red Hat Enterprise Linux 7에 포함되어 있지만 런타임 패키지는 아니므로 아무것도 실행하지 않아도 됩니다. 연결을 위한 헤더 파일 및 더미 라이브러리가 포함된 개발 패키지일 뿐입니다. 따라서 이전 Red Hat Enterprise Linux 버전에서 컴파일 및 연결(해당 헤더 및 라이브러리에 대해 compat-gcc-\* 사용)을 실행할 수 있습니다. 이 패키지 사용에 대한 자세한 내용은 rpm -qpi compat-glibc-*.

정적 연결 이유

다음과 같은 일부 경우 정적 연결이 합리적인 선택이 될 수 있습니다.

  • 동적 연결에 사용할 수 없는 라이브러리
  • chroot 환경 또는 컨테이너에서 코드를 실행하려면 완전히 정적 연결이 필요할 수 있습니다. 그러나 Red Hat에서는 glibc-static 패키지를 사용한 정적 연결은 지원되지 않습니다.

추가 리소스

16.3. GCC에서 라이브러리 사용

라이브러리는 프로그램에서 재사용할 수 있는 코드 패키지입니다. C 또는 C++ 라이브러리는 다음 두 부분으로 구성됩니다.

  • 라이브러리 코드
  • 헤더 파일

라이브러리를 사용하는 코드 컴파일

헤더 파일은 라이브러리의 인터페이스를 설명합니다. 라이브러리에서 사용할 수 있는 함수 및 변수입니다. 헤더 파일의 정보는 코드를 컴파일하는 데 필요합니다.

일반적으로 라이브러리의 헤더 파일은 애플리케이션 코드와 다른 디렉터리에 저장됩니다. GCC에 헤더 파일이 있는 위치를 지정하려면 -I 옵션을 사용합니다.

$ gcc ... -Iinclude_path ...

include_path 를 헤더 파일 디렉터리의 실제 경로로 바꿉니다.

I 옵션을 여러 번 사용하여 헤더 파일로 여러 디렉터리를 추가할 수 있습니다. 헤더 파일을 찾을 때 이러한 디렉터리는 -I 옵션에 표시되는 순서대로 검색됩니다.

라이브러리를 사용하는 코드 연결

실행 파일을 연결할 때 애플리케이션의 오브젝트 코드와 라이브러리의 바이너리 코드를 모두 사용할 수 있어야 합니다. 정적 및 동적 라이브러리의 코드는 다양한 형태로 제공됩니다.

  • 정적 라이브러리는 아카이브 파일로 사용할 수 있습니다. 개체 파일의 그룹이 포함되어 있습니다. 아카이브 파일의 확장자는 .a.a입니다.
  • 동적 라이브러리는 공유 개체로 사용할 수 있습니다. 이 파일은 실행 파일의 형식입니다. 공유 오브젝트의 파일 이름 확장자는 .so.

GCC에 라이브러리의 아카이브 또는 공유 오브젝트 파일을 지정하려면 -L 옵션을 사용합니다.

$ gcc ... -Llibrary_path -lfoo ...

library_path 를 라이브러리 디렉터리의 실제 경로로 바꿉니다.

L 옵션을 여러 번 사용하여 여러 디렉터리를 추가할 수 있습니다. 라이브러리를 찾을 때 이러한 디렉터리는 -L 옵션 순서로 검색됩니다.

옵션의 순서가 중요합니다. GCC는 이 라이브러리의 디렉토리를 알고 있지 않으면 foo 라이브러리와 연결할 수 없습니다. 따라서 라이브러리를 연결하는 데 - l 옵션을 사용하기 전에 - L 옵션을 사용하여 라이브러리 디렉터리를 지정합니다.

컴파일 및 연결 코드는 하나의 단계에서 라이브러리를 사용합니다.

코드를 컴파일하고 하나의 gcc 명령에 연결할 수 있는 경우 한 번에 위에서 언급한 두 가지 상황에 대해 옵션을 사용합니다.

추가 리소스

16.4. GCC에서 정적 라이브러리 사용

정적 라이브러리는 오브젝트 파일을 포함하는 아카이브로 사용할 수 있습니다. 연결한 후 결과 실행 파일의 일부가 됩니다.

참고

Red Hat은 다양한 이유로 정적 연결 사용을 권장하지 않습니다. 16.2절. “정적 및 동적 연결”을 참조하십시오. 특히 Red Hat에서 제공하는 라이브러리에 대해 필요할 때만 정적 링크를 사용합니다.

사전 요구 사항

참고

Red Hat Enterprise Linux의 일부인 대부분의 라이브러리는 동적 연결에만 지원됩니다. 아래 단계는 동적 연결에 사용할 수 없는 라이브러리에서만 작동합니다. 16.6절. “GCC에서 정적 및 동적 library 사용”을 참조하십시오.

절차

소스 및 개체 파일의 프로그램을 연결하려면 정적으로 링크된 라이브러리 foo 를 추가합니다. libfoo.a:

  1. 코드가 포함된 디렉터리로 변경합니다.
  2. foo 라이브러리의 헤더를 사용하여 프로그램 소스 파일을 컴파일합니다.

    $ gcc ... -Iheader_path -c ...

    header_pathfoo 라이브러리의 헤더 파일이 포함된 디렉터리의 경로로 바꿉니다.

  3. foo 라이브러리와 프로그램을 연결합니다.

    $ gcc ... -Llibrary_path -lfoo ...

    library_pathlibfoo.a 파일이 포함된 디렉터리의 경로로 바꿉니다.

  4. 프로그램을 실행하려면 다음을 실행합니다.

    $ ./program
경고

정적 링크와 관련된 -static GCC 옵션은 모든 동적 연결을 금지합니다. 대신 -Wl,-Bstatic-Wl,-Bdynamic 옵션을 사용하여 링커 동작을 보다 정확하게 제어합니다. 16.6절. “GCC에서 정적 및 동적 library 사용”을 참조하십시오.

16.5. GCC에서 동적 라이브러리 사용

동적 라이브러리는 연결 시간과 런타임 모두에 필요한 독립 실행형 실행 파일로 사용할 수 있습니다. 애플리케이션의 실행 파일과는 별개로 유지됩니다.

사전 요구 사항

  • GCC가 시스템에 설치되어 있습니다.
  • 유효한 프로그램을 구성하는 소스 또는 개체 파일 세트로, 일부 동적 라이브러리 foo 및 다른 라이브러리가 없습니다.
  • libfoo.so파일로 사용 가능한 foo 라이브러리

프로그램 Against a Dynamic Library

동적 라이브러리 foo 에 대해 프로그램을 연결하려면 다음을 수행합니다.

$ gcc ... -Llibrary_path -lfoo ...

프로그램이 동적 라이브러리와 연결되어 있는 경우 결과 프로그램은 항상 런타임에 라이브러리를 로드해야 합니다. 라이브러리를 찾는 데는 두 가지 옵션이 있습니다.

  • 실행 파일 자체에 저장된 rpath 값 사용
  • 런타임 시 LD_LIBRARY_PATH 변수 사용

실행 가능한 파일에 rpath Value Stored 사용

rpath 는 연결될 때 실행 파일의 일부로 저장되는 특수 값입니다. 나중에 프로그램이 실행 파일에서 로드되면 런타임 링커는 rpath 값을 사용하여 라이브러리 파일을 찾습니다.

GCC 와 연결하는 동안 path library_pathrpath 로 저장합니다.

$ gcc ... -Llibrary_path -lfoo -Wl,-rpath=library_path ...

경로 library_pathlibfoo.so 파일이 포함된 디렉터리를 가리켜야 합니다.

경고

-Wl,-rpath= 옵션 뒤에는 공백이 없습니다.

나중에 프로그램을 실행하려면 다음을 실행합니다.

$ ./program

LD_LIBRARY_PATH 환경 변수 사용

프로그램의 실행 파일에 rpath 를 찾을 수 없는 경우 런타임 링커는 LD_LIBRARY_PATH 환경 변수를 사용합니다. 이 변수의 값은 공유 라이브러리 오브젝트가 있는 경로에 따라 각 프로그램에 대해 변경해야 합니다.

library_path 에 있는 라이브러리를 사용하여 rpath 가 설정되지 않은 프로그램을 실행하려면 다음을 실행합니다.

$ export LD_LIBRARY_PATH=library_path:$LD_LIBRARY_PATH
$ ./program

rpath 값을 제외하면 유연성이 제공되지만, 프로그램을 실행할 때마다 LD_LIBRARY_PATH 변수를 설정해야 합니다.

라이브러리를 기본 디렉터리에 배치

런타임 링커 구성은 여러 디렉터리를 동적 라이브러리 파일의 기본 위치로 지정합니다. 이러한 기본 동작을 사용하려면 라이브러리를 적절한 디렉터리에 복사합니다.

동적 링커 동작에 대한 자세한 설명은 이 문서의 범위를 벗어납니다. 자세한 내용은 다음 리소스를 참조하십시오.

  • 동적 링커의 Linux 도움말 페이지:

    $ man ld.so
  • /etc/ld.so.conf 설정 파일의 내용:

    $ cat /etc/ld.so.conf
  • 디렉터리가 포함된 추가 구성없이 동적 링커에서 인식하는 라이브러리의 보고:

    $ ldconfig -v

16.6. GCC에서 정적 및 동적 library 사용

경우에 따라 일부 라이브러리를 정적 및 일부 동적으로 연결해야 할 수도 있습니다.

사전 요구 사항

소개

GCC 는 동적 라이브러리와 정적 라이브러리를 모두 인식합니다. l foo 옵션이 나오면 gcc 는 먼저 foo 라이브러리의 동적으로 연결된 버전이 포함된 공유 오브젝트(a .so 파일)를 찾은 다음, 정적 버전의 라이브러리를 포함하는 아카이브 파일(.a)을 찾습니다. 따라서 다음과 같은 상황이 발생할 수 있습니다.

  • 공유 오브젝트만 찾을 수 있으며 이에 대한 gcc 링크
  • 해당 아카이브만 발견되고 이에 대한 gcc 링크만 정적으로 표시됩니다.
  • 공유 오브젝트와 아카이브가 모두 있습니다. gcc 는 공유 오브젝트에 대한 기본 동적 링크를 선택합니다.
  • 공유 오브젝트 또는 아카이브를 찾을 수 없으며 연결이 실패합니다.

이러한 규칙으로 인해 연결할 라이브러리의 정적 또는 동적 버전을 선택하는 가장 좋은 방법은 gcc 에서 해당 버전만 찾는 것입니다. -L경로 옵션을 지정할 때 라이브러리 버전이 포함된 디렉토리를 사용하거나 그대로 두어 어느 정도까지 제어할 수 있습니다.

또한 동적 연결이 기본값이기 때문에 연결을 명시적으로 지정해야 하는 유일한 상황은 두 버전이 있는 라이브러리를 정적으로 연결해야 합니다. 두 가지 가능한 솔루션이 있습니다.

  • l 옵션 대신 파일 경로로 정적 라이브러리 지정
  • 옵션을 링크에 전달하려면 -Wl 옵션을 사용합니다.

파일을 기준으로 정적 라이브러리 지정

일반적으로 gcc-l foo옵션을 사용하여 foo 라이브러리에 연결하도록 지시됩니다. 그러나 라이브러리가 포함된 libfoo.a 파일에 대한 전체 경로를 지정할 수 있습니다.

$ gcc ... path/to/libfoo.a ...

파일 확장자 에서 gcc 는 이것이 프로그램과 연결할 라이브러리임을 이해할 것입니다. 그러나 라이브러리 파일의 전체 경로를 지정하는 것은 덜 유연한 방법입니다.

W l 옵션 사용

gcc 옵션 -Wl 은 옵션을 기본 링커에 전달하는 특수 옵션입니다. 이 옵션의 구문은 다른 gcc 옵션과 다릅니다. -Wl 옵션 뒤에 쉼표로 구분된 링커 옵션 목록이 오는 반면, 다른 gcc 옵션에는 공백으로 구분된 옵션 목록이 필요합니다. gcc 에서 사용하는 ld 링커는 이 옵션 뒤에 있는 라이브러리를 각각 정적으로 또는 동적으로 연결해야 하는지를 지정하기 위해 -Bstatic-Bdynamic 옵션을 제공합니다. B static과 라이브러리를 링커에 전달한 후에는 다음 라이브러리가 -B dynamic 옵션과 동적으로 연결되도록 기본 동적 연결 동작을 수동으로 복원해야 합니다.

프로그램을 연결하려면 먼저 라이브러리를 정적으로 연결(libfirst.a) 및 두 번째 동적으로 연결(lib second.so), 다음을 실행합니다.

$ gcc ... -Wl,-Bstatic -lfirst -Wl,-Bdynamic -lsecond ...
참고

gcc 는 기본 ld 이외의 링커를 사용하도록 구성할 수 있습니다. -Wl 옵션은 골드 링커에도 적용됩니다.

추가 리소스

17장. GCC를 사용하여 라이브러리 만들기

이 장에서는 라이브러리를 만드는 단계를 설명하고 Linux 운영 체제에서 라이브러리를 위해 사용하는 필수 개념을 설명합니다.

17.1. 라이브러리 이름 지정

특수 파일 이름 규칙은 라이브러리에 사용됩니다. foo라는 라이브러리는 lib foo. so 또는 libfoo .a .a 로 존재할 것으로 예상됩니다. 이 규칙은 gcc 의 입력 옵션을 연결함으로써 자동으로 이해되지만 출력 옵션은 지원하지 않습니다.

  • 라이브러리에 대해 연결할 때 라이브러리는 -l 옵션을 -l foo : 로 사용하여 foo 이름으로만 지정할 수 있습니다.

    $ gcc ... -lfoo ...
  • 라이브러리를 생성할 때 전체 파일 이름 libfoo.so 또는 libfoo.a 를 지정해야 합니다.

추가 리소스

17.2. < Mechanism>

동적으로 로드된 라이브러리(공유 오브젝트)는 soname 이라는 메커니즘을 사용하여 여러 호환 가능한 라이브러리 버전을 관리합니다.

사전 요구 사항

문제 소개

동적으로 로드된 라이브러리(공유 오브젝트)는 독립 실행 파일로 존재합니다. 이렇게 하면 라이브러리에 종속된 애플리케이션을 업데이트하지 않고 라이브러리를 업데이트할 수 있습니다. 그러나 이 개념에는 다음과 같은 문제가 발생합니다.

  • 실제 라이브러리 버전을 지정합니다.Specifies the actual version of the library.
  • 동일한 라이브러리의 여러 버전이 있어야 합니다.
  • 각 버전의 ABI 호환성 신호

< Mechanism>

이 문제를 해결하기 위해 Linux는 soname이라는 메커니즘을 사용합니다.

라이브러리 foo 버전 X.Y 는 버전 번호에서 X 와 동일한 다른 버전과 호환되는 ABI입니다. 호환성을 유지하는 마이너 변경으로 숫자 Y 가 증가합니다. 호환성을 중단시키는 주요 변경 사항은 숫자 X 를 증가시킵니다.

실제 라이브러리 foo 버전 X.Ylibfoo.so.x .y 파일로존재합니다. 라이브러리 파일 내에서 libfoo.so.x 값을 사용하여 soname이 기록되어 호환성을 신호합니다.

애플리케이션이 빌드되면 링커에서 libfoo.so 파일을 검색하여 라이브러리를 찾습니다. 이 이름의 심볼릭 링크가 있어야 실제 라이브러리 파일을 가리키는 심볼릭 링크가 있어야 합니다. 그런 다음 링커는 라이브러리 파일에서 soname을 읽고 이를 애플리케이션 실행 파일에 기록합니다. 마지막으로 링커는 이름 또는 파일 이름이 아니라 soname을 사용하여 라이브러리에 대한 종속성을 선언하도록 애플리케이션을 생성합니다.

런타임 동적 링커가 실행하기 전에 애플리케이션을 연결하는 경우 애플리케이션의 실행 파일에서 soname을 읽습니다. 이 soname은 libfoo.so.x 입니다. 이 이름의 심볼릭 링크가 있어야 실제 라이브러리 파일을 가리키는 심볼릭 링크가 있어야 합니다. 이렇게 하면 soname이 변경되지 않기 때문에 버전의 Y 구성 요소에 관계없이 라이브러리를 로드할 수 있습니다.

참고

버전 번호의 Y 구성 요소는 단일 번호로만 제한되지 않습니다. 또한 일부 라이브러리는 버전으로 버전을 인코딩합니다.

파일에서 soname 읽기

라이브러리 파일의 soname을 표시하려면 somelibrary:

$ objdump -p somelibrary | grep SONAME

somelibrary 를 검사할 라이브러리의 실제 파일 이름으로 바꿉니다.

17.3. GCC를 사용하여 동적 library 생성

동적으로 연결된 라이브러리(공유 오브젝트)를 사용하면 코드 재사용 및 라이브러리 코드 업데이트를 통해 리소스 보존을 수행할 수 있습니다. 이 섹션에서는 소스에서 동적 라이브러리를 빌드하고 설치하는 단계를 설명합니다.

사전 요구 사항

절차

  1. 라이브러리 소스를 사용하여 디렉터리로 변경합니다.
  2. 위치 독립적인 코드 옵션을 사용하여 각 소스 파일을 오브젝트 파일로 컴파일 -fPIC:

    $ gcc ... -c -fPIC some_file.c ...

    오브젝트 파일의 이름은 원본 소스 코드 파일과 동일하지만 해당 확장자는 .o 입니다.

  3. 오브젝트 파일에서 공유 라이브러리를 연결합니다.

    $ gcc -shared -o libfoo.so.x.y -Wl,-soname,libfoo.so.x some_file.o ...

    사용되는 주요 버전 번호는 X이고 마이너 버전 번호는 Y입니다.

  4. libfoo.so.x.y 파일을 시스템의 동적 링커가 찾을 수 있는 적절한 위치에 복사합니다. Red Hat Enterprise Linux에서 라이브러리 디렉터리는 /usr/lib64 입니다.

    # cp libfoo.so.x.y /usr/lib64

    이 디렉터리의 파일을 조작하려면 루트 권한이 필요합니다.

  5. soname 메커니즘에 대한 심볼릭 링크 구조를 생성합니다.

    # ln -s libfoo.so.x.y libfoo.so.x
    # ln -s libfoo.so.x libfoo.so

추가 리소스

17.4. GCC 및 ar를 사용하여 정적 library 생성

정적 링크를 위한 라이브러리를 생성할 수 있는 경우 오브젝트 파일을 특수 유형의 아카이브 파일로 변환할 수 있습니다.

참고

Red Hat은 보안상의 이유로 정적 링크 사용을 권장하지 않습니다. 특히 Red Hat에서 제공하는 라이브러리에 대해 필요할 때만 정적 링크를 사용합니다. 16.2절. “정적 및 동적 연결”을 참조하십시오.

사전 요구 사항

절차

  1. GCC를 사용하여 중간 개체 파일을 만듭니다.

    $ gcc -c source_file.c ...

    필요한 경우 소스 파일을 더 추가합니다. 결과 오브젝트 파일은 파일 이름을 공유하지만 .o 파일 이름 확장자를 사용합니다.

  2. binutils 패키지의 ar 툴을 사용하여 오브젝트 파일을 정적 라이브러리(아카이브)로 전환합니다.

    $ ar rcs libfoo.a source_file.o ...

    libfoo.a 파일이 생성됩니다.

  3. nm 명령을 사용하여 결과 아카이브를 검사합니다.

    $ nm libfoo.a
  4. 정적 라이브러리 파일을 적절한 디렉터리에 복사합니다.
  5. 라이브러리를 연결할 때 GCC는 라이브러리가 정적 연결을 위한 아카이브인 .a 파일 이름 확장자에서 자동으로 인식됩니다.

    $ gcc ... -lfoo ...

추가 리소스

  • ar 툴을 위한 Linux 도움말 페이지:

    $ man ar

18장. Make를 사용하여 더 많은 코드 관리

GNU Make 유틸리티(일반적으로 Make 로 축약됨)는 소스 파일에서 실행 파일 생성을 제어하는 툴입니다. 복잡한 프로그램의 어느 부분이 변경되었는지 자동으로 결정하며 다시 컴파일해야 합니다. make 는 Makefile이라는 구성 파일을 사용하여 프로그램 빌드 방식을 제어합니다.

18.1. GNU makeMakefile 개요

특정 프로젝트의 소스 파일에서 사용 가능한 양식(일반적으로 실행 파일)을 만들려면 몇 가지 필수 단계를 수행합니다. 작업 및 해당 시퀀스를 기록하여 나중에 반복할 수 있습니다.

Red Hat Enterprise Linux에는 이러한 목적을 위해 설계된 빌드 시스템인 GNU make 가 포함되어 있습니다.

사전 요구 사항

  • 컴파일 및 연결의 개념 이해

GNU make

GNU make 는 빌드 프로세스를 설명하는 지침이 포함된 Makefiles를 읽습니다. Makefile에는 특정 조건(대상)을 충족하는 방법을 설명하는 특정 작업(메시피)을 설명하는 여러 규칙이 포함되어있습니다. 규칙은 다른 규칙에 따라 계층적으로 달라질 수 있습니다.

옵션 없이 make 를 실행하면 현재 디렉터리에서 Makefile을 찾아 기본 대상에 도달하려고 시도합니다. 실제 Makefile 파일 이름은 Makefile,makefileGNUmakefile 중 하나일 수 있습니다. 기본 대상은 Makefile 콘텐츠에서 결정됩니다.

Makefile 세부 정보

makefiles는 타겟레시피로 구성된 변수규칙을 정의하는 비교적 간단한 구문을 사용합니다. target은 규칙이 실행되는 경우 출력을 지정합니다. 레시피가 있는 줄은 탭 문자로 시작해야 합니다.

일반적으로 Makefile에는 소스 파일을 컴파일하는 규칙, 결과 개체 파일을 연결하는 규칙 및 계층 구조의 맨 위 진입점 역할을 하는 대상이 포함됩니다.

단일 파일 hello.c 로 구성된 C 프로그램을 빌드하려면 다음 Makefile 을 고려해 보십시오.

all: hello

hello: hello.o
        gcc hello.o -o hello

hello.o: hello.c
        gcc -c hello.c -o hello.o

이는 타겟 all 에 도달하도록 지정합니다. hello 파일은 필수입니다. hello를 얻으려면 hello .o (gcc로 링크됨 )가 필요하며 hello.c (gcc에 의해 컴파일됨 )에서 생성됩니다.

모두 기본 대상입니다. 이는 마침표로 시작하지 않는 첫 번째 대상이기 때문입니다. 그러면 현재 디렉터리에 이 Makefile 이 포함된 경우 인수 없이 make 를 모두 실행하는 것과 동일합니다.

일반적인 Makefile

보다 일반적인 Makefile은 단계 일반화에 변수를 사용하고 소스 파일을 제외한 모든 항목을 제거하는 대상 "clean"을 추가합니다.

CC=gcc
CFLAGS=-c -Wall
SOURCE=hello.c
OBJ=$(SOURCE:.c=.o)
EXE=hello

all: $(SOURCE) $(EXE)

$(EXE): $(OBJ)
        $(CC) $(OBJ) -o $@

%.o: %.c
        $(CC) $(CFLAGS) $< -o $@

clean:
        rm -rf $(OBJ) $(EXE)

이러한 Makefile에 소스 파일을 더 추가하려면 SOURCE 변수가 정의된 줄에 해당 파일을 추가해야 합니다.

추가 리소스

18.2. 예제: Makefile을 사용하여 C 프로그램 빌드

아래 예제의 단계에 따라 Makefile을 사용하여 샘플 C 프로그램을 빌드합니다.

사전 요구 사항

절차

  1. hellomake 디렉터리를 생성하고 이 디렉터리로 변경합니다.

    $ mkdir hellomake
    $ cd hellomake
  2. 다음 콘텐츠를 사용하여 hello.c 파일을 생성합니다.

    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
      printf("Hello, World!\n");
      return 0;
    }
  3. 다음 콘텐츠를 사용하여 Makefile 파일을 생성합니다.

    CC=gcc
    CFLAGS=-c -Wall
    SOURCE=hello.c
    OBJ=$(SOURCE:.c=.o)
    EXE=hello
    
    all: $(SOURCE) $(EXE)
    
    $(EXE): $(OBJ)
            $(CC) $(OBJ) -o $@
    
    %.o: %.c
            $(CC) $(CFLAGS) $< -o $@
    
    clean:
            rm -rf $(OBJ) $(EXE)
    경고

    Makefile 레시피 행은 탭 문자로 시작해야 합니다. 브라우저에서 위의 텍스트를 복사할 때 대신 공백을 붙여넣을 수 있습니다. 이 변경 사항을 수동으로 수정합니다.

  4. make: 실행

    $ make
    gcc -c -Wall hello.c -o hello.o
    gcc hello.o -o hello

    그러면 실행 가능한 파일 hello 가 생성됩니다.

  5. 실행 파일 hello:

    $ ./hello
    Hello, World!
  6. Makefile target clean 을 실행하여 생성된 파일을 제거합니다.

    $ make clean
    rm -rf hello.o hello

추가 리소스

18.3. make에 대한 문서 리소스

make 에 대한 자세한 내용은 아래 나열된 리소스를 참조하십시오.

설치된 문서

  • maninfo 툴을 사용하여 시스템에 설치된 도움말 페이지와 정보 페이지를 확인합니다.

    $ man make
    $ info make

온라인 문서

19장. C 및 C++ Application Development에 Eclipse IDE 사용

일부 개발자는 명령줄 도구 배열 대신 IDE를 사용하는 것을 선호합니다. Red Hat은 C 및 C++ 애플리케이션 개발을 지원하는 Eclipse IDE를 제공합니다.

C 및 C++ 애플리케이션 개발용 Eclipse 사용

Eclipse IDE에 대한 자세한 설명과 C 및 C++ 애플리케이션 개발에 대한 자세한 설명은 이 문서의 범위를 벗어납니다. 아래 연결된 리소스를 참조하십시오.

추가 리소스

V 부. 애플리케이션 디버깅

디버깅 애플리케이션은 매우 광범위한 주제입니다. 이 부분에서는 개발자에게 여러 상황에서 디버깅을 위한 가장 일반적인 기술을 제공합니다.

20장. 실행 중인 애플리케이션 디버깅

이 장에서는 개발자가 직접 액세스할 수 있는 시스템에서 필요에 따라 여러 번 실행할 수 있는 애플리케이션을 디버깅하는 기술을 소개합니다.

20.1. 디버깅 정보를 사용하여 디버깅 활성화

애플리케이션과 라이브러리를 디버깅하려면 디버깅 정보가 필요합니다. 다음 섹션에서는 이 정보를 가져오는 방법에 대해 설명합니다.

20.1.1. 디버깅 정보

실행 가능한 코드를 디버깅하는 동안 두 가지 종류의 정보를 사용하면 툴을 허용하고 프로그래머를 확장하여 바이너리 코드를 파악할 수 있습니다.

  • 소스 코드 텍스트
  • 소스 코드 텍스트가 바이너리 코드와 관련된 방법에 대한 설명입니다.

이를 디버깅 정보라고 합니다.

Red Hat Enterprise Linux는 실행 가능한 바이너리, 공유 라이브러리 또는 debuginfo 파일에 ELF 형식을 사용합니다. 이러한 ELF 파일 내에 DWARF 형식은 디버그 정보를 유지하는 데 사용됩니다.

DWARF 기호는 readelf -w file 명령으로 읽습니다.

경고

UNIX에서 STABS를 사용하는 경우도 있습니다. STABS는 더 오래되고 성능이 낮은 형식입니다. Red Hat에서는 사용하지 않는 것이 좋습니다. GCC 및 GDB는 최선의 노력으로 STABS 프로덕션 및 소비를 지원합니다. Valgrind 및 elfutils와 같은 다른 툴에서는 STABS를 전혀 지원하지 않습니다.

추가 리소스

20.1.2. GCC를 사용하여 C 및 C++ 애플리케이션 디버깅 활성화

디버깅 정보는 크기 때문에 기본적으로 실행 파일에 포함되지 않습니다. C 및 C++ 애플리케이션을 사용하여 디버깅할 수 있도록 하려면 컴파일러에 디버깅 정보를 작성하도록 명시적으로 지정해야 합니다.To enable debugging of your C and C++ applications with it, you must explicitly instruct the compiler to create debugging information.

GCC를 사용하여 디버깅 정보 생성 활성화

코드를 컴파일 및 연결할 때 GCC 로 디버깅 정보를 생성할 수 있도록 하려면 -g 옵션을 사용합니다.

$ gcc ... -g ...
  • 컴파일러 및 링커에서 수행하는 최적화로 인해 원래 소스 코드와 관련되기 어려운 실행 코드가 발생할 수 있습니다. 변수는 롤백되지 않고 주변 항목에 병합된 작업을 최적화할 수 있습니다. 이는 디버깅에 부정적인 영향을 미칩니다. 디버깅 환경을 개선하려면 -Og 옵션으로 최적화를 설정하는 것이 좋습니다. 그러나 최적화 수준을 변경하면 실행 코드가 변경되고 일부 버그를 제거하기 위해 실제 동작이 변경될 수 있습니다.
  • f compare-debug GCC 옵션은 디버그 정보와 디버그 정보 없이 GCC에서 컴파일한 코드를 테스트합니다. 결과 두 바이너리 파일이 동일한 경우 테스트가 통과합니다. 이 테스트를 사용하면 디버깅 옵션의 영향을 받지 않으므로 디버그 코드에 숨겨진 버그가 없습니다. f compare-debug 옵션을 사용하면 컴파일 시간이 크게 증가합니다. 이 옵션에 대한 자세한 내용은 GCC 도움말 페이지를 참조하십시오.
추가 리소스

20.1.3. debuginfo 패키지

debuginfo 패키지에는 프로그램 및 라이브러리의 디버깅 정보 및 디버그 소스 코드가 포함되어 있습니다.

사전 요구 사항
debuginfo 패키지

Red Hat Enterprise Linux 리포지토리에서 패키지에 설치된 애플리케이션 및 라이브러리의 경우 다른 채널을 통해 사용 가능한 별도의 debuginfo 패키지로 디버깅 정보 및 디버그 소스 코드를 가져올 수 있습니다. debuginfo 패키지에는 DWARF debuginfo 및 바이너리 패키지를 컴파일하는 데 사용되는 소스 파일이 포함된 .debug 파일이 포함되어 있습니다. debuginfo 패키지 콘텐츠는 /usr/lib/debug 디렉터리에 설치됩니다.

debuginfo 패키지는 동일한 이름, 버전, 릴리스 및 아키텍처가 있는 바이너리 패키지에 대해서만 유효한 디버깅 정보를 제공합니다.

  • 바이너리 패키지: packagename-version-release.architecture.rpm
  • debuginfo package: packagename-debuginfo-version-release.architecture.rpm

20.1.4. GDB를 사용하여 애플리케이션 또는 라이브러리용 debuginfo 패키지 가져오기

GNU Debugger(GDB)는 누락된 디버그 정보를 자동으로 인식하고 패키지 이름을 확인합니다.

사전 요구 사항
절차
  1. 디버그하려는 애플리케이션 또는 라이브러리에 연결된 GDB를 시작합니다. GDB는 누락된 디버깅 정보를 자동으로 인식하고 실행할 명령을 제안합니다.

    $ gdb -q /bin/ls
    Reading symbols from /usr/bin/ls...Reading symbols from /usr/bin/ls...(no debugging symbols found)...done.
    (no debugging symbols found)...done.
    Missing separate debuginfos, use: debuginfo-install coreutils-8.22-21.el7.x86_64
    (gdb)
  2. 계속하지 않고 GDB를 종료합니다. qEnter.

    (gdb) q
  3. GDB에서 제안한 명령을 실행하여 필요한 debuginfo 패키지를 설치합니다.

    # debuginfo-install coreutils-8.22-21.el7.x86_64

    애플리케이션 또는 라이브러리의 debuginfo 패키지를 설치하면 모든 종속 항목에 대해 debuginfo 패키지를 설치합니다.

  4. GDB가 debuginfo 패키지를 제안할 수 없는 경우 20.1.5절. “애플리케이션 또는 라이브러리에 대한 debuginfo 패키지 가져오기 수동으로” 의 절차를 따르십시오.
추가 리소스

20.1.5. 애플리케이션 또는 라이브러리에 대한 debuginfo 패키지 가져오기 수동으로

설치를 위해 debuginfo 패키지를 수동으로 선택하려면 실행 가능한 파일을 찾아 설치하는 패키지를 찾습니다.

참고

GDB를 사용하여 설치를 위한 패키지를 결정하는 것이 좋습니다. GDB가 설치할 패키지를 제안할 수 없는 경우에만 이 수동 절차를 사용하십시오.

사전 요구 사항
절차
  1. 애플리케이션 또는 라이브러리의 실행 파일을 찾습니다.

    1. 애플리케이션 파일을 찾으려면 which 명령을 사용합니다.

      $ which nautilus
      /usr/bin/nautilus
    2. locate 명령을 사용하여 라이브러리 파일을 찾습니다.

      $ locate libz | grep so
      /usr/lib64/libz.so
      /usr/lib64/libz.so.1
      /usr/lib64/libz.so.1.2.7

      포함된 오류 메시지를 디버깅하는 원래의 이유로 라이브러리에서 추가 번호가 동일한 결과를 선택합니다. 확실하지 않은 경우 나머지 절차에 따라 라이브러리 파일 이름에 추가 번호가 포함되지 않은 결과를 표시하십시오.

      참고

      locate 명령은 mlocate 패키지에서 제공합니다. 설치하고 사용을 활성화하려면 다음을 수행합니다.

      # yum install mlocate
      # updatedb
  2. 파일 경로를 사용하여 해당 파일을 제공하는 패키지를 검색합니다.

    # yum provides /usr/lib64/libz.so.1.2.7
    Loaded plugins: product-id, search-disabled-repos, subscription-manager
    zlib-1.2.7-17.el7.x86_64 : The compression and decompression library
    Repo        : @anaconda/7.4
    Matched from:
    Filename    : /usr/lib64/libz.so.1.2.7

    출력에서 형식 이름-버전.distribution 의 패키지 목록을 제공합니다. 이 단계에서는 yum 출력에 표시된 버전이 실제 설치된 버전이 아닐 수 있으므로 패키지 이름만 중요합니다.

    중요

    이 단계에서 결과를 생성하지 않으면 바이너리 파일을 제공하는 패키지를 결정할 수 없으며 이 절차가 실패합니다.

  3. rpm 하위 수준 패키지 관리 툴을 사용하여 시스템에 설치된 패키지 버전을 찾습니다. 패키지 이름을 인수로 사용합니다.

    $ rpm -q zlib
    zlib-1.2.7-17.el7.x86_64

    출력에서는 설치된 패키지에 대한 세부 정보를 제공합니다. 버전.distribution .

  4. debuginfo -install 유틸리티를 사용하여debuginfo 패키지를 설치합니다. 명령에서 이전 단계에서 결정한 패키지 이름과 기타 세부 정보를 사용합니다.

    # debuginfo-install zlib-1.2.7-17.el7.x86_64

    애플리케이션 또는 라이브러리의 debuginfo 패키지를 설치하면 모든 종속 항목에 대해 debuginfo 패키지를 설치합니다.

추가 리소스

20.2. GDB를 사용하여 애플리케이션의 내부 상태 검사

애플리케이션이 제대로 작동하지 않는 이유를 찾으려면 해당 실행을 제어하고 내부 상태를 디버거로 검사합니다. 이 섹션에서는 이 작업에 GNU Debugger(GDB)를 사용하는 방법을 설명합니다.

20.2.1. GNU Debugger(GDB)

디버거는 코드 실행 및 코드 상태의 검사를 제어할 수 있는 도구입니다. 이 기능은 프로그램에서 발생하는 상황과 이유를 조사하는 데 사용됩니다.

Red Hat Enterprise Linux에는 명령줄 사용자 인터페이스를 통해 이 기능을 제공하는 GNU 디버거(GDB)가 포함되어 있습니다.

GDB에 대한 그래픽 프런트 엔드의 경우 Eclipse 통합 개발 환경을 설치합니다. Eclipse 사용을 참조하십시오.

GDB 기능

단일 GDB 세션이 디버그할 수 있습니다.

  • 다중 스레드 및 프로그램 예약
  • 한 번에 여러 프로그램
  • 원격 시스템 또는 gdbserver 유틸리티가 있는 컨테이너의 프로그램들이 TCP/IP 네트워크 연결을 통해 연결됨
디버깅 요구 사항

실행 코드를 디버깅하려면 GDB는 해당 디버깅 정보를 필요로 합니다.

  • 사용자가 개발한 프로그램의 경우 코드를 빌드하는 동안 디버깅 정보를 생성할 수 있습니다.
  • 패키지에서 설치한 시스템 프로그램의 경우 해당 debuginfo 패키지를 설치해야 합니다.

20.2.2. GDB를 프로세스에 연결

프로세스를 검사하려면 GDB를 프로세스에 연결해야 합니다.

사전 요구 사항
GDB로 프로그램 시작

프로그램이 프로세스로 실행되지 않으면 GDB로 시작합니다.

$ gdb program

program 을 파일 이름 또는 프로그램의 경로로 바꿉니다.

GDB는 프로그램의 실행을 시작합니다. run 명령으로 프로세스 실행을 시작하기 전에 중단점 및 the gdb 환경을 설정할 수 있습니다.

GDB를 Already Running Process에 연결

GDB를 프로세스로 이미 실행 중인 프로그램에 연결하려면 다음을 수행합니다.

  1. ps 명령을 사용하여 프로세스 ID(pid )를 찾습니다.

    $ ps -C program -o pid h
     pid

    program 을 파일 이름 또는 프로그램의 경로로 바꿉니다.

  2. 이 프로세스에 GDB를 연결합니다.

    $ gdb program -p pid

    프로그램을 프로그램의 파일 이름 또는 경로로 교체하고 pidps 출력의 실제 프로세스 ID 번호로 바꿉니다.

Already running GDB를 Already Running Process에 연결

이미 실행 중인 GDB를 이미 실행 중인 프로그램에 연결하려면 다음을 수행합니다.

  1. GDB 명령을 사용하여 ps 명령을 실행하고 프로그램의 프로세스 ID(pid)를 찾습니다.

    (gdb) shell ps -C program -o pid h
     pid

    program 을 파일 이름 또는 프로그램의 경로로 바꿉니다.

  2. attach 명령을 사용하여 GDB를 프로그램에 연결합니다.

    (gdb) attach pid

    ps 출력의 실제 프로세스 ID 번호로 pid 를 교체합니다.

참고

경우에 따라 GDB가 해당 실행 파일을 찾지 못할 수 있습니다. file 명령을 사용하여 경로를 지정합니다.

(gdb) file path/to/program
추가 리소스

20.2.3. GDB를 사용하여 프로그램 코드를 단계별로 실행

GDB 디버거가 프로그램에 연결되면 여러 명령을 사용하여 프로그램의 실행을 제어할 수 있습니다.

사전 요구 사항
GDB 명령어를 사용하여 코드 전달
R (run)
프로그램 실행을 시작합니다. 실행이 인수와 함께 실행되면 해당 인수는 프로그램이 정상적으로 시작된 것처럼 실행 파일에 전달됩니다. 일반적으로 사용자는 중단점을 설정한 후 이 명령을 실행합니다.
start
프로그램의 실행을 시작하고 기본 함수의 시작 부분에서 중지합니다. start 를 인수로 실행하면 프로그램이 정상적으로 시작된 것처럼 해당 인수가 실행 파일에 전달됩니다.
c (계속)

현재 상태에서 프로그램을 계속 실행합니다. 프로그램 실행이 다음 중 하나가 true가 될 때까지 계속됩니다.

  • Breakpoint에 도달합니다.
  • 지정된 조건이 충족됨
  • 프로그램에 의해 수신된 신호
  • 오류가 발생했습니다.
  • 프로그램이 종료
N (next)

이 명령의 일반적으로 알려진 또 다른 이름은 step 입니다. 현재 소스 파일의 다음 코드 줄에 도달할 때까지 현재 상태에서 프로그램을 계속 실행합니다. 프로그램 실행이 다음 중 하나가 true가 될 때까지 계속됩니다.

  • Breakpoint에 도달합니다.
  • 지정된 조건이 충족됨
  • 프로그램에 의해 수신된 신호
  • 오류가 발생했습니다.
  • 프로그램이 종료
s (단계)
이 명령의 다른 일반적으로 알려진 이름은 다음과 같습니다. step 명령은 현재 소스 파일에서 코드의 각 순차적 줄에서 실행을 중지합니다. 그러나 현재 함수 호출이 포함된 소스 라인에서 실행이 중지된 경우 GDB는 함수 호출 을 입력한 후(실행하지 않고) 실행을 중지합니다.
위치 까지
위치 옵션으로 지정한 코드 위치에 도달할 때까지 실행을 계속합니다.
Fini (마지막)

프로그램 실행을 다시 시작하고 실행이 함수에서 반환될 때 중지됩니다. 프로그램 실행이 다음 중 하나가 true가 될 때까지 계속됩니다.

  • Breakpoint에 도달합니다.
  • 지정된 조건이 충족됨
  • 프로그램에 의해 수신된 신호
  • 오류가 발생했습니다.
  • 프로그램이 종료
Q (quit)
실행을 종료하고 GDB를 종료합니다.
추가 리소스

20.2.4. GDB를 사용하여 프로그램 내부 값 표시

프로그램의 내부 변수의 값을 표시하는 것은 프로그램이 무엇을 하는지 이해하는 데 중요합니다. GDB는 내부 변수를 검사하는 데 사용할 수 있는 여러 명령을 제공합니다. 이 섹션에서는 이러한 명령을 가장 유용하게 설명합니다.

사전 요구 사항
  • GDB 디버거에 대한 이해
GDB 명령 프로그램의 내부 상태를 표시
p (인쇄)

지정된 인수의 값을 표시합니다. 일반적으로 인수는 간단한 단일 값에서 구조까지 복잡한 변수의 이름입니다. 인수는 프로그램 변수 및 라이브러리 함수 또는 테스트 중인 프로그램에 정의된 함수 사용을 포함하여 현재 언어로 유효한 표현식일 수도 있습니다.

출력 명령을 사용하여 데이터 구조(예: 클래스, groups)의 사용자 지정 표시를 위해 GDB를 Python 또는 Guile 스크립트로 확장할 있습니다.

BT( backtrace)

현재 실행 지점에 도달하는 데 사용되는 함수 호출 체인 또는 실행이 전송될 때까지 사용되는 함수의 함수 체인을 표시합니다. 이는 제거 원인과 같은 심각한 버그(예: 분할 오류)를 조사하는 데 유용합니다.

backtrace 명령에 전체 옵션을 추가하면 로컬 변수도 표시됩니다.

btinfo 프레임 명령을 사용하여 표시된 데이터의 사용자 지정 디스플레이에 대해 프레임 필터 Python 스크립트를 사용하여 GDB를 확장할 수 있습니다. 프레임 이라는 용어는 단일 함수 호출과 연관된 데이터를 나타냅니다.

info

info 명령은 다양한 항목에 대한 정보를 제공하는 일반적인 명령입니다. 항목을 지정하는 옵션이 필요합니다.

  • info args 명령은 현재 선택된 프레임인 함수 호출의 인수를 표시합니다.
  • info locals 명령은 현재 선택된 프레임에 로컬 변수를 표시합니다.

가능한 항목 목록은 GDB 세션에서 명령 도움말 정보를 실행하십시오.

(gdb) help info
l (list)
프로그램이 중지된 소스 코드에서 행을 표시합니다. 이 명령은 프로그램 실행이 중지된 경우에만 사용할 수 있습니다. 내부 상태를 표시하는 명령은 엄격하게 아니지만 list 는 사용자가 프로그램 실행의 다음 단계에서 내부 상태에 대한 변경 사항을 이해하는 데 도움이 됩니다.
추가 리소스

20.2.5. GDB 차단기를 사용하여 정의된 코드 위치 실행 중지

많은 경우 특정 줄의 코드에 도달할 때까지 프로그램을 실행하도록 하는 것이 좋습니다.

사전 요구 사항
  • GDB 이해
GDB에서 구분점 사용

Breakpoints는 GDB에 프로그램의 실행을 중지하도록 지시하는 마커입니다. points는 소스 코드 줄과 가장 일반적으로 연관되어 있습니다. point를 배치하려면 소스 파일 및 행 번호를 지정해야 합니다.

  • 중단을 배치하려면:

    • 소스 코드 파일의 이름과 해당 파일의 행을 지정합니다.

      (gdb) br file:line
    • 파일이 없으면 현재 실행 지점에 있는 소스 파일의 이름이 사용됩니다.

      (gdb) br line
    • 또는 함수 이름을 사용하여 Breakpoint를 배치합니다.

      (gdb) br function_name
  • 작업에 대해 일정 횟수가 반복된 후 프로그램이 오류가 발생할 수 있습니다. 실행을 중단할 추가 조건을 지정하려면 다음을 수행합니다.

    (gdb) br file:line if condition

    C 또는 C++ 언어의 조건으로 조건을 바꿉니다. 파일과 의 의미는 위와 동일합니다.

  • 모든 중단점 및 감시점의 상태를 검사 하려면 다음을 수행합니다.

    (gdb) info br
  • 정보 br 의 출력에 표시된 번호를 사용하여 중단점을 제거하려면 다음을 수행합니다.

    (gdb) delete number
  • 지정된 위치에서 중단 항목을 제거하려면 다음을 수행합니다.

    (gdb) clear file:line
추가 리소스

20.2.6. GDB Watchpoints를 사용하여 데이터 액세스 및 변경 사항 실행 중지

대부분의 경우 특정 데이터가 변경되거나 액세스될 때까지 프로그램을 실행하도록 하는 것이 유리합니다. 이 섹션에는 가장 일반적인 시계가 나열되어 있습니다.

사전 요구 사항
  • GDB이해
GDB에서 Watchpoint 사용

Watchpoints는 GDB 가 프로그램의 실행을 중지하도록 지시하는 마커입니다. Watchpoints는 데이터와 관련이 있습니다. 감시 포인트를 배치하려면 변수, 여러 변수 또는 메모리 주소를 설명하는 표현식을 지정해야 합니다.

  • 데이터 변경에 대한 감시 지점을 배치 하려면 다음을 실행합니다 (쓰기).

    (gdb) watch expression

    보고자 하는 내용을 설명하는 표현식 으로 표현식을 바꿉니다. 변수의 경우 표현식 은 변수 이름과 동일합니다.

  • 데이터 액세스를 위한 감시 지점을 배치 하려면(읽기:).

    (gdb) rwatch expression
  • 데이터 액세스(읽기 및 쓰기) 대한 감시 지점을 배치 하려면 다음을 수행하십시오.

    (gdb) awatch expression
  • 모든 감시점 및 중단점의 상태를 검사 하려면 다음을 수행합니다.

    (gdb) info br
  • 감시 지점을 제거하려면 다음을 수행합니다.

    (gdb) delete num

    num 옵션을 info br 명령으로 보고된 번호로 바꿉니다.

추가 리소스

20.2.7. GDB를 사용하여 Forking 또는 Threaded programs 디버깅

일부 프로그램은 포크 또는 스레드를 사용하여 병렬 코드 실행을 수행합니다. 여러 동시 실행 경로를 디버깅하려면 특별한 고려 사항이 필요합니다.

사전 요구 사항
  • GDB 디버거에 대한 이해
  • 프로세스의 개념 및 스레드 이해
GDB를 사용하여 포크된 프로그램 디버깅

포크는 프로그램(상위)이 자체(자체)의 독립적인 사본을 만들 때 발생하는것입니다. 다음 설정 및 명령을 사용하여 GDB의 발생 포크에 영향을 미칩니다.

  • follow-fork-mode 설정은 GDB가 포크 뒤의 상위 또는 하위 항목을 따르는지 여부를 제어합니다.

    follow-fork-mode 상위 설정
    중지한 후 상위 프로세스를 디버깅합니다. 이는 기본값입니다.
    follow-fork-mode 하위 설정
    중지한 후 하위 프로세스를 디버깅합니다.
    show follow-fork-mode
    follow-fork-mode 의 현재 설정을 표시합니다.
  • 설정된 detach-on-fork 설정은 GDB가 다른(후로) 프로세스를 계속 제어하거나 실행되도록 유지할지 여부를 제어합니다.

    detach-on-fork on 설정
    따르지 않는 프로세스( follow-fork-mode값에 따라 다름)는 분리되고 독립적으로 실행됩니다. 이는 기본값입니다.
    detach-on-fork off 설정
    GDB는 두 프로세스를 모두 제어합니다. 뒤에 오는 프로세스( follow-fork-mode값에 따라)는 정상적으로 디버그되지만 다른 프로세스는 일시 중지됩니다.
    show detach-on-fork
    detach-on-fork 의 현재 설정을 표시합니다.
GDB를 사용하여 스레드 프로그램 디버깅

GDB는 개별 스레드를 디버그하고 독립적으로 조작 및 검사할 수 있습니다. GDB가 검사된 스레드만 중지하도록 하려면 명령 집합을 사용하지 않고 에서 target-async를 설정합니다. 이러한 명령을 .gdbinit 파일에 추가할 수 있습니다. 해당 기능이 켜진 후 GDB는 스레드 디버깅을 수행할 준비가 되었습니다.

GDB는 현재 스레드 의 개념을 사용합니다. 기본적으로 명령은 현재 스레드에만 적용됩니다.

정보 스레드
idgid 숫자가 있는 스레드 목록을 표시하고 현재 스레드를 나타냅니다.
스레드 ID
지정된 id를 현재 스레드로 사용하여 스레드를 설정합니다.Sets the thread with the specified id as the current thread.
thread apply ids 명령
ids 가 나열된 모든 스레드에 command 명령을 적용합니다. ids 옵션은 공백으로 구분된 스레드 ID 목록입니다. 특수 값 all 은 모든 스레드에 명령을 적용합니다.
조건인 경우 위치 스레드 ID 중단
스레드 번호 id 에 대해서만 특정 조건이 있는 특정 위치에 정지됨을 설정합니다.
조사 표현식 스레드 ID
스레드 번호 ID 에 대해서만 표현식 으로 정의된 감시 지점을 설정합니다.
명령&
명령 명령을 실행하고 GDB 프롬프트 (gdb) 로 즉시 돌아가 백그라운드에서 코드 실행을 계속합니다.
interrupt
백그라운드에서 실행을 중지합니다.
추가 리소스

20.3. 애플리케이션 상호 작용 기록

실행 가능한 애플리케이션 코드는 운영 체제 및 공유 라이브러리의 코드와 상호 작용합니다. 이러한 상호 작용의 활동 로그를 기록하면 실제 애플리케이션 코드를 디버깅하지 않고도 애플리케이션의 동작에 충분한 통찰력을 제공할 수 있습니다. 또는 애플리케이션의 상호 작용을 분석하면 버그 매니페스트를 나타내는 조건을 파악하는 데 도움이 될 수 있습니다.

20.3.1. 애플리케이션 상호 작용 기록에 유용한 도구

Red Hat Enterprise Linux는 애플리케이션 상호 작용을 분석하기 위한 다양한 툴을 제공합니다.

strace

strace 툴을 사용하면 애플리케이션과 Linux 커널 간의 상호 작용을 추적(및 변조)할 수 있습니다(시스템 호출, 신호 전달 및 프로세스 상태 변경 등).

  • strace 출력은 자세히 설명하고 strace 가 기본 커널 코드에 대한 지식을 사용하여 매개변수 및 결과를 해석하므로 호출을 잘 설명합니다. 숫자는 각 상수 이름으로 변경되고, 비트로 결합된 플래그는 플래그 목록으로 확장된 플래그, 실제 문자열을 제공하기 위해 역참조된 문자 배열에 대한 포인터 등입니다. 그러나 최신 커널 기능에 대한 지원이 부족할 수 있습니다.
  • strace 를 사용하는 경우 로그 필터를 설정하는 경우를 제외하고는 특정 설정이 필요하지 않습니다.
  • strace를 사용하여 애플리케이션 코드를 추적하면 애플리케이션 실행 속도가 크게 느려질 수 있습니다. 따라서 strace는 많은 프로덕션 배포에 적합하지 않습니다. 또는 이러한 경우 SystemTap을 사용하는 것이 좋습니다.
  • 추적된 시스템 호출 및 신호 목록을 제한하여 캡처된 데이터 양을 줄일 수 있습니다.
  • strace는 kernel-userspace 상호 작용만 캡처하고 라이브러리 호출을 추적하지 않습니다. 예를 들면 다음과 같습니다. 라이브러리 호출에 ltrace를 사용하는 것이 좋습니다.
ltrace

ltrace 툴을 사용하면 애플리케이션의 사용자 공간 호출을 공유 오브젝트(dynamic 라이브러리)에 기록할 수 있습니다.

  • ltrace 를 사용하면 모든 라이브러리에 대한 추적 호출을 사용할 수 있습니다.
  • 추적된 호출을 필터링하여 캡처된 데이터 양을 줄일 수 있습니다.
  • ltrace 를 사용하는 경우 로그 필터를 설정하는 경우를 제외하고 ltrace를 사용할 필요가 없습니다.
  • ltrace 는 가볍고 빨라지므로 strace 를 사용하여 커널 함수를 추적하는 대신 ltrace 와 같은 glibc 와 같은 라이브러리에서 해당 인터페이스를 추적할 수 있습니다. 그러나 ltrace 는 syscall 추적에서 덜 정확할 수 있습니다.
  • ltrace 는 제한된 라이브러리 호출 집합에만 매개 변수를 디코딩할 수 있습니다: 관련 구성 파일에 정의된 호출입니다. ltrace 패키지의 일부로 일부 libacl,libc, libm 호출과 시스템 호출을 위한 시제품이 제공됩니다. ltrace 출력에는 주로 원시 번호와 포인터만 포함되어 있습니다. ltrace 출력을 해석하려면 일반적으로 출력에 있는 라이브러리의 실제 인터페이스 선언을 컨설팅해야 합니다.
SystemTap

SystemTap은 Linux 시스템에서 실행 중인 프로세스 및 커널 활동을 조사하기 위한 계측 플랫폼입니다. SystemTap은 사용자 지정 이벤트 핸들러를 프로그래밍하는 데 자체 스크립팅 언어를 사용합니다.

  • strace 및 ltrace 를 사용하는 것과 비교했을 때 로깅을 스크립팅하면 초기 설정 단계에서 더 많은 작업을 수행할 수 있습니다. 그러나 스크립팅 기능은 단순히 로그를 생성하는 것 이상으로 SystemTap의 유용성을 확장합니다.
  • SystemTap은 커널 모듈을 생성하고 삽입하여 작동합니다. SystemTap 사용은 효율적이며 시스템 또는 애플리케이션 실행 성능이 크게 저하되지 않습니다.
  • SystemTap에는 사용 예 집합이 함께 제공됩니다.
GDB

GNU Debugger는 주로 로깅이 아닌 디버깅을 위한 것입니다. 그러나 일부 기능은 애플리케이션의 상호 작용이 주요 관심 활동인 시나리오에서도 유용합니다.

  • GDB를 사용하면 상호 작용 이벤트 캡처를 편리하게 결합하고 후속 실행 경로를 즉시 디버깅할 수 있습니다.
  • GDB는 다른 도구의 문제가 있는 상황을 초기 식별한 후 드물거나 단수 이벤트에 대한 응답을 분석하는 데 가장 적합합니다. 빈번한 이벤트가 있는 모든 시나리오에서 GDB를 사용하는 것은 비효율적이거나 불가능하게 됩니다.
추가 리소스

20.3.2. strace를 사용하여 애플리케이션의 시스템 호출 모니터링

strace 툴을 사용하면 애플리케이션과 Linux 커널 간의 상호 작용을 추적(선택적으로 변조)합니다(시스템 호출, 신호 전달 및 프로세스 상태 변경 등)

사전 요구 사항
  • strace 가 시스템에 설치되어 있습니다.

    • strace 를 설치하려면 root로 실행합니다.

      # yum install strace
절차

strace 의 추적 사양 구문에서는 시스템 호출을 식별하는 데 도움이 되는 정규식 및 syscall 클래스를 제공합니다.

  1. 모니터링할 프로세스를 실행하거나 연결합니다.

    • 모니터링할 프로그램이 실행되고 있지 않으면 strace 를 시작하고 프로그램을 지정합니다:

      $ strace -fvttTyy -s 256 -e trace=call program

      위 예제에서 사용되는 옵션은 필수가 아닙니다. 필요한 경우 다음을 수행하십시오.

      • f 옵션 " follow forks"의 약어입니다. 이 옵션은 포크, vfork 및 복제 시스템 호출에서 생성한 하위 항목을 추적합니다.
      • -v 또는 -e abbrev=none 옵션은 출력 약어를 비활성화하고 다양한 구조 필드를 생략합니다.
      • -tt 옵션은 각 행의 접두사를 절대 타임스탬프로 지정하는 -t 옵션의 변형입니다. -tt 옵션을 사용하면 인쇄된 시간에 microseconds가 포함됩니다.
      • T 옵션은 각 시스템 호출에 사용된 시간을 줄 끝에 출력합니다.
      • y 옵션 은 파일 설명자 번호와 관련된 경로를 출력할 수 있는 -y 옵션의 변형입니다. y 옵션 은 경로뿐만 아니라 장치 파일 설명자와 연결된 소켓 파일 설명자 및 블록 또는 문자 장치 번호와 관련된 프로토콜 관련 정보를 출력합니다.
      • -s 옵션은 인쇄할 최대 문자열 크기를 제어합니다. 파일 이름은 문자열로 간주되지 않으며 항상 전체적으로 인쇄됩니다.
      • -e trace 는 추적할 시스템 호출 집합을 제어합니다.

        호출 을 쉼표로 구분된 시스템 호출 목록으로 바꿉니다. 호출이 남아 있으면 strace 는 모든 시스템 호출을 표시합니다. 일부 시스템 호출 그룹에 대한 요약은 strace(1) 매뉴얼 페이지에 제공됩니다.

    • 프로그램이 이미 실행 중인 경우 프로세스 ID(pid)를 찾아 strace 를 여기에 연결합니다.

      $ ps -C program
      (...)
      $ strace -fvttTyy -s 256 -e trace=call -ppid
    • 분기된 프로세스 또는 스레드를 추적하지 않으려면 -f 옵션을 사용하지 마십시오.
  1. strace 는 애플리케이션 및 세부 정보에 의해 수행된 시스템 호출을 표시합니다.

    대부분의 경우 시스템 호출에 대한 필터가 설정되지 않은 경우 애플리케이션 및 해당 라이브러리는 많은 호출을 만들고 strace 출력을 즉시 표시합니다.

  2. strace 는 추적된 모든 프로세스가 종료될 때 종료됩니다. 추적 프로그램이 종료되기 전에 모니터링을 종료하려면 Ctrl+C 를 누릅니다.

    • strace 가 프로그램을 시작한 경우 종료 신호(이 경우, 이 경우)가 시작되는 프로그램에 전송됩니다. 그러나 이 프로그램은 차례로 해당 신호를 무시할 수 있습니다.
    • strace 를 이미 실행 중인 프로그램에 연결하면 strace 와 함께 프로그램이 종료됩니다.
  3. 애플리케이션에서 수행한 시스템 호출 목록을 분석합니다.

    • 리소스 액세스 또는 가용성 관련 문제는 반환 오류를 호출할 때 로그에 있습니다.
    • 시스템 호출 및 호출 시퀀스 패턴에 전달되는 값은 애플리케이션 동작의 원인에 대한 통찰력을 제공합니다.
    • 애플리케이션이 충돌하면 중요한 정보가 로그 끝에 있을 수 있습니다.
    • 출력에는 많은 추가 정보가 포함되어 있습니다. 그러나 더 정확한 필터를 생성하고 절차를 반복할 수 있습니다.
참고
  • 둘 다 출력을 보고 파일에 저장하는 것이 유리합니다. 이렇게 하려면 tee 명령을 실행합니다.

    $ strace ...-o |tee your_log_file.log>&2
  • 다른 프로세스에 해당하는 별도의 출력을 보려면 다음을 실행합니다.

    $ strace ... -ff -o your_log_file

    프로세스 ID(pid )가 있는프로세스출력은 your_log_file.pid 에 저장됩니다.

추가 리소스

20.3.3. ltrace를 사용하여 애플리케이션의 라이브러리 기능 호출 모니터링

ltrace 툴을 사용하면 애플리케이션에서 수행한 호출을 모니터링하여 라이브러리(공유 오브젝트)에서 사용 가능한 기능을 수행할 수 있습니다.

사전 요구 사항
절차
  1. 가능한 경우 관심 있는 라이브러리 및 기능을 식별합니다.
  2. 모니터링할 프로그램이 실행되지 않는 경우 ltrace 를 시작하고 프로그램을 지정합니다:

    $ ltrace -f -l library -e function program

    -e-l 옵션을 사용하여 출력을 필터링합니다.

    • 함수로 표시할 함수 이름을 제공합니다 . e 기능 옵션은 여러 번 사용할 수 있습니다. 밖으로 나가면 ltrace 는 모든 함수에 대한 호출을 표시합니다.
    • 함수를 지정하는 대신 -l 라이브러리 옵션을 사용하여 전체 라이브러리를 지정할 수 있습니다. 이 옵션은 -e 기능 옵션과 유사하게 작동합니다.

    자세한 내용은 ltrace(1)_ 매뉴얼 페이지를 참조하십시오.

    프로그램이 이미 실행중인 경우 해당 프로세스 ID (pid)를 찾아 ltrace 를 연결합니다.

    $ ps -C program
    (...)
    $ ltrace ... -ppid

    분기된 프로세스 또는 스레드를 추적하지 않으려면 -f 옵션을 남겨 둡니다.

  3. ltrace 는 애플리케이션에서 수행한 라이브러리 호출을 표시합니다.

    대부분의 경우 애플리케이션에서 많은 수의 호출을 수행하고 필터가 설정되지 않은 경우 ltrace 출력이 즉시 표시됩니다.

  4. ltrace 는 프로그램이 종료되면 종료됩니다.

    추적 프로그램이 종료되기 전에 모니터링을 종료하려면 ctrl+C 를 누릅니다.

    • ltrace 가 프로그램을 시작하면 프로그램은 ltrace 와 함께 종료됩니다.
    • ltrace 를 이미 실행 중인 프로그램에 연결한 경우 프로그램은 ltrace 와 함께 종료됩니다.
  5. 애플리케이션에서 수행한 라이브러리 호출 목록을 분석합니다.

    • 애플리케이션이 충돌하면 중요한 정보가 로그 끝에 있을 수 있습니다.
    • 출력에는 불필요한 정보가 많이 포함되어 있습니다. 그러나 더 정확한 필터를 생성하고 절차를 반복할 수 있습니다.
참고

둘 다 출력을 보고 파일에 저장하는 것이 유리합니다. 이 작업을 수행하려면 tee 명령을 사용합니다.

$ ltrace ... |& tee your_log_file.log
추가 리소스
  • strace(1) 도움말 페이지
  • Red Hat Developer Toolset 사용자 가이드 - ltrace

20.3.4. SystemTap을 사용하여 애플리케이션의 시스템 호출 모니터링

SystemTap 툴을 사용하면 커널 이벤트에 대한 사용자 정의 이벤트 처리기를 등록할 수 있습니다. strace 와 비교하여 사용하기가 어렵지만 SystemTap 은 더 효율적이고 복잡한 처리 로직을 사용할 수 있습니다.

사전 요구 사항
절차
  1. 콘텐츠를 사용하여 my_script.stp 파일을 생성합니다.

    probe begin
    {
      printf("waiting for syscalls of process %d \n", target())
    }
    
    probe syscall.*
    {
      if (pid() == target())
        printf("%s(%s)\n", name, argstr)
    }
    
    probe process.end
    {
      if (pid() == target())
        exit()
    }
  2. 모니터링할 프로세스의 프로세스ID(pid )를 찾습니다.

    $ ps -aux
  3. 스크립트를 사용하여 SystemTap 을 실행합니다.

    # stap my_script.stp -x pid

    pid 값은 프로세스 ID입니다.

    스크립트가 로드된 커널 모듈로 컴파일됩니다. 이렇게 하면 명령을 입력하고 출력을 가져오는 사이에 약간의 지연이 발생합니다.

  4. 프로세스에서 시스템 호출을 수행하면 호출 이름과 해당 매개 변수가 터미널에 출력됩니다.
  5. 프로세스가 종료되면 스크립트가 종료되거나 Ctrl+C 를 누르면 종료됩니다.
추가 리소스
  • SystemTap Beginners 가이드
  • SystemTap Tapset 참조
  • strace 기능과 근접한 더 큰 SystemTap 스크립트는 /usr/share/systemtap/examples/process/strace.stp 로 사용할 수 있습니다. 스크립트를 실행하려면 다음을 수행합니다.

    # stap --example strace.stp -x pid

    또는

    # stap --example strace.stp -c "cmd args …​"

20.3.5. GDB를 사용하여 애플리케이션 시스템 호출을 상호 작용

GDB는 프로그램을 실행하는 동안 발생하는 다양한 종류의 상황에서 실행을 중지합니다. 프로그램이 시스템 호출을 수행할 때 실행을 중지하려면 GDB catchpoint 를 사용합니다.

사전 요구 사항

GDB를 사용하여 시스템 호출에서 프로그램 실행 중지

  1. catchpoint를 설정합니다.

    (gdb) catch syscall syscall-name

    명령 catch syscall 은 프로그램에서 시스템 호출을 수행할 때 실행을 중단하는 특수 유형의 hierarchy를 설정합니다.

    syscall-name 옵션은 호출 이름을 지정합니다. 다양한 시스템 호출에 대해 여러 catchpoints를 지정할 수 있습니다. syscall-name 옵션을 벗어나면 GDB가 모든 시스템 호출에서 중지됩니다.

  2. 프로그램이 실행을 시작하지 않은 경우 시작합니다.

    (gdb) r

    프로그램 실행이 중지되는 경우 이를 다시 시작합니다.

    (gdb) c
  3. GDB는 프로그램에서 지정된 시스템 호출을 수행한 후 실행을 중지합니다.
추가 리소스

20.3.6. GDB를 사용하여 애플리케이션에 의한 신호 처리 처리

GDB는 프로그램을 실행하는 동안 발생하는 다양한 종류의 상황에서 실행을 중지합니다. 프로그램이 운영 체제에서 신호를 수신할 때 실행을 중지하려면 GDB catchpoint 를 사용합니다.

사전 요구 사항
GDB를 사용하여 신호 수신 시 프로그램 실행 중지
  1. catchpoint를 설정합니다.

    (gdb) catch signal signal-type

    명령 catch 신호는 프로그램이 신호가 수신될 때 실행을 중단하는 특수 유형의 Breakpoint를 설정합니다. signal-type 옵션은 신호 유형을 지정합니다. 모든 신호를 캡처하려면 특수 값 'all' 을 사용합니다.

  2. 프로그램이 실행을 시작하지 않은 경우 시작합니다.

    (gdb) r

    프로그램 실행이 중지되는 경우 이를 다시 시작합니다.

    (gdb) c
  3. GDB는 프로그램이 지정된 신호를 수신한 후 실행을 중지합니다.
추가 리소스

21장. 충돌한 애플리케이션 디버깅

애플리케이션을 직접 디버깅할 수 없는 경우도 있습니다. 이러한 상황에서는 종료 시 애플리케이션에 대한 정보를 수집하고 이후에 분석할 수 있습니다.

21.1. 코어 덤프

이 섹션에서는 코어 덤프 의 개념과 사용 방법에 대해 설명합니다.

사전 요구 사항

  • 디버깅 정보 이해

설명

코어 덤프는 애플리케이션이 작동을 중지하고 ELF 형식으로 저장된 애플리케이션 메모리 부분의 사본입니다. 애플리케이션의 내부 변수 및 스택을 모두 포함하므로 애플리케이션의 최종 상태를 검사할 수 있습니다. 각 실행 파일 및 디버깅 정보로 보강된 경우 실행 중인 프로그램 분석과 유사한 방식으로 디버거를 사용하여 코어 덤프 파일을 분석할 수 있습니다.

Linux 운영 체제 커널은 이 기능이 활성화된 경우 코어 덤프를 자동으로 기록할 수 있습니다. 또는 실행 중인 애플리케이션에 신호를 보내 실제 상태와 관계없이 코어 덤프를 생성할 수 있습니다.

주의

일부 제한은 코어 덤프를 생성하는 기능에 영향을 줄 수 있습니다.

21.2. 코어 덤프를 사용하여 애플리케이션 Crashes 기록

애플리케이션 충돌을 기록하려면 코어 덤프 저장을 설정하고 시스템에 대한 정보를 추가합니다.

절차

  1. 코어 덤프를 활성화합니다. /etc/systemd/system.conf 파일을 편집하고 DefaultLimitCORE 를 포함하는 행을 다음으로 변경합니다.

    DefaultLimitCORE=infinity
  2. 시스템을 재부팅합니다.

    # shutdown -r now
  3. 코어 덤프 크기의 제한을 제거합니다.

    # ulimit -c unlimited

    이 변경을 반대하려면 무제한 이 아닌 값 0을 사용하여 명령을 실행합니다.

  4. 애플리케이션이 충돌하면 코어 덤프가 생성됩니다. 코어 덤프의 기본 위치는 충돌 시 애플리케이션의 작업 디렉터리입니다.
  5. 시스템에 대한 추가 정보를 제공하는 SOS 보고서를 생성합니다.

    # sosreport

    이렇게 하면 구성 파일 복사본과 같은 시스템에 대한 정보가 포함된 tar 아카이브가 생성됩니다.

  6. 코어 덤프와 SOS 보고서를 디버깅이 수행되는 컴퓨터로 전송합니다. 알려진 경우 실행 파일을 전송합니다.

    중요

    실행 파일을 알 수 없는 경우 코어 파일에 대한 후속 분석에서 해당 파일을 식별합니다.

  7. 선택 사항: 코어 덤프 및 SOS 보고서를 제거한 후 디스크 공간을 확보합니다.

추가 리소스

21.3. 코어 덤프를 사용하여 애플리케이션 Crash 상태 검사

사전 요구 사항

  • 코어 덤프 파일 및 SOS 보고서
  • GDB 및 elfutils가 시스템에 설치되어 있습니다.

절차

  1. 충돌이 발생한 실행 파일을 식별하려면 코어 덤프 파일을 사용하여 eu-unstrip 명령을 실행합니다.

    $ eu-unstrip -n --core=./core.9814
    0x400000+0x207000 2818b2009547f780a5639c904cded443e564973e@0x400284 /usr/bin/sleep /usr/lib/debug/bin/sleep.debug [exe]
    0x7fff26fff000+0x1000 1e2a683b7d877576970e4275d41a6aaec280795e@0x7fff26fff340 . - linux-vdso.so.1
    0x35e7e00000+0x3b6000 374add1ead31ccb449779bc7ee7877de3377e5ad@0x35e7e00280 /usr/lib64/libc-2.14.90.so /usr/lib/debug/lib64/libc-2.14.90.so.debug libc.so.6
    0x35e7a00000+0x224000 3ed9e61c2b7e707ce244816335776afa2ad0307d@0x35e7a001d8 /usr/lib64/ld-2.14.90.so /usr/lib/debug/lib64/ld-2.14.90.so.debug ld-linux-x86-64.so.2

    출력에는 공백으로 구분된 한 줄의 각 모듈에 대한 세부 정보가 포함되어 있습니다. 정보는 다음 순서로 나열됩니다.

    1. 모듈이 매핑된 메모리 주소
    2. 모듈의 build-id 및 검색된 메모리의 위치
    3. 모듈의 실행 파일 이름, 알 수 없는 경우 또는 로 표시됨 또는 모듈이 파일에서 로드되지 않은 경우
    4. 사용 가능한 경우 파일 이름으로 표시되는 디버깅 정보의 소스입니다 . 실행 파일 자체에 포함된 경우 또는 전혀 표시되지 않는 경우 입니다.
    5. 기본 모듈의 공유 라이브러리 이름(soname), 또는 [exe]

    이 예에서 중요한 세부 사항은 텍스트 [exe] 를 포함하는 행의 파일 이름 /usr/bin/sleep 및 build-id 2818b2009547f780a56394cded443e564973e 입니다. 이 정보를 사용하여 코어 덤프를 분석하는 데 필요한 실행 파일을 식별할 수 있습니다.

  2. 충돌한 실행 파일을 가져옵니다.

    • 가능한 경우 충돌이 발생한 시스템에서 복사합니다. 코어 파일에서 추출한 파일 이름을 사용합니다.
    • 또는 시스템에서 동일한 실행 파일을 사용합니다. Red Hat Enterprise Linux를 기반으로 빌드된 각 실행 파일에는 고유한 build-id 값이 포함된 참고 사항이 포함되어 있습니다. 로컬에서 사용 가능한 관련 실행 파일의 build-id를 확인합니다.

      $ eu-readelf -n executable_file

      이 정보를 사용하여 원격 시스템의 실행 파일과 로컬 사본을 일치시킵니다. 코어 덤프에 나열된 로컬 파일 및 build-id의 build-id가 일치해야 합니다.

    • 마지막으로, 애플리케이션이 RPM 패키지에서 설치된 경우 패키지에서 실행 파일을 가져올 수 있습니다. sosreport 출력을 사용하여 필요한 패키지의 정확한 버전을 찾습니다.
  3. 실행 파일에서 사용하는 공유 라이브러리를 가져옵니다. 실행 파일에 대해 와 동일한 단계를 사용합니다.
  4. 애플리케이션이 패키지로 배포되는 경우 GDB에서 실행 파일을 로드하여 누락된 debuginfo 패키지의 힌트를 표시합니다. 자세한 내용은 20.1.4절. “GDB를 사용하여 애플리케이션 또는 라이브러리용 debuginfo 패키지 가져오기” 의 내용을 참조하십시오.
  5. 핵심 파일을 자세히 검사하려면 GDB를 사용하여 실행 파일 및 코어 덤프 파일을 로드합니다.

    $ gdb -e executable_file -c core_file

    누락된 파일 및 디버깅 정보에 대한 추가 메시지는 디버깅 세션에 누락된 항목을 식별하는 데 도움이 됩니다. 필요한 경우 이전 단계로 돌아갑니다.

    패키지 대신 디버깅 정보를 파일로 사용할 수 있는 경우 GDB에서 symbol-file 명령을 사용하여 이 파일을 로드합니다.

    (gdb) symbol-file program.debug

    program.debug 를 실제 파일 이름으로 교체합니다.

    참고

    코어 덤프에 포함된 모든 실행 파일에 대한 디버깅 정보를 설치할 필요가 없을 수도 있습니다. 이러한 실행 가능한 파일은 애플리케이션 코드에서 사용하는 라이브러리입니다. 이러한 라이브러리는 분석 중인 문제에 직접 기여하지 않을 수 있으며, 디버깅 정보를 포함할 필요가 없습니다.

  6. GDB 명령을 사용하여 충돌 시 애플리케이션 상태를 검사합니다. 20.2절. “GDB를 사용하여 애플리케이션의 내부 상태 검사”을 참조하십시오.

    참고

    코어 파일을 분석할 때 GDB는 실행 중인 프로세스에 연결되지 않습니다. 실행을 제어하기 위한 명령에는 아무런 영향이 없습니다.

추가 리소스

21.4. gcore를 사용하여 프로세스 메모리 덤프

코어 덤프 디버깅의 워크플로를 사용하면 프로그램의 오프라인 상태를 분석할 수 있습니다. 프로세스를 통해 환경에 액세스하기 어려울 때와 같이 아직 실행 중인 프로그램과 함께 이 워크플로를 사용하는 것이 유리합니다. gcore 명령을 사용하여 실행 중인 동안 프로세스의 메모리를 덤프할 수 있습니다.

사전 요구 사항

절차

gcore 를 사용하여 프로세스 메모리를 덤프하려면 다음을 수행합니다.

  1. 프로세스 ID(pid)를 확인합니다. ps,pgreptop 과 같은 툴 사용 :

    $ ps -C some-program
  2. 이 프로세스의 메모리를 덤프합니다.

    $ gcore -o filename pid

    그러면 파일 파일 이름이 생성되고 여기에 프로세스 메모리를 덤프합니다. 메모리가 덤프되는 동안 프로세스 실행이 중지됩니다.

  3. 코어 덤프가 완료되면 프로세스가 정상적인 실행을 재개합니다.
  4. 시스템에 대한 추가 정보를 제공하는 SOS 보고서를 생성합니다.

    # sosreport

    이렇게 하면 구성 파일 복사본과 같은 시스템에 대한 정보가 포함된 tar 아카이브가 생성됩니다.

  5. 프로그램의 실행 파일, 코어 덤프 및 SOS 보고서를 디버깅이 수행되는 컴퓨터로 전송합니다.
  6. 선택 사항: 코어 덤프 및 SOS 보고서를 전송하여 디스크 공간을 회수합니다.

추가 리소스

21.5. GDB로 프로세스 메모리 덤프

덤프되지 않은 프로세스 메모리를 표시할 수 있습니다. 따라서 프로세스 메모리에 중요한 데이터가 포함되어 있는 경우 리소스를 저장하고 추가 보안을 유지할 수 있습니다. 커널 코어 덤프(kdump)와 수동 코어 덤프(gcore, GDB)는 모두 이러한 방식으로 표시된 메모리를 덤프하지 않습니다.

경우에 따라 이러한 보호에 관계없이 프로세스 메모리의 전체 내용을 덤프해야 합니다. 다음 절차에서는 GDB 디버거를 사용하여 이 작업을 수행하는 방법을 설명합니다.

사전 요구 사항

절차

  1. /proc/PID/coredump_filter 파일의 설정을 무시하도록 GDB를 설정합니다.

    (gdb) set use-coredump-filter off
  2. 메모리 페이지 플래그 VM_DONTDUMP 를 무시하도록 GDB를 설정합니다.

    (gdb) set dump-excluded-mappings on
  3. 메모리를 덤프합니다.

    (gdb) gcore core-file

    core-file 을 메모리를 덤프하려는 파일 이름으로 교체합니다.

추가 리소스

VI 부. 성능 모니터링

개발자는 성능에 가장 큰 영향을 미치는 프로그램 영역에 중점을 두도록 프로그램을 프로파일링합니다. 수집되는 데이터 유형에는 프로그램의 섹션이 가장 많은 프로세서 시간을 사용하고 메모리가 할당되는 위치가 포함됩니다. 프로파일링은 실제 프로그램 실행에서 데이터를 수집합니다. 따라서 수집된 데이터의 품질은 프로그램에 의해 수행되는 실제 작업의 영향을 받습니다. 프로파일링 중에 수행되는 작업은 실제 사용을 대표해야 합니다. 이로 인해 프로그램의 실제 사용으로 인해 발생하는 문제가 개발 중에 해결됩니다.

Red Hat Enterprise Linux에는 프로파일링 데이터를 수집하는 다양한 툴(Valgrind , OProfile, perf, SystemTap)이 포함되어 있습니다. 각 도구는 다음 섹션에 설명된 대로 특정 유형의 프로필 실행을 수행하는 데 적합합니다.

22장. valgrind

Valgrind 는 애플리케이션을 자세히 프로파일링하는 데 사용할 수 있는 동적 분석 툴을 구축하기 위한 계측 프레임워크입니다. 기본 설치에서는 이미 5개의 표준 툴을 제공합니다. Valgrind 툴은 일반적으로 메모리 관리 및 스레드 문제를 조사하는 데 사용됩니다. Valgrind 에서는 사용자 공간 바이너리에 대한 계측을 제공하여 초기화되지 않은 메모리 사용, 부적절한 메모리 할당/삭제, 시스템 호출에 대한 부적절한 인수와 같은 오류를 확인합니다. 그 프로파일링 툴은 대부분의 바이너리에서 사용할 수 있지만 다른 프로파일에 비해 Valgrind 프로파일 실행 속도가 훨씬 느려집니다. Valgrind 는 바이너리를 프로파일링하기 위해 특수 가상 머신 내에서 실행하므로 Valgrind 가 모든 바이너리 명령을 인터셉트할 수 있습니다. Valgrind의 툴은 사용자 공간 프로그램에서 메모리 관련 문제를 찾는 데 가장 유용하며 시간별 문제 또는 커널 공간 계측 및 디버깅을 디버깅하는 데는 적합하지 않습니다.

Valgrind 보고서는 조사 중인 프로그램 또는 라이브러리를 위해 debuginfo 패키지를 설치할 때 가장 유용하고 정확합니다. 20.1절. “디버깅 정보를 사용하여 디버깅 활성화”을 참조하십시오.

22.1. Valgrind 툴

Valgrind 제품군은 다음 툴로 구성됩니다.

Memcheck

이 도구는 프로그램에서 메모리 관리 문제를 감지합니다.

  • 메모리에서 모든 읽기 및 쓰기 확인
  • malloc,free,new 또는 delete에 대한 호출과 같은 메모리 조작을 가로채는 것입니다.

Memcheck 는 메모리 관리 문제가 다른 수단을 사용하여 감지하기 어려울 수 있으므로 가장 많이 사용되는 Valgrind 도구일 수 있습니다. 이러한 문제는 종종 장기간 감지되지 않고 결국 진단하기 어려운 충돌을 유발합니다.

특정 도구를 선택하지 않은 경우 Mem check 가 기본 도구로 작동합니다.

cachegrind
cachegrind 는 CPU에서 I1, D1 및 L2 캐시의 자세한 시뮬레이션을 수행하여 코드에서 캐시 누락의 원인을 정확하게 파악하는 캐시 프로파일러입니다. 또한 각 소스 코드에 대한 캐시 누락, 메모리 참조 및 지침의 수를 표시합니다. cachegrind 도 함수별, 모듈당 및 전체 프로그램 요약을 제공하며, 각 개별 머신 명령에 대한 개수를 표시할 수 있습니다.
callgrind
cachegrind 와 마찬가지로callgrind 에서는 캐시 동작을 모델링할 수 있습니다. 그러나 호출grind 의 주요 목적은 실행된 코드에 대한 callgraphs 데이터를 기록하는 것입니다.
large largeif
largestif 는 힙 프로파일러입니다. 이는 프로그램이 사용하는 힙 메모리의 양을 측정하여 힙 블록, 힙 관리 오버헤드 및 스택 크기에 대한 정보를 제공합니다. 힙 프로파일러는 힙 메모리 사용량을 줄이는 방법을 찾는 데 유용합니다. 가상 메모리를 사용하는 시스템에서 최적화된 힙 메모리 사용량이 있는 프로그램은 메모리가 부족해질 가능성이 적으며 페이징이 줄어들 때 더 빠르게 실행될 수 있습니다.
Helgrind

POSIX pthreads 스레드를 사용하는 프로그램에서 helgrind 는 동기화 오류를 탐지합니다. 이러한 오류는 다음과 같습니다.

  • POSIX pthreads API의 오용
  • 잠금 문제 해결으로 발생하는 잠재적인 교착 상태
  • 데이터 경쟁 (즉, 적절한 잠금없이 메모리에 액세스)

22.2. Valgrind 사용

valgrind 패키지와 해당 종속 항목은 Valgrind 프로파일 실행을 수행하는 데 필요한 모든 툴을 설치합니다. Valgrind 를 사용하여 프로그램을 프로파일링하려면 다음을 사용합니다.

$ valgrind --tool=toolname program

이름에 대한 인수 목록은 22.1절. “Valgrind 툴” 을 참조하십시오. Valgrind 도구 제품군 외에도 toolname 에 대한 유효한 인수도 없습니다. 이 인수를 사용하면 프로파일링을 수행하지 않고 Valgrind 에서 프로그램을 실행할 수 있습니다. 이는 Valgrind 자체를 디버깅하거나 벤치마킹하는 데 유용합니다.

또한 Valgrind 에 모든 정보를 특정 파일에 보내도록 지시할 수도 있습니다. 이 작업을 수행하려면 --log-file=파일 이름을 사용합니다. 예를 들어 실행 가능한 파일 hello 의 메모리 사용량을 확인하고 프로파일 정보를 출력 으로 보내려면 다음을 사용합니다.

$ valgrind --tool=memcheck --log-file=output hello

Valgrind 에 대한 자세한 내용과 함께 Valgrind 도구 모음에 대한 기타 사용 가능한 문서는 22.3절. “추가 정보” 를 참조하십시오.

22.3. 추가 정보

Valgrind 에 대한 자세한 내용은 man valgrind 를 참조하십시오. Red Hat Enterprise Linux는 또한 다음에서 PDF 및 HTML로 사용할 수 있는 포괄적인 Valgrind 문서 도서를 제공합니다.

  • /usr/share/doc/valgrind-version/valgrind_manual.pdf
  • /usr/share/doc/valgrind-version/html/index.html

23장. OProfile

OProfileoprofile 패키지에서 제공하는 낮은 오버헤드의 시스템 전체 성능 모니터링 툴입니다. 시스템의 프로세서의 성능 모니터링 하드웨어를 사용하여 메모리가 참조되는 경우, 두 번째 수준 캐시 요청 수 및 수신된 하드웨어 인터럽트 수와 같이 시스템의 커널 및 실행 파일에 대한 정보를 검색합니다. 또한 OProfile 은 JVM(Java Virtual Machine)에서 실행되는 애플리케이션을 프로파일링할 수 있습니다.

다음은 OProfile:에서 제공하는 도구의 목록입니다.

ophelp
시스템 프로세서에 대한 사용 가능한 이벤트를 각 이벤트에 대한 간략한 설명과 함께 표시합니다.
operf

기본 프로파일링 툴입니다. operf 툴에서는 시스템의 성능 모니터링 하드웨어를 사용하여 OProfile 을 다른 툴과 함께 작동할 수 있는 Linux 성능 이벤트 하위 시스템을 사용합니다.

이전에 사용된 opcontrol 툴과 달리 초기 설정은 필요하지 않으며 --system-wide 옵션을 사용하지 않는 경우 루트 권한 없이 사용할 수 있습니다.

ocount
절대 이벤트 발생 횟수를 계산하는 툴입니다. 프로세스당, CPU당 또는 스레드당 전체 시스템의 이벤트를 계산할 수 있습니다.
opimport
샘플 데이터베이스 파일을 외부 바이너리 형식에서 시스템의 네이티브 형식으로 변환합니다. 다른 아키텍처의 샘플 데이터베이스를 분석할 때만 이 옵션을 사용합니다.
opannotate
디버깅 기호를 사용하여 애플리케이션을 컴파일하는 경우 실행 파일에 대한 주석이 달린 소스를 생성합니다.
opreport
기록된 성능 데이터를 읽고 프로필 사양에 지정된 대로 요약을 생성합니다. 다른 프로필 사양을 사용하여 동일한 프로필 데이터에서 다른 보고서를 생성할 수 있습니다.

23.1. OProfile 사용

operf 는 프로파일링 데이터를 수집하는 데 권장되는 도구입니다. 툴에는 초기 구성이 필요하지 않으며 모든 옵션이 명령줄에 전달됩니다. 레거시 opcontrol 도구와 달리 operfroot 권한 없이 실행할 수 있습니다. operf 도구를 사용하는 방법에 대한 자세한 내용은 시스템 관리자 가이드의 operf 사용 장을 참조하십시오.

예 23.1. ocount 사용

다음 예제에서는 sleep 유틸리티를 실행하는 동안 ocount 로 이벤트 양을 계산하는 방법을 보여줍니다.

$ ocount -e INST_RETIRED -- sleep 1

Events were actively counted for 1.0 seconds.
Event counts (actual) for /bin/sleep:
Event Count % time counted
INST_RETIRED 683,011 100.00
참고

이벤트는 프로세서 구현에 따라 다릅니다. Perf _event_paranoid 옵션을 설정하거나 개수를 사용자 공간 이벤트로만 제한해야 할 수 있습니다.

예 23.2. 기본 operf usage

다음 예에서 operf 도구는 ls -l ~ 명령에서 프로파일링 데이터를 수집하는 데 사용됩니다.

  1. ls 명령에 대한 디버깅 정보를 설치합니다.

    # debuginfo-install -y coreutils
  2. 프로파일링을 실행합니다.

    $ operf ls -l ~
    Profiling done.
  3. 수집된 데이터를 분석합니다.

    $ opreport --symbols
    CPU: Intel Skylake microarchitecture, speed 3.4e+06 MHz (estimated)
    Counted cpu_clk_unhalted events () with a unit mask of 0x00 (Core cycles when at least one thread on the physical core is not in halt state) count 100000
    samples % image name symbol name
    161 81.3131 no-vmlinux /no-vmlinux
    3 1.5152 libc-2.17.so get_next_seq
    3 1.5152 libc-2.17.so strcoll_l
    2 1.0101 ld-2.17.so _dl_fixup
    2 1.0101 ld-2.17.so _dl_lookup_symbol_x
    [...]

예 23.3. operf to Profile a Java Program에 사용

다음 예에서 operf 도구는 Java (JIT) 프로그램에서 프로파일링 데이터를 수집하는 데 사용되며 opreport 도구는 기호별 데이터를 출력하는 데 사용됩니다.

  1. 이 예제에 사용된 데모 Java 프로그램을 설치합니다. 이 패키지는 선택적 채널에 포함된 java-1.8.0-openjdk-demo 패키지의 일부입니다. Optional 채널 사용 방법에 대한 지침은 Add the Optional and Supplementary Repositories 에서 참조하십시오. 선택적 채널이 활성화되면 패키지를 설치합니다.

    # yum install java-1.8.0-openjdk-demo
  2. OProfileoprofile-jit 패키지를 설치하여 Java 프로그램에서 프로파일링 데이터를 수집할 수 있습니다.

    # yum install oprofile-jit
  3. OProfile 데이터 디렉터리를 생성합니다.

    $ mkdir ~/oprofile_data
  4. 데모 프로그램을 사용하여 디렉터리로 변경합니다.

    $ cd /usr/lib/jvm/java-1.8.0-openjdk/demo/applets/MoleculeViewer/
  5. 프로파일링을 시작합니다.

    $ operf -d ~/oprofile_data appletviewer \
    -J"-agentpath:/usr/lib64/oprofile/libjvmti_oprofile.so" example2.html
  6. 홈 디렉터리로 변경하고 수집된 데이터를 분석합니다.

    $ cd
    $ opreport --symbols --threshold 0.5

    샘플 출력은 다음과 같을 수 있습니다.

    $ opreport --symbols --threshold 0.5
    Using /home/rkratky/oprofile_data/samples/ for samples directory.
    CPU: Intel Ivy Bridge microarchitecture, speed 3600 MHz (estimated)
    Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (No unit mask) count 100000
    samples  %        image name               symbol name
    14270    57.1257  libjvm.so                /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.51-1.b16.el7_1.x86_64/jre/lib/amd64/server/libjvm.so
    3537     14.1593  23719.jo                 Interpreter
    690       2.7622  libc-2.17.so             fgetc
    581       2.3259  libX11.so.6.3.0          /usr/lib64/libX11.so.6.3.0
    364       1.4572  libpthread-2.17.so       pthread_getspecific
    130       0.5204  libfreetype.so.6.10.0    /usr/lib64/libfreetype.so.6.10.0
    128       0.5124  libc-2.17.so             __memset_sse2

23.2. OProfile 문서

OProfile 에 대한 자세한 내용은 oprofile(1) 매뉴얼 페이지를 참조하십시오. Red Hat Enterprise Linux는 file:///usr/share/doc/oprofile-버전/ 에서 OProfile 에 대한 두 가지 포괄적인 가이드를 제공합니다.

OProfile Manual
설정 및 OProfile 사용에 대한 자세한 지침이 있는 포괄적인 설명서는 file:///usr/share/doc/oprofile-버전/oprofile.html에서 확인할 수 있습니다.
OProfile Internals
OProfile 의 내부 작동에 대한 설명서 ( OProfile 업스트림에 기여하는 데 유용한 문서) file:///usr/share/doc/oprofile-버전/internals.html에서 찾을 수 있습니다.

24장. SystemTap

SystemTap은 Linux 시스템에서 실행 중인 프로세스 및 커널 활동을 유도하는 데 유용한 계측 플랫폼입니다. 프로브를 실행하려면 다음을 수행합니다.

  1. 지정된 작업을 트리거해야 하는 시스템 이벤트(예: 가상 파일 시스템, 패킷 전송)를 지정하는 SystemTap 스크립트 를 작성합니다(예: 인쇄, 구문 분석 또는 기타 조작).
  2. SystemTap은 스크립트를 커널 모듈로 컴파일하는 C 프로그램으로 변환합니다.
  3. SystemTap은 커널 모듈을 로드하여 실제 프로브를 수행합니다.

SystemTap 스크립트는 시스템의 정상적인 작동에 대한 개입을 최소화하여 시스템 작업을 모니터링하고 시스템 문제를 진단하는 데 유용합니다. 다시 컴파일하고 조정된 코드를 다시 설치할 필요 없이 시스템 테스트를 실행하는 빠르게 계측할 수 있습니다. SystemTap은 커널 공간을 조사하는 SystemTap 스크립트를 컴파일하기 위해 다음 세 가지 커널 정보 패키지의 정보를 사용합니다.

  • kernel-variant-devel-version
  • kernel-variant-debuginfo-version
  • kernel-debuginfo-common-arch-version

이러한 커널 정보 패키지는 검색할 커널과 일치해야 합니다. 또한 여러 커널에 대한 SystemTap 스크립트를 컴파일하려면 각 커널의 커널 정보 패키지도 설치해야 합니다.

24.1. 추가 정보

SystemTap에 대한 자세한 내용은 다음 Red Hat 문서를 참조하십시오.

25장. Linux (PCL) 툴 및 perf를 위한 성능 counter (PCL)

PCL(PCL )은 성능 데이터를 수집하고 분석하기 위한 프레임워크를 제공하는 커널 기반 하위 시스템입니다. Red Hat Enterprise Linux 7에는 수집된 성능 데이터를 분석하기 위해 데이터와 사용자 공간 툴을 수집하는 커널 하위 시스템이 포함되어 있습니다. PCL 하위 시스템은 폐지된 지침 및 프로세서 클럭 사이클을 포함하여 하드웨어 이벤트를 측정하는 데 사용할 수 있습니다. 또한 주요 페이지 폴트 및 컨텍스트 스위치를 포함하여 소프트웨어 이벤트를 측정할 수 있습니다. 예를 들어, PCL 카운터는 프로세스 종료 및 프로세서 클럭 사이클의 명령 수에서 지시자(IPC)를 계산할 수 있습니다. 낮은 IPC 비율은 코드가 CPU를 제대로 사용하지 않는다는 것을 나타냅니다. 다른 하드웨어 이벤트도 잘못된 CPU 성능을 진단하는 데 사용할 수 있습니다.

성능 카운터는 샘플을 기록하도록 구성할 수도 있습니다. 상대적인 샘플 양은 성능에 가장 큰 영향을 미치는 코드 영역을 식별하는 데 사용할 수 있습니다.

25.1. perf Tool 명령

유용한 perf 명령은 다음과 같습니다.

perf stat
perf 명령은 실행되는 명령과 사용되는 클럭 사이클을 포함하여 일반적인 성능 이벤트에 대한 전체 통계를 제공합니다. 옵션을 사용하면 기본 측정 이벤트 이외의 이벤트를 선택할 수 있습니다.
perf record
perf 명령은 성능 데이터를 파일에 기록하며, 이 파일은 perf 보고서를 사용하여 나중에 분석할 수 있습니다.
perf 보고서
perf 명령은 파일에서 성능 데이터를 읽고 기록된 데이터를 분석합니다.
perf 목록
perf 명령은 특정 시스템에서 사용 가능한 이벤트를 나열합니다. 이러한 이벤트는 시스템의 성능 모니터링 하드웨어 및 소프트웨어 구성에 따라 달라집니다.

perf 도움말 을 사용하여 전체 perf 명령 목록을 가져옵니다. 각 perf 명령에서 도움말 페이지 정보를 검색하려면 perf help 명령을 사용합니다.

25.2. Perf 사용

프로그램 실행의 통계 또는 샘플을 수집하기 위해 기본 PCL 인프라를 사용하는 것은 상대적으로 간단합니다. 이 섹션에서는 전체 통계 및 샘플링의 간단한 예를 제공합니다.

make 및 해당 하위 항목에 대한 통계를 수집하려면 다음 명령을 사용합니다.

# perf stat -- make all

perf 명령은 다양한 하드웨어 및 소프트웨어 카운터를 수집합니다. 그런 다음 다음 정보를 출력합니다.

Performance counter stats for 'make all':

  244011.782059  task-clock-msecs         #      0.925 CPUs
          53328  context-switches         #      0.000 M/sec
            515  CPU-migrations           #      0.000 M/sec
        1843121  page-faults              #      0.008 M/sec
   789702529782  cycles                   #   3236.330 M/sec
  1050912611378  instructions             #      1.331 IPC
   275538938708  branches                 #   1129.203 M/sec
     2888756216  branch-misses            #      1.048 %
     4343060367  cache-references         #     17.799 M/sec
      428257037  cache-misses             #      1.755 M/sec

  263.779192511  seconds time elapsed

perf 도구는 또한 샘플을 기록할 수 있습니다. 예를 들어 make 명령과 해당 하위 항목에 대한 데이터를 기록하려면 다음을 사용합니다.

# perf record -- make all

이렇게 하면 샘플이 저장되는 파일과 수집된 샘플 수가 출력됩니다.

[ perf record: Woken up 42 times to write data ]
[ perf record: Captured and wrote 9.753 MB perf.data (~426109 samples) ]

PCL(Linux용 성능 counter) 도구는 OProfile과 충돌

OProfile과 PCP for Linux (PCL) 모두 동일한 하드웨어 성능 모니터링 장치 (PMU)를 사용합니다. PCL perf 명령을 사용하려는 동안 OProfile이 실행 중인 경우 OProfile을 시작할 때 다음과 같은 오류 메시지가 발생합니다.

Error: open_counter returned with 16 (Device or resource busy). /usr/bin/dmesg may provide additional information.

Fatal: Not all events could be opened.

perf 명령을 사용하려면 먼저 OProfile을 종료합니다.

# opcontrol --deinit

그런 다음 perf.data 를 분석하여 샘플의 상대적 빈도를 확인할 수 있습니다. 보고서 출력에는 샘플에 대한 명령, 오브젝트 및 기능이 포함됩니다. perf 보고서를 사용하여 perf.data 분석을 출력합니다. 예를 들어 다음 명령은 가장 많은 시간을 사용하는 실행 파일에 대한 보고서를 생성합니다.

# perf report --sort=comm

결과 출력:

# Samples: 1083783860000
#
# Overhead          Command
# ........  ...............
#
    48.19%         xsltproc
    44.48%        pdfxmltex
     6.01%             make
     0.95%             perl
     0.17%       kernel-doc
     0.05%          xmllint
     0.05%              cc1
     0.03%               cp
     0.01%            xmlto
     0.01%               sh
     0.01%          docproc
     0.01%               ld
     0.01%              gcc
     0.00%               rm
     0.00%              sed
     0.00%   git-diff-files
     0.00%             bash
     0.00%   git-diff-index

왼쪽의 열에는 샘플의 상대적 양이 표시되어 있습니다. 이 출력은 xsltproc 및cabundle xmltex에서 대부분의 시간을 소비한다는 것을 보여줍니다. 완료하는 데 걸리는 시간을 줄이려면 xsltproc 및 rhcos xmltex 에 집중하십시오. xsltproc 에서 실행한 함수를 나열하려면 다음을 실행합니다.

# perf report -n --comm=xsltproc

이 경우 다음을 생성합니다.

comm: xsltproc
# Samples: 472520675377
#
# Overhead  Samples                    Shared Object  Symbol
# ........ ..........  .............................  ......
#
    45.54%215179861044  libxml2.so.2.7.6               [.] xmlXPathCmpNodesExt
    11.63%54959620202  libxml2.so.2.7.6               [.] xmlXPathNodeSetAdd__internal_alias
     8.60%40634845107  libxml2.so.2.7.6               [.] xmlXPathCompOpEval
     4.63%21864091080  libxml2.so.2.7.6               [.] xmlXPathReleaseObject
     2.73%12919672281  libxml2.so.2.7.6               [.] xmlXPathNodeSetSort__internal_alias
     2.60%12271959697  libxml2.so.2.7.6               [.] valuePop
     2.41%11379910918  libxml2.so.2.7.6               [.] xmlXPathIsNaN__internal_alias
     2.19%10340901937  libxml2.so.2.7.6               [.] valuePush__internal_alias

부록 A. 개정 내역

버전 7-6.1, 2018년 10월 30일 Vladimim RuntimeClassr Slvik
7.6 GA 릴리스에 대한 빌드입니다.
버전 7-6, Tue Aug 21 2018 Vladimim supposedr Slvik
7.6 베타 릴리스에 대한 빌드입니다.
버전 7-5.1, Tue 10 2018년 4월 10일, Vladimimhierar Slvik
7.5 GA 릴리스를 위한 빌드
버전 7-5, Tue 2019년 1월 9일 Vladim RuntimeClassr Sloctetsvik
7.5 Beta의 새로운 서적 버전의 공개됨
버전 7-4.1, Tue Aug 22 2017, Vladimim supposedr Slvik
연결된 제품의 새 릴리스에 대한 업데이트입니다.
버전 7-4, Wed Jul 26 2017, Vladimim RuntimeClassr Slvik
7.4 GA 릴리스를 위한 빌드 개발을 위한 워크스테이션 설정에 대한 새로운 장입니다.
버전 1-12, 2017년 5월 26일, Vladim RuntimeClassr Slvik
오래된 정보를 제거하려면 업데이트합니다.
버전 7-3.9, 2017년 5월 15일, Robert Kroctets
7.4 베타 릴리스를 빌드합니다.