커널이 바라보는 가상 메모리 영역

totohero의 이미지

어떤 유저 프로세스가 시스템콜을 호출하면, 그 시스템콜은 커널 모드에서 수행되잖습니까? 그렇다면 해당 시스템콜이 수행되는 동안 커널이 바라보는 가상 메모리는 시스템콜을 호출한 프로세스의 가상 메모리와는 다르겠지요? 각 프로세스의 가상 메모리에 대한 내용 (페이지 테이블의 베이스 주소 등등)은 current 포인터(process control block이던가요?)를 따라가다보면 있을 것 같은데, 커널 자체에 대한 가상 메모리 맵핑 상황은 어떻게 알 수 있나요?

hb_kim의 이미지

같습니다.

익명 사용자의 이미지

hb_kim wrote:
같습니다.

같다구요? 프로세스의 가상 메모리와 시스템콜 처리시의 가상 메모리가 같다는 말인가요? 그렇다면 서로 다른 프로세스가 호출하는 시스템콜의 처리시의 가상 메모리는 다르겠네요? 그런데 제가 디바이스 드라이버를 만들때의 경험으로는 장치 발견시, 장치에 대한 정보를 가진 커널 글로벌 객체를 할당 받고, ioctl에서 이 글로벌 객체에 접근하는 식으로 코딩했던것 같은데요?
hb_kim의 이미지

여기에 설명이 잘 되어 있네요.

http://www.csn.ul.ie/~mel/projects/vm/guide/html/understand/node30.html

Anonymous wrote:
hb_kim wrote:
같습니다.

같다구요? 프로세스의 가상 메모리와 시스템콜 처리시의 가상 메모리가 같다는 말인가요? 그렇다면 서로 다른 프로세스가 호출하는 시스템콜의 처리시의 가상 메모리는 다르겠네요? 그런데 제가 디바이스 드라이버를 만들때의 경험으로는 장치 발견시, 장치에 대한 정보를 가진 커널 글로벌 객체를 할당 받고, ioctl에서 이 글로벌 객체에 접근하는 식으로 코딩했던것 같은데요?

처음 세 문장과 맨 마지막 문장 사이의 연결관계가 명확하지가 않군요.

totohero의 이미지

맨 마지막 문장의 의미는, 서로 다른 프로세스가 호출한 시스템콜이 완전히 서로 다른 메모리 영역을 보게되면, 각 시스템콜(예를 들어 장ㄷ치 드라이버의 ioctl 같은...)이 어떻게 하나의 커널 글로벌 객체(장치를 나타내는 하나의 객체)를 공유할 수 있겠느냐의 의미였는데, 말씀하신 문서를 읽어보니 설명이 되는 듯하군요. 커널 영역으로 할당된 1G 영역은 서로 다른 프로세스 사이에도 변하지 않으니까요. 답변 감사합니다.

hb_kim wrote:
여기에 설명이 잘 되어 있네요.
처음 세 문장과 맨 마지막 문장 사이의 연결관계가 명확하지가 않군요.
totohero의 이미지

다시 궁금증이... ^^; 그렇다면 시스템콜로 user 영역 메모리에 대한 포인터를 넘겨주고 시스템콜이 이 영역을 수정하게 할때, 굳이 커널에, 같은 크기 메모리를 할당하고 copy_from_user/copy_to_user를 할 필요는 없는 것 아닌가요?

hb_kim wrote:
같습니다.
hwandori의 이미지

시스템 콜에서 복귀했을때는 사용자 모드인데 사용자모드에서는 커널공간의 데이터를 접근할수 없지 않나요? 그러므로 사용자모드에서 접근가능할수 있게 커널공간의 데이터를 사용자공간의 데이터로 복사해야 할것 같은데요..

totohero의 이미지

커널 공간으로 사용자 메모리를 복사하지 않고, 시스템콜이 사용자 영역을 바로 수정하는 식으로 하면 안되냐는 것인데요. 그 경우 사용자 모드에서 커널 공간을 액세스할 일이 없겠죠.

hwandori wrote:
시스템 콜에서 복귀했을때는 사용자 모드인데 사용자모드에서는 커널공간의 데이터를 접근할수 없지 않나요? 그러므로 사용자모드에서 접근가능할수 있게 커널공간의 데이터를 사용자공간의 데이터로 복사해야 할것 같은데요..
hb_kim의 이미지

이것은 zero-copy 라고 일컬어지는데, 말로는 일견 간단하게 들리지만 실제로 성능/효율등을 감안해서 구현하려면 아주 만만한것은 아니거든요?

totohero wrote:
다시 궁금증이... ^^; 그렇다면 시스템콜로 user 영역 메모리에 대한 포인터를 넘겨주고 시스템콜이 이 영역을 수정하게 할때, 굳이 커널에, 같은 크기 메모리를 할당하고 copy_from_user/copy_to_user를 할 필요는 없는 것 아닌가요?
hb_kim wrote:
같습니다.
익명 사용자의 이미지

"만만치 않다"는 것은 해당 영역을 DMA 버퍼로 쓴다든지, 네트워크 패킷의 일부여서 얼라인먼트 문제가 걸린다든지 하는 걸 말씀하시는지요? 아무튼, 그런 문제가 없이, 크기를 확실히 아는 (예를 들어) 어떤 구조체를 넘겨준다든지 할때에는 굳이 copy_from/to_user로 복사할 필요는 아닌 것이지요? (저는 여태, 같은 물리 메모리를 커널과 사용자 모드에서 바라보는 가상 주소가 다를거라고 생각해서 그 변환이 일어나는 것이리라 생각했는데 말이죠)

hb_kim wrote:
이것은 zero-copy 라고 일컬어지는데, 말로는 일견 간단하게 들리지만 실제로 성능/효율등을 감안해서 구현하려면 아주 만만한것은 아니거든요?

totohero wrote:
다시 궁금증이... ^^; 그렇다면 시스템콜로 user 영역 메모리에 대한 포인터를 넘겨주고 시스템콜이 이 영역을 수정하게 할때, 굳이 커널에, 같은 크기 메모리를 할당하고 copy_from_user/copy_to_user를 할 필요는 없는 것 아닌가요?
hb_kim wrote:
같습니다.
hb_kim의 이미지

Data copy 가 문제가 되는 경우는 소량의 구조체를 복사하는 때가 아니고 대량의 블록 데이터등을 복사하는게 더 크겠죠? 보통 패킷 방식의 DMA 를 사용하는 디바이스 드라이버에서 zero-copy 가 고려됩니다. 디바이스가 어짜피 DMA 를 사용해서 데이터 전송을 하는데 이를 다시 CPU 사이클 낭비해 가면서 복사해가면 좀 아깝다는 생각도 들고요. 그런데 보통 블록 데이터라면 I/O 성능 향상을 위해서 블록 캐시를 쓰고 prefetch 등도 하게 되니까, 아무래도 유저 영역의 메모리를 직접 scatter-gather DMA 로 액세스 한다는 컨셉과 잘 안맞게 되구요.

구조체등 소량의 데이터를 주고 받는데는 data copy는 별 문제가 되지 않습니다만, 많은 커널 프로그래밍 초보분들이 실제 설계 밸런스에 대한 감이 없어서 이를 순순히 받아들이지 못하고, 아무래도 효율적으로 하기 위해서 본인의 드라이버에는 mmap() 을 써야 되는것 아닌가 하는 의구심을 떨치지 못하죠.

뭐 사실 그렇게 어려운것 까지는 아니지만 mmap 은 고사하고 패킷 방식의 DMA 을 쓰는 디바이스 드라이버를 설계해서 제품 품질까지 구현해서 내놓을 정도의 실력을 가진 분이면, 이 바닥에서는 "만만치 않은' 실력을 가지신 분이라고 해야겠죠.

Anonymous wrote:
"만만치 않다"는 것은 해당 영역을 DMA 버퍼로 쓴다든지, 네트워크 패킷의 일부여서 얼라인먼트 문제가 걸린다든지 하는 걸 말씀하시는지요? 아무튼, 그런 문제가 없이, 크기를 확실히 아는 (예를 들어) 어떤 구조체를 넘겨준다든지 할때에는 굳이 copy_from/to_user로 복사할 필요는 아닌 것이지요? (저는 여태, 같은 물리 메모리를 커널과 사용자 모드에서 바라보는 가상 주소가 다를거라고 생각해서 그 변환이 일어나는 것이리라 생각했는데 말이죠)
totohero의 이미지

totohero wrote:
다시 궁금증이... ^^; 그렇다면 시스템콜로 user 영역 메모리에 대한 포인터를 넘겨주고 시스템콜이 이 영역을 수정하게 할때, 굳이 커널에, 같은 크기 메모리를 할당하고 copy_from_user/copy_to_user를 할 필요는 없는 것 아닌가요?
hb_kim wrote:
같습니다.

google에서는 다음과 같은 답변을 들었습니다.

http://groups.google.com/groups?hl=ko&lr=&threadm=ac9276f6.0410201547.35d95ee3%40posting.google.com&rnum=3&prev=/groups%3Fq%3Dtotohero%2540empal.com%26hl%3Dko%26lr%3D%26selm%3Dac9276f6.0410201547.35d95ee3%2540posting.google.com%26rnum%3D3

hb_kim의 이미지

리눅스 계열 nerd 들은 별별 변명을 다 생각해낼수 있겠지만 사실 그중 정당한 이유라고 할수 있는것은 제가 볼땐 없습니다.

제가 보기엔 '아직 못했다' 가 정답입니다.

윈도우즈의 IO manager에는 direct IO 라고 유저 모드 액세스에 zero copy 로 DMA 데이터를 쓸수 있도록 해주는 모드가 오래전부터 있어왔습니다.

리눅스에서도 할수 있습니다. 누군가 분명 이미 해놓았을겁니다 - 그것도 여러 군데에서. 다만 아직 아무도 커널 메인트리에 들어가도록 공개하지 않았을 뿐이겠죠. 리눅스 배포판 회사가 아니면서, 리눅스 관련 커널 해킹을 하는 회사에서 흔히 있는 일입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.