mmap, msync 및 linux 프로세스 종료
저는 mmap()을 MAP_SHARED 플래그 세트와 함께 mmap()을 사용하여 고정된 크기의 구조와 잘 알려진 파일 이름을 연결하여 리눅스에서 실행되는 C 프로그램에서 특정 프로그램 상태의 지속성을 구현하기 위해 mmap을 사용하고자 합니다.성능상의 이유로 msync()를 아예 호출하지 않기를 원하며, 다른 프로그램은 이 파일에 액세스하지 않습니다.프로그램이 종료되고 다시 시작되면 동일한 파일을 다시 매핑하여 종료 전 상태를 복구합니다.제 질문은 다음과 같습니다. 만약 제가 파일 설명자에서 msync()를 호출하지 않는다면, 제 프로세스가 SIGKILL로 종료되더라도 커널은 메모리에 대한 모든 업데이트가 디스크에 기록되고 이후 복구가 가능하다는 것을 보장할 것인가요?또한 프로그램이 msync()를 호출하지 않더라도 커널이 주기적으로 페이지를 디스크에 쓰는 일반적인 시스템 오버헤드가 발생합니까?
편집: 데이터 작성 여부에 대한 문제는 해결했지만, 이 문제를 open()/write()/fsync()로 처리하려고 할 때 예기치 않은 시스템 로드가 발생할 수 있으며 프로세스가 KILL/SEGV/AB에 부딪힐 경우 일부 데이터가 손실될 위험이 있습니다.RT/등지식이 풍부한 사람이 참여하기를 바라며 '리눅스 커널' 태그를 추가했습니다.
라이너스 토발즈가 이 질문 http://www.realworldtech.com/forum/ ? threadid=113923&curpostid=114068에 답하는 댓글을 찾았습니다.
매핑된 페이지는 파일 시스템 캐시의 일부입니다. 즉, 해당 페이지를 변경한 사용자 프로세스가 죽더라도 페이지는 커널에 의해 관리되며 해당 파일에 대한 모든 동시 액세스가 커널을 통과하므로 다른 프로세스가 해당 캐시에서 서비스됩니다.에서는 이 이것이 문서가 데,입니다를 msync.
RobH가 링크를 수정해줘서 고마워요.
편집:
새로운 플래그인 MAP_SYNC는 Linux 4.15 이후 도입되었으며, 이는 일관성을 보장할 수 있습니다.
이 플래그가 있는 공유 파일 매핑을 사용하면 일부 메모리가 프로세스의 주소 공간에 쓰기 가능하게 매핑되지만 시스템이 충돌하거나 재부팅된 후에도 동일한 오프셋으로 동일한 파일에 표시됩니다.
참조:
http://man7.org/linux/man-pages/man2/mmap.2.html 페이지에서 MAP_SYNC 검색
https://lwn.net/Articles/731706/
나는 덜 게을리해서 데이터가 디스크에 확실히 기록되어 있는지에 대한 질문에 코드를 작성해서 답하기로 했습니다.답은 그것이 쓰여질 것이라는 것입니다.
다음은 mmap'd 파일에 일부 데이터를 기록한 후에 갑자기 자동으로 종료되는 프로그램입니다.
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef struct {
char data[100];
uint16_t count;
} state_data;
const char *test_data = "test";
int main(int argc, const char *argv[]) {
int fd = open("test.mm", O_RDWR|O_CREAT|O_TRUNC, (mode_t)0700);
if (fd < 0) {
perror("Unable to open file 'test.mm'");
exit(1);
}
size_t data_length = sizeof(state_data);
if (ftruncate(fd, data_length) < 0) {
perror("Unable to truncate file 'test.mm'");
exit(1);
}
state_data *data = (state_data *)mmap(NULL, data_length, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_POPULATE, fd, 0);
if (MAP_FAILED == data) {
perror("Unable to mmap file 'test.mm'");
close(fd);
exit(1);
}
memset(data, 0, data_length);
for (data->count = 0; data->count < 5; ++data->count) {
data->data[data->count] = test_data[data->count];
}
kill(getpid(), 9);
}
이전 프로그램이 종료된 후 결과 파일의 유효성을 검사하는 프로그램은 다음 프로그램입니다.
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
typedef struct {
char data[100];
uint16_t count;
} state_data;
const char *test_data = "test";
int main(int argc, const char *argv[]) {
int fd = open("test.mm", O_RDONLY);
if (fd < 0) {
perror("Unable to open file 'test.mm'");
exit(1);
}
size_t data_length = sizeof(state_data);
state_data *data = (state_data *)mmap(NULL, data_length, PROT_READ, MAP_SHARED|MAP_POPULATE, fd, 0);
if (MAP_FAILED == data) {
perror("Unable to mmap file 'test.mm'");
close(fd);
exit(1);
}
assert(5 == data->count);
unsigned index;
for (index = 0; index < 4; ++index) {
assert(test_data[index] == data->data[index]);
}
printf("Validated\n");
}
혼란을 가중시키는 무언가를 발견했습니다.
munmap은 매핑된 개체에 영향을 주지 않습니다. 즉, munmap으로 호출해도 매핑된 영역의 내용이 디스크 파일에 기록되지 않습니다.MAP_SHARED 영역에 대한 디스크 파일 업데이트는 메모리 매핑된 영역에 저장할 때 커널의 가상 메모리 알고리즘에 의해 자동으로 수행됩니다.
UNIX® Environment의 Advanced Programming에서 발췌한 내용입니다.
Linux manpage에서:
MAP_SHARED 이 개체를 매핑하는 다른 모든 프로세스와 이 매핑을 공유합니다.영역에 저장하는 것은 파일에 쓰는 것과 동등하게 임대됩니다.msync(2) 또는 munmap(2)이 호출될 때까지 파일이 실제로 업데이트되지 않을 수 있습니다.
그 둘은 모순된 것 같습니다.APUE가 잘못되었습니까?
저는 당신의 질문에 대한 정확한 답을 찾지 못해서 하나를 더 추가하기로 결정했습니다.
- 먼저 데이터 손실과 관련하여 write 또는 mmap/memcpy 메커니즘을 사용하면 페이지 캐시에 쓰기가 가능하며 페이지 교체 설정/알고를 기반으로 OS에서 백그라운드 스토리지에 동기화됩니다.예를 들어 Linux에는 디스크에 플러시할 "오래된" 페이지로 간주되는 vm.dirty_writeback_centisec이 있습니다.이제 쓰기 호출이 성공한 후 프로세스가 종료되더라도 데이터가 커널 페이지에 이미 존재하기 때문에 데이터가 손실되지 않습니다. 이는 결국 스토리지에 기록될 것입니다.OS 자체가 충돌(커널 패닉, 전원 끄기 등)하는 경우에만 데이터를 잃을 수 있습니다.데이터가 스토리지에 도달했는지 확실하게 확인하는 방법은 fsync 또는 msync(맵핑된 영역의 경우)를 호출하는 것입니다.
- 시스템 로드 문제와 관련하여, 예, 각 요청에 대해 msync/fsync를 호출하면 처리 속도가 크게 느려지기 때문에, 필요한 경우에만 이 작업을 수행할 수 있습니다.여러분은 OS 충돌에 대한 데이터 손실을 방지하고 있습니다. 이는 드물고 아마도 가장 잘 살 수 있는 것이라고 생각합니다.한 가지 일반적인 최적화 작업은 일정한 간격으로 동기화를 발행하는 것으로, 균형을 잘 잡기 위해 1초를 말합니다.
리눅스 manpage 정보가 잘못되었거나 Linux가 심하게 부적합합니다.msync변경 사항이 파일의 논리적 상태에 커밋되는지 또는 를 사용하는 다른 프로세스인지 여부와 관련이 없는 것으로 예상됩니다.mmap아니면read파일에 액세스하려면 변경 사항을 확인하십시오. 이는 순전히 아날로그입니다.fsync전원 장애 또는 기타 하드웨어 수준의 장애 발생 시 데이터 무결성을 보장하는 목적을 제외하고는 노옵으로 취급해야 합니다.
맨페이지에 의하면,
msync(2) 또는 munmap()이 호출될 때까지 파일이 실제로 업데이트되지 않을 수 있습니다.
그래서 당신은 당신이 전화하는 것을 확실히 해야 할 것입니다.munmap()최소한 탈출하기 전에 말입니다
언급URL : https://stackoverflow.com/questions/5902629/mmap-msync-and-linux-process-termination
'programing' 카테고리의 다른 글
| 데이터 프레임을 벡터(행 단위)로 변환 (0) | 2023.10.02 |
|---|---|
| 테두리 스타일은 끈적거리는 위치 요소와 함께 작동하지 않습니다. (0) | 2023.09.27 |
| 커서_SHARING, Bind Variable Peeeking 및 히스토그램 간의 관계 (0) | 2023.09.27 |
| Angularjs 와 Angular의 차이 (0) | 2023.09.27 |
| 적절한 인수를 사용하여 C에서 execl()을 호출하는 방법은 무엇입니까? (0) | 2023.09.27 |