여기실행 파일을 다시 작성할 수 있으며 프로세스가 제대로 실행될 것이라고 말합니다. 프로세스가 다시 시작되면 다시 읽혀질 것입니다.
그러나 프로세스가 실행되는 동안(scp를 사용하여 개발에서 테스트 서버로) 바이너리 파일을 바꾸려고 하면 '파일 사용 중'이라고 표시됩니다. 그리고 공유 라이브러리 파일(*.so)을 교체하면 이를 연결하는 모든 프로세스가 중단됩니다.
왜 그렇습니까? 뭔가 빠졌나요? 프로세스를 중지/충돌시키지 않고 바이너리 파일을 어떻게 바꿀 수 있습니까?
답변1
에서 언급했듯이소프트웨어 패키지가 업그레이드되는 동안에도 제대로 실행되는 이유는 무엇입니까?, 잠금은 파일 이름이 아닌 inode에 설정됩니다. 바이너리를 로드하고 실행하면 파일이 사용 중으로 표시됩니다. 따라서 파일에 쓰려고 하면 ETXTBSY(파일 사용 중) 오류가 발생합니다.
이제 공유 라이브러리의 경우 약간 다릅니다. 라이브러리는 mmap()
. 지정될 수 있지만 MAP_DENYWRITE
적어도 Linux의 Glibc는 이를 자동으로 무시합니다(맨 페이지에 따르면 자유롭게 소스를 확인하십시오). 이것을 확인하십시오실. 따라서 실제로 파일을 쓸 수 있으며 메모리 매핑되어 있으므로 모든 변경 사항이 거의 즉시 표시됩니다. 벽돌라이브러리를 덮어써서 컴퓨터를 보호하세요.
따라서 올바른 업데이트 방법은 다음과 같습니다.
파일 제거 - 파일 시스템에서 데이터에 대한 참조를 제거하여 해당 파일을 사용하려는 새로 생성된 응용 프로그램에서 해당 파일에 액세스할 수 없도록 하고, 이미 해당 파일을 열거나 매핑한 사람은 데이터에 액세스할 수 있도록 유지합니다. ;
업데이트된 내용으로 새 파일을 생성합니다.
새로 생성된 프로세스는 업데이트된 콘텐츠를 사용하고, 실행 중인 애플리케이션은 이전 버전에 액세스합니다. 이것이 정상적인 패키지 관리 유틸리티가 수행하는 작업입니다. 하지만 완전히 위험이 없는 것은 아닙니다. 예를 들어 동적으로 코드를 로드하는 애플리케이션(사용 dlsym()
및 친구)은 라이브러리의 API가 자동으로 변경되는 경우 문제를 경험하게 됩니다.
정말로 그 자리에 있고 싶다면,정말안전 측면에서는 시스템을 종료하고, 다른 운영 체제 인스턴스에서 파일 시스템을 마운트하고, 업데이트하고 업데이트된 시스템을 다시 불러옵니다.
답변2
rpm 업그레이드도 동일한 작업을 수행합니다. 충돌이 발생하지 않는 동안 바이너리와 라이브러리를 실행합니다.
그렇다면 차이점은 무엇입니까?
- 파일 연결 해제
- 같은 이름으로 새 파일 쓰기
이는 파일을 제자리에서 대체하지 않습니다. 사용 중인 바이너리를 참조하는 inode는 열려 있는 마지막 개체가 완료될 때까지 여전히 "사용 중"입니다. 새 파일은 새 inode 번호로 생성됩니다.
이제 scp
또는 cp
파일을 제자리에서 교체하려고 시도합니다. 그러면 inode가 참조하는 콘텐츠가 변경됩니다. 설명하신 대로 작동하지 않습니다.