"/dev/zero를 이용한 mmap에 대한 질문"

익명 사용자의 이미지

다음은 구동 프로그램입니다.

#include
#include
#include
#include
#include
#include

typedef struct _song
{
int a;
char b[8];
} t_song;

t_song *p_song;

void main(int argc, char **argv)
{
int input, output, count = 3, i, size;
size_t filesize;
void *source, *target;
char *endchar = '\0';

if(argc != 2)
{
fprintf(stderr, "usage copyfile source\n");
exit(1);
}

if((input = open(argv[1], O_RDWR| O_CREAT | O_TRUNC, 0666)) == -
1)
{
fprintf(stderr, "Error opening output file %s\n", argv[1]);
exit(1);
}
size = sizeof(t_song) * count;
lseek(input, size-1, SEEK_SET);
write(input, &endchar, 1);
filesize = lseek(input, 0, SEEK_END);
printf("file name is |%s| file size is %d\n", argv[1],filesize);
printf("int size is %d, char size is %d\n", sizeof(p_song->a),
sizeof(p_song
->b));
printf("t_song size is %d\n", sizeof(t_song));

if((p_song = (t_song *) mmap(0, size, PROT_WRITE|PROT_READ,
MAP_SHARED, inpu
t, 0)) == \
(void
*) -1)
{
perror("Error mapping input file");
fprintf(stderr, "mapping file is %s\n", argv[1]);
exit(1);
}
puts("after mmap1");

for(i = 0; i < count; i++)
{
p_song[i].a = i;
strcpy(p_song[i].b,"song");
}
puts("after allocation");

filesize = lseek(input, 0, SEEK_END);
printf("first file size is %d, input size is %d\n", filesize, \
sizeof(t_song) * count);
if(msync((void *)p_song, size, MS_SYNC) == -1)
{
perror("msync() failed");
exit(1);
}

filesize = lseek(input, 0, SEEK_END);
printf("second file size is %d\n", filesize);

if(munmap(p_song, size) == -1)
{
perror("munmap() failed");
exit(1);
}

puts("after munmap");

/************1*************/
if((p_song = (t_song *) mmap(0, size, PROT_READ, MAP_SHARED,
input, 0)) == \
(void
*) -1)
{
fprintf(stderr, "Error mapping input file %s\n", argv[1]);
exit(1);
}

puts("after mmap2");

if(msync((void *)p_song, size, MS_SYNC/*|MS_INVALIDATE*/) == -1)
{
perror("msync() failed");
exit(1);
}

for (i = 0; i < count; i++)
{
printf("p_song[%d].a is %d, b is |%s|\n",i, p_song[i].a,
p_song[i].b);
}

/************3*************/
if(munmap(p_song, size) == -1)
{
perror("munmap() failed");
exit(1);
}

/****************************/
puts("after munmap2");
close(input);
exit(0);
}

1. 목적

대충보면 아시겠지만, argv[1]으로 파일이름을 입력받아 적절한 데이타
를 mmap를 이용해서 입력하고 다시 이 파일의 내용을 mmap를 이용해서
확인해 보는 그런 프로그램입니다.

2.출력
2-1. t_mmap songsong(임의의 파일 입력시)

file name is |songsong| file size is 36
int size is 4, char size is 8
t_song size is 12
after mmap1
after allocation
first file size is 36, input size is 36
second file size is 36
after munmap
after mmap2
p_song[0].a is 0, b is |song|
p_song[1].a is 1, b is |song|
p_song[2].a is 2, b is |song|
after munmap2

2-2. t_mmap /dev/zero(SVR4의 특수목적파일)

file name is |/dev/zero| file size is 0
int size is 4, char size is 8
t_song size is 12
after mmap1
after allocation
first file size is 0, input size is 36
second file size is 0
after munmap
after mmap2
p_song[0].a is 0, b is ||
p_song[1].a is 0, b is ||
p_song[2].a is 0, b is ||
after munmap2

3. 질문

SVR4에서 /dev/zero는 mmap를 위한 특수목적 파일로, 읽을 때 0바이트
를 반환하고 장치에 쓰여지는 모든 것들을 버린다고 합니다.

만약 그렇다면 결과는 맞게 나온 것 같은데...

richard stevens저작의 unpv1의 27.8장에 그림27.19, 27.20을 보
면 /dev/zero를 이용하여 이곳에 mutex를 올려놓고 이를 여러 프
로세스가 공유하는 예제를 볼수 있습니다.

분명 mutex를 /dev/zero에 올려놓는다는 것은 하나의 Process가 올려놓
은 mutex정보를 임의의 순간에 임의의 Process가 공유할수 있어야 하는
데 위의 실험결과대로 장치에 쓰여지는 모든 것들이 지워진다고 한다면
어떻게 임의의 Process가 mutex를 공유할수 있을까요?

그리고 /dev/zero를 이용한 mmap가 과연 어느 경우에 쓰일수 있을지에
대하여도 매우 궁금합니다.

이 점에 대하여..고수님들의 현명한 조언을 기대합니다.

익명 사용자의 이미지


결론부터 이야기 한다면 위의 프로그램은
Test 방법부터 문제가 있음을 알려드립니다.

일반적으로 anonymouse memory를 얻는 방법이
두자지가 있습니다. 하나는 anon을 flag로지정하는 방법이고
두번째는 위의 소스처럼(flag가 지원되지 않을시) /dev/zero
를 사용하는 방법입니다. 그런데 이렇게 map되어진 memory를
동시(여러 Process)에 사용된다면 없지만 위의 소스처럼
map->unmap->map의 방법으로 사용하여 자료가 남아 있을
확인한다는 것은 우문이라는 생각이 되는군요.

만약 영속적인 공간을 원했다면 file에다가 map을 했어야지요.
그렇다면 위의 소스는 원하는 자료를 확인 할수 있을겁니다.
만약 Multi-Process하에서 Multi-Thread의 Control을 원하신다면
file을 통한 map되어진 memory로 mutex를 공유하시면 됩니다.
그러면 원하시는 결과를 얻을수 있을 겁니다.

익명 사용자의 이미지

님의 친절한 답변에 깊은 감사를 드리오며 그럼에도 불구하고
아직 이해되지 않은 면이 있어서 몇자 첨언하고자 합니다.

만약 영속적인 공간을 원했다면 file에다가 map을 했어야지요.
그렇다면 위의 소스는 원하는 자료를 확인 할수 있을겁니다.
만약 Multi-Process하에서 Multi-Thread의 Control을 원하신다면
file을 통한 map되어진 memory로 mutex를 공유하시면 됩니다.
그러면 원하시는 결과를 얻을수 있을 겁니다.

--> 그거야 너무나 당연한 결론입니다. 그런데...

문제는 파일로 가능하다는 것이야 누구나 다 아는 사실이지만 리처
드 스티븐스는 파일로 mutex를 공유하는 방법이 아닌 다른 방법,
즉 /dev/zero를 이용한 mutex의 공유를 추천하고 있다는 것입니다.

님의 말씀이 사실이라면 왜 스티븐스는 file이 아닌 자료가 보존되
지도 않는 /dev/zero에다가 mutex를 공유하는 방법을 추천했을까요?

그 이유에 대하여 합리적인 답변을 기대합니다.

저는 개인적으로 mutex를 전혀 관련없는 Process에서 공유하는 방법
을 다음과 같이 생각하고 있습니다.

참고하셔서 저의 생각의 모자란 점을 지적해 주시기 바랍니다.

1. file 이용

파일이름으로 uique한 filename을 만들어 이것에다 mutex를 공유하고
여러 process들 간에 사용한다.

이 방법의 단점은 자주 이용되는 mutex의 성격상 속도에 문제가 있을
수 있다.

2. shared memory를 이용.

mutex를 shared memory에 써서 모든 Process에 공유하는 방법.

1의 방법보다 빠른 것은 사실이나 System Wide하게 쓰려면 갯수제한
(100개정도)이 있을 수 있다.

만약 이러한 제한을 피하려면 Shared memory에 mutex를 여러개 쓸 수
있게끔 만들어야 하는데 이렇게 되려면 복잡한 로직과 동시성 제어를
위한 semphore와 같은 추가 자료구조가 필요할 수 있다.

3. ananmous 메모리 대응

1의 방법에서의 단점인 open에 드는 시간을 최소화 할 수 있다.

그러나 특정 시스템에는 구동이 되지 않을 수 있다.

4. /dev/zero를 이용

특성상 읽은 후에 모든 내용을 삭제하므로 제대로된 목적을 달성
할 수 있을지 의문스럽다.

그럼에도 불구하고 리처드 스티븐스가 추천하는 이유가 무엇인지
무지 궁금함.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.