구체적으로, 포크()는 리눅스에서 malloc()에서 동적으로 할당된 메모리를 어떻게 처리합니까?
저는 부모와 자녀가 함께 하는 프로그램이 있습니다.포크() 이전에 부모 프로세스는 malloc()를 호출하고 일부 데이터로 배열을 채웠습니다.포크() 이후에 아이는 해당 데이터가 필요합니다.파이프를 사용할 수 있지만 다음 코드가 작동하는 것 같습니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main( int argc, char *argv[] ) {
char *array;
array = malloc( 20 );
strcpy( array, "Hello" );
switch( fork() ) {
case 0:
printf( "Child array: %s\n", array );
strcpy( array, "Goodbye" );
printf( "Child array: %s\n", array );
free( array );
break;
case -1:
printf( "Error with fork()\n" );
break;
default:
printf( "Parent array: %s\n", array );
sleep(1);
printf( "Parent array: %s\n", array );
free( array );
}
return 0;
}
출력은 다음과 같습니다.
Parent array: Hello
Child array: Hello
Child array: Goodbye
Parent array: Hello
스택에 할당된 데이터는 하위에서 사용할 수 있지만 힙에 할당된 데이터는 하위에서도 사용할 수 있는 것으로 보입니다.마찬가지로 자식은 스택의 부모 데이터를 수정할 수 없고, 자식은 힙의 부모 데이터를 수정할 수 없습니다.그래서 저는 아이가 스택과 힙 데이터의 복사본을 얻는다고 가정합니다.
Linux에서는 항상 이런 경우가 있습니까?그렇다면 이를 지원하는 설명서는 어디에 있습니까?fork() man 페이지를 확인했는데 힙에 동적으로 할당된 메모리에 대해 구체적으로 언급하지 않았습니다.
프로세스에 할당된 각 페이지(스택이 있는 가상 메모리 페이지 또는 힙 페이지)는 분기된 프로세스가 액세스할 수 있도록 복사됩니다.
실제로 시작할 때 바로 복사되지 않고 Copy-on-Write(쓰기 시 복사)로 설정되어 있습니다. 즉, 프로세스 중 하나(부모 또는 자식)가 페이지를 수정하려고 하면 페이지가 서로 손상되지 않도록 복사되며 포크() 지점의 모든 데이터에 액세스할 수 있습니다.
예를 들어, 실제 실행 파일이 메모리에 매핑된 코드 페이지는 일반적으로 읽기 전용이므로 분기된 모든 프로세스에서 재사용됩니다. 이 페이지는 다시 복사되지 않습니다. 아무도 거기에 쓰지 않고 읽기만 하기 때문에 쓰기 시 복사가 필요하지 않습니다.
포크 후 자식은 부모로부터 완전히 독립되지만 부모의 복사본인 특정 항목을 상속받을 수 있습니다.힙의 경우, 자식은 개념적으로 포크 시점에 부모 힙의 복사본을 갖게 됩니다.그러나 자녀의 주소 공간에서 머리 부분을 수정하면 자녀의 복사본만 수정됩니다(예: 쓰기 시 복사).
설명서의 경우:저는 문서가 일반적으로 blah, blah blah를 제외한 모든 것을 복사한다고 명시한다는 것을 알아차렸습니다.
짧은 대답은 '쓰면 더러워진다'입니다. - 더 긴 대답은... 훨씬 더 긴 것입니다.
그러나 모든 의도와 목적에서 - C 수준에서 안전하게 가정할 수 있는 작업 모델은 포크() 직후에 두 프로세스가 완전히 동일하다는 것입니다. 즉, 아이가 100% 정확한 복사본을 얻는다는 것입니다. (하지만 포크()의 반환 값을 중심으로 잠시 동안) - 그리고 나서 각 측면이 메모리를 수정하고 스택과 더미를 쌓으면서 분기하기 시작합니다.
따라서 부모가 자신의 공간에 복사한 것과 동일한 데이터로 시작하여 수정하고 수정한 것으로 간주하는 반면 부모는 자신의 복사본을 계속합니다.
실제로는 좀 더 복잡합니다. 더러운 일을 함으로써 완전한 복사를 피하려고 하기 때문입니다. 필요할 때까지 복사하는 것을 피하려고 하기 때문입니다.
DW.
부모가 자식에 의해 업데이트되지 않았기 때문에 예제가 작동하지 않습니다.해결책은 다음과 같습니다.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
typedef struct
{
int id;
size_t size;
} shm_t;
shm_t *shm_new(size_t size)
{
shm_t *shm = calloc(1, sizeof *shm);
shm->size = size;
if ((shm->id = shmget(IPC_PRIVATE, size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) < 0)
{
perror("shmget");
free(shm);
return NULL;
}
return shm;
}
void shm_write(shm_t *shm, void *data)
{
void *shm_data;
if ((shm_data = shmat(shm->id, NULL, 0)) == (void *) -1)
{
perror("write");
return;
}
memcpy(shm_data, data, shm->size);
shmdt(shm_data);
}
void shm_read(void *data, shm_t *shm)
{
void *shm_data;
if ((shm_data = shmat(shm->id, NULL, 0)) == (void *) -1)
{
perror("read");
return;
}
memcpy(data, shm_data, shm->size);
shmdt(shm_data);
}
void shm_del(shm_t *shm)
{
shmctl(shm->id, IPC_RMID, 0);
free(shm);
}
int main()
{
void *array = malloc(20);
strcpy((char *) array, "Hello");
printf("parent: %s\n", (char *) array);
shm_t *shm = shm_new(sizeof array);
int pid;
if ((pid = fork()) == 0)
{ /* child */
strcpy((char *) array, "Goodbye");
shm_write(shm, array);
printf("child: %s\n", (char *) array);
return 0;
}
/* Wait for child to return */
int status;
while (wait(&status) != pid);
/* */
shm_read(array, shm);
/* Parent is updated by child */
printf("parent: %s\n", (char *) array);
shm_del(shm);
free(array);
return 0;
}
언급URL : https://stackoverflow.com/questions/4597893/specifically-how-does-fork-handle-dynamically-allocated-memory-from-malloc
'programing' 카테고리의 다른 글
SQL Server에서 세미콜론을 언제 사용해야 합니까? (0) | 2023.06.07 |
---|---|
명령 및 인수와 함께 python 하위 프로세스를 사용하는 동안 "OSError: [Errno 2] 해당 파일 또는 디렉터리 없음" (0) | 2023.06.07 |
ggplot2 상자 그림에서 특이치 무시 (0) | 2023.06.07 |
사용자별로 조건을 충족하는 초기 항목 필터링 (0) | 2023.06.07 |
Angular 2 및 TypeScript 약속 (0) | 2023.06.07 |