라이브러리 로딩 ld.so.conf



  라이브러리란 프로그램들이 공통으로 사용할 수 있는 기능을 포함하고 있는 오브젝트 파일입니다.  


  동적 라이브러리는 프로그램을 컴파일하여 생성되는 바이너리에 포함하지 않고 바이너리가 실행하는 시점 또는 실행 후에 포함시킬 수 있도록 제작된 라이브러리를 말합니다. 그래서 동적이라는 이름이 붙게 된 것입니다. 이런 형ㅌ식의 라이브러리는 프로그램을 실행할 때 호출되는 로더에 의해서 메모리에 적재됩니다.


  동적 라이브러리를 호출하기 위해서는 path 지정이 필수적입니다. 해당 라이브러리가 어디에 위치해 있는지 모든 디렉토리를 탐색하고 로드하기에는 비효율적이기 때문입니다. 우리가 흔히 설정하는 LD_LIBRARY_PATH 환경변수가 동적 라이브러리 호출을 위한 path 지정에 사용되는 환경 변수이며 또 다른 방법으로는 시스템 설정을 통해서 지정할 수 있습니다. 시트템 설정을 위한 설정 파일이 리눅스는 /etc/ld.so,conf 파일 입니다. Kernel 버전이 2.6 이상부터는 /etc/ld.so.conf.d/ 디렉토레 내에 *.conf 파일 형식으로 여려 파일을 통해 설정을 할 수 있습니다.


  로더는 LD_LIBRARY_PATH 또는 ld.so.conf에 명시된 디렉토리 내에서 동적 라이브러리를 찾으며 해당 디렉토리에 없으면, Not Found 에러를 출력합니다. 컴파일 시 Link 오류나 실행시 Loading 오류가 발생한다면 우선적으로 두가지 설정을 확인해 봐야 합니다.


  LD_LIBRARY_PATH 나 ld.so.conf 두 곳 모두 설정할 필요는 없으나 다음과 같은 경우에는 ld.so.conf 에 설정하도록 유의해야 합니다. 바이너리에 setuid, setgid 등이 설정된 경우 리눅스의 로더는 LD_LIBRARY_PATH 환경 변수 설정을 무시해 버린다고 합니다. 그도 그럴것이 악의적으로 시스템 주요 함수들이 setuid를 가진 바이너리가 호출한 라이브러리에 의해서 오버라이딩 된다면 시스템에 엄청난 일을 가져다 줄 것 입니다.(프로세스 등의 문제들, 해킹) 그런 보안을 고려한 것인지 모르겠지만 로더는 ( uid != euid || gid != egid ) 상황에서 LD_LIBRARY_PATH 를 무시하기 때문에 아무리 컴파일시에 link가 정상이고 ldd로 확인해도 정상이지만 바이너리 실행시 해당 라이브러리를 찾을 수 없다는 오류를 만나게 됩니다. 이런 경우는 LD_LIBRARY_PATH가 아니라 ld.so.conf 에 설정을 해줘야 합니다.

 


관련 명령어 :

  • ldconfig - /etc/ld.so.conf 설정된 동적 라이브러리 정보를 /etc/ld.so.cache 파일로 만들어 주는 일을 한다. 이로서 로더는 ld.so.cache 정보를 기반으로 보다 빠르게 라이브러리를 찾아 낼 수 가 있다. ld.so.conf 설정을 변경하면 반드시 ldconfig 명령을 수행하여 cache 를 갱신해 주도록 하자.
  • ldconfig
    ldconfig -p

  • ldd - 공유 라이브러리의 의존성을 검사해 준다. 동적 라이브러리도 공유 라이브러리 이므로 link 시나 load 시에 에러가 난다면 점검을 해보자.
  • ldd <binary name>

  •  objdump - 오브젝트 파일에 대한 정보를 출력해 준다. Dynamic Section의 NEEDED 로 표기된 항목이 공유 라이브러리를 표시한다고 한다.
  • objdump -p <object(binary) name>


관련 링크 :  




'System Programming > Linux Kernel' 카테고리의 다른 글

udev  (0) 2016.09.12
커널 타이머  (0) 2016.06.08
[Linux] ticket spin lock  (0) 2016.05.17
spin_lock, spin_lock_irq, spin_lock_irqsave  (2) 2016.05.17

크로스 컴파일 실행파일 no such file or directory 문제




크로스 컴파일 하여 타겟 보드에 넣었을 때 실행되지 않고,

no such file or directory 가 출력되는 경우에 해결하는 방법입니다.


실행시 no such file or directory가 출력되는 실행파일을 file 명령어를 통해

Shared Library를 확인 합니다.


file 해당파일

ex)

test: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.16, not stripped


file 명령어를 실행하면 그 파일의 ELF 정보 및 사용하는 공유 라이브러리 정보가 나옵니다.


실행파일에서 사용하는 공유라이브러리가 /lib 혹은 /etc/ld.so.conf 파일에 저장되어 있는 경로에 있는지 확인 합니다.


없을 경우에는 타겟보드에 저장된 올바른 라이브러리 파일을 생성하거나 심볼릭 링크를 통해 생성 합니다.



ex) ld-linux.so.3 파일이 없어서 나타나는 경우


/lib 디렉토리내에 ld-linux.so.3가 없어 나타나는 경우에는 대게 arm 라이브러리 중 ld-linux-armhf.so.3가 있습니다.


ld-linux.so.3는 프로그램이 메모리에 적재되는 시점에서 실행에 필요한 라이브러리를 링킹해주는 파일입니다.


이 링킹은 target platform인 Arm 에서는 ld-linux-armhf.so.3가 담당합니다. 그에 따라 복사 또는 파일명 변경이 아닌 심볼릭 링크를 걸어주어야 합니다.



sudo ln -s /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3


정상적으로 파일을 생성 혹은 링크했다면, 재실행 시 문제되지 않고 정상 실행이 될 것 입니다.

HDMI Hot Plug Detect Pin and +5V Pin


  HDMI 의 Pin 및 Pin map에는 Hot Plug Detect(HPD) 핀이 존재 합니다.

이 핀의 목적은 송신부(PC or 셋탑박스 등의 영상 전송 장치)에서 출력 장치인 디스플레이 장치가 접속이 되었는지 감지하는 핀입니다.

이 핀은 수신부가 출력을 내고, 송신부가 수신하는 형태로 동작을 합니다. 인터럽트 핸들링과 유사 혹은 같습니다.


  그러나, 수신측의 HPD Pin은 송신측의 +5V 출력에 풀업이 되어 있어 송신측에도 영향을 받습니다. 규격에서는 송신측에서 +2.0V 이상이면 인식을 하며, 수신측 출력은 +2.4V 이상이여야 합니다. 또한 송신측 +5V는 +4.7이상 유지해야 합니다.



[레벨쉬프트가 들어간 HDMI Tx/Rx 예제]


위의 그림과 같이 송신측 +5V와 수신측 HPD가 풀업 저항으로 연결되어 있습니다.


  문제 발생하는 경우로는, 송신측 +5V가 약할 경우 송신측에서 수신측을 인식하지 못하는 경우가 발생합니다. 이 문제는 수신측이 HPD을 제어하기 때문입니다. 송신측 +5V의 전압이 낮을 경우 수신측에서 송신측을 인식하지 못하는 사태가 발생하고, 그에 따라 수신측은 HPD를 Low 상태로 유지 합니다. 그렇게 될 경우에는 송신측은 출력을 내보내지 않습니다.


  위와 같은 현상이 발생되면, 출력 장치에 따라 출력이 되고 안되고 하는 현상이 발생하기도 합니다.

따라서, 디버깅 및 동작 확인 시 등의 경우에 HPD가 작동하여 DDC를 통해 송수신측이 서로 EDID Data를 주고 받는지, 그 후에 송신측에서 받은 EDID 데이터를 통해 정상적인 Signal이 나오는지에 대한 확인이 필요합니다.

 

  HDMI의 동작 순서에 따라 확인하면, 어떠한 부분에서 문제점이 발생하는지 알 수 있습니다.







참고 : http://wellplay.tistory.com/





/*                                                                                                                                                                 

 *     clock_gettime

 * gcc -Wall -o now now.c -lrt [-D_LOCAL_TIME]

 */

#include <stdio.h>

#include <stdlib.h>

#include <time.h>


#define BUFSIZE     64


/*

    1. 현재 시간을 얻어 온다. clock_gettime / gettimeofday

    2. tm으로 변환해 정보를 출력한다. localtime_r / gmtime_r

    3. 문자열로 변환해 출력한다. asctime_r

*/


int main(void)

{

    struct timespec ts;

    struct tm tm;

    struct tm *ret_tm;


    char buf1[BUFSIZE] = { 0 };

    char *ret_asc;

    int ret;



    /* get current time (struct timespec format) */

    ret = clock_gettime (CLOCK_REALTIME, &ts);

    if (ret < 0)

    {

        perror ("clock_gettime");

        return (EXIT_FAILURE);

    }


    /* change it to 'struct tm' format */

#ifdef _LOCAL_TIME

    ret_tm = localtime_r (&ts.tv_sec, &tm);

#else

    ret_tm = gmtime_r (&ts.tv_sec, &tm);

#endif

    if (ret_tm == NULL)

    {

#ifdef _LOCAL_TIME

        perror ("localtime_r");

#else

        perror ("gmtime_r");

#endif

        return (EXIT_FAILURE);

    }


    printf ("mon: %d day: %d, %d:%d:%d\n",

      tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);


    /* make time string */

    ret_asc = asctime_r (&tm, buf1);

    if (ret_asc == NULL)

    {

        perror ("ret_asc");

        return (EXIT_FAILURE);

    }


    printf ("%s\n", buf1);



    return (EXIT_SUCCESS);

}

+ Recent posts