IT

약한 연결의 실용적인 응용은 무엇입니까?

itgroup 2023. 10. 30. 20:53
반응형

약한 연결의 실용적인 응용은 무엇입니까?

특수 컴파일러 명령어를 사용하면 기호가 약하다고 선언될 수 있습니다.위키피디아에 의하면:

weak symbol은 객체 파일이나 동적 라이브러리에서 다른 심볼 정의에 의해 무시될 수 있는 심볼 정의입니다.

어떤 시나리오 또는 어떤 애플리케이션에 약한 기호가 필요합니까?대표적인 사용 사례는 무엇입니까?

임베디드 개발에서, 예를 들어 인터럽트 포인터 벡터가 있을 때, 관심 없는 인터럽트에 대한 기본 핸들러를 얻기 위해 약한 링크를 사용하는 것은 매우 편리합니다.

이것은 빈 핸들러를 정의한 다음(한 번), 기본 핸들러에 약하게 연결된 인터럽트 포인터마다 적절하게 이름이 지정된 기호를 하나씩 새로 추가함으로써 작동합니다.

그러면 벡터는 이러한 기호로 채워집니다. 이 기호들은 모두 동일한 실제 코드를 가리키며, 이 기호들 중 하나를 동일한 (적절한) 이름을 사용하여 구현하기로 결정할 때까지 사용자의 코드는 약한 링크를 "오버파워"하여 코드에 대한 포인터가 인터럽트 테이블에 설치되도록 합니다.

이것은 종종 C와 어셈블리의 일부 혼합물에서 구현되지만, C 의사 코드를 사용하면 다음과 같은 것을 가질 수 있습니다.

static void placeholder_isr(void)
{
}

/* Introduce properly-named function pointers, with weak linking.
 * NOTE: This syntax is completely fictional as far as I know.
*/
void (*timer1_isr)() = placeholder_isr __attribute("weak linking");
void (*timer2_isr)() = placeholder_isr __attribute("weak linking");
void (*usart1_isr)() = placeholder_isr __attribute("weak linking");
void (*usart2_isr)() = placeholder_isr __attribute("weak linking");
void (*dma1_isr)() = placeholder_isr __attribute("weak linking");
void (*dma1_isr)() = placeholder_isr __attribute("weak linking");

/* Declare the table of interrupt handlers. */
static void (*isr_table)[] = {
  timer1_isr,
  timer2_isr,
  usart1_isr,
  usart2_isr,
  dma1_isr,
  dma2_isr,
} __attribute("isr vector"); /* Attribute to place it where it needs to go. */

그러면 필요할 때 자신만의 기능을 구현할 수 있습니다.

void timer1_isr(void)
{
  /* Handler ISR from timer1. */
}

다른 것을 바꿀 필요 없이 "그냥" 작동합니다.물론 위의 "지원 코드"에서 기대하는 이름이면 됩니다.

약한 링크의 한 가지 용도는 C++ 표준에서 교체 가능한 기능을 구현하는 것입니다.즉,

void *operator new(std::size_t);
void *operator new(std::size_t, std::nothrow_t const &) noexcept;
void *operator new[](std::size_t);
void *operator new[](std::size_t, const std::nothrow_t&) noexcept;
void operator delete(void *) noexcept;
void operator delete(void *, std::nothrow_t const &) noexcept;
void operator delete[](void *) noexcept;
void operator delete[](void *, std::nothrow_t const &) noexcept;

이러한 기능들은 구현에 의해 제공되어야 하는 기능들이지만, 프로그램이 이러한 기능들을 구현하는 경우, 프로그램의 구현이 구현의 버전을 대체하거나 재정의합니다.이는 약한 연동을 통해 쉽게 구현할 수 있습니다.

일반적이고 일상적인 사용 사례는 인라인 및 템플릿 기능입니다.

예를 들어 코드의 이 부분은 다음과 같이 컴파일됩니다.g++ -shared -fPIC:

extern void a();

inline void foo() { a(); }

void bar() { foo(); }
void baz() { foo(); }

기호 bar와 baz는 다음과 같이 T(정규값)로 표시됩니다.nm그리고 foo는 W - weak로 표시됩니다.

(즉,mn -C ./a.out)

근거:

인라인 함수와 템플릿은 헤더에 정의될 수 있으며 보통 소스의 다른 부분에서 여러 번 정의되고 마지막으로 하나만 활성 상태로 유지됩니다.

Waken으로 표시되지 않으면 여러 "foo" 기호가 충돌하거나 컴파일러가 인라인을 비활성화할 수 없습니다.

weak 속성으로 인해 선언이 전역이 아닌 weak 심볼로 표시됩니다.이것은 사용자 코드에서 무시할 수 있는 라이브러리 함수를 정의할 때 주로 유용하지만, 비함수 선언과 함께 사용할 수도 있습니다.취약 기호는 ELF 대상과 GNU 어셈블러 및 링커를 사용할 때 a.out 대상에 대해서도 지원됩니다.

취약 속성 예제:

약한

extern void foo() __attribute__((weak));

int main() {
if (foo) foo();
} 

축구의

void foo() {
printf("in foo.\n");
} 

힘이 센

extern void foo() ;

int main() {
if (foo) foo();
} 

컴파일링

$ cc weak.c // Compiles OK
$ cc strong.c // undefined reference to `foo'

"foo"가 약하다고 선언되면, 그 정의는 생략될 수도 있고, 다른 라이브러리로 대체될 수도 있으며, 일종의 "링크-타임 바인딩"을 특징으로 합니다.링크기는 정의되지 않은 약한 기호에 대해 0을 채웁니다.

코드의 다른 부분에서 함수 정의를 재정의할 수 있으려면 일반적으로 약한 링크를 사용합니다.이것은 일반적으로 라이브러리를 사용할 경우 사용자 지정 함수로 재정의할 수 있는 기본 오류 처리기를 지정하는 라이브러리의 경우입니다.

언급URL : https://stackoverflow.com/questions/15525537/what-are-practical-applications-of-weak-linking

반응형