RHEL 10에서 C 및 C++ 애플리케이션 개발
Red Hat Enterprise Linux 10에서 개발자 워크스테이션 설정 및 C 및 C++ 애플리케이션 개발 및 디버깅
초록
1장. 개발 워크스테이션 설정 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux 10은 사용자 지정 애플리케이션 개발을 지원합니다. 이 장에서는 일반적인 개발 사용 사례와 필요한 툴에 대해 설명합니다. 그래픽 환경을 포함한 RHEL 시스템이 설치 및 서브스크립션되었는지 확인해야 합니다.
1.1. 디버그 및 소스 리포지토리 활성화 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux의 표준 설치는 디버그 및 소스 리포지토리를 활성화하지 않습니다. 이러한 리포지토리에는 시스템 구성 요소를 디버그하고 성능을 측정하는 데 필요한 정보가 포함되어 있습니다.
프로세스
BaseOS 디버그 정보 패키지 채널을 활성화합니다.
# subscription-manager repos --enable rhel-10-for-$(uname -i)-baseos-debug-rpmsBaseOS 소스 패키지 채널을 활성화합니다.
# subscription-manager repos --enable rhel-10-for-$(uname -i)-baseos-source-rpmsAppStream 디버그 정보 패키지 채널을 활성화합니다.
# subscription-manager repos --enable rhel-10-for-$(uname -i)-appstream-debug-rpmsAppStream 소스 패키지 채널을 활성화합니다.
# subscription-manager repos --enable rhel-10-for-$(uname -i)-appstream-source-rpms$(uname -i)부분은 자동으로 시스템 아키텍처에 일치하는 값으로 교체됩니다.Expand 아키텍처 이름 현재의 64비트 Intel 및 AMD
x86_64
64비트 ARM
aarch64
IBM POWER
ppc64le
64-bit IBM Z
s390x
1.2. 애플리케이션 버전 관리를 위해 설정 링크 복사링크가 클립보드에 복사되었습니다!
효과적인 버전 제어는 모든 멀티 개발자 프로젝트에 필수적입니다. Red Hat Enterprise Linux에는 분산 버전 제어 시스템인 Git이 포함되어 있습니다.
프로세스
git패키지를 설치합니다.# dnf install git선택 사항: Git 커밋과 연결된 전체 이름을 설정합니다.
$ git config --global user.name "Full_Name"선택 사항: Git 커밋과 연결된 이메일 주소를 설정합니다.
$ git config --global user.email "email@example.com"전체 이름과 email@example.com 을 이름 및 이메일 주소로 바꿉니다.
선택 사항: Git에서 시작한 기본 텍스트 편집기를 변경하려면
core.editor구성 옵션의 값을 설정합니다.$ git config --global core.editor command명령을 선택한 텍스트 편집기를 시작하는 데 사용할 명령으로 교체합니다.
1.3. C 및 C++를 사용하여 애플리케이션을 개발하도록 설정 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux에는 C 및 C++ 애플리케이션 생성 도구가 포함되어 있습니다.
사전 요구 사항
- 디버그 및 소스 리포지토리를 활성화해야 합니다.
프로세스
GNU 컴파일러 컬렉션(GCC), GNU Debugger(GDB) 및 기타 개발 툴을 포함한 개발 도구 패키지 그룹을 설치합니다.
# dnf group install "Development Tools"clang컴파일러 및lld링커를 포함하여 LLVM 기반 툴체인을 설치합니다.# dnf install llvm-toolset선택 사항: Fortran 종속 항목의 경우 GNU Fortran 컴파일러를 설치합니다.
# dnf install gcc-gfortran
1.4. 애플리케이션 디버그로 설정 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux는 여러 디버깅 및 조정 툴을 제공하여 내부 애플리케이션 동작을 분석하고 문제를 해결합니다.
사전 요구 사항
- debug 및 source 리포지토리가 활성화되어 있습니다.
프로세스
디버깅을 위한 툴을 설치합니다.
# dnf install gdb valgrind systemtap ltrace stracedebuginfo-install툴을 사용하려면dnf-utils패키지를 설치합니다.# dnf install dnf-utils환경을 설정하기 위해 SystemTap 도우미 스크립트를 실행합니다.
# stap-prepstap-prep은 현재 실행 중인 커널과 관련된 패키지를 설치합니다. 이 패키지는 설치된 커널과 동일하지 않을 수 있습니다.stap-prep이 올바른kernel-debuginfo및kernel-headers패키지를 설치하려면uname -r명령을 사용하여 현재 커널 버전을 다시 확인하고 필요한 경우 시스템을 재부팅합니다.SELinux정책으로 인해 관련 애플리케이션이 정상적으로 실행될 수 있을 뿐만 아니라 디버깅 상황에서도 실행할 수 있습니다. 자세한 내용은 SELinux 사용을 참조하십시오.
추가 리소스
1.5. 애플리케이션 성능을 측정하도록 설정 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux에는 개발자가 애플리케이션 성능 손실의 원인을 식별하는 데 도움이 되는 여러 애플리케이션이 포함되어 있습니다.
사전 요구 사항
- debug 및 source 리포지토리가 활성화되어 있습니다.
프로세스
성능 측정을 위한 툴을 설치합니다.
# dnf install perf papi pcp-zeroconf valgrind strace sysstat systemtap환경 설정을 위해 SystemTap 도우미 스크립트를 실행합니다.
# stap-prepstap-prep 은 현재 실행 중인 커널과 관련된 패키지를 설치합니다. 이 패키지는 설치된 커널과 동일하지 않을 수 있습니다. stap-prep 이 올바른 kernel-debuginfo 및 kernel-headers 패키지를 설치하려면
uname -r명령을 사용하여 현재 커널 버전을 다시 확인하고 필요한 경우 시스템을 재부팅합니다.PCP(Performance Co- Cryostat) 수집기 서비스를 활성화하고 시작합니다.
# systemctl enable pmcd && systemctl start pmcd
2장. C 또는 C++ 애플리케이션 생성 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat은 C 및 C++ 언어를 사용하여 애플리케이션을 생성하는 데 필요한 여러 툴을 제공합니다. 이 섹션에는 가장 일반적인 개발 작업 중 일부가 나열되어 있습니다.
2.1. RHEL 10의 gcc 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux 10은 GCC 14를 표준 컴파일러로 제공합니다.
GCC 14의 기본 언어 표준 설정은 C++17입니다. 이는 명령줄 옵션 -std=gnu++17 을 명시적으로 사용하는 것과 동일합니다.
C++20 등과 같은 이후 언어 표준에서는 이러한 이후 언어 표준에 도입된 라이브러리 기능은 실험적으로 유지됩니다.
2.2. GCC를 사용하여 코드 빌드 링크 복사링크가 클립보드에 복사되었습니다!
소스 코드를 실행 코드로 변환해야 하는 상황에 대해 알아봅니다.
2.2.1. 코드 양식 간 관계 링크 복사링크가 클립보드에 복사되었습니다!
C 및 C++ 언어에는 빌드 프로세스의 다양한 단계를 통해 생성되는 세 가지 형태의 코드가 있습니다. 이러한 관계를 이해하면 GCC에서 효과적으로 작업할 수 있습니다.
C 및 C++ 언어에는 세 가지 형태의 코드가 있습니다.
C 또는 C++ 언어로 작성된 소스 코드 는 일반 텍스트 파일로 제공됩니다.
파일은 일반적으로
.c.cc,.cpp,.h,.i.i와 같은 확장자를사용합니다.지원되는 확장 기능 및 해석의 전체 목록은 gcc 매뉴얼 페이지를 참조하십시오.$ man gcc컴파일러로 소스 코드를 컴파일 하여 생성된 개체 코드입니다. 이는 중간 형식입니다.
오브젝트 코드 파일은
.o확장자를 사용합니다.개체 코드를 링커 와 연결하여 생성된 실행 코드 .
Linux 애플리케이션 실행 파일은 파일 이름 확장자를 사용하지 않습니다. 공유 오브젝트( Cryostat) 실행 파일은
.so파일 이름 확장자를 사용합니다.
정적 연결을 위한 라이브러리 아카이브 파일도 있습니다. 이는 .a 파일 이름 확장을 사용하는 오브젝트 코드의 변형입니다. 정적 연결은 권장되지 않습니다. 정적 및 동적 연결을 참조하십시오.
소스 코드에서 실행 가능한 코드를 생성하는 작업은 다음 두 단계로 수행되며, 이 단계는 다른 애플리케이션 또는 툴이 필요합니다.
- 소스 파일은 오브젝트 파일로 컴파일됩니다.
- 오브젝트 파일 및 라이브러리가 연결되어 있습니다(이전의 컴파일된 소스 포함).
GCC는 컴파일러와 링커 둘 다에 대한 지능형 드라이버로 사용할 수 있습니다. 이를 통해 필요한 작업(컴파일 및 연결)에 대해 단일 gcc 명령을 사용할 수 있습니다. GCC는 작업 및 해당 시퀀스를 자동으로 선택합니다.
GCC를 실행하여만 컴파일하거나 링크만 실행하거나 두 단계를 수행할 수 있습니다. 이는 입력 유형 및 요청된 출력 유형에 따라 결정됩니다.
대규모 프로젝트에는 일반적으로 각 작업을 위해 GCC를 별도로 실행하는 빌드 시스템이 필요하므로 GCC가 동시에 수행할 수 있더라도 컴파일 및 연결을 두 가지 작업으로 사용하는 것이 좋습니다.
2.2.2. 소스 파일을 오브젝트 코드로 컴파일 링크 복사링크가 클립보드에 복사되었습니다!
즉시 실행 파일이 아닌 소스 파일에서 오브젝트 코드 파일을 생성하려면 GCC에 오브젝트 코드 파일만 출력으로 생성하도록 지시해야 합니다. 이 작업은 대규모 프로젝트의 빌드 프로세스의 기본 작업을 나타냅니다.
사전 요구 사항
- C 또는 C++ 소스 코드 파일
- GCC가 시스템에 설치되어 있음
프로세스
- 터미널에서 소스 코드 파일이 포함된 디렉터리에 대해 엽니다.
-c옵션을 사용하여gcc를 실행합니다.$ gcc -c source.c another_source.c오브젝트 파일은 원래 소스 코드 파일을 반영하는 파일 이름으로 생성됩니다.
source.c결과는source.o입니다.참고C++ 소스 코드를 사용하면 C++ 표준 라이브러리 종속성을 편리하게 처리하기 위해
gcc명령을g++로 바꿉니다.
2.2.3. GCC를 사용하여 C 및 C++ 애플리케이션 디버깅 활성화 링크 복사링크가 클립보드에 복사되었습니다!
컴파일러는 바이너리를 작게 유지하기 위해 기본적으로 디버그 정보를 생략합니다. C 및 C++ 애플리케이션을 디버깅할 수 있도록 하려면 컴파일러에 디버깅 데이터를 생성하도록 명시적으로 지시해야 합니다.
프로세스
C 또는 C++ 애플리케이션을 GCC로 컴파일하고 연결할 때 디버깅 정보를 생성하려면 컴파일 명령에
-g옵션을 추가합니다.$ gcc ... -g ...이 옵션은 GCC에 출력 바이너리에 디버그 정보를 포함하도록 지시합니다.
-g옵션 및 추가 디버깅 옵션에 대한 자세한 내용은 GCC 매뉴얼 페이지를 참조하십시오.디버그 정보에 매크로 정의를 포함하려면 -g 대신
옵션을 사용합니다.-g3$ gcc ... -g3 ...디버그 옵션이 실행 코드에 영향을 미치지 않는지 테스트하려면
-fcompare-debugGCC 옵션을 사용합니다. 이 옵션은 다음과 같습니다.- 디버그 정보를 사용하여 한 번 코드를 두 번 컴파일합니다.
- 생성된 바이너리 파일 비교
두 바이너리가 동일한 경우 테스트를 통과합니다.
이 테스트에서는 디버깅 옵션이 코드에 숨겨진 버그를 도입하지 않도록 합니다.
-fcompare-debug를 사용하면 컴파일 시간이 크게 증가합니다. 자세한 내용은 GCC 매뉴얼 페이지를 참조하십시오.중요컴파일러 및 링커 최적화는 다음을 통해 디버깅을 어렵게 만들 수 있습니다. * 사용되지 않는 것으로 표시되는 변수 제거 * 루프 병합 * 작업 병합 * 소스 코드와 실행 코드 간의 관계 변경
디버깅 환경을 개선하려면
-Og옵션을 사용하는 것이 좋습니다. 그러나 최적화 수준을 변경하면 실행 코드 동작을 변경하고 잠재적으로 버그를 숨길 수 있습니다.
2.2.4. GCC를 사용한 코드 최적화 링크 복사링크가 클립보드에 복사되었습니다!
단일 프로그램은 하나 이상의 일련의 머신 명령으로 변환될 수 있습니다. 컴파일 중에 코드를 분석하는 데 더 많은 리소스를 할당하면 최적의 결과를 얻을 수 있습니다.
GCC를 사용하면 -O 수준 옵션을 사용하여 최적화 수준을 설정할 수 있습니다. 이 옵션은 수준 대신 값 집합을 허용합니다.
| level | 설명 |
|---|---|
|
| 컴파일 속도를 최적화 - 코드 최적화(기본값) 없음. |
|
| 코드 실행 속도를 높이기 위해 최적화합니다(숫자가 클수록 속도가 커집니다). |
|
| 파일 크기에 맞게 최적화합니다. |
|
|
레벨 |
|
| 디버깅 환경을 위해 최적화합니다. |
릴리스 빌드의 경우 최적화 옵션 -O2 를 사용합니다.
개발 중에 -Og 옵션은 일부 상황에서 프로그램 또는 라이브러리를 디버깅하는 데 유용합니다. 일부 버그는 특정 최적화 수준에서만 표시되므로 릴리스 최적화 수준으로 프로그램 또는 라이브러리를 테스트합니다.
GCC는 개별 최적화를 활성화하는 다양한 옵션을 제공합니다. 자세한 내용은 gcc 도움말 페이지를 참조하십시오.
2.2.5. GCC를 사용하여 코드 강화 옵션 링크 복사링크가 클립보드에 복사되었습니다!
컴파일러가 소스 코드를 개체 코드로 변환하면 일반적으로 악용되는 상황을 방지하고 보안을 강화하기 위해 다양한 검사를 추가할 수 있습니다. 올바른 컴파일러 옵션 집합을 선택하면 소스 코드를 변경하지 않고도 더 안전한 프로그램 및 라이브러리를 생성하는 데 도움이 될 수 있습니다.
- 릴리스 버전 옵션
다음 옵션 목록은 Red Hat Enterprise Linux를 대상으로 하는 개발자에게 권장됩니다.
$ gcc ... -O2 -g -Wall -Wl,-z,now,-z,relro -fstack-protector-strong -fstack-clash-protection -D_FORTIFY_SOURCE=3 ...-
프로그램의 경우
-fPIE및-pieWITH independent Executable 옵션을 추가합니다. -
동적으로 연결된 라이브러리의 경우 필수
-fPIC(Independent Code) 옵션을 통해 보안이 간접적으로 증가합니다.
-
프로그램의 경우
- 개발 옵션
다음 옵션을 사용하여 개발 중에 보안 결함을 탐지합니다. 릴리스 버전의 옵션과 함께 이러한 옵션을 사용합니다.
$ gcc ... -Walloc-zero -Walloca-larger-than -Wextra -Wformat-security -Wvla-larger-than ...- -
fhardened -
GCC 14는 새로운 플래그인
-fhardened를 제공하여 ABI에 영향을 주지 않고 생성된 코드의 보안을 개선할 수 있는 여러 다른 플래그를 사용할 수 있습니다. - -
Falyzer -
GCC는 보안 관련 문제를 포함하여 소스 코드의 잠재적인 문제에 대한 경고를 트리거하는
-fanalyzer플래그를 제공합니다.-fanalyzer는 종종 잘못된 긍정 및 음수를 가지고 있기 때문에 공식적인 분석 도구가 아닌 더 많이 조사해야하는 잠재적 버그를 찾는 데 사용해야합니다. 이 플래그는 컴파일 중에 사용된 시간과 메모리를 크게 늘립니다. C 코드에서만 사용하십시오.
2.2.6. 실행 파일을 생성하기 위해 코드 연결 링크 복사링크가 클립보드에 복사되었습니다!
링크는 C 또는 C++ 애플리케이션을 빌드할 때 최종 단계입니다. 링크는 모든 오브젝트 파일 및 라이브러리를 실행 파일로 결합합니다.
사전 요구 사항
- 하나 이상의 오브젝트 파일
- gcc가 시스템에 설치되어 있어야 함
프로세스
- 오브젝트 코드 파일이 포함된 디렉터리로 변경합니다.
run
gcc:$ gcc ... objfile.o another_object.o ... -o executable-fileexecutable-file 이라는 실행 파일은 제공된 오브젝트 파일 및 라이브러리에서 생성됩니다. 추가 라이브러리를 연결하려면 오브젝트 파일 목록 뒤에 필요한 옵션을 추가합니다.
자세한 내용은 GCC에서 라이브러리 사용을 참조하십시오.
참고C++ 소스 코드를 사용하면 C++ 표준 라이브러리 종속성을 편리하게 처리하기 위해
gcc명령을g++로 바꿉니다.
추가 리소스
2.2.7. 예: GCC를 사용하여 C 프로그램 빌드(단일 단계로 컴파일 및 연결) 링크 복사링크가 클립보드에 복사되었습니다!
이 예제에서는 간단한 예제 C 프로그램을 빌드하는 정확한 단계를 보여줍니다.
이 예제에서는 코드를 컴파일하고 연결하는 것은 한 단계로 수행됩니다.
프로세스
hello-c디렉토리를 생성합니다.$ mkdir hello-c생성된 디렉터리로 변경합니다.
$ cd hello-c다음 콘텐츠를 사용하여
hello.c파일을 생성합니다.#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }코드를 컴파일하고 GCC에 연결합니다.
$ gcc hello.c -o helloworld이렇게 하면 코드를 컴파일하고 개체 파일
hello.o.o를 만들고 개체 파일에서 실행 파일helloworld를 연결합니다.결과 실행 파일을 실행합니다.
$ ./helloworldHello, World!
추가 리소스
2.2.8. 예: GCC를 사용하여 C 프로그램 빌드( 두 단계로 컴파일 및 연결) 링크 복사링크가 클립보드에 복사되었습니다!
이 예제에서는 간단한 예제 C 프로그램을 빌드하는 정확한 단계를 보여줍니다.
이 예제에서 코드를 컴파일하고 연결하는 것은 두 가지 별도의 단계입니다.
프로세스
hello-c디렉토리를 생성합니다.$ mkdir hello-c생성된 디렉터리로 변경합니다.
$ cd hello-c다음 콘텐츠를 사용하여
hello.c파일을 생성합니다.#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }GCC를 사용하여 코드를 컴파일합니다.
$ gcc -c hello.c오브젝트 파일
hello.o가 생성됩니다.오브젝트 파일에서 실행 가능한 파일
helloworld를 연결합니다.$ gcc hello.o -o helloworld결과 실행 파일을 실행합니다.
$ ./helloworld Hello, World!선택 사항: 상위 디렉터리로 다시 변경합니다.
$ cd ..선택 사항:
hello-c디렉터리를 제거합니다.$ rm -r hello-c
추가 리소스
2.2.9. 예: GCC를 사용하여 C++ 프로그램 빌드(단 단계로 컴파일 및 연결) 링크 복사링크가 클립보드에 복사되었습니다!
이 예제에서는 샘플 최소 C++ 프로그램을 빌드하는 정확한 단계를 보여줍니다.
이 예제에서는 코드를 컴파일하고 연결하는 것은 한 단계로 수행됩니다.
프로세스
hello-cpp디렉토리를 생성합니다.$ mkdir hello-cpp생성된 디렉터리로 변경합니다.
$ cd hello-cpp다음 콘텐츠를 사용하여
hello.cpp파일을 생성합니다.#include <iostream> int main() { std::cout << "Hello, World!\n"; return 0; }코드를 컴파일하고
g++로 연결합니다.$ g++ hello.cpp -o helloworld이렇게 하면 코드를 컴파일하고 개체 파일
hello.o.o를 만들고 개체 파일에서 실행 파일helloworld를 연결합니다.결과 실행 파일을 실행합니다.
$ ./helloworldHello, World!선택 사항: 상위 디렉터리로 다시 변경합니다.
$ cd ..선택 사항:
hello-cpp디렉터리를 제거합니다.$ rm -r hello-cpp
2.2.10. 예: GCC를 사용하여 C++ 프로그램 빌드( 두 단계로 컴파일 및 연결) 링크 복사링크가 클립보드에 복사되었습니다!
이 예제에서는 샘플 최소 C++ 프로그램을 빌드하는 정확한 단계를 보여줍니다.
이 예제에서 코드를 컴파일하고 연결하는 것은 두 가지 별도의 단계입니다.
프로세스
hello-cpp디렉토리를 생성합니다.$ mkdir hello-cpp생성된 디렉터리로 변경합니다.
$ cd hello-cpp다음 콘텐츠를 사용하여
hello.cpp파일을 생성합니다.#include <iostream> int main() { std::cout << "Hello, World!\n"; return 0; }g++로 코드를 컴파일합니다.$ g++ -c hello.cpp오브젝트 파일
hello.o가 생성됩니다.오브젝트 파일에서 실행 가능한 파일
helloworld를 연결합니다.$ g++ hello.o -o helloworld결과 실행 파일을 실행합니다.
$ ./helloworldHello, World!선택 사항: 상위 디렉터리로 다시 변경합니다.
$ cd ..선택 사항:
hello-cpp디렉터리를 제거합니다.$ rm -r hello-cpp
2.3. GCC에서 라이브러리 사용 링크 복사링크가 클립보드에 복사되었습니다!
코드에서 라이브러리 사용에 대해 알아봅니다.
2.3.1. 라이브러리 이름 지정 규칙 링크 복사링크가 클립보드에 복사되었습니다!
특수 파일 이름 규칙은 라이브러리에 사용됩니다. foo라는 라이브러리는 lib foo .so 또는 파일로 존재할 것으로 예상됩니다. 이 규칙은 GCC의 입력 옵션을 연결하지만 출력 옵션에 의해 자동으로 이해되지 않습니다.
libfoo . a
라이브러리에 대해 연결할 때 -lfoo:
-l옵션을 사용하여 foo 라는 이름으로만 라이브러리를 지정할 수 있습니다.$ gcc ... -lfoo ...-
라이브러리를 생성할 때 전체 파일 이름
libfoo.so또는libfoo.a를지정해야 합니다.
추가 리소스
2.3.2. 정적 및 동적 연결 링크 복사링크가 클립보드에 복사되었습니다!
개발자는 완전히 컴파일된 언어로 애플리케이션을 빌드할 때 정적 또는 동적 링크를 사용할 수 있습니다. 특히 Red Hat Enterprise Linux에서 C 및 C++ 언어 사용의 맥락에서 정적 연결과 동적 연결의 차이점을 이해하는 것이 중요합니다. 요약하면 Red Hat은 Red Hat Enterprise Linux용 애플리케이션에서 정적 링크를 사용하지 않는 것이 좋습니다.
- 정적 연결 및 동적 연결 비교
- 정적 링크를 사용하면 라이브러리가 결과 실행 파일의 일부가 됩니다. 동적 링크는 이러한 라이브러리를 별도의 파일로 유지합니다.
정적 연결에는 여러 가지 단점이 있으며 특히 전체 애플리케이션 및 glibc 및 libstdc++ 라이브러리의 경우 피해야 합니다.
resource use: 정적 연결로 인해 더 큰 실행 파일이 더 많은 코드가 포함됩니다. 라이브러리에서 제공되는 이 추가 코드는 시스템의 여러 프로그램에서 공유할 수 없으므로 런타임 시 파일 시스템 사용량과 메모리 사용량을 늘릴 수 있습니다. 동일한 정적으로 연결된 프로그램을 실행하는 여러 프로세스가 여전히 코드를 공유합니다.
반면 정적 애플리케이션에는 더 적은 런타임 재배치가 필요하므로 시작 시간을 단축하고 개인 상주 설정 크기(RSS) 메모리가 줄어듭니다. 정적 연결을 위한 생성된 코드는 위치 독립 코드(PIC)에 의해 도입된 오버헤드로 인해 동적 연결을 위한 것보다 더 효율적일 수 있습니다.
보안: ABI 호환성을 제공하는 동적 링크 라이브러리는 이러한 라이브러리에 따라 실행 파일을 변경하지 않고도 업데이트할 수 있습니다. 이는 Red Hat이 보안 업데이트를 제공하는 Red Hat Enterprise Linux의 일부로 Red Hat에서 제공하는 라이브러리에서 특히 중요합니다. 이러한 라이브러리에 대한 정적 연결은 권장되지 않습니다.
호환성: 정적 연결은 운영 체제에서 제공하는 라이브러리 버전과 관계없이 실행 파일을 제공하는 것으로 보입니다. 그러나 대부분의 라이브러리는 다른 라이브러리에 의존합니다. 정적 연결을 사용하면 이 종속성은 유연성이 떨어지고 결과적으로 앞으로 및 이전 버전과의 호환성이 모두 손실됩니다. 정적 연결은 실행 파일이 빌드된 시스템에서만 작동하도록 보장됩니다.
GNU C 라이브러리(glibc)의 정적 라이브러리를 연결하는 애플리케이션은 여전히 동적 라이브러리로 시스템에 glibc 가 있어야 합니다. 또한 애플리케이션 실행 시 사용 가능한 glibc 의 동적 라이브러리 변형은 애플리케이션을 연결하는 동안 존재하는 것과 약간 동일한 버전이어야 합니다. 결과적으로 정적 연결은 실행 파일이 빌드된 시스템에서만 작동하도록 보장됩니다.
지원 범위: Red Hat에서 제공하는 대부분의 정적 라이브러리는 CodeReady Linux Builder 채널에 있으며 Red Hat에서 지원하지 않습니다.
기능: 일부 라이브러리, 특히 GNU C 라이브러리(glibc)는 정적으로 연결된 경우 기능 감소를 제공합니다.
예를 들어 정적으로 연결된 경우 glibc 는 동일한 프로그램에서 dlopen() 함수에 대한 스레드 및 모든 형태의 호출을 지원하지 않습니다.
- 정적 연결 사례
정적 연결은 다음과 같은 경우에 합리적인 선택일 수 있습니다.
- 동적 연결에 사용할 수 없는 라이브러리를 사용하는 경우
-
빈 chroot 환경 또는 컨테이너에서 코드를 실행하는 데 완전히 정적 링크가 필요한 경우입니다. 그러나
glibc-static패키지를 사용한 정적 연결은 Red Hat에서 지원되지 않습니다.
2.3.3. 링크 시간 최적화 링크 복사링크가 클립보드에 복사되었습니다!
LTO(링크 시간 최적화)는 다음과 같은 이점이 있습니다.
- LTO를 사용하면 컴파일러가 링크 타임에 중간 표현을 사용하여 프로그램의 모든 변환 단위에서 다양한 최적화를 수행할 수 있습니다. 결과적으로 실행 파일과 라이브러리가 작아서 더 빨리 실행됩니다.
LTO를 사용하여 컴파일 시간에 패키지 소스 코드를 보다 철저하게 분석할 수 있으므로 잠재적인 코딩 오류에 대한 다양한 GCC 진단이 향상됩니다.
- 확인된 문제
- LTO에는 다음과 같은 알려진 문제가 있습니다.
하나의 정의 규칙(ODR)을 위반하면
-Wodr경고가 생성됩니다.ODR을 위반하면 정의되지 않은 동작이 발생하면
-Wodr경고가 생성됩니다. 이는 일반적으로 프로그램의 버그를 가리킵니다.-Wodr경고는 기본적으로 활성화되어 있습니다.LTO로 인해 메모리 사용량 증가
컴파일러는 프로그램이 구성된 변환 단위를 처리할 때 더 많은 메모리를 사용합니다. 프로그램이 제한된 시스템에서 LTO를 비활성화하거나 병렬 처리 수준을 낮춥니다.
GCC가 사용되지 않는 기능 제거
GCC는 컴파일러가 asm() 문을 참조하는 기호를 인식할 수 없기 때문에 사용되지 않는 함수를 제거할 수 있습니다. 이로 인해 컴파일 오류가 발생할 수 있습니다. 이를 방지하려면 프로그램에서 사용하는 기호에
__attribute__(used)를 추가합니다.-fPIC옵션으로 컴파일하면 오류가 발생합니다.GCC는 asm() 문의 내용을 구문 분석하지 않으므로 코드를
-fPIC명령줄 옵션으로 컴파일하면 오류가 발생할 수 있습니다. 이를 방지하려면 변환 단위를 컴파일할 때-fno-lto옵션을 사용합니다. 자세한 내용은 LTO FAQ {mdash}; 어셈블리 언어의 Symbol에서 확인할 수 있습니다.asm() 문에서
.symver지시문을 사용하여 기호 버전 관리를 구현하는 것은 LTO와 호환되지 않습니다. 그러나symver특성을 사용하여 기호 버전 관리를 구현할 수 있습니다. 예를 들면 다음과 같습니다.__attribute__ ((_symver_ ("<symbol>@VERS_1"))) void <symbol>_v1 (void) { }
2.3.4. GCC가 있는 라이브러리 사용 링크 복사링크가 클립보드에 복사되었습니다!
라이브러리는 프로그램에서 재사용할 수 있는 코드의 패키지입니다. C 또는 C++ 라이브러리는 다음 두 부분으로 구성됩니다.
- 라이브러리 코드
헤더 파일
- 라이브러리를 사용하는 코드 컴파일
- 헤더 파일은 라이브러리의 인터페이스, 즉 라이브러리에서 사용할 수 있는 함수 및 변수를 설명합니다. 헤더 파일의 정보는 코드를 컴파일하는 데 필요합니다.
일반적으로 라이브러리의 헤더 파일은 애플리케이션 코드와 다른 디렉터리에 배치됩니다. GCC 헤더 파일이 어디에 있는지 알려주려면 -I 옵션을 사용합니다.
$ gcc ... -Iinclude_path ...
include_path 를 헤더 파일 디렉터리의 실제 경로로 바꿉니다.
예를 들어 상대 경로를 지정하려면 some/interesting/directory:
$ gcc ... -Isome/interesting/directory ...
I 옵션을 여러 번 사용하여 헤더 파일이 있는 여러 디렉터리를 추가할 수 있습니다. 헤더 파일을 찾을 때 이러한 디렉터리는 -I 옵션에 표시되는 순서대로 검색됩니다.
- 라이브러리를 사용하는 코드 연결
실행 파일을 연결할 때 애플리케이션의 오브젝트 코드와 라이브러리의 바이너리 코드를 모두 사용할 수 있어야 합니다. 정적 및 동적 라이브러리의 코드는 다음과 같은 다양한 형태로 제공됩니다.
-
정적 라이브러리는 아카이브 파일로 사용할 수 있습니다. 오브젝트 파일 그룹이 포함되어 있습니다. 아카이브 파일의 확장자는
.a입니다. -
동적 라이브러리는 공유 오브젝트로 사용할 수 있습니다. 이는 일종의 실행 파일입니다. 공유 오브젝트에는 파일 이름 확장자
.so가 있습니다.
-
정적 라이브러리는 아카이브 파일로 사용할 수 있습니다. 오브젝트 파일 그룹이 포함되어 있습니다. 아카이브 파일의 확장자는
GCC에 라이브러리의 아카이브 또는 공유 오브젝트 파일이 어디에 있는지 알려주려면 -L 옵션을 사용합니다.
$ gcc ... -Llibrary_path -lfoo ...
library_path 를 라이브러리 디렉터리의 실제 경로로 바꿉니다.
L 옵션을 여러 번 사용하여 여러 디렉터리를 추가할 수 있습니다. 라이브러리를 찾으면 이러한 디렉터리가 -L 옵션 순서대로 검색됩니다.
옵션 순서는 중요합니다. GCC는 이 라이브러리가 있는 디렉토리를 모르는 한 라이브러리 foo 에 대해 연결할 수 없습니다. 따라서 라이브러리에 연결하는 -l 옵션을 사용하기 전에 -L 옵션을 사용하여 라이브러리 디렉터리를 지정합니다.
- 한 단계에서 라이브러리를 사용하는 코드 컴파일 및 연결
-
단일
gcc명령으로 컴파일 및 링크를 연결하면 컴파일 시간 및 링크 시간 옵션을 결합합니다.
2.3.5. GCC가 있는 정적 라이브러리 사용 링크 복사링크가 클립보드에 복사되었습니다!
정적 라이브러리는 오브젝트 파일이 포함된 아카이브로 사용할 수 있습니다. 연결 후 결과 실행 파일의 일부가 됩니다.
Red Hat은 보안상의 이유로 정적 연결을 사용하지 않는 것이 좋습니다. 정적 및 동적 연결을 참조하십시오. 특히 Red Hat이 제공하는 라이브러리와 관련하여 필요할 때만 정적 링크를 사용하십시오.
사전 요구 사항
- GCC가 시스템에 설치되어 있어야 합니다.
- 정적 및 동적 연결을 이해해야 합니다.
- 유효한 프로그램을 구성하는 소스 또는 오브젝트 파일 세트가 있으므로 일부 정적 라이브러리 foo 와 다른 라이브러리가 필요하지 않습니다.
foo 라이브러리는
libfoo.a파일로 사용할 수 있으며 동적 연결을 위해libfoo.so파일이 제공되지 않습니다.참고Red Hat Enterprise Linux의 일부인 대부분의 라이브러리는 동적 연결에서만 지원됩니다. 아래 단계는 동적 링크에 사용할 수 없는 라이브러리에서만 작동합니다.
프로세스
소스 및 오브젝트 파일에서 프로그램을 연결하려면
lib foo.a파일로 찾을 정적으로 연결된 라이브러리 foo를 추가합니다.- 코드가 포함된 디렉터리로 변경합니다.
foo 라이브러리의 헤더를 사용하여 프로그램 소스 파일을 컴파일합니다.
$ gcc ... -Iheader_path -c ...header_path 를 foo 라이브러리의 헤더 파일이 포함된 디렉터리의 경로로 바꿉니다.
프로그램을 foo 라이브러리와 연결합니다.
$ gcc ... -Llibrary_path -lfoo ...library_path 를
libfoo.a파일이 포함된 디렉터리의 경로로 바꿉니다.나중에 프로그램을 실행하려면 다음을 수행하십시오.
$ ./program주의정적 링크와 관련된
-staticGCC 옵션은 모든 동적 연결을 금지합니다. 대신-Wl,-Bstatic및-Wl,-Bdynamic옵션을 사용하여 링커 동작을 보다 정확하게 제어합니다. GCC에서 정적 및 동적 라이브러리 사용을 참조하십시오.
2.3.6. GCC를 사용하는 동적 라이브러리 사용 링크 복사링크가 클립보드에 복사되었습니다!
동적 라이브러리는 독립 실행형 실행 파일로 사용할 수 있으며, 연결 시간과 런타임에 필요합니다. 애플리케이션의 실행 파일과 무관하게 유지됩니다.
사전 요구 사항
- GCC는 시스템에 설치되어 있어야 합니다.
- 유효한 프로그램을 구성하는 소스 또는 오브젝트 파일 세트에는 일부 동적 라이브러리 foo 및 기타 라이브러리가 필요하지 않습니다.
foo 라이브러리는 libfoo.so 파일로 사용 가능해야 합니다.
- 동적 라이브러리에 대한 프로그램 연결
- 동적 라이브러리 foo 에 대해 프로그램을 연결하려면 다음을 수행합니다.
$ *gcc ... -L__library_path__ -l__foo__ ...*
프로그램이 동적 라이브러리에 연결되어 있는 경우 결과 프로그램은 항상 런타임 시 라이브러리를 로드해야 합니다. 라이브러리를 찾는 방법은 다음 두 가지가 있습니다.
-
실행 파일 자체에 저장된 실행 경로값 사용 런타임에
LD_LIBRARY_PATH변수 사용실행 파일에 저장된 실행 경로값 사용-
실행 경로는연결될 때 실행 파일의 일부로 저장된 특수 값입니다. 나중에 프로그램이 실행 파일에서 로드되면 런타임 링커는실행 경로값을 사용하여 라이브러리 파일을 찾습니다.
GCC 와 연결하는 동안 library_path 를 실행 경로로 저장하기 위해 다음을 수행합니다.
$ gcc ... -Llibrary_path -lfoo -Wl,-run path=library_path ...
path library_path 는 libfoo.so 파일이 포함된 디렉토리를 가리켜야 합니다.
-Wl,-run path= 옵션에 쉼표 뒤에 공백을 추가하지 마십시오.
나중에 프로그램을 실행하려면 다음을 수행합니다.
$ ./program
LD_LIBRARY_PATH환경 변수 사용라이브러리를 찾기 위해 검색 경로를 설정하는 또 다른 방법은
LD_LIBRARY_PATH환경 변수를 사용하는 것입니다. 이 변수의 값은 각 프로그램에 대해 변경해야 합니다. 이 값은 공유 라이브러리 오브젝트가 있는 경로를 나타내며 모든 프로그램 호출에 대해 설정해야 합니다.LD_LIBRARY_PATH환경 변수를 설정합니다.$ export LD_LIBRARY_PATH=library_path:$LD_LIBRARY_PATH프로그램을 실행합니다.
$ ./program
- 실행 경로 및
LD_LIBRARY_PATH의 상호 작용 -
Red Hat Enterprise Linux 10에서 연결 중에 프로그램에 인코딩된
실행 경로는연결된 라이브러리를LD_LIBRARY_PATH에서 찾을 수 없는 경우에만 사용됩니다.LD_LIBRARY_PATH전에 실행 경로가 검색되는 Red Hat Enterprise Linux 10의 이전 동작을 복원하기 위해-Wl,--disable-new-dtags옵션을 사용할 수 있습니다. - 라이브러리가 기본 디렉터리에 배치
- 런타임 링커 구성은 여러 디렉터리를 동적 라이브러리 파일의 기본 위치로 지정합니다. 이 기본 동작을 사용하려면 라이브러리를 적절한 디렉터리에 복사합니다.
이 문서에서는 동적 연결 동작을 자세히 다루지 않습니다. 자세한 내용은 다음 리소스를 참조하십시오.
- 동적 링커에 대한 Linux 도움말 페이지:
$ man ld.so
-
/etc/ld.so.conf구성 파일의 콘텐츠:
$ cat /etc/ld.so.conf
- 추가 구성 없이 동적 링커에서 인식하는 라이브러리의 보고서이며, 여기에는 디렉터리가 포함됩니다.
$ ldconfig -v
2.3.7. GCC에서 정적 및 동적 라이브러리 사용 링크 복사링크가 클립보드에 복사되었습니다!
경우에 따라 일부 라이브러리를 정적 및 기타 라이브러리를 동적으로 연결해야 하는 경우가 있습니다. 이 혼합 연결 접근 방식을 사용하려면 GCC가 다양한 라이브러리 유형을 처리하는 방법을 이해해야 합니다.
GCC 는 동적 라이브러리와 정적 라이브러리를 모두 인식합니다. lfoo 옵션이 발생하면 gcc 는 먼저 foo 라이브러리의 동적으로 연결된 버전이 포함된 공유 오브젝트( .so 파일)를 찾은 다음 라이브러리의 정적 버전이 포함된 아카이브 파일(.a)을 찾습니다. 따라서 이 검색으로 인해 다음과 같은 상황이 발생할 수 있습니다.
- 공유 오브젝트만 발견되고 gcc 만 동적으로 연결됩니다.
- 아카이브만 발견되고 gcc 만 정적으로 연결됩니다.
- 공유 오브젝트와 아카이브가 모두 있으며 기본적으로 gcc 는 공유 오브젝트에 대한 동적 연결을 선택합니다.
- 공유 오브젝트 또는 아카이브를 찾을 수 없으며 연결에 실패합니다.
이러한 규칙으로 인해 연결을 위한 정적 또는 동적 라이브러리 버전을 선택하는 가장 좋은 방법은 gcc 에서 해당 버전만 찾는 것입니다. 이는 -L경로 옵션을 지정할 때 라이브러리 버전이 포함된 디렉터리를 사용하거나 남겨 두어 어느 정도 제어할 수 있습니다.
또한 동적 링크가 기본값이므로 두 버전이 모두 있는 라이브러리를 정적으로 연결해야 하는 유일한 상황은 링크에서 명시적으로 지정해야 합니다. 두 가지 가능한 해결 방법이 있습니다.
-
-l옵션 대신 파일 경로별 정적 라이브러리 지정 링커에 옵션을 전달하려면
-Wl옵션 사용- 파일별 정적 라이브러리 지정
-
일반적으로 gcc 는 foo 라이브러리에 대해
-lfoo옵션을 사용하여 연결하라는 지시를 받습니다. 그러나 대신 라이브러리를 포함하는libfoo.a파일의 전체 경로를 지정할 수 있습니다.
$ *gcc ... path/to/libfoo.a ...*
파일 확장자 .a 에서gcc 는 프로그램과 연결할 라이브러리임을 이해할 것입니다. 그러나 라이브러리 파일의 전체 경로를 지정하는 것은 덜 유연합니다.
Wl옵션 사용-
gcc 옵션
-Wl은 옵션을 기본 링커에 전달하는 특수 옵션입니다. 이 옵션의 구문은 다른 gcc 옵션과 다릅니다. wl옵션 뒤에는 쉼표로 구분된 링커 옵션 목록이 있고 다른 gcc 옵션에는 공백으로 구분된 옵션 목록이 필요합니다.
gcc 에서 사용하는 ld 링커는 이 옵션의 라이브러리를 정적으로 연결하는 -Bstatic 옵션과 -Bdynamic 을 제공하여 동적으로 연결합니다. Bstatic 및 라이브러리를 링커에 전달한 후에는 다음 라이브러리가 옵션과 동적으로 연결되도록 기본 동적 연결 동작을 수동으로 복원해야 합니다.
-B dynamic
프로그램을 연결하려면 먼저 정적(lib first.a) 및 두 번째 동적으로(lib second.so ) 링크 라이브러리를 연결합니다.
$ gcc ... -Wl,-Bstatic -lfirst -Wl,-Bdynamic -lsecond ...
GCC 는 기본 ld 이외의 링커를 사용하도록 구성할 수 있습니다.
2.4. GCC를 사용하여 라이브러리 생성 링크 복사링크가 클립보드에 복사되었습니다!
라이브러리를 생성하는 단계와 Linux 운영 체제에서 라이브러리에 사용하는 필수 개념에 대해 알아봅니다. 또한 라이브러리에 사용되는 특수 파일 이름 규칙을 알아야 합니다. 2.3.1절. “라이브러리 이름 지정 규칙”을 참조하십시오.
2.4.1. soname 메커니즘 링크 복사링크가 클립보드에 복사되었습니다!
동적으로 로드된 라이브러리(공유 오브젝트)는 soname 이라는 메커니즘을 사용하여 여러 호환 가능한 라이브러리 버전을 관리합니다. 이 개념을 이해하려면 다음을 수행하십시오.
- 동적 연결 및 라이브러리를 이해해야 합니다.
- ABI 호환성의 개념을 이해해야 합니다.
- 라이브러리 이름 지정 규칙을 이해해야 합니다.
심볼릭 링크를 이해해야 합니다.
- 문제 도입
- 동적으로 로드된 라이브러리(공유 오브젝트)는 독립적인 실행 파일로 존재합니다. 이렇게 하면 종속된 애플리케이션을 업데이트하지 않고 라이브러리를 업데이트할 수 있습니다. 그러나 이 개념에서는 다음과 같은 문제가 발생합니다.
- 라이브러리의 실제 버전 확인
- 동일한 라이브러리의 여러 버전이 필요
여러 버전의 각 ABI 호환성
- soname 메커니즘
- 이를 해결하기 위해 Linux는 soname이라는 메커니즘을 사용합니다.
foo 라이브러리 버전 X.Y 는 버전 번호에서 동일한 X 값을 가진 다른 버전과 호환됩니다. 호환성을 유지하는 사소한 변경으로 인해 Y 수가 증가합니다. 주요 변경으로 인해 호환성이 증가하여 X 가 증가합니다.
실제 foo 라이브러리 버전 X.Y 는 libfoo.so.x.y 파일로 존재합니다. 라이브러리 파일 내부에서 soname은 libfoo.so.x 값으로 기록되어 호환성을 알립니다.
빌드 중에 링커는 라이브러리 파일을 가리키는 libfoo.so 라는 심볼릭 링크를 검색합니다. 이 이름의 심볼릭 링크가 있어야 실제 라이브러리 파일을 가리킵니다. 그런 다음 링커는 라이브러리 파일에서 soname을 읽고 애플리케이션 실행 파일에 기록합니다. 마지막으로 링커는 이름 또는 파일 이름이 아닌 soname을 사용하여 라이브러리에 대한 종속성을 선언하는 애플리케이션을 생성합니다.
런타임 동적 링커가 실행하기 전에 애플리케이션을 연결하면 애플리케이션의 실행 파일에서 soname을 읽습니다. 이 soname은 libfoo.so.x 입니다. 이 이름의 심볼릭 링크가 있어야 실제 라이브러리 파일을 가리킵니다. 이렇게 하면 soname이 변경되지 않기 때문에 버전의 Y 구성 요소와 관계없이 라이브러리를 로드할 수 있습니다.
버전 번호의 Y 구성 요소는 단일 수에만 국한되지 않습니다. 또한 일부 라이브러리는 해당 버전을 이름으로 인코딩합니다.
- 파일에서 soname 읽기
라이브러리 파일의 이름을 표시하려면
some Cryostat:$ objdump -p somelibrary | grep SONAME
일부 Cryostat 를 검사하려는 라이브러리의 실제 파일 이름으로 교체합니다.
- 파일 이름에서 라이브러리 이름 및 버전 찾기
예를 들어
libevent-2.0.so.5.1.9파일로 존재하는 라이브러리를 고려해 보십시오. 실제 구성 요소를 찾으려면 다음을 수행합니다.-
먼저 표준 라이브러리 파일 이름 접두사
lib를 무시하고 시작합니다. -
나머지 부분을 앞의 두 부분으로 나누고
.so.문자열 뒤에 나머지 부분을 나눕니다. -
첫 번째 부분은 라이브러리의 이름인
event-2.0입니다. -
두 번째 부분은
5.1.9입니다. X 버전 구성 요소를 찾으려면 첫 번째 점:5이전의 모든 것을 가져 가십시오. -
나머지 요소는 Y 버전 구성 요소
1.9입니다.
-
먼저 표준 라이브러리 파일 이름 접두사
따라서 라이브러리의 이름은 event-2.0 이고 X 버전 구성 요소는 5이고 Y 는 1.9입니다.
이 라이브러리 파일의 이름은 모든 Y 구성 요소인 libevent-2.0.so.5 까지입니다.
최신 버전이지만 호환되는 라이브러리 버전이 릴리스되면 동일한 soname을 사용하고 Y 버전 구성 요소가 증가합니다. 새 파일 이름은 libevent-2.0.so.5.1.10 입니다.
2.4.2. GCC를 사용하여 동적 라이브러리 생성 링크 복사링크가 클립보드에 복사되었습니다!
동적으로 연결된 라이브러리(공유 오브젝트)를 사용하면 다음을 수행할 수 있습니다.
- 코드 재사용을 통한 리소스 보존
- 라이브러리 코드를 쉽게 업데이트하여 보안 향상
다음 단계에 따라 소스에서 동적 라이브러리를 빌드하고 설치합니다.
사전 요구 사항
- soname 메커니즘을 이해해야 합니다.
- GCC는 시스템에 설치되어 있어야 합니다.
- 라이브러리의 소스 코드가 있어야 합니다.
프로세스
- 라이브러리 소스가 있는 디렉터리로 변경합니다.
독립적인 코드 옵션
-fPIC을 사용하여 각 소스 파일을 오브젝트 파일로 컴파일합니다.$ gcc ... -c -fPIC some_file.c ...오브젝트 파일의 이름은 원래 소스 코드 파일과 동일하지만 확장자는
.o입니다.오브젝트 파일에서 공유 라이브러리를 연결합니다.
$ gcc -shared -o libfoo.so.x.y -Wl,-soname,libfoo.so.x some_file.o ...사용되는 주요 버전 번호는 X 및 마이너 버전 번호 Y입니다.
libfoo.so.x.y파일을 시스템의 동적 링커가 찾을 수 있는 적절한 위치에 복사합니다. Red Hat Enterprise Linux에서 라이브러리용 디렉터리는/usr/lib64입니다.# cp libfoo.so.x.y /usr/lib64이 디렉터리의 파일을 조작하려면 root 권한이 필요합니다.
soname에 대한 심볼릭 링크를 생성합니다.
# ln -s libfoo.so.x.y libfoo.so.x링커 이름에 대한 심볼릭 링크를 생성합니다.
# ln -s libfoo.so.x libfoo.so
추가 리소스
2.4.3. GCC 및 ar를 사용하여 정적 라이브러리 생성 링크 복사링크가 클립보드에 복사되었습니다!
오브젝트 파일을 특별한 유형의 아카이브 파일로 변환하면 정적 연결을 위한 라이브러리를 생성할 수 있습니다.
Red Hat은 보안상의 이유로 정적 링크를 사용하지 않습니다. 특히 Red Hat이 제공하는 라이브러리와 관련하여 필요할 때만 정적 링크를 사용하십시오. 자세한 내용은 정적 및 동적 연결을 참조하십시오.
사전 요구 사항
- GCC 및 binutils가 시스템에 설치되어 있어야 합니다.
- 정적 및 동적 연결을 이해해야 합니다.
- 라이브러리로 공유할 함수가 있는 소스 파일을 사용할 수 있습니다.
프로세스
GCC를 사용하여 중간 오브젝트 파일을 생성합니다.
$ gcc -c source_file.c ...필요한 경우 소스 파일을 더 추가합니다. 결과 오브젝트 파일은 파일 이름을 공유하지만
.o파일 이름 확장자를 사용합니다.binutils패키지의ar툴을 사용하여 오브젝트 파일을 정적 라이브러리(archive)로 전환합니다.$ ar rcs libfoo.a source_file.o ...libfoo.a파일이 생성됩니다.nm명령을 사용하여 결과 아카이브를 검사합니다.$ nm libfoo.a- 정적 라이브러리 파일을 적절한 디렉터리에 복사합니다.
라이브러리에 대해 연결할 때 GCC는 라이브러리가 정적 연결을 위한 아카이브인
.a파일 이름 확장에서 자동으로 인식합니다.$ gcc ... -lfoo ...
2.5. make를 사용하여 더 많은 코드 관리 링크 복사링크가 클립보드에 복사되었습니다!
GNU make 유틸리티(일반적으로 축약된 make )는 소스 파일에서 실행 파일의 생성을 제어하기 위한 툴입니다. 복잡한 프로그램의 어떤 부분이 변경되어 다시 컴파일해야 하는지 자동으로 결정합니다. make 는 Makefiles라는 구성 파일을 사용하여 프로그램 빌드 방식을 제어합니다.
2.5.1. GNU make 및 Makefile 개요 링크 복사링크가 클립보드에 복사되었습니다!
특정 프로젝트의 소스 파일에서 사용 가능한 양식(일반적으로 실행 파일)을 생성하려면 몇 가지 필요한 단계를 수행합니다. 나중에 반복할 수 있도록 동작 및 시퀀스를 기록합니다.
Red Hat Enterprise Linux에는 이러한 목적을 위해 설계된 빌드 시스템인 GNU make 가 포함되어 있습니다.
- GNU
make이란 무엇입니까? -
GNU
make는 빌드 프로세스를 설명하는 지침이 포함된 Makefiles를 읽습니다. Makefile에는 특정 작업(시피)을 사용하여 특정 조건(대상)을 충족하는 방법을 설명하는 여러 규칙이 포함되어있습니다. 규칙은 다른 규칙에 따라 계층적으로 달라질 수 있습니다.
옵션 없이 make 를 실행하면 현재 디렉터리에서 Makefile을 찾아 기본 대상에 연결을 시도합니다. 실제 Makefile 파일 이름은 Makefile,makefile 및 GNUmakefile 중 하나일 수 있습니다. 기본 대상은 Makefile 콘텐츠에서 결정됩니다.
특정 대상을 사용하여 make 를 실행하려면 다음을 수행합니다.
$ make target
- Makefile 구조 및 구문
- makefiles는 타겟 과 레시피 로 구성된 변수 및 규칙을 정의하는 데 비교적 간단한 구문을 사용합니다. 대상은 규칙이 실행되는 경우 출력을 지정합니다. 레시피가 있는 줄은 TAB 문자로 시작해야 합니다.
일반적으로 Makefile에는 소스 파일을 컴파일하는 규칙, 결과 개체 파일을 연결하는 규칙 및 계층 구조의 맨 위에 있는 진입점 역할을 하는 대상이 포함됩니다.
- 기본 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
이 예제에서는 모든 대상에 도달하는 데 파일 hello 가 필요함을 보여줍니다. hello를 얻으려면 ( hello.ogcc로 링크됨)가 필요하며 hello.c 에서 생성됩니다( gcc로 컴파일됨).
대상은 마침표(.)로 시작하지 않는 첫 번째 대상이므로 all 은 기본 대상입니다. 인수 없이 make 를 실행하면 현재 디렉터리에 이 Makefile 이 포함된 경우 모든 실행과 동일합니다.
- 변수가 포함된 고급 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 변수가 정의된 행에만 추가해야 합니다.
2.5.2. 예: Makefile을 사용하여 C 프로그램 빌드 링크 복사링크가 클립보드에 복사되었습니다!
이 예제의 단계에 따라 Makefile을 사용하여 샘플 C 프로그램을 빌드합니다.
사전 요구 사항
프로세스
hellomake디렉토리를 생성합니다.$ mkdir hellomake생성된 디렉터리로 변경합니다.
$ cd hellomake다음 콘텐츠를 사용하여
hello.c파일을 생성합니다.#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello, World!\n"); return 0; }다음 콘텐츠를 사용하여
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 레시피 라인은 탭 문자로 시작해야 합니다! 위의 텍스트를 문서에서 복사할 때 cut-and-paste 프로세스가 탭 대신 공백을 붙여넣을 수 있습니다. 이 경우 문제를 수동으로 수정합니다.
실행
make:$ makegcc -c -Wall hello.c -o hello.o gcc hello.o -o hello그러면 실행 파일
hello가 생성됩니다.실행 파일
hello를 실행합니다.$ ./helloHello, World!생성된 파일을 제거하려면 Makefile target
clean을 실행합니다.$ make cleanrm -rf hello.o hello
추가 리소스
2.5.3. 작성을 위한 문서 리소스 링크 복사링크가 클립보드에 복사되었습니다!
make 에 대한 자세한 내용은 아래 나열된 리소스를 참조하십시오.
- 설치된 문서
-
시스템에 설치된 도움말 페이지를 보려면
man유틸리티를 사용합니다.
$ man makeinfo유틸리티를 사용하여 시스템에 설치된 정보 페이지를 확인합니다.$ info make
-
시스템에 설치된 도움말 페이지를 보려면
3장. 애플리케이션 디버깅 링크 복사링크가 클립보드에 복사되었습니다!
애플리케이션 디버깅은 매우 광범위한 주제입니다. 이 부분에서는 개발자에게 여러 상황에서 디버깅을 위한 가장 일반적인 기술을 제공합니다.
3.1. 디버깅 정보를 사용하여 디버깅 활성화 링크 복사링크가 클립보드에 복사되었습니다!
애플리케이션 및 라이브러리를 디버깅하려면 디버깅 정보가 필요합니다. 다음 섹션에서는 이 정보를 가져오는 방법을 설명합니다.
3.1.1. 디버깅 정보 링크 복사링크가 클립보드에 복사되었습니다!
실행 가능한 코드를 디버깅하는 동안 두 가지 유형의 정보를 사용하여 툴을 허용하고 이 툴을 확장하여 바이너리 코드를 이해할 수 있습니다.
- 소스 코드 텍스트
- 소스 코드 텍스트가 바이너리 코드와 어떻게 관련되어 있는지에 대한 설명
이러한 정보를 디버깅 정보라고 합니다.
Red Hat Enterprise Linux는 실행 바이너리, 공유 라이브러리 또는 debuginfo 파일에 ELF 형식을 사용합니다. 이러한 ELF 파일 내에서 DWARF 형식은 디버그 정보를 보관하는 데 사용됩니다.
ELF 파일에 저장된 DWARF 정보를 표시하려면 readelf -w file 명령을 실행합니다.
STABS는 더 오래되고 성능이 낮은 형식이며 경우에 따라 UNIX에서 사용됩니다. Red Hat은 사용하지 않는 것이 좋습니다. GCC 및 GDB는 최상의 노력으로만 STABS 생산 및 소비를 제공합니다. Valgrind 및 elfutils 와 같은 다른 툴은 STABS에서 작동하지 않습니다.
3.1.2. GCC를 사용하여 C 및 C++ 애플리케이션 디버깅 활성화 링크 복사링크가 클립보드에 복사되었습니다!
컴파일러는 바이너리를 작게 유지하기 위해 기본적으로 디버그 정보를 생략합니다. C 및 C++ 애플리케이션을 디버깅할 수 있도록 하려면 컴파일러에 디버깅 데이터를 생성하도록 명시적으로 지시해야 합니다.
프로세스
C 또는 C++ 애플리케이션을 GCC로 컴파일하고 연결할 때 디버깅 정보를 생성하려면 컴파일 명령에
-g옵션을 추가합니다.$ gcc ... -g ...이 옵션은 GCC에 출력 바이너리에 디버그 정보를 포함하도록 지시합니다.
-g옵션 및 추가 디버깅 옵션에 대한 자세한 내용은 GCC 매뉴얼 페이지를 참조하십시오.디버그 정보에 매크로 정의를 포함하려면 -g 대신
옵션을 사용합니다.-g3$ gcc ... -g3 ...디버그 옵션이 실행 코드에 영향을 미치지 않는지 테스트하려면
-fcompare-debugGCC 옵션을 사용합니다. 이 옵션은 다음과 같습니다.- 디버그 정보를 사용하여 한 번 코드를 두 번 컴파일합니다.
- 생성된 바이너리 파일 비교
두 바이너리가 동일한 경우 테스트를 통과합니다.
이 테스트에서는 디버깅 옵션이 코드에 숨겨진 버그를 도입하지 않도록 합니다.
-fcompare-debug를 사용하면 컴파일 시간이 크게 증가합니다. 자세한 내용은 GCC 매뉴얼 페이지를 참조하십시오.중요컴파일러 및 링커 최적화는 다음을 통해 디버깅을 어렵게 만들 수 있습니다. * 사용되지 않는 것으로 표시되는 변수 제거 * 루프 병합 * 작업 병합 * 소스 코드와 실행 코드 간의 관계 변경
디버깅 환경을 개선하려면
-Og옵션을 사용하는 것이 좋습니다. 그러나 최적화 수준을 변경하면 실행 코드 동작을 변경하고 잠재적으로 버그를 숨길 수 있습니다.
3.1.3. debuginfo 및 debugsource 패키지 링크 복사링크가 클립보드에 복사되었습니다!
debuginfo 및 debugsource 패키지에는 프로그램 및 라이브러리의 디버깅 정보 및 디버그 소스 코드가 포함되어 있습니다. Red Hat Enterprise Linux 리포지토리의 패키지에 설치된 애플리케이션 및 라이브러리의 경우 추가 채널에서 별도의 debuginfo 및 debugsource 패키지를 얻을 수 있습니다.
- 디버깅 정보 패키지 유형
-
debuginfo 패키지:debuginfo패키지는 바이너리 코드 기능에 대해 사람이 읽을 수 있는 이름을 제공하는 데 필요한 디버깅 정보를 제공합니다. 이러한 패키지에는 DWARF 디버깅 정보가 포함된.debug파일이 포함되어 있습니다. 이러한 파일은/usr/lib/debug디렉토리에 설치됩니다.
Debugsource 패키지: debugsource 패키지에는 바이너리 코드를 컴파일하는 데 사용되는 소스 파일이 포함되어 있습니다. debuginfo 및 debugsource 패키지가 모두 설치되어 있으면 GDB 또는 LLDB와 같은 디버거는 바이너리 코드의 실행을 소스 코드와 연결할 수 있습니다. 소스 코드 파일은 /usr/src/debug 디렉터리에 설치됩니다.
3.1.4. GDB를 사용하여 애플리케이션 또는 라이브러리의 debuginfo 패키지 가져오기 링크 복사링크가 클립보드에 복사되었습니다!
코드를 디버깅하려면 디버깅 정보가 필요합니다. 패키지에서 설치된 코드의 경우 GNU Debugger(GDB)는 누락된 디버그 정보를 자동으로 인식하고 패키지 이름을 해결하며 패키지를 가져오는 방법에 대한 구체적인 조언을 제공합니다.
사전 요구 사항
- 디버그하려는 애플리케이션 또는 라이브러리가 시스템에 설치되어 있어야 합니다.
-
GDB 및
debuginfo-install도구가 시스템에 설치되어 있어야 합니다. -
debuginfo및debugsource패키지를 제공하는 리포지토리는 시스템에서 구성하고 활성화해야 합니다. 자세한 내용은 디버그 및 소스 리포지토리 활성화를 참조하십시오.
프로세스
디버그하려는 애플리케이션 또는 라이브러리에 연결된 GDB를 시작합니다. GDB는 누락된 디버깅 정보를 자동으로 인식하고 실행할 명령을 제안합니다.
$ gdb -q /bin/lsReading symbols from /bin/ls...Reading symbols from .gnu_debugdata for /usr/bin/ls...(no debugging symbols found)...done. (no debugging symbols found)...done. Missing separate debuginfos, use: dnf debuginfo-install coreutils-9.5-6.el10.x86_64 (gdb)GDB를 종료합니다. q 를 입력하고 Enter 를 사용하여 확인합니다.
(gdb) qGDB에서 제안한 명령을 실행하여 필요한
debuginfo패키지를 설치합니다.# dnf debuginfo-install coreutils-9.5-6.el10.x86_64dnf패키지 관리 도구는 변경 사항에 대한 요약을 제공하고 확인을 요청하면 필요한 모든 파일을 확인, 다운로드 및 설치합니다.GDB가
debuginfo패키지를 제안할 수 없는 경우 에 설명된 절차를 따르십시오.
3.1.5. 애플리케이션 또는 라이브러리의 debuginfo 패키지 수동 가져오기 링크 복사링크가 클립보드에 복사되었습니다!
실행 파일을 찾은 다음 설치하는 패키지를 찾아 설치해야 하는 debuginfo 패키지를 수동으로 확인할 수 있습니다.
GDB를 사용하여 설치 패키지를 확인합니다. GDB가 설치할 패키지를 제안할 수 없는 경우에만 이 수동 절차를 사용하십시오.
사전 요구 사항
- 애플리케이션 또는 라이브러리가 시스템에 설치되어 있어야 합니다.
- 애플리케이션 또는 라이브러리가 패키지에서 설치되었습니다.
-
debuginfo-install툴은 시스템에서 사용할 수 있어야 합니다. -
debuginfo패키지를 제공하는 채널은 시스템에서 구성하고 활성화해야 합니다.
프로세스
애플리케이션 또는 라이브러리의 실행 파일을 찾습니다.
애플리케이션 파일을 찾으려면 다음 명령을 사용합니다.
$ which less/usr/bin/lesslocate명령을 사용하여 라이브러리 파일을 찾습니다.$ locate libz | grep so/usr/lib64/libz.so.1 /usr/lib64/libz.so.1.2.11원래 디버깅에 오류 메시지가 포함된 경우 라이브러리의 파일 이름에 오류 메시지에 언급된 것과 동일한 추가 번호가 있는 결과를 선택합니다. 확실하지 않은 경우 라이브러리 파일 이름에 추가 번호가 포함되지 않은 결과를 사용하여 나머지 절차를 따르십시오.
참고locate명령은mlocate패키지에서 제공합니다. 이를 설치하고 사용하려면 다음을 수행합니다.# dnf install mlocate데이터베이스를 업데이트합니다.
# updatedb
파일을 제공한 패키지의 이름과 버전을 검색합니다.
$ rpm -qf /usr/lib64/libz.so.1.3.1.zlib-ngzlib-ng-compat-2.2.3-1.el10.x86_64출력은 다음과 같이 이름:epoch-버전.릴리스.아키텍처 형식으로 설치된 패키지에 대한 세부 정보를 제공합니다.
중요이 단계에서 결과가 생성되지 않으면 바이너리 파일을 제공한 패키지를 확인할 수 없습니다. 몇 가지 가능한 사례가 있습니다.
- 파일은 현재 구성의 패키지 관리 도구에서 알 수 없는 패키지에서 설치됩니다.
-
파일은 로컬로 다운로드되고 수동으로 설치된 패키지에서 설치됩니다. 이 경우 적절한
debuginfo패키지를 자동으로 확인할 수 없습니다. - 패키지 관리 툴이 잘못 구성되어 있습니다.
-
파일이 어떤 패키지에서도 설치되지 않았습니다. 이러한 경우 해당
debuginfo패키지가 없습니다.
추가 단계는 이 단계에 따라 달라지므로 이 상황을 해결하거나 이 절차를 중지해야 합니다. 정확한 문제 해결 단계를 설명하는 것은 이 절차의 범위를 벗어납니다.
dnf유틸리티를 사용하여 debuginfo 패키지를 설치합니다. 명령에서 패키지 이름 및 이전 단계에서 확인한 기타 세부 정보를 사용합니다.debuginfo-install# dnf debuginfo-install zlib-ng-compat-2.2.3-1.el10.x86_64
3.2. GDB를 사용하여 애플리케이션 내부 상태 검사 링크 복사링크가 클립보드에 복사되었습니다!
애플리케이션이 제대로 작동하지 않는 이유를 찾으려면 디버거를 사용하여 실행을 제어하고 내부 상태를 검사합니다. 이 섹션에서는 이 작업에 GNU Debugger(GDB)를 사용하는 방법에 대해 설명합니다.
3.2.1. GNU 디버거(GDB) 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux에는 명령줄 사용자 인터페이스를 통해 프로그램 내에서 발생하는 상황을 조사할 수 있는 GNU 디버거(GDB)가 포함되어 있습니다.
GDB로 그래픽 프런트 엔드를 사용하려면 Eclipse 통합 개발 환경을 설치합니다. Eclipse 사용을 참조하십시오.
- GDB 기능
단일 GDB 세션은 다음 유형의 프로그램을 디버깅할 수 있습니다.
- 다중 스레드 및 포크 프로그램
- 한 번에 여러 프로그램
-
TCP/IP 네트워크 연결을 통해 연결된
gdbserver유틸리티가 있는 원격 머신 또는 컨테이너의 프로그램
- 디버깅 요구 사항
실행 가능한 코드를 디버깅하려면 GDB에 해당 특정 코드에 대한 디버깅 정보가 필요합니다.
- 사용자가 개발한 프로그램의 경우 코드를 빌드하는 동안 디버깅 정보를 생성할 수 있습니다.
- 패키지에서 설치된 시스템 프로그램의 경우 debuginfo 패키지를 설치해야 합니다.
3.2.2. 프로세스에 GDB 연결 링크 복사링크가 클립보드에 복사되었습니다!
프로세스를 검사하려면 GDB를 프로세스에 연결해야 합니다.
사전 요구 사항
프로세스
GDB로 프로그램을 시작합니다.
GDB를 사용하여 프로그램을 실행합니다.
$ gdb program프로그램을 프로그램 파일 이름 또는 경로로 바꿉니다.
GDB는 프로그램 실행을 시작하도록 설정합니다.
run명령으로 프로세스 실행을 시작하기 전에 Cryostat 및gdb환경을 설정할 수 있습니다.- 이미 실행 중인 프로세스에 GDB를 연결합니다.
ps명령을 사용하여 프로세스 ID(pid)를 찾습니다.$ ps -C program -o pid hpid프로그램을 프로그램 파일 이름 또는 경로로 바꿉니다.
GDB를 이 프로세스에 연결합니다.
$ gdb -p pidpid 를
ps출력의 실제 프로세스 ID 번호로 바꿉니다.
실행 중인 프로그램에 활성 GDB 세션을 연결합니다.
shellGDB 명령을 사용하여ps명령을 실행하고 프로그램의 프로세스 ID(pid)를 찾습니다.(gdb) shell ps -C program -o pid hpid프로그램을 프로그램 파일 이름 또는 경로로 바꿉니다.
attach명령을 사용하여 GDB를 프로그램에 연결합니다.(gdb) attach pidpid 를
ps출력의 실제 프로세스 ID 번호로 바꿉니다.참고경우에 따라 GDB가 해당 실행 파일을 찾지 못할 수 있습니다.
file명령을 사용하여 경로를 지정합니다.(gdb) file path/to/program
3.2.3. GDB를 사용하여 프로그램 코드를 단계별로 처리 링크 복사링크가 클립보드에 복사되었습니다!
GDB 디버거가 프로그램에 연결되면 여러 명령을 사용하여 프로그램 실행을 제어할 수 있습니다. 이러한 명령을 사용하면 디버깅 세션 중에 코드를 단계적으로 처리하고, Cryostat를 설정하고, 프로그램 흐름을 제어할 수 있습니다.
이러한 GDB 명령을 효과적으로 사용하려면 이러한 방법을 통해 디버깅 정보를 사용할 수 있어야 합니다. * 프로그램은 디버깅 정보를 사용하여 컴파일되고 빌드됩니다. * 관련 debuginfo 패키지가 설치됩니다.
GDB는 프로그램 실행을 단계별로 처리하고 제어하기 위한 명령 세트를 제공합니다.
R (run): 프로그램 실행을 시작합니다. 임의의 인수와 함께 run 을 실행하면 해당 인수가 프로그램이 정상적으로 시작된 것처럼 실행 파일에 전달됩니다. 사용자는 일반적으로 Cryostat를 설정한 후 이 명령을 실행합니다.
start: 프로그램의 실행을 시작하지만 프로그램의 주요 기능의 시작 부분에서 중지합니다. start 가 임의의 인수로 실행되면 프로그램이 정상적으로 시작된 것처럼 해당 인수가 실행 파일에 전달됩니다.
c (continue): 현재 상태에서 프로그램을 계속 실행합니다. 프로그램 실행은 다음 중 하나가 사실이 될 때까지 계속됩니다: * 구현에 도달합니다. * 지정된 조건이 충족됩니다. * 프로그램이 신호를 수신합니다. * 오류가 발생합니다. * 프로그램이 종료됩니다.
N (다음): 현재 소스 파일의 다음 코드에 도달할 때까지 현재 상태에서 프로그램을 계속 실행합니다. 프로그램 실행은 다음 중 하나가 사실이 될 때까지 계속됩니다: * 구현에 도달합니다. * 지정된 조건이 충족됩니다. * 프로그램이 신호를 수신합니다. * 오류가 발생합니다. * 프로그램이 종료됩니다.
s (단계): 단계 명령은 현재 소스 파일의 각 연속 코드 줄에서도 실행을 중지합니다. 그러나 함수 호출을 포함하는 소스 행에서 실행이 현재 중지된 경우 GDB는 함수 호출 을 입력한 후 실행을 중지합니다(실행하지 않는 경우).
위치 까지: 위치 옵션에 의해 지정된 코드 위치에 도달 할 때까지 계속 실행됩니다.
fini (finish): 프로그램의 실행을 다시 시작하고 함수에서 실행이 반환될 때 중지됩니다. 프로그램 실행은 다음 중 하나가 사실이 될 때까지 계속됩니다: * 구현에 도달합니다. * 지정된 조건이 충족됩니다. * 프로그램이 신호를 수신합니다. * 오류가 발생합니다. * 프로그램이 종료됩니다.
Q (quit): 실행을 종료하고 GDB를 종료합니다.
3.2.4. GDB를 사용하여 프로그램 내부 값 표시 링크 복사링크가 클립보드에 복사되었습니다!
프로그램의 내부 변수의 값을 표시하는 것은 프로그램이 무엇을 하는지 이해하는 데 중요합니다. GDB는 내부 변수를 검사하는 데 사용할 수 있는 여러 명령을 제공합니다. 다음은 이러한 명령 중 가장 유용합니다.
- P(인쇄)
지정된 인수의 값을 표시합니다. 일반적으로 인수는 단순한 단일 값부터 구조까지 모든 복잡성의 변수 이름입니다. 인수는 프로그램 변수 및 라이브러리 함수의 사용을 포함하여 현재 언어에서 유효하거나 테스트 중인 프로그램에 정의된 함수일 수도 있습니다.
인쇄 명령을 사용하여 데이터 구조(예: 클래스, 구조)를 사용자 지정하기 위해 매우적합한 Python 또는 Guile 스크립트로 GDB를 확장할 수 있습니다.BT(backtrace)현재 실행 지점에 도달하는 데 사용되는 함수 호출 체인 또는 실행이 종료될 때까지 사용되는 함수 체인을 표시합니다. 이는 악성 원인을 사용하여 심각한 버그(예: 분할 오류)를 조사하는 데 유용합니다.
backtrace명령에전체옵션을 추가하면 로컬 변수도 표시됩니다.bt및info frame 명령을 사용하여 표시되는 데이터의 사용자 지정 표시를 위해 프레임 필터Python 스크립트를 사용하여 GDB를 확장할 수 있습니다. 프레임은 단일 함수 호출과 연결된 데이터를 나타냅니다.infoinfo명령은 다양한 항목에 대한 정보를 제공하는 일반적인 명령입니다. 설명할 항목을 지정하는 옵션이 필요합니다.-
info args명령은 현재 선택된 프레임인 함수 호출의 옵션을 표시합니다. -
info locals명령은 현재 선택한 프레임에 로컬 변수를 표시합니다.
사용 가능한 항목 목록은 GDB 세션에서 명령
도움말 정보를실행합니다.(gdb) help info-
- L (list)
- 프로그램 소스 코드를 표시합니다. 프로그램이 시작되었지만 현재 중지된 경우 이 명령은 몇 가지 컨텍스트 행과 함께 프로그램이 현재 중지된 소스 코드를 나열합니다. 프로그램이 시작되기 전에 주요 기능이 나열됩니다. 내부 상태를 표시하는 명령은 엄격하게 아니지만, 목록은 사용자가 프로그램 실행의 다음 단계에서 발생할 내부 상태에 대한 변경 사항을 이해하는 데 도움이 됩니다.
3.2.5. GDB Cryostat를 사용하여 정의된 코드 위치에서 실행을 중지 링크 복사링크가 클립보드에 복사되었습니다!
종종 코드의 작은 부분만 조사됩니다. Cryostat는 GDB가 코드의 특정 위치에서 프로그램의 실행을 중지하도록 지시하는 마커입니다. Cryostat는 가장 일반적으로 소스 코드 행과 연결되어 있습니다. 이 경우 Cryostat를 배치하려면 소스 파일 및 행 번호를 지정해야 합니다.
프로세스
Cryostat 를 배치 하려면 다음을 수행합니다.
소스 코드 파일의 이름과 해당 파일에서 행을 지정합니다.
(gdb) br file:line파일이 없으면 현재 실행 시점에 있는 소스 파일의 이름이 사용됩니다.
(gdb) br line또는 함수 이름을 사용하여 Cryostat를 시작에 넣습니다.
(gdb) br function_name작업의 특정 반복 횟수 후에 프로그램에 오류가 발생할 수 있습니다. 실행을 중지하려면 추가 조건 을 지정하려면 다음을 수행합니다.
(gdb) br file:line if condition조건 을 C 또는 C++ 언어의 조건으로 바꿉니다. 파일 및 행의 의미는 위의 내용과 동일합니다.
모든 Cryostat 및 감시 지점의 상태를 검사하려면 다음을 수행합니다.
(gdb) info brinfo br의 출력에 표시된 대로 번호를 사용하여 Cryostat를 제거하려면 다음을 수행합니다.(gdb) delete number지정된 위치에서 Cryostat를 제거하려면 다음을 수행합니다.
(gdb) clear file:line
3.2.6. GDB 감시 지점을 사용하여 데이터 액세스 및 변경 시 실행을 중지 링크 복사링크가 클립보드에 복사되었습니다!
대부분의 경우 특정 데이터가 변경되거나 액세스될 때까지 프로그램이 실행되도록 하는 것이 좋습니다. Watchpoints는 특정 데이터 조건이 충족되면 GDB 에 프로그램 실행을 중지하도록 지시하는 마커입니다.
프로세스
데이터 변경(쓰기)에 대한 감시 지점을 배치하려면 다음을 수행합니다.
(gdb) watch expression조사할 항목을 설명하는 표현식으로 표현식을 바꿉니다. 변수의 경우 표현식 은 변수 이름과 동일합니다.
데이터 액세스에 대한 감시 지점을 배치하려면 다음을 수행합니다.
(gdb) rwatch expression모든 데이터 액세스에 대한 감시 지점을 배치하려면(읽기 및 쓰기 모두)
(gdb) awatch expression모든 감시 지점 및 Cryostat의 상태를 검사하려면 다음을 수행합니다.
(gdb) info br감시 지점을 제거하려면 다음을 수행합니다.
(gdb) delete numnum 옵션을
info br명령으로 보고된 번호로 바꿉니다.
3.2.7. GDB를 사용하여 포크 또는 스레드 프로그램 디버깅 링크 복사링크가 클립보드에 복사되었습니다!
일부 프로그램은 포크 또는 스레드를 사용하여 병렬 코드 실행을 수행합니다. 여러 동시 실행 경로를 디버깅하려면 특별한 고려 사항이 필요합니다.
프로세스 작성 및 스레드의 개념을 이해해야 합니다.
- GDB를 사용하여 분기된 프로그램 디버깅
Forking은 프로그램(부모)이 자체(하위)의 독립적인 복사본을 생성하는 상황입니다. 다음 설정 및 명령을 사용하여 포크가 발생할 때 GDB가 수행하는 작업에 영향을 미칩니다.
follow-fork-mode설정은 GDB가 포크 후 상위 또는 자식을 따르는지 여부를 제어합니다.follow-fork-mode 상위 설정- 포크 후 상위 프로세스를 디버깅합니다. 이는 기본값입니다.
follow-fork-mode 하위 설정- 포크 후 하위 프로세스를 디버깅합니다.
follow-fork-mode 표시-
follow-fork-mode의 현재 설정을 표시합니다.
set detach-on-fork설정은 GDB가 다른 프로세스를 계속 제어하거나 실행할지 여부를 제어합니다.detach-on-fork 설정-
따르지 않는 프로세스(Follow-fork-mode값에 따라 다름)는 분리되고 독립적으로 실행됩니다. 이는 기본값입니다. detach-on-fork off 설정-
GDB는 두 프로세스를 모두 제어합니다.
후속 프로세스(Follow-fork-mode값에 따라 다름)는 다른 프로세스가 일시 중단되는 동안 정상적으로 디버깅됩니다. detach-on-fork 표시-
detach-on-fork의 현재 설정을 표시합니다.
- GDB를 사용하여 스레드 프로그램 디버깅
-
GDB에는 개별 스레드를 디버그하고 독립적으로 조작하고 검사할 수 있습니다. GDB를 검사한 스레드만 중지하도록 하려면
중지되지 않은 명령 세트를사용하고target-async를 설정합니다. 이러한 명령을.gdbinit파일에 추가할 수 있습니다. 해당 기능을 켜면 GDB는 스레드 디버깅을 수행할 준비가 되었습니다.
GDB는 현재 스레드 의 개념을 사용합니다. 기본적으로 명령은 현재 스레드에만 적용됩니다.
정보 스레드-
현재 스레드를 나타내는 ID 및
gid번호가 있는 스레드 목록을 표시합니다. 스레드 ID-
지정된 ID가 있는 스레드를 현재 스레드로 설정합니다.
스레드 적용 ids 명령-
ids로 나열된 모든 스레드에command명령을 적용합니다.ids옵션은 공백으로 구분된 스레드 ID 목록입니다. 특수 값all은 명령을 모든 스레드에 적용합니다. 조건이있는 경우 위치 스레드 ID 중단-
스레드 번호 ID에 대해 특정
조건이있는 특정위치에서Cryostat를설정합니다. 워치 표현식 스레드 ID-
스레드 번호 ID에 대해서만
표현식으로 정의된 감시 지점을설정합니다. Command&-
command명령을 실행하고 gdb 프롬프트(gdb)로 즉시 돌아가 백그라운드에서 모든 코드 실행을 계속합니다. 인터럽트- 백그라운드에서 실행을 중지합니다.
추가 리소스
3.3. 애플리케이션 상호 작용 기록 링크 복사링크가 클립보드에 복사되었습니다!
실행 가능한 애플리케이션 코드는 운영 체제 및 공유 라이브러리의 코드와 상호 작용합니다. 이러한 상호 작용의 활동 로그를 기록하면 실제 애플리케이션 코드를 디버깅하지 않고도 애플리케이션의 동작에 대한 충분한 통찰력을 제공할 수 있습니다. 또는 애플리케이션의 상호 작용을 분석하면 버그 매니페스트가 있는 조건을 파악하는 데 도움이 될 수 있습니다.
3.3.1. 애플리케이션 상호 작용을 기록하는 데 유용한 툴 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux는 애플리케이션의 상호 작용을 분석하기 위한 여러 툴을 제공합니다.
- strace
strace툴을 사용하면 기본적으로 애플리케이션에서 사용하는 시스템 호출(커널 함수)을 로깅할 수 있습니다.-
툴은 기본 커널 코드를 알고 있는 매개변수 및 결과를 해석하므로 호출에 대한 자세한 출력을 제공할 수 있습니다. 숫자는 해당 상수 이름, 플래그 목록으로 확장된 비트별 결합된 플래그, 실제 문자열을 제공하기 위해 역참조된 문자 배열에 대한 포인터로 변환됩니다. 최신 커널 기능에 대한 지원이 부족할 수 있습니다.strace - 추적된 호출을 필터링하여 캡처된 데이터의 양을 줄일 수 있습니다.
-
strace를 사용하려면 로그 필터 설정을 제외하고 특정 설정이 필요하지 않습니다. -
strace를 사용하여 애플리케이션 코드를 추적하면 애플리케이션 실행 속도가 크게 느려집니다. 결과적으로strace는 많은 프로덕션 배포에 적합하지 않습니다. 또는ltrace또는 SystemTap을 사용하는 것이 좋습니다. -
Red Hat Developer Toolset에서 사용할 수 있는
strace버전은 시스템 호출 변조도 수행할 수 있습니다. 이 기능은 디버깅에 유용합니다.
-
- ltrace
ltrace툴을 사용하면 애플리케이션의 사용자 공간 호출을 공유 오브젝트(동적 라이브러리)에 기록할 수 있습니다.-
ltrace툴을 사용하면 모든 라이브러리에 대한 호출을 추적할 수 있습니다. - 추적된 호출을 필터링하여 캡처된 데이터의 양을 줄일 수 있습니다.
-
ltrace를 사용하려면 로그 필터 설정을 제외하고 특정 설정이 필요하지 않습니다. -
ltrace툴은 가볍고 빠르게strace에 대한 대안을 제공합니다.strace를 사용하여 커널 함수를 추적하는 대신glibcwithltrace와 같은 라이브러리에서 해당 인터페이스를 추적할 수 있습니다. -
ltrace는strace와 같은 알려진 호출 세트를 처리하지 않으므로 라이브러리 함수에 전달된 값을 설명하지 않습니다.ltrace출력에는 원시 번호와 포인터만 포함됩니다.ltrace출력을 해석하려면 출력에 있는 라이브러리의 실제 인터페이스 선언을 참조해야 합니다.
참고Red Hat Enterprise Linux 10에서 알려진 문제로 인해
ltrace가 시스템 실행 파일을 추적하지 못합니다. 이 제한은 사용자가 빌드한 실행 파일에 적용되지 않습니다.-
- SystemTap
SystemTap은 Linux 시스템에서 실행 중인 프로세스 및 커널 활동을 검증하기 위한 계측 플랫폼입니다. SystemTap은 사용자 지정 이벤트 처리기를 프로그래밍하는 데 자체 스크립팅 언어를 사용합니다.
-
strace및ltrace를 사용하는 것과 비교하여 로깅을 스크립팅하는 것은 초기 설정 단계에서 더 많은 작업을 의미합니다. 그러나 스크립팅 기능은 로그를 생성하는 것 외에도 SystemTap의 유용성을 확장합니다. - SystemTap은 커널 모듈을 생성하고 삽입하여 작동합니다. SystemTap 사용은 효율적이며 시스템 또는 애플리케이션 실행 속도가 크게 느려지지 않습니다.
- SystemTap에는 일련의 사용 예가 포함되어 있습니다.
-
- GDB
GNU Debugger(GDB)는 주로 로깅이 아닌 디버깅을 위한 것입니다. 그러나 일부 기능은 애플리케이션의 상호 작용이 주요 활동인 경우에도 유용합니다.
- GDB를 사용하면 상호 작용 이벤트 캡처와 후속 실행 경로의 즉각적인 디버깅을 편리하게 결합할 수 있습니다.
- GDB는 다른 도구에서 문제가 있는 상황을 처음 식별한 후 드물거나 단수적인 이벤트에 대한 응답을 분석하는 데 가장 적합합니다. 빈번한 이벤트가 있는 모든 시나리오에서 GDB를 사용하면 비효율적이거나 불가능하게 됩니다.
3.3.2. strace를 사용하여 애플리케이션의 시스템 호출 모니터링 링크 복사링크가 클립보드에 복사되었습니다!
strace 툴을 사용하면 애플리케이션에서 수행하는 시스템(커널) 호출을 모니터링할 수 있습니다.
사전 요구 사항
프로세스
모니터링할 시스템 호출을 식별합니다.
strace를 시작하고 프로그램에 연결합니다.모니터링하려는 프로그램이 실행되지 않으면
strace를 시작하고 프로그램을 지정합니다.$ strace -fvttTyy -s 256 -e trace=call program프로그램이 이미 실행중인 경우 프로세스 ID (pid)를 찾으십시오.
$ ps -C program프로세스에
strace를 연결합니다.$ strace -fvttTyy -s 256 -e trace=call -ppid
-
호출 을 표시할 시스템 호출으로 교체합니다.
-e trace=호출옵션을 여러 번 사용할 수 있습니다. 생략하면strace는 모든 시스템 호출 유형을 표시합니다. 자세한 내용은 strace(1) 매뉴얼 페이지를 참조하십시오. -
분기된 프로세스 또는 스레드를 추적하지 않으려면
-f옵션을 생략합니다.
strace툴에는 애플리케이션에서 수행한 시스템 호출과 세부 정보가 표시됩니다.대부분의 경우 애플리케이션 및 해당 라이브러리는 많은 수의 호출을 수행하고 시스템 호출에 대한 필터가 설정되지 않은 경우
strace출력이 즉시 표시됩니다.strace툴은 프로그램이 종료되면 종료됩니다.추적된 프로그램이 종료되기 전에 모니터링을 종료하려면 를 누릅니다.
-
strace가 프로그램을 시작한 경우 프로그램은strace와 함께 종료됩니다. -
이미 실행중인 프로그램에
strace를 첨부한 경우 프로그램은strace와 함께 종료됩니다.
-
애플리케이션에서 수행한 시스템 호출 목록을 분석합니다.
- 리소스 액세스 또는 가용성에 대한 문제는 호출에서 오류를 반환할 때 로그에 존재합니다.
- 시스템 호출 및 호출 시퀀스 패턴에 전달된 값은 애플리케이션의 동작 원인에 대한 통찰력을 제공합니다.
- 애플리케이션이 충돌하면 중요한 정보는 로그 끝에 있을 수 있습니다.
출력에는 많은 불필요한 정보가 포함되어 있습니다. 그러나 관심 있는 시스템 호출에 대한 보다 정확한 필터를 구성하고 절차를 반복할 수 있습니다.
참고출력을 보고 파일에 저장하는 것이 좋습니다. 이 작업을 수행하려면
tee명령을 사용합니다.$ strace ... |& tee your_log_file.log
3.3.3. ltrace를 사용하여 애플리케이션의 라이브러리 함수 호출 모니터링 링크 복사링크가 클립보드에 복사되었습니다!
ltrace 툴을 사용하면 라이브러리(공유 오브젝트)에서 사용할 수 있는 기능에 대한 애플리케이션 호출을 모니터링할 수 있습니다.
Red Hat Enterprise Linux 10에서 알려진 문제로 인해 ltrace 가 시스템 실행 파일을 추적하지 못합니다. 이 제한은 사용자가 빌드한 실행 파일에 적용되지 않습니다.
사전 요구 사항
프로세스
- 가능한 경우 라이브러리 및 관심 함수를 식별합니다.
ltrace를 시작하고 프로그램에 연결합니다.모니터링하려는 프로그램이 실행되고 있지 않은 경우
ltrace를 시작하고 프로그램을 지정합니다.$ ltrace -f -l library -e function program프로그램이 이미 실행중인 경우 프로세스 ID (pid)를 찾으십시오.
$ ps -C programltrace를 프로세스에 연결합니다.$ ltrace -f -l library -e function -ppid program-e,-f및-l옵션을 사용하여 출력을 필터링합니다.-
함수로 표시할 함수 이름을 제공합니다.
e 함수옵션은 여러 번 사용할 수 있습니다. 제외하면ltrace는 모든 함수에 대한 호출을 표시합니다. -
함수를 지정하는 대신
-l라이브러리 옵션을 사용하여 전체 라이브러리를 지정할 수 있습니다. 이 옵션은-e 함수옵션과 유사하게 작동합니다. -
분기된 프로세스 또는 스레드를 추적하지 않으려면
-f옵션을 생략합니다.
자세한 내용은 ltrace(1)_ 매뉴얼 페이지를 참조하십시오.
-
함수로 표시할 함수 이름을 제공합니다.
ltrace는 애플리케이션에서 수행한 라이브러리 호출을 표시합니다.대부분의 경우 애플리케이션은 많은 수의 호출을 수행하고 필터가 설정되지 않은 경우
ltrace출력이 즉시 표시됩니다.ltrace는 프로그램이 종료되면 종료됩니다.추적된 프로그램이 종료되기 전에 모니터링을 종료하려면 를 누릅니다. *
ltrace가 프로그램을 시작한 경우 프로그램은ltrace와 함께 종료됩니다. * 이미 실행중인 프로그램에ltrace를 첨부하면 프로그램이ltrace와 함께 종료됩니다.-
Ctrl+C 를 눌러
ltrace를 중지합니다. 애플리케이션에서 수행하는 라이브러리 호출 목록을 분석합니다.
- 애플리케이션이 충돌하면 중요한 정보는 로그 끝에 있을 수 있습니다.
- 출력에는 많은 불필요한 정보가 포함되어 있습니다. 그러나 더 정확한 필터를 구성하고 절차를 반복할 수 있습니다.
출력을 보고 파일에 저장하는 것이 좋습니다. 이 작업을 수행하려면 tee 명령을 사용합니다.
+
$ ltrace ... |& tee your_log_file.log
3.3.4. SystemTap을 사용하여 애플리케이션의 시스템 호출 모니터링 링크 복사링크가 클립보드에 복사되었습니다!
SystemTap 툴을 사용하면 커널 이벤트에 대한 사용자 지정 이벤트 처리기를 등록할 수 있습니다. strace 툴과 비교하면 사용하기가 더 어렵지만 더 효율적이며 더 복잡한 처리 논리를 사용할 수 있습니다. strace.stp 라는 SystemTap 스크립트는 SystemTap과 함께 설치되고 SystemTap을 사용하여 strace 기능의 근사 기능을 제공합니다.
프로세스
모니터링할 프로세스의 프로세스 ID(pid)를 찾습니다.
$ ps -auxstrace.stp스크립트를 사용하여 SystemTap을 실행합니다.# stap /usr/share/systemtap/examples/process/strace.stp -x pidpid 값은 프로세스 ID입니다.
이 스크립트는 커널 모듈로 컴파일된 후 로드됩니다. 이렇게 하면 명령을 입력하고 출력을 가져오는 사이에 약간의 지연이 발생합니다.
- 프로세스에서 시스템 호출을 수행하면 호출 이름과 해당 매개 변수가 터미널에 출력됩니다.
-
스크립트가 종료되거나
Ctrl+C를 누르면 스크립트가 종료됩니다.
3.3.5. GDB를 사용하여 애플리케이션 시스템 호출 인터셉트 링크 복사링크가 클립보드에 복사되었습니다!
GNU Debugger(GDB)를 사용하면 프로그램 실행 중에 발생하는 다양한 상황에서 실행을 중지할 수 있습니다. 프로그램이 시스템 호출을 수행할 때 실행을 중지하려면 GDB catchpoint 를 사용합니다.
프로세스
catchpoint를 설정합니다.
(gdb) catch syscall syscall-name명령
catch syscall은 프로그램이 시스템 호출을 수행할 때 실행을 중단하는 특수 유형의 Cryostat를 설정합니다.syscall-name옵션은 호출의 이름을 지정합니다. 다양한 시스템 호출에 대해 여러 catchpoint를 지정할 수 있습니다.syscall-name옵션을 남겨 두면 GDB가 모든 시스템 호출에서 중지됩니다.프로그램 실행을 시작합니다.
프로그램의 실행을 시작하지 않은 경우 다음을 시작합니다.
(gdb) r프로그램 실행이 중지되면 다시 시작하십시오.
(gdb) c
- GDB는 프로그램이 지정된 시스템 호출을 수행한 후 실행을 중지합니다.
- 특정 상황에 따라 프로그램 상태 및 사전 실행을 검사하려면 추가 GDB 명령을 사용하십시오.
GDB 디버깅 세션을 종료하려면 다음을 수행합니다.
(gdb) q
3.3.6. GDB를 사용하여 애플리케이션의 신호 인터셉트 링크 복사링크가 클립보드에 복사되었습니다!
GNU Debugger(GDB)를 사용하면 프로그램 실행 중에 발생하는 다양한 상황에서 실행을 중지할 수 있습니다. 프로그램이 운영 체제에서 신호를 수신할 때 실행을 중지하려면 GDB catchpoint 를 사용합니다.
프로세스
catchpoint를 설정합니다.
(gdb) catch signal signal-type명령
catch 신호는프로그램에서 신호를 수신할 때 실행을 중단하는 특수한 유형을 설정합니다.signal-type옵션은 신호 유형을 지정합니다. 모든 신호를 캡처하려면 특수 값'all'을 사용합니다.프로그램이 실행되도록 합니다.
프로그램의 실행을 시작하지 않은 경우 다음을 시작합니다.
(gdb) r프로그램 실행이 중지되면 다시 시작하십시오.
(gdb) c
- GDB는 프로그램이 지정된 신호를 수신한 후 실행을 중지합니다.
- 신호를 처리하는 프로그램 코드를 디버깅하거나 수신되는 신호에 대한 지식을 사용하여 실행을 재개합니다.
나중에 GDB 디버깅 세션을 종료하려면 다음을 수행합니다.
(gdb) q
3.4. Crashed 애플리케이션 디버깅 링크 복사링크가 클립보드에 복사되었습니다!
경우에 따라 애플리케이션을 직접 디버깅할 수 없습니다. 이러한 상황에서는 종료 시점에 애플리케이션에 대한 정보를 수집하여 나중에 분석할 수 있습니다.
3.4.1. 코어 덤프: What they are and how to use them 링크 복사링크가 클립보드에 복사되었습니다!
코어 덤프는 애플리케이션이 작동을 중지한 시점의 애플리케이션 메모리의 사본으로, ELF 형식으로 저장됩니다. 애플리케이션의 최종 상태를 검사할 수 있는 모든 애플리케이션의 내부 변수와 스택을 포함합니다. 해당 실행 파일 및 디버깅 정보로 보강되면 실행 중인 프로그램을 분석하는 것과 유사한 방식으로 디버거를 사용하여 코어 덤프 파일을 분석할 수 있습니다.
이 기능이 활성화된 경우 Linux 운영 체제 커널은 코어 덤프를 자동으로 기록할 수 있습니다. 또는 실행 중인 애플리케이션에 신호를 보내 실제 상태와 관계없이 코어 덤프를 생성할 수 있습니다.
일부 제한은 코어 덤프를 생성하는 기능에 영향을 미칠 수 있습니다. 현재 제한을 보려면 다음을 수행합니다.
$ ulimit -a
3.4.2. 코어 덤프와 함께 애플리케이션 충돌 링크 복사링크가 클립보드에 복사되었습니다!
애플리케이션 충돌을 기록하려면 코어 덤프 저장을 설정하고 시스템에 대한 정보를 추가합니다.
프로세스
코어 덤프를 활성화하려면
/etc/systemd/system.conf파일에 다음 행이 포함되어 있는지 확인합니다.DumpCore=yes DefaultLimitCORE=infinity이러한 설정이 이전에 있는지와 이전 값이 무엇인지 설명하는 주석을 추가할 수도 있습니다. 이렇게 하면 필요한 경우 나중에 이러한 변경 사항을 되돌릴 수 있습니다. 주석은
#문자로 시작하는 줄입니다.파일을 변경하려면 관리자 수준 액세스 권한이 필요합니다.
새 구성을 적용합니다.
# systemctl daemon-reexec코어 덤프 크기에 대한 제한을 제거합니다.
# ulimit -c unlimited이 변경 사항을 되돌리려면
무제한대신 값0을 사용하여 명령을 실행합니다.시스템 정보 수집을 위한
sosreport유틸리티를 제공하는sos패키지를 설치합니다.# dnf install sos-
애플리케이션이 충돌하면
systemd-coredump에서 코어 덤프가 생성되고 처리됩니다. SOS 보고서를 생성하여 시스템에 대한 추가 정보를 제공합니다.
# sosreport이렇게 하면 구성 파일의 사본과 같이 시스템에 대한 정보가 포함된
.tar아카이브가 생성됩니다.코어 덤프를 찾습니다.
$ coredumpctl list executable-name코어 덤프를 내보냅니다.
$ coredumpctl dump executable-name > /path/to/file-for-export애플리케이션이 여러 번 충돌하면 첫 번째 명령의 출력에 더 캡처된 코어 덤프가 나열됩니다. 이 경우 두 번째 명령에 대한 구성은 다른 정보를 사용하여 보다 정확한 쿼리를 구성합니다. 자세한 내용은 coredumpctl(1) 매뉴얼 페이지를 참조하십시오.
코어 덤프와 SOS 보고서를 디버깅이 수행되는 컴퓨터로 전송합니다. 알려진 경우 실행 가능한 파일도 전송합니다.
중요실행 파일을 알 수 없는 경우 코어 파일의 후속 분석이 해당 파일을 식별합니다.
- 선택 사항: 코어 덤프 및 SOS 보고서를 전송한 후 제거하여 디스크 공간을 확보합니다.
3.4.3. 코어 덤프를 사용하여 애플리케이션 충돌 상태 검사 링크 복사링크가 클립보드에 복사되었습니다!
사전 요구 사항
- 충돌이 발생한 시스템에서 코어 덤프 파일과 sosreport가 있어야 합니다.
- GDB 및 elfutils가 시스템에 설치되어 있어야 합니다.
프로세스
크래시가 발생한 실행 파일을 확인하려면 core dump 파일을 사용하여
eu-unstrip명령을 실행합니다.$ eu-unstrip -n --core=./core.98140x400000+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출력에는 한 줄에 있는 각 모듈에 대한 세부 정보가 공백으로 구분되어 있습니다. 정보는 다음 순서로 나열됩니다.
- 모듈이 매핑된 메모리 주소
- 모듈의 build-id 및 메모리에서 발견된 위치
-
모듈의 실행 파일 이름, 알 수 없는 경우
-로 표시되거나 파일에서 모듈이 로드되지 않은 경우. -
디버깅 정보의 소스, 사용 가능한 경우 파일 이름으로 표시됨, 실행 파일 자체에 포함된 경우 또는 전혀 존재하지 않는 경우
-
기본 모듈의 공유 라이브러리 이름(soname) 또는
[exe]
이 예에서 중요한 세부 사항은
[exe]텍스트가 포함된 행의/usr/bin/sleep및 build-id2818b2009547f780a5639c904cded443e564973e564973e입니다. 이 정보를 사용하면 코어 덤프 분석에 필요한 실행 파일을 확인할 수 있습니다.충돌이 발생한 실행 파일을 가져옵니다.
- 가능한 경우 충돌이 발생한 시스템에서 복사합니다. 코어 파일에서 추출한 파일 이름을 사용합니다.
시스템에서 동일한 실행 파일을 사용할 수도 있습니다. Red Hat Enterprise Linux에 빌드된 각 실행 파일에는 고유한 build-id 값이 있는 노트가 포함되어 있습니다. 로컬에서 사용 가능한 실행 파일의 빌드 ID를 확인합니다.
$ eu-readelf -n executable_file원격 시스템의 실행 파일을 로컬 사본과 일치시키려면 이 정보를 사용합니다. 코어 덤프에 나열된 로컬 파일 및 build-id의 build-id가 일치해야 합니다.
-
마지막으로 애플리케이션이 RPM 패키지에서 설치된 경우 패키지에서 실행 파일을 가져올 수 있습니다.
sosreport출력을 사용하여 필요한 정확한 버전의 패키지를 찾습니다.
- 실행 파일에서 사용하는 공유 라이브러리를 가져옵니다. 실행 파일에 대해 와 동일한 단계를 사용합니다.
- 애플리케이션이 패키지로 배포되는 경우 GDB에서 실행 파일을 로드하여 누락된 debuginfo 패키지에 대한 힌트를 표시합니다. 자세한 내용은 GDB를 사용하여 애플리케이션 또는 라이브러리의 debuginfo 패키지 가져오기를 참조하십시오.
코어 파일을 자세히 검사하려면 실행 파일 및 코어 덤프 파일을 GDB로 로드합니다.
$ gdb -e executable_file -c core_file누락된 파일 및 디버깅 정보에 대한 추가 메시지는 디버깅 세션에 누락된 항목을 식별하는 데 도움이 됩니다. 필요한 경우 이전 단계로 돌아갑니다.
애플리케이션의 디버깅 정보를 패키지 대신 파일로 사용할 수 있는 경우
기호 파일 명령을 사용하여 GDB에서 이 파일을 로드합니다.(gdb) symbol-file program.debugprogram.debug 를 실제 파일 이름으로 교체합니다.
참고코어 덤프에 포함된 모든 실행 파일에 대한 디버깅 정보를 설치할 필요가 없을 수 있습니다. 이러한 실행 파일의 대부분은 애플리케이션 코드에서 사용하는 라이브러리입니다. 이러한 라이브러리는 분석 중인 문제에 직접 기여하지 않을 수 있으며 이에 대한 디버깅 정보를 포함할 필요가 없습니다.
GDB 명령을 사용하여 충돌한 순간에 애플리케이션 상태를 검사합니다. GDB를 사용한 애플리케이션 내부 상태 검사를 참조하십시오.
참고코어 파일을 분석할 때 GDB는 실행 중인 프로세스에 연결되어 있지 않습니다. 실행을 제어하는 명령은 영향을 미치지 않습니다.
종료 시 애플리케이션 스택만 보려면
eu-stack유틸리티를 사용하여 코어 파일을 엽니다.$ *eu-stack --core __core-file__*그러면 애플리케이션 스택 목록이 표시됩니다.
추가 리소스
3.4.4. coredumpctl을 사용하여 코어 덤프 생성 및 액세스 링크 복사링크가 클립보드에 복사되었습니다!
systemd 의 coredumpctl 툴은 충돌이 발생한 시스템에서 코어 덤프 작업을 크게 간소화할 수 있습니다. 이 절차에서는 응답하지 않는 프로세스의 코어 덤프를 캡처하는 방법을 간략하게 설명합니다.
사전 요구 사항
코어 덤프 처리에
systemd-coredump를 사용하도록 시스템을 구성해야 합니다. 이것이 사실인지 확인하려면 다음을 수행하십시오.$ sysctl kernel.core_pattern출력이 다음과 같이 시작되면 구성이 올바르게 됩니다.
kernel.core_pattern = |/usr/lib/systemd/systemd-coredump
프로세스
실행 파일 이름의 알려진 부분에 따라 중단 프로세스의 PID를 찾습니다.
$ pgrep -a executable-name-fragment이 명령은 양식으로 행을 출력합니다.
PID command-line명령줄 값을 사용하여 PID 가 의도한 프로세스에 속하는지 확인합니다.
예를 들면 다음과 같습니다.
$ pgrep -a bc5459 bc중단 신호를 프로세스에 보냅니다.
# kill -ABRT PIDcoredumpctl에 의해 코어가 캡처되었는지 확인합니다.$ coredumpctl list PID예를 들면 다음과 같습니다.
$ coredumpctl list 5459TIME PID UID GID SIG COREFILE EXE Thu 2019-11-07 15:14:46 CET 5459 1000 1000 6 present /usr/bin/bc필요에 따라 코어 파일을 추가로 검사하거나 사용합니다.
PID 및 기타 값에 따라 코어 덤프를 지정할 수 있습니다. 자세한 내용은 coredumpctl(1) 매뉴얼 페이지를 참조하십시오.
다음 단계
코어 파일의 세부 정보를 표시하려면 다음을 실행합니다.
$ coredumpctl info PIDGDB 디버거에서 코어 파일을 로드하려면 다음을 실행합니다.
$ coredumpctl debug PID디버깅 정보의 가용성에 따라 GDB는 다음과 같이 실행할 명령을 제안할 수 있습니다.
Missing separate debuginfos, use: dnf debuginfo-install bc-1.07.1-23.el10.x86_64이 프로세스에 대한 자세한 내용은 GDB를 사용하여 애플리케이션 또는 라이브러리의 debuginfo 패키지 가져오기를 참조하십시오.
다른 위치에서 추가 처리를 위해 코어 파일을 내보내려면 다음을 실행합니다.
$ coredumpctl dump PID > /path/to/file_for_export/path/to/file_for_export 를 코어 덤프를 배치할 파일로 바꿉니다.
$ coredumpctl dump PID > /path/to/file_for_export
3.4.5. gcore를 사용하여 프로세스 메모리 덤프 링크 복사링크가 클립보드에 복사되었습니다!
코어 덤프 디버깅의 워크플로를 사용하면 프로그램의 상태를 오프라인으로 분석할 수 있습니다. 경우에 따라 프로세스로 환경에 액세스하기 어려울 때와 같이 여전히 실행 중인 프로그램과 함께 이 워크플로를 사용할 수 있습니다. gcore 명령을 사용하여 여전히 실행 중인 프로세스의 메모리를 덤프할 수 있습니다.
프로세스
프로세스 ID(pid)를 확인합니다.
ps,pgrep와 같은 도구를 사용하십시오.$ ps -C some-program이 프로세스의 메모리를 덤프합니다.
$ gcore -o filename pid이렇게 하면 파일 파일 이름이 생성되고 프로세스 메모리가 덤프됩니다. 메모리가 덤프되는 동안 프로세스의 실행이 중지됩니다.
- 코어 덤프가 완료되면 프로세스가 일반 실행을 다시 시작합니다.
SOS 보고서를 생성하여 시스템에 대한 추가 정보를 제공합니다.
# sosreport이렇게 하면 구성 파일의 사본과 같은 시스템에 대한 정보가 포함된 tar 아카이브가 생성됩니다.
- 프로그램의 실행 파일, 코어 덤프 및 SOS 보고서를 디버깅이 수행되는 컴퓨터로 전송합니다.
- 선택 사항: 코어 덤프 및 SOS 보고서를 전송한 후 제거하여 디스크 공간을 확보합니다.
3.4.6. GDB를 사용하여 보호된 프로세스 메모리 덤프 링크 복사링크가 클립보드에 복사되었습니다!
프로세스 메모리를 덤프하지 않도록 표시할 수 있습니다. 이렇게 하면 프로세스 메모리에 민감한 데이터(예: 뱅킹 또는 회계 애플리케이션 또는 전체 가상 머신)가 포함된 경우 리소스를 저장하고 추가 보안을 보장할 수 있습니다. 커널 코어 덤프(kdump)와 수동 코어 덤프(gcore, GDB) 모두 이러한 방식으로 표시된 메모리를 덤프하지 않습니다.
경우에 따라 이러한 보호에 관계없이 프로세스 메모리의 전체 내용을 덤프해야 합니다. 이 절차에서는 GDB 디버거를 사용하여 이 작업을 수행하는 방법을 설명합니다.
프로세스
/proc/PID/coredump_filter파일의 설정을 무시하려면 GDB를 설정합니다.(gdb) set use-coredump-filter off메모리 페이지 플래그를
VM_DONTDUMP: 무시하도록 GDB를 설정합니다.(gdb) set dump-excluded-mappings on메모리를 덤프합니다.
(gdb) gcore core-filecore-file 을 메모리를 덤프하려는 파일 이름으로 교체합니다.
3.5. 컨테이너에서 애플리케이션 디버깅 링크 복사링크가 클립보드에 복사되었습니다!
문제 해결의 다양한 측면에 맞는 다양한 명령줄 툴을 사용할 수 있습니다. 다음은 일반적인 명령줄 툴과 함께 카테고리를 제공합니다.
이는 명령줄 툴의 전체 목록이 아닙니다. 컨테이너 애플리케이션을 디버깅하기 위한 툴 선택은 컨테이너 이미지와 사용 사례에 따라 크게 달라집니다.
예를 들어 systemctl,journalctl,ip,netstat,ping,traceroute,perf,iostat 툴에서는 보안상의 이유로 rootless 컨테이너에서 제한되는 네트워킹, systemd 서비스 또는 하드웨어 성능 카운터와 같은 시스템 수준 리소스와 상호 작용하므로 루트 액세스 권한이 필요할 수 있습니다.
루트리스 컨테이너는 승격된 권한이 필요 없이 작동하여 사용자 네임스페이스 내에서 루트가 아닌 사용자로 실행하여 호스트 시스템에서 향상된 보안 및 격리를 제공합니다. 호스트와의 제한된 상호 작용, 공격 면적 감소 및 보안 강화를 통해 권한 상승 취약점의 위험을 완화합니다.
루트 저장 컨테이너는 일반적으로 루트 사용자로 승격된 권한으로 실행되며 시스템 리소스 및 기능에 대한 전체 액세스 권한을 부여합니다. 근본 컨테이너는 유연성 및 제어 기능을 제공하지만 권한 상승 및 호스트 시스템의 취약점으로 인해 보안 위험이 발생합니다.
rootful 및 rootless 컨테이너에 대한 자세한 내용은 podman RHEL 시스템 역할 및 rootless 컨테이너에 대한 특수 고려 사항을 사용하여 바인딩 마운트를 사용하여 rootless 컨테이너 생성 을 참조하십시오.
- systemd 및 프로세스 관리 툴
-
systemctl: 컨테이너 내에서 systemd 서비스를 제어하여 시작, 중지, 활성화 및 작업을 비활성화합니다.journalctl: systemd 서비스에서 생성한 로그를 확인하여 컨테이너 문제 해결을 지원합니다. - 네트워킹 툴
-
IP: 컨테이너 내에서 네트워크 인터페이스, 라우팅 및 주소를 관리합니다.netstat: 네트워크 연결, 라우팅 테이블 및 인터페이스 통계를 표시합니다.Ping: 컨테이너 또는 호스트 간의 네트워크 연결을 확인합니다.traceroute: 네트워크 문제를 진단하는 데 유용한 경로에 도달하는 데 걸리는 경로를 식별합니다. - 프로세스 및 성능 툴
-
ps: 컨테이너 내에서 현재 실행 중인 프로세스를 나열합니다.top: 컨테이너 내 프로세스의 리소스 사용량에 대한 실시간 정보를 제공합니다.htop: 리소스 사용률을 모니터링하기 위한 대화형 프로세스 뷰어입니다.perf: CPU 성능 프로파일링, 추적 및 모니터링은 시스템 또는 애플리케이션 내에서 성능 병목 현상을 정확하게 파악하는 데 도움이 됩니다.vmstat: 컨테이너 내의 가상 메모리 통계를 보고하여 성능 분석을 지원합니다.iostat: 컨테이너 내 블록 장치에 대한 입력/출력 통계를 모니터링합니다.GDB(GNU Debugger): 사용자가 실행을 추적 및 제어하고, 변수를 검사하며, 런타임 중에 메모리를 분석하고, 등록할 수 있도록 하여 프로그램을 검사하고 디버깅하는 데 도움이 되는 명령줄 디버거입니다. 자세한 내용은 Red Hat OpenShift 컨테이너 내에서 애플리케이션 디버깅 문서를 참조하십시오.strace: 프로그램에서 수행한 시스템 호출을 인터셉트하고 기록하므로 프로그램과 운영 체제 간의 상호 작용을 표시하여 문제를 해결할 수 있습니다. - 보안 및 액세스 제어 도구
-
sudo: 승격된 권한으로 명령을 실행할 수 있습니다.chroot: 명령의 루트 디렉토리를 변경하여 다른 루트 디렉터리 내에서 테스트 또는 문제 해결에 유용합니다. - podman-Specific Tools
-
podman logs: 실행 시 하나 이상의 컨테이너에 존재하는 로그를 모두 표시합니다.podman inspect: 이름 또는 ID로 식별된 컨테이너 및 이미지에 대한 하위 수준 정보를 표시합니다.Podman 이벤트: Podman에서 발생하는 이벤트를 모니터링하고 출력합니다. 각 이벤트에는 타임스탬프, 유형, 상태, 이름(해당되는 경우) 및 이미지(해당되는 경우)가 포함됩니다. 기본 로깅 메커니즘은journald입니다.podman run --health-cmd: 상태 점검을 사용하여 컨테이너 내부에서 실행되는 프로세스의 상태 또는 준비 상태를 확인합니다.podman top: 실행 중인 컨테이너 프로세스를 표시합니다.podman exec: 실행 중인 컨테이너에서 명령을 실행하거나 실행 중인 컨테이너에 연결하는 것은 컨테이너에서 발생하는 상황을 더 잘 이해할 수 있도록 매우 유용합니다.Podman 내보내기: 컨테이너가 실패하면 기본적으로 어떤 일이 발생했는지 알 수 없습니다. 컨테이너에서 파일 시스템 구조를 내보내면 마운트된 볼륨에 없는 다른 로그 파일을 확인할 수 있습니다.
4장. 개발을 위한 추가 툴 세트 링크 복사링크가 클립보드에 복사되었습니다!
C 및 C++ 개발을 위한 추가 툴셋은 애플리케이션 빌드, 분석 및 최적화를 위한 기능을 제공합니다. 이러한 툴셋을 사용하면 개발 워크플로를 정의하고 애플리케이션 품질을 개선할 수 있습니다.
4.1. GCC Toolset 사용 링크 복사링크가 클립보드에 복사되었습니다!
4.1.1. GCC Toolset이란 무엇입니까? 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux 10에는 업데이트된 개발 및 성능 분석 도구가 포함된 Application Stream인 GCC Toolset이 도입되었습니다. GCC Toolset은 Red Hat Developer Toolset 과 유사합니다.
GCC Toolset은 AppStream 리포지토리의 소프트웨어 컬렉션 형태로 Application Stream으로 사용할 수 있습니다. GCC Toolset은 Red Hat Enterprise Linux 서브스크립션 수준 계약에서 완전하게 지원되며 기능적으로 완전하며 프로덕션 용도로 사용됩니다. GCC Toolset에서 제공하는 애플리케이션 및 라이브러리는 Red Hat Enterprise Linux 시스템 버전을 대체하지 않으며 재정의하지 않으며 자동으로 기본 설정되거나 선호되지 않습니다. 소프트웨어 컬렉션이라는 프레임워크를 사용하면 추가 개발자 도구 세트가 /opt/ 디렉터리에 설치되고 사용자가 필요에 따라 scl 유틸리티를 사용하여 명시적으로 활성화합니다. 특정 도구 또는 기능에 대해 별도로 명시하지 않는 한 Red Hat Enterprise Linux에서 지원하는 모든 아키텍처에서 GCC 도구 세트를 사용할 수 있습니다.
지원 기간에 대한 자세한 내용은 Red Hat Enterprise Linux Application Streams 라이프 사이클 을 참조하십시오.
4.1.2. GCC Toolset 설치 링크 복사링크가 클립보드에 복사되었습니다!
시스템에 GCC Toolset을 설치하면 주요 툴과 필요한 모든 종속 항목이 설치됩니다. 툴셋의 일부는 기본적으로 설치되지 않으며 별도로 설치해야 합니다.
프로세스
GCC Toolset 버전 N 을 설치하려면 다음을 수행합니다.
# dnf install gcc-toolset-N
4.1.3. GCC Toolset에서 개별 패키지 설치 링크 복사링크가 클립보드에 복사되었습니다!
전체 도구 세트 대신 GCC Toolset의 특정 툴만 설치하려면 사용 가능한 패키지를 나열하고 dnf 패키지 관리 도구를 사용하여 선택한 툴을 설치합니다. 이 절차는 툴셋과 함께 기본적으로 설치되지 않은 패키지에도 유용합니다.
프로세스
GCC Toolset 버전 N:에서 사용할 수 있는 패키지를 나열합니다.
$ dnf list available gcc-toolset-N-\다음 패키지를 설치하려면 다음을 수행합니다.
# dnf install package_namepackage_name 을 설치할 패키지 목록으로 바꿉니다. 예를 들어
gcc-toolset-15-annobin-annocheck및gcc-toolset-15-binutils-devel패키지를 설치하려면 다음을 수행합니다.# dnf install gcc-toolset-15-annobin-annocheck gcc-toolset-15-binutils-devel
4.1.4. GCC Toolset 설치 제거 링크 복사링크가 클립보드에 복사되었습니다!
시스템에서 GCC Toolset을 제거하려면 dnf 패키지 관리 툴을 사용하여 제거합니다.
프로세스
GCC Toolset 버전 N 을 제거하려면 다음을 수행합니다.
# dnf remove gcc-toolset-N \
4.1.5. GCC Toolset에서 툴 실행 링크 복사링크가 클립보드에 복사되었습니다!
GCC Toolset에서 툴을 실행하려면 scl 유틸리티를 사용합니다.
프로세스
GCC Toolset 버전 N:에서 툴 버전을 확인하십시오.
$ gcc-toolset-N-env gcc --versionGCC Toolset 버전 N 에서 툴을 실행합니다.
$ gcc-toolset-N-env tool예를 들어 GCC Toolset 버전 15에서
gcc툴을 실행하려면 다음을 실행합니다.$ gcc-toolset-15-env gcc --versionGCC Toolset 버전 15에서
make툴을 실행하려면 다음을 수행합니다.$ gcc-toolset-15-env make -j4
4.1.6. GCC Toolset으로 쉘 세션 실행 링크 복사링크가 클립보드에 복사되었습니다!
GCC Toolset을 사용하면 명시적으로 scl 명령을 사용하지 않고 GCC Toolset 툴 버전이 이러한 툴의 시스템 버전 대신 사용되는 쉘 세션을 실행할 수 있습니다. 이 기능은 개발 설정을 설정하거나 테스트할 때와 같이 대화형으로 도구를 여러 번 시작해야 하는 경우에 유용합니다.
프로세스
GCC Toolset 버전의 툴 버전이 다음 툴의 시스템 버전을 재정의하는 쉘 세션을 실행하려면 다음을 수행합니다.
$ gcc-toolset-N-env bash예를 들어 GCC Toolset 버전 15의 도구가 이러한 툴의 시스템 버전을 재정의하는 쉘 세션을 실행하려면 다음을 수행합니다.
$ gcc-toolset-15-env bash참고scl유틸리티는 Red Hat Enterprise Linux 10의 GCC Toolset에는 사용되지 않습니다.scl enable명령은 GCC Toolset에서 작동하지 않습니다.
4.2. GCC Toolset 15 링크 복사링크가 클립보드에 복사되었습니다!
Red Hat Enterprise Linux의 GCC 도구 세트 15는 C, C++ 및 Fortran에 대한 업데이트된 컴파일러 및 디버거를 제공합니다. 이를 통해 시스템 안정성 및 지원을 유지하면서 현재 기능을 사용하여 애플리케이션을 빌드, 테스트 및 최적화할 수 있습니다.
4.2.1. GCC Toolset 15 툴 및 버전 링크 복사링크가 클립보드에 복사되었습니다!
GCC Toolset 15는 RHEL에서 애플리케이션을 빌드하고 디버깅하기 위한 업데이트된 개발 툴 버전을 제공합니다. 다음 표에는 툴과 해당 버전이 나열되어 있습니다.
- [도구 목록]
| 이름 | 버전 | 설명 |
| GCC | 15.1.0 | C, C++ 및 Fortran을 지원하는 이식 가능한 컴파일러 제품군입니다. |
| binutils | 2.44 | 오브젝트 파일 및 바이너리를 검사하고 조작하는 바이너리 툴 및 기타 유틸리티 컬렉션입니다. |
| dwz | 0.16 | ELF 공유 라이브러리 및 ELF 실행 파일에 포함된 DWARF 디버깅 정보를 최적화하는 툴입니다. |
4.2.2. GCC Toolset 15의 C++ 호환성 링크 복사링크가 클립보드에 복사되었습니다!
GCC Toolset 15는 다양한 C++ 언어 표준을 지원합니다. 기본 표준은 C++17이지만 C++98, C++11, C++14 또는 C++20, C++23, C++26과 같은 다른 옵션을 선택할 수 있습니다. 다른 표준을 선택하려면 코드를 빌드할 때 적절한 컴파일러 플래그를 사용하십시오.
이 호환성 정보는 GCC Toolset 15의 GCC에만 적용됩니다.
GCC Toolset 15의 GCC 컴파일러는 다음 C++ 표준을 사용할 수 있습니다.
- C++98
- 이 언어 표준은 GCC Toolset 15에서 사용할 수 있습니다. 이 표준을 사용하여 구축된 바이너리, 공유 라이브러리 및 오브젝트는 GCC Toolset 15, Red Hat Developer Toolset 및 RHEL 5, 6, 7, 8의 GCC와 함께 빌드할지 여부에 관계없이 자유롭게 혼합할 수 있습니다.
- C++11
이 언어 표준은 GCC Toolset 15에서 사용할 수 있습니다.
C++11 언어 버전 사용은 해당 플래그로 컴파일된 모든 C++ 오브젝트가 GCC 버전 5 이상을 사용하여 빌드된 경우 지원됩니다.
- C++14
이 언어 표준은 GCC Toolset 15에서 사용할 수 있습니다.
C++14 언어 버전 사용은 해당 플래그로 컴파일된 모든 C++ 오브젝트가 GCC 버전 6 이상을 사용하여 빌드된 경우 지원됩니다.
- C++17
이 언어 표준은 GCC Toolset 15에서 사용할 수 있습니다.
이는 GNU 확장이 포함된 GCC Toolset 15의 기본 언어 표준 설정이며
-std=gnu++17옵션을 사용하는 것과 동일합니다.C++17 언어 버전 사용은 해당 플래그로 컴파일된 모든 C++ 오브젝트가 GCC 버전 10 이상을 사용하여 빌드된 경우 지원됩니다.
- C++20, C++23, C++26
이러한 언어 표준은 실험적이고 불안정하며 지원되지 않는 기능으로만 GCC Toolset 15에서 사용할 수 있습니다. 또한 이러한 표준을 사용하여 구축된 오브젝트, 바이너리 파일 및 라이브러리의 호환성은 보장할 수 없습니다.
C++20 표준을 활성화하려면 명령줄 옵션
-std=c++20을g++명령줄에 추가합니다.C++23 표준을 활성화하려면 명령줄 옵션
-std=c++23을g++명령줄에 추가합니다.C++26 표준을 활성화하려면
g++명령줄 명령줄에-std=c++26명령줄을 추가합니다.
모든 언어 표준은 표준 호환 변형과 GNU 확장 모두에서 사용할 수 있습니다.
GCC Toolset 15로 빌드된 개체와 시스템 툴체인, particular .o 또는 .a 파일로 빌드된 오브젝트를 결합할 때 GCC Toolset 15를 사용하십시오. 이렇게 하면 GCC Toolset 15에서만 제공하는 최신 라이브러리 기능이 링크 타임에 해결될 수 있습니다.
4.2.3. GCC 도구 세트 15의 GCC 세부 사항 링크 복사링크가 클립보드에 복사되었습니다!
- 라이브러리의 정적 연결
- 보다 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset 15로 구축된 애플리케이션에 정적으로 연결되어 있습니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
- 연결할 때 오브젝트 파일 후 라이브러리 지정
GCC Toolset 15에서 라이브러리는 linker 스크립트를 사용하여 연결되며 정적 아카이브를 통해 일부 기호를 지정할 수 있습니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하기 위해 필요합니다. 그러나 링커 스크립트는 해당 공유 오브젝트 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하고 오브젝트 파일을 추가하는 옵션이 오브젝트 파일을 지정하기 전에 라이브러리를 추가하는 옵션이 지정되면 오브젝트 파일에 필요한 기호를 인식하지 못합니다.
$ gcc-toolset-15-env gcc -lsomelib objfile.o이러한 방식으로 GCC Toolset 15의 라이브러리를 사용하면 링커 오류 메시지가
기호에 대한 정의되지 않은 참조가 발생합니다. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리를 추가하여 옵션을 지정합니다.$ gcc-toolset-15-env gcc objfile.o -lsomelib이 권장 사항은 GCC 의 기본 Red Hat Enterprise Linux 버전을 사용하는 경우에도 적용됩니다.
4.2.4. GCC Toolset 15의 binutils 세부 사항 링크 복사링크가 클립보드에 복사되었습니다!
- 라이브러리의 정적 연결
- GCC Toolset 15는 최신 라이브러리 기능을 애플리케이션에 정적으로 연결하여 여러 Red Hat Enterprise Linux 버전에서 호환성을 보장합니다. 보안 업데이트를 다시 빌드해야 하므로 정적으로 연결된 코드는 사소한 보안 위험이 발생할 수 있습니다. 보안 취약점이 발견되면 Red Hat은 개발자에게 보안 권고를 통해 영향을 받는 애플리케이션을 다시 빌드하도록 알립니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
- 연결할 때 오브젝트 파일 후 라이브러리 지정
GCC Toolset 15에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하기 위해 필요합니다. 그러나 링커 스크립트는 해당 공유 오브젝트 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하고 오브젝트 파일을 추가하는 옵션이 오브젝트 파일을 지정하기 전에 라이브러리를 추가하는 옵션이 지정되면 오브젝트 파일에 필요한 기호를 인식하지 못합니다.
$ gcc-toolset-15-env gcc ld -lsomelib objfile.o이러한 방식으로 GCC Toolset 15의 라이브러리를 사용하면 링커 오류 메시지가
기호에 대한 정의되지 않은 참조가 발생합니다. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리를 추가하는 옵션을 지정합니다.$ gcc-toolset-15-env ld objfile.o -lsomelib이 권장 사항은 binutils 의 기본 Red Hat Enterprise Linux 버전을 사용하는 경우에도 적용됩니다.
4.2.5. GCC Toolset 15의 annobin 세부 사항 링크 복사링크가 클립보드에 복사되었습니다!
경우에 따라 GCC Toolset 15의 annobin 과 gcc 간의 동기화 문제로 인해 다음과 유사한 오류 메시지와 함께 컴파일이 실패할 수 있습니다.
cc1: fatal error: inaccessible plugin file
opt/rh/gcc-toolset-15/root/usr/lib/gcc/_architecture_-linux-gnu/15/plugin/gcc-annobin.so
expanded from short plugin name gcc-annobin: No such file or directory
플러그인 디렉터리로 변경합니다.
$ cd /opt/rh/gcc-toolset-15/root/usr/lib/gcc/architecture-linux-gnu/15/pluginannobin.so에서
gcc-에 심볼릭 링크를 만듭니다.annobin.so$ ln -s annobin.so gcc-annobin.so
아키텍처를 시스템에서 사용되는 아키텍처로 교체합니다.
-
aarch64 -
i686 -
ppc64le -
s390x -
x86_64
4.3. 컴파일러 툴셋 링크 복사링크가 클립보드에 복사되었습니다!
RHEL 10에서는 다음과 같은 컴파일러 툴셋을 Application Streams로 제공합니다.
- LLVM Toolset은 LLVM 컴파일러 인프라 프레임워크, C 및 C++ 언어용 Clang 컴파일러, LLDB 디버거 및 코드 분석을 위한 관련 툴을 제공합니다.
-
rust Toolset은 Rust 프로그래밍 언어 컴파일러
rustc, 빌드 툴 및 종속성 관리자, 즉벤더 플러그인및 필수 라이브러리를 제공합니다. -
Go Toolset은 Go 프로그래밍 언어 도구 및 라이브러리를 제공합니다. Go는
golang이라고 합니다.
사용법에 대한 자세한 내용 및 자세한 내용은 Red Hat Developer Tools 페이지에서 컴파일러 툴셋 사용자 가이드를 참조하십시오.
4.4. Annobin 프로젝트 링크 복사링크가 클립보드에 복사되었습니다!
Annobin 프로젝트는 Watermark 사양 프로젝트의 구현입니다. 워터마크 사양 프로젝트는 속성을 결정하기 위해 Executable 및 Linkable Format (ELF) 오브젝트에 마커를 추가하려고 합니다. Annobin 프로젝트는 annobin 플러그인과 annock Cryostat 프로그램으로 구성됩니다.
annobin 플러그인은 GNU 컴파일러 컬렉션(GCC) 명령줄, 컴파일 상태 및 컴파일 프로세스를 스캔하고 ELF 노트를 생성합니다. ELF 노트는 바이너리가 빌드된 방법을 기록하고 보안 강화 검사를 수행하기 위한 annocheck 프로그램에 대한 정보를 제공합니다.
보안 강화 검사기는 annocheck 프로그램의 일부이며 기본적으로 활성화되어 있습니다. 바이너리 파일을 확인하여 프로그램이 필요한 보안 강화 옵션으로 빌드되었는지 여부를 확인하고 올바르게 컴파일되었는지 확인합니다. annocheck 는 ELF 오브젝트 파일의 디렉토리, 아카이브 및 RPM 패키지를 재귀적으로 검사할 수 있습니다.
파일은 ELF 형식이어야 합니다. annocheck 는 다른 바이너리 파일 유형을 처리하지 않습니다.
다음 섹션에서는 다음을 수행하는 방법을 설명합니다.
-
annobin플러그인 사용 -
annocheck프로그램 사용 -
중복
annobin노트 제거
4.4.1. annobin 플러그인 사용 링크 복사링크가 클립보드에 복사되었습니다!
다음 섹션에서는 다음을 수행하는 방법을 설명합니다.
-
annobin플러그인 활성화 -
annobin플러그인에 옵션을 전달
4.4.1.1. annobin 플러그인 활성화 링크 복사링크가 클립보드에 복사되었습니다!
다음 섹션에서는 gcc 및 clang 을 통해 annobin 플러그인을 활성화하는 방법을 설명합니다.
프로세스
gcc로annobin플러그인을 활성화하려면 다음을 사용합니다.$ gcc -fplugin=annobingcc가annobin플러그인을 찾을 수 없는 경우 다음을 사용합니다.$ gcc -iplugindir=/path/to/directory/containing/annobin//path/to/directory/containing/annobin/ 을
annobin이 포함된 디렉토리의 절대 경로로 바꿉니다.annobin플러그인이 포함된 디렉터리를 찾으려면 다음을 사용합니다.$ gcc --print-file-name=plugin
clang을 사용하여annobin플러그인을 활성화하려면 다음을 사용합니다.$ clang -fplugin=/path/to/directory/containing/annobin//path/to/directory/containing/annobin/ 을
annobin이 포함된 디렉토리의 절대 경로로 바꿉니다.
4.4.1.2. annobin 플러그인에 옵션 전달 링크 복사링크가 클립보드에 복사되었습니다!
다음 섹션에서는 gcc 및 clang 을 통해 annobin 플러그인에 옵션을 전달하는 방법을 설명합니다.
프로세스
gcc를 사용하여annobin플러그인에 옵션을 전달하려면 다음을 사용합니다.$ gcc -fplugin=annobin -fplugin-arg-annobin-option file-name옵션을
annobin명령줄 인수로 바꾸고 file-name 을 파일 이름으로 교체합니다.예를 들어
annobin이 수행하는 작업에 대한 추가 세부 정보를 표시하려면 다음을 사용합니다.$ gcc -fplugin=annobin -fplugin-arg-annobin-verbose file-namefile-name 을 파일 이름으로 교체합니다.
clang을 사용하여annobin플러그인에 옵션을 전달하려면 다음을 사용합니다.$ clang -fplugin=/path/to/directory/containing/annobin/ -Xclang -plugin-arg-annobin -Xclang option file-name옵션을
annobin명령줄 인수로 바꾸고 /path/to/directory/containing/annobin/ 을annobin이 포함된 디렉터리의 절대 경로로 바꿉니다.예를 들어
annobin이 수행하는 작업에 대한 추가 세부 정보를 표시하려면 다음을 사용합니다.$ clang -fplugin=/usr/lib64/clang/10/lib/annobin.so -Xclang -plugin-arg-annobin -Xclang verbose file-namefile-name 을 파일 이름으로 교체합니다.
4.4.2. annocheck 프로그램 사용 링크 복사링크가 클립보드에 복사되었습니다!
다음 섹션에서는 annocheck 를 사용하여 검사하는 방법을 설명합니다.
- 파일
- 디렉터리
- RPM 패키지
-
annocheck추가 도구
ELF 오브젝트 파일의 디렉토리, 아카이브 및 RPM 패키지를 재귀적으로 검사합니다. 파일은 ELF 형식이어야 합니다. annocheck 는 다른 바이너리 파일 유형을 처리하지 않습니다.
4.4.2.1. annocheck를 사용하여 파일 검사 링크 복사링크가 클립보드에 복사되었습니다!
다음 섹션에서는 nocheck를 사용하여 ELF 파일을 검사하는 방법을 설명합니다.
프로세스
파일을 검사하려면 다음을 사용합니다.
$ annocheck file-namefile-name 을 파일 이름으로 교체합니다.
참고파일은 ELF 형식이어야 합니다.
annocheck는 다른 바이너리 파일 유형을 처리하지 않습니다.annocheck는 ELF 오브젝트 파일이 포함된 정적 라이브러리를 처리합니다.
4.4.2.2. annocheck를 사용하여 디렉토리 검사 링크 복사링크가 클립보드에 복사되었습니다!
다음 섹션에서는 nocheck 를 사용하여 디렉터리에서 ELF 파일을 검사하는 방법을 설명합니다.
프로세스
디렉터리를 스캔하려면 다음을 사용합니다.
$ annocheck directory-namedirectory-name 을 디렉터리 이름으로 교체합니다.
annocheck는 디렉터리의 콘텐츠, 하위 디렉터리 및 디렉터리 내의 모든 아카이브 및 RPM 패키지를 자동으로 검사합니다.참고annocheck는 ELF 파일만 찾습니다. 다른 파일 유형은 무시됩니다.
4.4.2.3. annocheck를 사용하여 RPM 패키지 검사 링크 복사링크가 클립보드에 복사되었습니다!
다음 섹션에서는 nocheck 를 사용하여 RPM 패키지에서 ELF 파일을 검사하는 방법을 설명합니다.
프로세스
RPM 패키지를 스캔하려면 다음을 사용합니다.
$ annocheck rpm-package-namerpm-package-name 을 RPM 패키지 이름으로 교체합니다.
annocheck는 RPM 패키지 내의 모든 ELF 파일을 재귀적으로 검사합니다.참고annocheck는 ELF 파일만 찾습니다. 다른 파일 유형은 무시됩니다.제공된 debug info RPM으로 RPM 패키지를 스캔하려면 다음을 사용합니다.
$ annocheck rpm-package-name --debug-rpm debuginfo-rpmrpm-package-name 을 RPM 패키지 이름으로 바꾸고 debuginfo-rpm 을 바이너리 RPM과 연결된 디버그 정보 RPM 이름으로 교체합니다.
4.4.2.4. annocheck 추가 툴 사용 링크 복사링크가 클립보드에 복사되었습니다!
annocheck 에는 바이너리 파일을 검사하는 데 필요한 여러 툴이 포함되어 있습니다. 명령줄 옵션을 사용하여 이러한 도구를 활성화할 수 있습니다.
다음 섹션에서는 다음을 활성화하는 방법을 설명합니다.
-
내장도구 -
참고도구 -
섹션 크기도구
여러 툴을 동시에 활성화할 수 있습니다.
강화 검사기는 기본적으로 활성화되어 있습니다.
4.4.2.4.1. 내장 툴 활성화 링크 복사링크가 클립보드에 복사되었습니다!
annocheck 내장 툴을 사용하여 바이너리 파일을 빌드한 컴파일러의 이름을 찾을 수 있습니다.
프로세스
내장 툴을활성화하려면 다음을 사용합니다.$ annocheck --enable-built-by기본툴에 대한 자세한 내용은--help명령줄 옵션을 참조하십시오.
4.4.2.4.2. 노트 도구 활성화 링크 복사링크가 클립보드에 복사되었습니다!
annocheck 노트 도구를 사용하여 annobin 플러그인에서 생성한 바이너리 파일 내에 저장된 노트를 표시할 수 있습니다.
프로세스
노트도구를 활성화하려면 다음을 사용합니다.$ annocheck --enable-notes노트는 주소 범위별로 정렬된 순서로 표시됩니다.
노트도구에 대한 자세한 내용은--help명령줄 옵션을 참조하십시오.
4.4.2.4.3. section-size 툴 활성화 링크 복사링크가 클립보드에 복사되었습니다!
annocheck 섹션 크기 툴을 사용하여 이름이 지정된 섹션의 크기를 표시할 수 있습니다.
프로세스
section-size툴을 활성화하려면 다음을 사용합니다.$ annocheck --section-size=namename 을 named 섹션의 이름으로 바꿉니다. 출력은 특정 섹션으로 제한됩니다. 결국 누적 결과가 생성됩니다.
섹션 크기도구에 대한 자세한 내용은--help명령줄 옵션을 참조하십시오.
4.4.2.4.4. 강화 검사 기본 사항 링크 복사링크가 클립보드에 복사되었습니다!
강화 검사기는 기본적으로 활성화되어 있습니다. --disable-hardened 명령줄 옵션을 사용하여 강화 검사기를 비활성화할 수 있습니다.
4.4.2.4.4.1. 강화 검사 옵션 링크 복사링크가 클립보드에 복사되었습니다!
annocheck 프로그램은 다음 옵션을 확인합니다.
-
이제 -z링커 옵션을 사용하여 lazy 바인딩이 비활성화됩니다. - 프로그램은 실행 가능한 메모리 영역에 스택이 없습니다.
- GOT 테이블의 재배치는 읽기 전용으로 설정됩니다.
- 프로그램 세그먼트에는 읽기, 쓰기 및 실행 권한 비트 세트가 3개 모두 없습니다.
- 실행 가능한 코드에 대한 재배치는 없습니다.
- 런타임에 공유 라이브러리를 찾는 runpath 정보에는 /usr에서 root로 지정된 디렉터리만 포함됩니다.
-
이 프로그램은
annobin노트를 사용하여 컴파일되었습니다. -
프로그램은
-fstack-protector-strong옵션을 활성화하여 컴파일되었습니다. -
이 프로그램은
-D_FORTIFY_SOURCE=2로 컴파일되었습니다. -
이 프로그램은
-D_GLIBCXX_ASSERTIONS로 컴파일되었습니다. -
프로그램은
-fexceptions가 활성화된 상태로 컴파일되었습니다. -
이 프로그램은
-fstack-clash-protection을 활성화하여 컴파일되었습니다. -
이 프로그램은
-O2이상에서 컴파일되었습니다. - 이 프로그램에는 쓰기 가능한 재할당이 없습니다.
- 동적 실행 파일에는 동적 세그먼트가 있습니다.
-
공유 라이브러리는
-fPIC또는-fPIE로 컴파일되었습니다. -
동적 실행 파일은
-fPIE로 컴파일되고-pie와 연결되어 있습니다. -
사용 가능한 경우
-fcf-protection=full옵션이 사용되었습니다. -
사용 가능한 경우
-mbranch-protection옵션이 사용됩니다. -
사용 가능한 경우
-mstackrealign옵션이 사용됩니다.
4.4.2.4.4.2. 강화 검사기 비활성화 링크 복사링크가 클립보드에 복사되었습니다!
다음 섹션에서는 강화 검사기를 비활성화하는 방법을 설명합니다.
프로세스
강화 검사기 없이 파일의 노트를 스캔하려면 다음을 사용합니다.
$ annocheck --enable-notes --disable-hardened file-namefile-name 을 파일 이름으로 교체합니다.
4.4.3. 중복 annobin 노트 제거 링크 복사링크가 클립보드에 복사되었습니다!
annobin 을 사용하면 바이너리 크기가 증가합니다. annobin으로 컴파일된 바이너리의 크기를 줄이기 위해 중복 노트를 제거할 수 있습니다. 중복 annobin annobin 노트를 제거하려면 binutils 패키지의 일부인 objcopy 프로그램을 사용합니다.
프로세스
중복
annobin노트를 제거하려면 다음을 사용합니다.$ objcopy --merge-notes file-namefile-name 을 파일 이름으로 교체합니다.
5장. RHEL 10에서 주요 변경 사항 링크 복사링크가 클립보드에 복사되었습니다!
다음은 RHEL 10에서 발생하는 중요한 변경 사항입니다.
5.1. C++의 변경 사항 중단 링크 복사링크가 클립보드에 복사되었습니다!
std::condition_variable::wait는 이제 스레드 취소 지점입니다.-
GCC 11 및 이전 버전에서는
std::condition_variable::wait함수가제외되어 스레드 취소와 호환되지 않았습니다. 결과적으로pthread_cancel에 대한 호출이std::condition_variable::wait에서 차단된 스레드를 취소하면 프로세스가 종료됩니다. GCC 12 이상에서는 스택을 풀링 해제하는pthread_cancel함수에 대한 호출을 통해std::condition_variable::wait를 취소할 수 있습니다. 대기에 의존하는 코드가 있는 경우 예외를 throw하지 않는 경우 코드를 검토하고 적절한 작업을 수행합니다. - 더 이상 사용되지 않는 클래스 템플릿, 특정 클래스 템플릿은 새로운 버전의 C++에서 더 이상 사용되지 않으며 GCC 12 이상에서 경고 진단을 생성합니다.
다음 클래스 템플릿은 C++11 이상에서 더 이상 사용되지 않습니다.
-
std::unary_function -
std::binary_function
-
-
std::iterator클래스 템플릿이 C++17 이상에서 더 이상 사용되지 않습니다.
경고 진단을 방지하려면 다음 작업 중 하나를 수행할 수 있습니다.
코드를 다른 변경을 수행하지 않으려면 GCC의 진단 실습을 사용하여 경고 진단을 음소거하십시오. 예를 들면 다음과 같습니다.
#pragma GCC diagnostic push #pragma GCC diagnostic ignored “-Wdeprecated-declarations" class Functor : public std::unary_function<int, int> { /* … */ }; #pragma GCC diagnostic pop코드가 이후 버전의 C++와 호환되도록 하려면 코드에서 이러한 클래스 템플릿을 중첩된 typedefs로 교체합니다. 예를 들어
std::unary_function기본 클래스를result_type및argument_typetypedefs로 교체할 수 있습니다.class Functor { using result_type = int; using argument_type = int; /* … */ };
5.2. glibc에 대한 변경 사항 중단 링크 복사링크가 클립보드에 복사되었습니다!
- 동적 링커에서 공유 오브젝트를 찾는 방법 변경
다음 목록에서는 동적 링커 검색 알고리즘의 변경 사항을 설명합니다.
-
동적 링커는 더 이상 라이브러리 검색 경로의
tls하위 디렉터리 또는AT_PLATFORM시스템 이름에 해당하는 하위 디렉터리에서 공유 오브젝트를 로드하지 않습니다. -
동적 링커는 더 이상 레거시
AT_HWCAP검색 메커니즘 이후 이름이 지정된 하위 디렉터리를 검색하지 않습니다.
-
동적 링커는 더 이상 라이브러리 검색 경로의
RHEL 8.4 이후 사용 가능한 glibc-hwcaps 메커니즘으로 애플리케이션을 포트합니다.
- 삭제된
catchsegv스크립트 및libSegFault.so공유 오브젝트 -
catchsegv스크립트 및 관련libSegFault.so공유 오브젝트가 제거되었습니다. 프로세스 외부 대안을 사용하여 coredump 및 backtraces(예:systemd-coredump및coredumpctl)를 차단할 수 있습니다.
5.3. C23 지원 링크 복사링크가 클립보드에 복사되었습니다!
glibc에서 C2X 지원-
GNU C 라이브러리는 C23 표준의 일부인 몇 가지 새로운 기능을 추가했습니다. 자세한 내용은
glibc설명서를 참조하십시오.
5.4. RHEL 10은 POWER에서 긴 두 배를 위해 IEEE 바이너리128을 사용합니다. 링크 복사링크가 클립보드에 복사되었습니다!
POWER(ppc64le) 아키텍처에서 긴 이중 유형의 기본 표현이 IBM 특정 이중 이중 형식에서 RHEL 10의 표준 IEEE 754 바이너리128 형식으로 변경됩니다. 두 형식 모두 16바이트를 사용하지만 내부 표현은 다릅니다. RHEL 10(glibc 및 libstdc++)의 C 및 C++ 코어 런타임 라이브러리는 두 형식을 모두 지원합니다. 나머지 시스템은 기본적으로 binary128을 사용합니다. 애플리케이션에서 POWER에서 long double 유형을 사용하는 경우 올바른 동작을 위해 RHEL 10에서 다시 컴파일해야 합니다.