시스템 콜과 디바이스드라이버의 파일오퍼레이션

joy21c의 이미지

시스템 콜과 디바이스드라이버의 파일오퍼레이션 수행관계는 어떻게 되나요?
응용프로그램에서 open, read 같은 시스템콜을 호출하면 우선 커널의 sys_open, sys_read 가 호출될 텐테
그 후에 어떻게 해당 디바이스의 파일오퍼레이션을 호출하나요?

그리고 open의 경우 실행되기 전까지는 그게 일반 파일인지 디바이스 파일인지 모를텐데
디바이스 드라이버에 open 오퍼레이션을 맵핑시켜주는 것이 의미가 있는건가요?

ssehoony의 이미지

질문 자체가 자문 자답인듯한데요.

유져 어플리케이션에서 open이나 read를 했을 때 디바이스의 어떤 오퍼레이션을 해야하는지 알려주기 위해
두번째로 물어보신 open 오퍼레이션에 맵핑을 시켜주는겁니다.

커널은 유져어플이 open을 호출했을 때 커널 스스로 어떤 함수를 콜 해야 하는지
커널 컴파일 당시에 결정되어 있지 않은 경우는 알수가 없죠.
그래서 커널 컴파일이 된 이후에는 두번째 질문을 하신 것 처럼
함수포인터를 이용해서 뭘 호출해야할지 해당 디바이스를 개발한 사람이 커널에게 알져주는 방식을 이용합니다.
이게 바로 디바이스 드라이버의 역할이죠.
즉 드라이버에는 실제 하드웨어를 오퍼레이션하는 실행코드와 그 코드들을 커널의 open, read 등과 연결하는
맵핑 정보를 갖고 있습니다.
커널은 그 드라이버가 알려준 맵핑값을 이용해 그냥 그대로 시키는 대로 합니다.
그래서 드라이버가 잘못된 맵핑을 가르쳐 줘도 커널은 그게 맞는가 보다 생각하고 그대로 믿고 따릅니다.
그리곤 '어라! 뭐가 이상하다'를 느끼면 'kernel panic'을 내 뱉고 죽어 버리지요.

제가 질문을 정확히 해야하고 답변했는지 잘 모르겠군요.
혹시 원하시는 답이 아니라면 질문을 좀 더 구체적으로 해주신다면
같이 고민해 볼 수 있을 듯 하군요.

swunk의 이미지

질문의 답이 될지 모르겠습니다만...

두번째 질문에 대해서 말씀드리겠습니다.
네트워크 카드를 예로 들어서 설명하면 네트워크 카드는 사용자가 ifconfig 명령어를 수행할때 디바이스의 open()함수가 호출됩니다. 사용자가 ifconfig 명령어를 수행하면 어떤 open() 함수를 수행해야하는 지는 알고 있어야 하기 때문에 디바이스의 open() 함수를 미리 등록해 놓는거죠...
예를 들어서 eth0가 3com의 3c509 네트워크 카드인 경우는 dev->open = &el3_open() 함수로 미리 매핑을 시켜 놓는거죠..여기서 dev 구조체는 커널이 가지고 있는 놈이고 모든 사용자가 3c509 드라이버를 insmod 하는 순간 dev->open 함수포인터는 el3_open을 가리키고 있는거고 사용자가 ifconfig 명령어를 수행하면 그때 el3_open 함수가 호출되는 겁니다. 그렇게 때문에 드라이버가 커널에 포함된 경우에는 컴파일시에 결정이 되어야 하고 모듈인 경우에는 모듈 insert 시에 미리 결정이 되어 있어야 합니다.
간단한 내용을 복잡하게 설명한것 같습니다. *^^*

첫번째 질문은 virtual file system 에 대한 내용을 알고 계시다면 이해가 금방 되실텐데...저도 확실히 아는것은 아니지만 아는대로 말씀 드리겠습니다.
유저 어플에서 read() 시스템 콜을 호출한 경우를 빌어서 말씀드리면...
님께서 말씀하신것 같이 라이브러리(libc.a)를 통하여 0x80 vector 테이블로 넘어가서 시스템콜 넘버를 알아온 후 sys_read() 함수가 호출됩니다.
sys_read()함수에서는 fget() 함수를 통해서 사용자가 지정한 file descriptor를 이용해서 file 구조체를 얻어오고, file 구조체의 f_op 함수포인터에 등록된 read()함수를 호출합니다. 여기서 만약 사용자가 지정한 fd가 socket이라고 한다면 socket 구조체의 ops가 가르키는 recvmsg()함수가 호출되고 이는 다시 sock 구조체의 proto 필드를 참조하여 tcp/udp 등을 판단한후 해당 프로토콜에 등록되어 있는 tcp_rcv() 혹은 udp_rcv() 함수등을 호출합니다. 이후 tcp/ip 등의 커널 스택을 지나서 실제 디바이스에 등록되어 있는 read() 함수가 호출이 됩니다.
적고 보니 예를 잘못 든것 같네요..read 시스템콜은 tcp 단에서 sleep 되어 기다리고 있다가 실제 패킷이 recv 되면 interrupt 가 걸려서 sleep 되어 있는 쓰레드를 깨우게 되죠..즉 네트워크 카드의 read() 함수는 어플에서 호출하는 것이 아니라 hw interrupt 에서 호출하게 되는 거죠...

여튼 나름대로 자세하게 설명하려고 노력했는데 도움되 되었나 모르겠습니다. 막상 원하시는 질문의 답이 안된것 같군요...자꾸 네트워크 디바이스를 예로들어서 말씀 드린 이유는 제가 알고 있는게 네트워크 밖에 없습니다. 추가 적인 질문 혹은 제가 답변 드린 부분에 대해 이해가 잘 안되는 부분이 있아면 답변 주시면 아는 범위내에서 고민해 보겠습니다.

mrjh76의 이미지

디바이스 드라이버를 공부하나 보군요!~?

아래 소스를 컴파일해서 실행해보면... 디바이스 드라이버의 구조를 이해하는데... 도움이 될 것입니다!!!

디바이스 드라이버의 가장 기본이 되는 뼈대(스켈레톤(?)) 드라이버입니다!!!

http://mrjh.f2.co.kr/iezn/index.php?idx=3&g_num=6&gs_num=22&category=&keyword=&&page=1&method=&m_search=&order=regdate&sort=desc&num=27&mode=view&sno=&order=regdate&sort=desc

소스 파일의 내용은 어떻게 올리는건지... 모르겠음... 음냐...

댓글 달기

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