실행중인 프로세스의 공유라이브러리 변경

hypnosis의 이미지

실행하는부분에서 dlopen 하여 라이브러리를 로드하고 계속 프로세스는 실행되고 있는 중에

공유라이브러리를 변경(교체)하고, 다시 dlopen 했을때 변경된 라이브러리로 읽지 않나요??

혹시 공유라이브러리로 하여 실행파일과 배포 하고 나중에 공유라이브러리 업데이트되어 배포할때
어떻게 하시는지 질문좀 드려봅니다.ㅠㅠ

구글링해서 한 사이트에서 저와 같은분을 찾은거 같은데 영어에 약하다 보니 내용이 눈에 쏙 안들어오네요..
http://comments.gmane.org/gmane.comp.gcc.help/45989

mirheekl의 이미지

다만 전제조건이, 해당 글에 따르면,

- 애초에 해당 라이브러리 자체가 매뉴얼 방식으로 로딩돼야 할것. 빌드시에 링크하는 일반적인 방법으로는 동적 엎어쓰기를 할 수 없다 합니다.
- 다시 읽기 전에 dlclose로 라이브러리를 닫아야 합니다.
- dlopen으로 오픈후 dlsym을 해주어야 함수의 주소를 다시 얻을 수 있다 합니다.

--

hypnosis의 이미지

내용 봐주셔서 감사합니다.

- 다시 읽기 전에 dlclose로 라이브러리를 닫아야 합니다.
- dlopen으로 오픈후 dlsym을 해주어야 함수의 주소를 다시 얻을 수 있다 합니다.

일단 위에 2가지 조건은 만족하여 실행하고 있는데요.. while(1) 로 무한 루프를 돌면서 처음에 dlopen으로 라이브러리를 로드하고
while 안에서 dlsym로 라이브러리에 적재되 있는 함수를 호출하고, 모든 작업이 끝났을때 dlclose로 라이브러리를 닫습니다.

그리고 sleep 을 줘서 1분가량 기다리고 난 다음 다시 위와 같은 작업을 반복하고 있는데요.

테스트 하다가 본것이 프로세스가 실행중일때 라이브러리를 변경해도 그대로 읽고 있지만 프로그램 종료후
재 컴파일 등 아무것도 하지않고 다시 실행했을땐 또 변경된 라이브러리로 로드하고 있네요..

뭘 해야 되는지 도통 감이 안잡히네요..

- 애초에 해당 라이브러리 자체가 매뉴얼 방식으로 로딩돼야 할것. 빌드시에 링크하는 일반적인 방법으로는 동적 엎어쓰기를 할 수 없다 합니다

이거에 대해선 이해력이 부족해서 무슨말인지... 잘 모르겠습니다.ㅠㅠ

mirheekl의 이미지

기존방식으로 라이브러리를 사용하면서 업데이트할때만 저 방식을 이용할 수는 없고, 아예 처음부터 dlopen으로 라이브러리를 로딩후 dlsym으로 주소를 얻는 방식으로 써야 된다는 것.

언급하신 문서에는 그렇게 써있습니다.

--

hypnosis의 이미지

답변 주셔서 감사합니다!

테스트 해봐야 더 확실히 알겠지만, 지금 해결은 했습니다! 해결한 방법은

일단, 제가 컴파일 할때 -rpath 를 사용해서 한번 로딩한 상태였던거 같고 이때 레퍼런스 카운트 값이 1이 된 상태이고,

다시 코드 안에서 dlopen해서 로드 하면 참조 카운트 값이 2가 되는데 dlclose를 해도 컴파일 할때 로딩한 참조값이 아직 1이 남아 있는 상태라

라이브러리를 변경한 후에도 dlclose가 제대로 안되서 그랬던거 같습니다. (예외 처리로 if(dlclose(handle) != 0 ) 이라고 해줬는데도 ..)

일단 코드에서 로딩할 라이브러리를 -rpath 에서 제거한 후, LD_LIBRARY_PATH 를 bash 에 지정해서 사용하였습니다.
테스트 후에 알게되는 점 있으면 추가로 더 적어볼께요^^ 도움주셔서 감사합니다.

ymir의 이미지

Makefile 이 어케 되어 있는지 모르겠지만, 내용으로 유추해 보면 실행파일에 라이브러리에 대한 linker 옵션이 있는게 아닐까 싶은데요..
그리고 dlfcn 으로 참조하는 라이브러리는 원래 라이브러리와 경로가 다른 게 아닐까 싶은데..

shared library 를 dlfcn 으로 사용하시려면 -rpath 나 LD_LIBRARY_PATH 에 대한 얘기는 필요 없어야 할 것 같습니다.
어차피 얘네는 프로그램 실행할 때 shared library 의 정보를 dynamic loader 에게 주는거라.. dlfcn 과는 상관 없고..
dlfcn 을 이용해서 직접 호출할 거면, 애초에 프로그램 자체도 해당 라이브러리에 대한 linker 옵션 없이 빌드를 해야 하겠죠.
실행할 때도 마찬가지.. 단, 프로그램 내에서는 그 library 의 경로를 정확히 알고 있어야 하겠구요.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

hypnosis의 이미지

항상 제 질문에 답변달아주셔서 감사합니다!

맨날 답변주시는 분이 답변주셔서 너무 반갑네요..ㅋㅋ
일단 코드 상에서 dlopen 할땐 단순히 파일명만 주었습니다. dlopen("****.so", RTLD_LAZY) 이런식으로요.

맨 처음 테스트 할땐, -rpath로 지정하면, 해당 디렉토리에서 그 라이브러리를 찾는다고 알고 있어서, 위와 같이 그냥 파일명만 입력해서 컴파일 했습니다.
근데 위에서 말한것처럼 참조 카운트 수가 제대로 감소 안되서 변경해도 제대로 적용되지 않은 현상을 봤던거 같구요..
(지금 실행중인 프로세스 라이브러리 참조 카운트 확인방법에 대해 조사하고 있었습니다..)

위 문제로 -rpath에서 라이브러리 옵션을 제거 하고, LD_LIBRARY_PATH 설정해서 테스트 해보니 되는것을 확인한 것이구요.

ymir님 말대로 지금 -rpath 와 LD_LIBRARY_PATH 를 제거 하고 테스트 해봤는데 x64 일때 /lib64, /usr/lib64 나 둘중에 *.so.* 파일을 복사하고
그 위치에 .so 파일을 링크를 걸어서 테스트 해본 결과 확실히 -rpath나 LD_LIBRARY_PATH 설정 없이 잘 실행됩니다. 공유라이브러리 변경해도 그대로 변경한대로 실행 됩니다.

질문 하나 더 드리자면.. 공유라이브러리를 사용한 실행파일을 배포 할때 사용자가 공유라이브러리를 /lib64 또는 /usr/lib64 디렉토리에 컴파일한 so 파일을 옮기고 링크 걸어서 사용하는 것이 맞을까요? 아니면 코드에 특정 디렉토리를 절대경로로 설정하여 그곳에다가 사용하는것이 맞을까요..

ymir의 이미지

dlopen("libtest.so", ..) 으로 쓰고, LD_LIBRARY_PATH 를 주었다는 뜻인가요?
아.. 그러면 뭐 상관 없을겁니다. 실행파일 빌드할 때 -ltest 옵션 주고 빌드한 후에 다시 dlopen 불렀다는 줄 알았네요.
-rpath 도 단순히 search 경로를 추가하는거니.. linker 옵션 안 줬다면 중복 로드했을 리는 없을텐데.. 좀 이상하네요.

그리고 어느 경로에 배포할지는 어느게 옳다 그르다는 없습니다. 정책에 따라 필요한 대로 하면 되죠.
/lib 이나 /usr/lib 에 있으면 기본 search 경로니까, 바로 찾아서 실행할 수 있을테고..
만약 다른 디렉토리에 넣을거면, LD_LIBRARY_PATH 보다는 절대 경로로 dlopen 을 부르는게 나을 것 같네요.

저라면 후자를 고르겠네요.. 제품 설치/삭제할 때에는 디렉토리 하나만 관리하면 되니깐.. ;;
시스템 디렉토리에 뭔가를 하면 또 불안해 하는 고객들도 많구요...

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

hypnosis의 이미지

조언 감사합니다^^

그냥 단순히 ymir님은 어떻게 할지 궁금해서 물어봤습니다.

다시한번 답변주신분들 감사합니다.

김정균의 이미지

readahead를 사용하는 시스템의 경우 library를 page cache에 올려 놓기 때문에 library가 변경이 되더라도 바로 반영이 되지 않을 수 있습니다. rhel 5의 경우에는 init.d 에서 readahead_early, readahead_later 로 적용을 하고, rhel 6에서는 /etc/sysconfig/readahead 에서 사용여부를 결정합니다.

그리고, shared library에 대해서는 http://www.ibm.com/developerworks/library/l-lpic1-v3-102-3/ 문서를 참고 하시면 도움이 되실 겁니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.