rm
공유 라이브러리에 의존하는 프로그램을 실행하는 동안 위험 없이 공유 라이브러리를 삭제할 수 있습니까(예: 명령 사용)? 내 생각에는 프로그램이 실행 중이면 라이브러리에서 필요한 모든 데이터가 메모리에 로드되기 때문에 그렇게 생각합니다.
그러나 나는 라이브러리( echo 123 > somelib.so
)를 다시 작성할 때 다음과 같은 이유로 이에 의존하는 프로그램이 손상되었음을 발견했습니다.Bus error
라이브러리가 이미 메모리에 있는데 디스크의 라이브러리가 변경되어 프로그램이 충돌하는 이유는 무엇입니까? 라이브러리가 메모리에 없으면 디스크에서 삭제해도 프로그램은 계속 실행될 수 있는 이유는 무엇입니까? 라이브러리의 데이터는 어디서 읽나요?
답변1
일반적으로 문서는 그렇지 않습니다.실제로delete를 사용하면 삭제되지만 rm
열려 있는 모든 파일 핸들도 닫힌 후에만 가능합니다. 파일이 프로세스의 메모리에 매핑될 때도 이것이 적용된다고 확신합니다. 그 후에 rm
는 파일을 다시 열 수 없지만 데이터와 매핑은 그대로 유지됩니다.
파일 데이터의 "버전"이 하나뿐이고 모든 읽기, 쓰기 및 공유 매핑이 동일한 데이터에 액세스하기 때문에 파일 수정은 또 다른 이야기입니다. 여기에 쓰레기를 쓰면 해당 파일에서 코드를 실행하는 프로세스도 쓰레기를 얻게 됩니다. Linux에서는 실행 파일을 사용하여 이 작업을 수행할 수 없으며 오류("텍스트 파일 사용 중")가 발생하지만 공유 라이브러리에 대한 이러한 보호 기능은 없습니다.
(시도해 볼 수 있습니다: cp -a /bin/cat /tmp/cat; /tmp/cat &
그런 다음 을 시도 하십시오 echo 123 >> /tmp/cat
. 그런 다음 fg
돌아가서 cat
Ctrl-C를 눌러 닫으십시오.)
rm
기술적으로 이것은 실제로 파일을 전혀 삭제하지 않고 파일 이름만 삭제한다고 말할 수 있습니다 . 파일은 여러 이름을 가질 수 있으며 이를 하드 링크라고 합니다. 그러나 이는 기본적으로 동일한 파일에 대한 여러 이름일 뿐입니다. 실제 삭제는 일반적으로 성이 삭제되면서 시작되지만 다소 독립적입니다.
답변2
내 생각에는 프로그램이 실행 중이면 라이브러리에서 필요한 모든 데이터가 메모리에 로드되기 때문에 그렇게 생각합니다.
실행 가능한 데이터 읽기필요할 때만179 134 080
그렇지 않으면 Google Chrome(바이너리의 현재 바이트 단위) 과 같은 무거운 애플리케이션을 실행하는 데 오랜 시간이 걸릴 것입니다 . 또한 Windows의 WinRAR을 사용하면 2^64 - 1
최대 크기의 자동 압축 풀기 아카이브를 생성할 수 있습니다 . 커널이 부팅하기 전에 모든 코드를 RAM에 로드해야 하는 경우 해당 코드를 추출할 수 없습니다.
라이브러리가 이미 메모리에 있는데 디스크의 라이브러리가 변경되어 프로그램이 충돌하는 이유는 무엇입니까?
전체가 메모리에 있는 것은 아니며 실행 프로세스에만 매핑됩니다. 커널이 실제로 라이브러리의 코드를 실행하기로 결정하면 해당 코드는 캐시되지만 그때까지는 디스크 드라이브에만 남아 있습니다.
라이브러리가 실행되어 읽고 캐시되었더라도 커널에 메모리가 부족하면 여전히 캐시될 수 있습니다.
실제로 파일을 교체했고 커널이 실행을 요청한 기능을 찾으려고 하기 때문에 충돌이 발생합니다. 파일을 덮어쓰면 이러한 함수는 쓰레기가 되어 애플리케이션이 충돌하게 됩니다.
라이브러리가 메모리에 없으면 디스크에서 삭제해도 프로그램은 계속 실행될 수 있는 이유는 무엇입니까? 라이브러리의 데이터는 어디서 읽나요?
Linux 커널에 사용되는 Unix 아키텍처에서는 열린 파일을 삭제할 수 있습니다. 파일에 대한 핸들 수가 0보다 크므로 파일은아니요마지막 손잡이가 닫힐 때까지 기술적으로 제거하십시오.
공유 라이브러리에 의존하는 프로그램이 실행되는 동안 공유 라이브러리를 삭제해도 안전합니까?
네, 완벽해요. 그러한 라이브러리를 덮어쓰는 것은 안전하지 않습니다. 커널은 이전(제거된) 라이브러리를 사용하기 때문에 다시 교체하는 것이 안전합니다. 이렇게 하면 시스템을 다시 시작하지 않고도 거의 모든 라이브러리를 교체할 수 있습니다. 이를 교체하는 경우에만 이를 사용하는 모든 응용 프로그램을 다시 시작해야 합니다.
마지막으로 Linux 커널은 몇 년 전에 패치되어 자체적으로 동적 교체가 가능해졌습니다.https://ostechnix.com/5-kernel-live-patching-tools-that-will-help-to-run-linux-servers-without-reboots/