linux /proc/cpuinfo로 aarch64인지 x86_64인지 가리고 싶습니다
x86_64에서 빌드된 프로그램이 있습니다. x86_64에서는 그냥 돌아가고, arm64에서는 qemu+kvm을 이용해서 binary translation을 해서 수행시키는 것으로 알고 있습니다. 두 환경 모두에 완전히 동일한 실행 파일을 사용합니다. 앞으로 arm이나 몇 가지 다른 타겟에서 마찬가지로 qemu+kvm 가상화를 이용해서 수행될 가능성이 있습니다.
실행 중에 이 프로그램의 host가 x86_64인지 arm64인지 혹은 다른 무엇인지 간단하게 구분하고 싶습니다. 현재 찾아낸 방법은 우선 uname -m을 fork-exec으로 수행하고, pipe를 이용해서 output을 읽어오는 것입니다. uname() 콜은 에뮬레이트 되더군요.
이것보다 간단하고 신뢰성 높은 방법을 찾고 있습니다.
한 가지 생각나는 건 뭔가 /proc/cpuinfo를 확인하는 것이었습니다. 제 데스크탑, 회사 워크스테이션, 그리고 회사의 arm64 보드에서 /proc/cpuinfo를 수행시켜 보니 우선 해당 파일의 형식이 많이 달라 보이더군요. 그 세 가지만 비교한다면, arm64는 cpu implementor라는 라인이 있고 x86_64는 없다거나, 형식과 내용에서 차이가 있어 보였습니다.
만약 눈으로 /proc/cpuinfo를 본다면, 주어진 cpuinfo가 arm64인지 x86_64인지 혹은 다른 무엇인지 알아낼 수 있는 방법이 있는지요?
%P.S. 여러 가지 아이디어들 감사합니다. popen으로 uname -m을 불러 해결했습니다.
음 ..
man -s 2 unameuname 명령이 uname() 을 사용합니다.중간에 uname() 콜이 에뮬레이트 된다는 표현이 있었군요.
가상 환경에서 host 의 정보를 확인하시려는 건가요?
그래서 uname() 이 안먹히는 상황이구요?
되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』
음 ..
단순히 실행되는 곳이 가상 환경인지 아닌지 판단하시려는 용도라면..
virt-what 같은 걸 써보시는도 괜찮을 것 같네요.
되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』
감사합니다
긴 이야기를 너무 짧게 썼는데, 제가 일하는 소프트웨어는 거대한 소프트웨어 프로젝트의 일부입니다. 아마 빌드 시스템이나 거기 들어 있는 몇몇 컴포넌트 때문에 aarch64 위에서 native로 컴파일 할 수는 없는 모양입니다. 빌드를 타겟 별로 다르게 하는 것도 고려할 수 없는 상황인 것 같구요.
그런데 aarch64 위에서도 동작을 해야 하게 되어서 qemu+kvm을 이용해 x86_64 바이너리를 돌리고 있습니다.
그간은 호스트 아키텍쳐를 알 필요가 없었습니다. 그런데 새 feature를 추가하면서 보니 호스트 아키텍쳐를 반드시 알아야 하는 상황이 되었습니다. 빌드 타임에 알면 더 좋지만 그건 안 되니까 런타임에라도 알았으면 했고요.
qemu 위에 실행되는 건 주로 호스트가 arm64일 때이긴 한데 x86도 그런 식으로 할 수는 있어서 가상 환경인지 아닌지를 아는 것만으로는 충분하지 않은 것 같습니다. 정확히는 현재로선 x86_64인지 aarch64인지 알아야 하고, 앞으로는 arm인지 mips인지 등등을 추가로 알아내야 할 수도 있습니다.
uname -m의 아웃풋을 파이프를 통해 읽는 건 이미 거의 어렵지 않게 되기는 한데, uname() 콜 한 번으로 될 일을 저렇게 복잡하게 처리하는 게 최선은 아닌 것 같아서 혹시 더 간단한 방법이 없는지 생각해 보게 되었습니다. /proc/cpuinfo도 보아하니 커널마다 다르고 권고 사항이 있지 사실 강제는 없다고 하는 것 같네요.
음 ..
개인적인 생각으로.. cpuinfo 를 파싱해서 정보를 뽑아 내는 것은..
이미 확인된 시스템에서는 확실하겠지만..
(거의 없을 것 같기는 하지만) 시스템이 변경되거나 했을 때..
계속해서 추가로 확인하는 작업을 해줘야 하고..
적절한 주석이 없다면 오히려 의도를 파악하기 힘들 수도 있을 것 같습니다.
일단은 uname 을 실행해서 아웃풋을 뽑아내놓고..
이후에 다른 방법은 없는지 찬찬히 모색해도 괜찮을 것 같습니다.
fork, exec, pipe 를 언급하셨는데..
popen 대신 직접 따로 구현하신 것처럼 들리네요.
특별한 이유가 있는게 아니라면, 간단히 이미 있는 거 써도 괜찮을 것 같습니다.
되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』
네..
cpuinfo는 말씀하신 것처럼 스탠다드가 없고 그냥 커널 버전/설정별로 다르게 집어넣는 것 같더군요. 우선은 uname 명령어를 사용하기로 했습니다.
그리고 popen은 몰랐네요. 감사합니다. :) C/C++로 멀티 프로세스 프로그램을 할 일이 없다 보니 옛날 옛적에 fork, exec, pipe로 쉘 만들었던 기억을 끄집어 내어 테스트를 했었습니다. 유사한 일을 할 때 bash script나 python을 써서 C에 popen이 있을 거라고 미처 생각을 못했었네요.
호스트의 /proc/cpuinfo 를 읽으려면 호스트
호스트의 /proc/cpuinfo 를 읽으려면 호스트 파일 시스템에 접근 가능해야 하는데,
그럴 바에는 오히려 호스트에서 uname 을 실행시키는게 낫지 않나요?
아.. 맞다.. arch 가 달라서 실행을 못하는구나
아.. 맞다.. arch 가 달라서 실행을 못하는구나..
...
제가 질문을 명료하게 못 한 것 같습니다. 기본적으로 문제의 프로그램은 C/C++ 응용 프로그램입니다. 복잡한 어른들의 사정으로 인해 x86_64용으로 빌드된 것을 arm64 위에서 돌리고자 부득이하게 qemu + kvm을 사용하는 것으로 알고 있습니다. 제 이해로는 host filesystem에 접근은 가능한데, 아닌가요?
제 목표는 call을 하면 arch를 리턴해 주는 C++ 혹은 C function call을 만드는 것입니다.
제 질문글에도 나와 있듯이 현재로는 pipe, fork, exec을 이용해서 host에서 uname을 실행시키는 게 제가 생각해 낸 최선입니다. 그런데 이건 원래 native execution이라면 uname() 콜 한 번으로 해결될 일이고, 기껏해야 3, 4줄짜리 코드입니다. 이에 반해 uname -m을 서브 프로세스에서 수행시켜서 아웃풋을 리다이렉션 해오는 일은 너무 복잡하고요.
간단한 솔루션이 없을까 해서 질문을 드리게 되었습니다.
한가지 간단한 방법 찾았어요. 호스트에서 미리
한가지 간단한 방법 찾았어요. 호스트에서 미리 uname -a 실행 후 결과를 txt 파일로 저장.
그후 게스트에서 해당 파일 읽으면 끝
...
이렇게 하려면 파일이 생기겠죠. 그런데 이게 uname -a를 popen 등을 이용해서 처리하는 것보다 나은 점이 있어 보이지 않습니다. 후자는 지저분한 파일이 생기지 않거든요.
그러고보니 텔넷이나 스스흐로 접속해서 유네임
그러고보니 텔넷이나 스스흐로 접속해서 유네임 실행시키는 방법도 있군요
[schoi0@sel-schoi0-d1 net]$
감사합니다.
다른 부분은 이해가 되는데 aarch64-linux-gnu-gcc 로 컴파일 해서 aarch64 실행 파일로 보이는 게 어떻게 x86_64 머신 위에 별다른 준비 없이 실행이 되나요?
[schoi0@sel-schoi0-d1 net]$
저도 모르는 사이에 qemu가
깔려 있었고 그거를 지우니 이번엔 그런 파일이 없다는 이상한 메시지가 나오면서 안 되네요. 파일은 리스팅은 됩니다.
아마 bash가 보고 파일 타입과 qemu 유무에 따라 에뮬레이션을 자동으로 해주는 모양이네요. 그럼 /proc/self/exe는 이 타-타겟용 실행파일에 대한 심볼릭 링크겠네요. 감사합니다.
수정) bash 수준에서 하는 게 아니라 리눅스 커널 수준에서 바이너리를 보고 호스트 네이티브가 아니면 qemu한테 던져주는 기능이 있나 보군요.
본래 용도는 인터프리터가 알려진 모든 종류의 파일을
본래 용도는 인터프리터가 알려진 모든 종류의 파일을 '자연스럽게 실행(execute)' 할 수 있도록 해주는 것입니다.
wine 을 설치하면 .exe (PE포맷), jre 를 설치하면 jar 파일을 '자연스럽게 실행' 할 수 있는 정도로 편합니다.
ls -l /proc/self/exe 해보세요.
프로그램에 인자를 주면 되지 않을까요? 이런
프로그램에 인자를 주면 되지 않을까요? 이런 서비스까지 제공할 필요는 없을 것 같습니다.
./aaaa -x86_64, ./aaaa -xarm64식으로 하면 될 것 같은데요.
사용자가 물론 올바른 인자를 주어야 하는 책임이 있고요.
..
상식적으론 그런데 (커맨드라인 옵션을 정의하고 파싱하는 좋은 라이브러리도 사내에 있고요) 실행 커맨드를 바꾸는 건 옵션이 아니라고 합니다. 저도 왜 그런지는 아직 도대체 이 프로그램이 거대한 프로젝트 내에서 어디서 어떻게 돌아가는지 다 파악을 못해서 정확히 모르겠습니다.
그리고 사실 호스트 아키텍쳐 찾는 게 그리 어려운 일은 아니구요.
프로그램 실행하기 전에 ARCH=`uname -m`과
프로그램 실행하기 전에 ARCH=`uname -m`과 같이 환경변수를 지정하고 프로그램 내에서 환경변수를 읽어서 판단하는 방법도 있을것 같네요.
--
익스펙토 페트로눔
..
프로그램을 실행하는 방식은 변경하고 싶지 않아 하더군요.
댓글 달기