디바이스 어드레스(?) 들에 대한 질문.

febace의 이미지

혼란이 찾아 왔습니다.
리눅스에서 프로그래밍 할 경우 생성되는 주소들은 가상 주소 이고
그것이 mmu의 도움을 받아서 드디어 피지컬 주소로 변환된다고 이해 하고 있었습니다.

그런데 어느날..디바이스 드라이버 관련 강좌를 보는데
LPT1(프린터)포트의 주소가 0x378이고 그 것에 접근을 할때에는

프로그램상에서 0x378로 직접 접근 하는 것을 볼수있었습니다.
제 머릿 속에는 0x378역시 가상 주소이고 그 것이 mmu를 통해 변환이 되기 때문에 피지칼 어드레스는 다를 것이다라는 결론에 도달하게 되었습니다.

하지만 그렇지 않았습니다. 0x378은 피지칼 주소였고. 갑자기 혼란이 찾아 왔습니다.

디바이스 드라이버를 만들때에 0x378과 같은 피지칼 주소를 사용하기도 하고
가상 주소를 사용하기도 하고 ( 이럴 경우에는 가상 메모리 -> 피지칼 메모리 테이블이 존재 하는 것을 볼수있었습니다. )

1.
어느 우에는 직접 피지칼 주소로 접근이 가능하고
어느 경우에는 가상->변환->피지칼 주소 접근이 가능한지.
그러한 것을 커널이 어떻게 알수있는지

2.
0x378이라는 주소는 어디서 지정하는 값인지

3.
사용자 프로그램에서 printf(0x378,"데이타"); 라고 하는 것은 어떠한 결과를 초래하는지..

참 궁금합니다..

자룡의 이미지

요새 프린트포트로의 접근을 하기위해 문서들을 보는 중입니다.

다른건 저도 잘 모르겠구요.
LPT1 의 주소 0x378 은 컴퓨터의 CMOS 에 들어가보면
설정이 그렇게 되어있더군요.

보통 0x3bc, 또는 0x378 로 설정하는것 같습니다.
이것은 윈도우에서도 0x378 로 직접 접근 되는것으로 보아
물리적 주소를 그냥 사용하는듯 합니다.

ioperm 으로 그 주소를 사용할 수 있는 권한을 얻고
outb 를 사용 그 주소로 직접 데이터를 보내는것 같습니다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <asm/io.h>

#define base 0x378           /* printer port base address */
#define value 255            /* numeric value to send to printer port */

main(int argc, char **argv)
{
   if (ioperm(base,1,1))
    fprintf(stderr, "Couldn't get the port at %x\n", base), exit(1);

   outb(value, base);
}

위 예제는 http://www.hut.fi/Misc/Electronics/circuits/parallel_output.html
에 나온 예제입니다.

그런데 현재 제 리눅스 머신 (레드햇8.0, 커널 2.4.X) 에서는
저 프로그램을 돌려도 프린터포트에서 값이 안나오네요.

현재 http://cyberelk.net/tim/parport/index.html 문서를 보려는 중인데
커널 2.4.X 에서 직접 접근이 불가능하게 된게 아닐까
추측만 하는 중이랍니다.

아니면 제가 프린터포트에서 나오는 값 검출을 위해 만든 LED 회로에
문제가 있는건지도 모르겠네요. ^^;;;;;

-----
이글을 읽는 모든 이에게 평화가 함께 하기를... ^^;

withlhw의 이미지

1. 프로그래밍을 할때 사용하는 메모리는 님께서 생각하시다 싶이
논리적인 주소 개념입니다. 왜냐면은 실제로 프로그래밍이 실행이
될때 메모리 주소 상에서 어느 부분에서 실행이 될지 모르거든요.
하지만 이건 프로그래밍의 성격에 따라 다릅니다.
여기서의 프로그래밍이란 어떤 특정 운영체제 하에서 실행되는
프로그램입니다. 운영체제의 서비스를 받지 못할 경우에는
물리적인 메모리 주소를 이용해서 프로그래밍 할 수 있겠죠.
이 문제는 운영체제에서 그런 서비스를 해주느냐 아니냐의 관점에서
보시면은 쉽게 생각이 되실 겁니다.

2. 프린터, 모니터, 키보드 등등은 I/O라고 부르는 입출력 장치 입니다.
이것은 운영체제에서 IRQ를 통해서 접근을 합니다. 예를 들어서
모니터에 어떤 값을 출력하기 위해서는 운영체제에서는 그래픽카드
로 특정 값을 보내면은 그래픽 카드는 그걸 받아서 모니터에 출력을
하는 거져. 그리고 이 주소는 논리적일 필요가 없습니다. 시스템이
각 하드웨어 장치랑 CPU랑 통신을 하기 위해 IRQ 번호를 할당해
놓으니깐여.
어셈블리 프로그래밍을 보면은 직접적으로 IRQ를 이용해서 하드웨어
에 접근을 많이 합니다. IRQ 몇번은 플로피, 등등등 미리 다 정해져
있습니다.

3. pritnf(0x378, '데이터');
라고 하면은 에러가 발생이 됩니다. 그 이윤 다 아시겠죠?
stdout 은 일반적으로 모니터 입니다. 이걸 프린터로 바꿔 버리고
나서 실행을 하시면은 출력되는 값은 프린터로 찍혀 나올껍니다.
저도 예전에 DOS에서 이걸 많이 사용해 봤거던요.
C:\dir *.* > lpt1
이라고 하면은 님이 원하는 결과를 얻을 수 있을껍니다. ^^;

flagoff의 이미지

mmu에서 말하는 주소는 메모리상의 주소를 말합니다.
프린트 포트나 하드웨어 주소는 일반적인 경우 cmos에서 제공하는 하드웨어 주소를 말하는것이죠
프로그래밍하는데 사용하는 주소는 32bit Linux의 경우4G의 메모리 공간을 사용하는데요
1G는 커널이 등록되고 나머지 3G에 환경변수 코드, 택스트,스택 영역이 올라가죠.
아무튼 가상주소는 저런것 종류의 한정된 자원을 속도로 보상하면서 사용하고자 하는것이구요.
coms에서 제공하는 하드웨어 주소에 인터럽트를 통한 제어는 cpu의 mmu와는 다릅니다.

pabitz의 이미지

자세한 내용은 생략하고,
질문하신 0x378은 분명 LPT1의 메모리 주소입니다.

x86에서 사용하는 MMU는 메모리 주소에 따라 사용되는 방법이 다릅니다.
그래서, 하드웨어의 물리적인 주소를 그대로 사용할 수 있습니다.

메모리 관련 자료 찾아 보시면 상세히 나옵니다.

seed의 이미지

일단 IO를 메모리에 메핑하는 방식, IO 라인을 따로 지정하는
방식이 있는데 x86은 후자입니다.
예를들어 CPU에 IO_or_MEM 과 비슷한 핀이 있어서
이게 0이면 메모리번지 ,1이번 IO번지를 지정하게되죠.
(어느게 메모리인지 IO인지 확인은 안해봤음.)
그러니까 똑같은 번지도 두가지로 접근 가능하다는겁니다.

>제 머릿 속에는 0x378역시 가상 주소이고 그 것이 mmu를 통해 변환이 되기 >때문에 피지칼 어드레스는 다를 것이다라는 결론에 도달하게 되었습니다.
x86에서 mmu를 통하지 않고는 주소를 읽거나 쓸수없습니다.
mmu가 참고하는것은 각각의 프로세스의
페이지 테이블(간단히 이렇게 부르죠..딴지걸지 마시길 -.-)입니다.
그런데... 만약 램이 128M있다면 3G 에서부터 3G +128M가
1:1로 매핑되어집니다.
다시말해 변환해도 주소값이 똑같다는거죠. -.-
그래서 커널내부에서 __pa 메크로는 단순히
logical address에서 3G를 빼는거죠.

ps.
위의 답글을 다 안읽어 봐서 중복되는게 있을지도 ?

익명 사용자의 이미지

위에서 설명해주신 분들이 쓰신 내용중 일부 오류가 있어서 정정할 겸 씁니다(이번에는 flamewar가 일어나지 않아야 할 텐데... :x ).

febace wrote:
1.
어느 우에는 직접 피지칼 주소로 접근이 가능하고
어느 경우에는 가상->변환->피지칼 주소 접근이 가능한지.
그러한 것을 커널이 어떻게 알수있는지

하드웨어 입출력 방식은 크게 두가지가 있는데, 하나는 입출력 포트 방식이고, 하나는 메모리맵 기반 방식입니다. i386 계열에서는 전통적인 방식은 전부 포트 기반이고, 최근의 PCI/USB/IEEE1394/기타 등등은 메모리맵 방식을 이용합니다(기기에 따라 두방식을 모두 지원하는 것도 있습니다).

질문하신 내용에 대한 답을 드리자면, 입출력 포트에 사용되는 주소는 일반 물리 주소와는 별개로 처리되기 때문에 MMU를 거치지 않습니다(메모리맵 방식이 하드웨어 주소공간을 일반 가상주소공간으로 맵하는 데 비해). 그래서 입출력 포트의 0x378번지와 일반 주소의 0x378번지를 구분하기 위해 입출력 포트 주소에 접근하기 위한 프로세서 명령어가 따로 존재합니다. in/out이 바로 그런 명령어들이죠.

Quote:
2.
0x378이라는 주소는 어디서 지정하는 값인지

IBM이 PC 아키텍쳐를 만들때 부여한 프린터용 입출력 포트 주소입니다.

Quote:
3.
사용자 프로그램에서 printf(0x378,"데이타"); 라고 하는 것은 어떠한 결과를 초래하는지..

fprintf를 말씀하시는 것이지요? fprintf의 첫번째 인수는 FILE * 타입의 포인터라 입출력 포트 주소와는 무관합니다. C 프로그램에서 포트 입출력을 하려면 ioperm(2)으로 포트 사용권한을 획득한 뒤 in()/out() 매크로를 써서 합니다.

더 자세한 내용은 인텔 프로세서 매뉴얼 볼륨 1의 12장을 참조하시기 바랍니다.

seed의 이미지

잘못을 지적해주셔서 감사합니다. :wink:

그런데 방준영님 홈페이지가 안들어가 지는데....딴데로 옮겨졌나요...

댓글 달기

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