Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

104258
1323
114606


[Linux][Device][Driver]tty driver - overview TTY 디바이스 드라이버

TTY 드라이버. 너무 쉬워서 리눅스 커널 교재에서는 다루지 않는 경우가 많은데요.

실제로, 각 시스템 마다 tty driver 타입으로 등록된 디바이스 드라이버를 디버깅해야 할 때가 있어요
처음 시스템을 부팅시키거나 tty driver 관련 문제가 나왔을 때 필요하죠. 

이럴 때 참고하면 아주 좋은 변수가 있어요. tty_driver랍니다.
자, 이렇게 선언되어 있어요. 주석문이 많은 걸 알려주죠.
LIST_HEAD(tty_drivers); /* linked list of tty drivers */


tty driver는 tty_register_driver() 함수를 호출하거든요. 그런데 아래 tty_drivers란 링크드 리스트에 등록을 하죠. 
int tty_register_driver(struct tty_driver *driver)
{
int error;
int i;
// ...생략...
mutex_lock(&tty_mutex);
list_add(&driver->tty_drivers, &tty_drivers);  //<<--
mutex_unlock(&tty_mutex);

어떤 tty driver이든 tty driver로 등록 후 tty_drivers란 링크드 리스트 변수에 등록을 해요.

자, 이제 이 변수를 T32로 직접 확인해 볼까요? 음, 보기 좀 거슬리네요. 
v.v %s %i %t %l tty_drivers
  (static struct list_head) [D:0xC125FEB8] tty_drivers = (
    (struct list_head *) [D:0xC125FEB8] next = 0xDC8A9578 -> (
      (struct list_head *) [D:0xDC8A9578] next = 0xDC8A0678 -> (
        (struct list_head *) [D:0xDC8A0678] next = 0xDC896378 -> (
          (struct list_head *) [D:0xDC896378] next = 0xDC887578 -> (
            (struct list_head *) [D:0xDC887578] next = 0xDDA6D078 -> (
              (struct list_head *) [D:0xDDA6D078] next = 0xDDA1F078,
              (struct list_head *) [D:0xDDA6D07C] prev = 0xDC887578),

아래 업데이트한 cmm을 쓰면 좀 더 비주얼하게 링크드 리스트를 볼 수 있어요.
(http://rousalome.egloos.com/9964132)

  0x0 (0)|  [C:0xC125FEB8] (
         |    [C:0xC125FEB8] next = 0xDC8A9578,
         |    [C:0xC125FEBC] prev = 0xDD9D4878),
  0x1 (1)|  [C:0xDC8A9578] (
         |    [C:0xDC8A9578] next = 0xDC8A0678,
         |    [C:0xDC8A957C] prev = 0xC125FEB8),
  0x2 (2)|  [C:0xDC8A0678] (
         |    [C:0xDC8A0678] next = 0xDC896378,
         |    [C:0xDC8A067C] prev = 0xDC8A9578),
  0x3 (3)|  [C:0xDC896378] (
         |    [C:0xDC896378] next = 0xDC887578,
         |    [C:0xDC89637C] prev = 0xDC8A0678),
  0x4 (4)|  [C:0xDC887578] (
         |    [C:0xDC887578] next = 0xDDA6D078,
         |    [C:0xDC88757C] prev = 0xDC896378),
  0x5 (5)|  [C:0xDDA6D078] (
         |    [C:0xDDA6D078] next = 0xDDA1F078,
         |    [C:0xDDA6D07C] prev = 0xDC887578),
  0x6 (6)|  [C:0xDDA1F078] (
         |    [C:0xDDA1F078] next = 0xDD9D4878,
         |    [C:0xDDA1F07C] prev = 0xDDA6D078),
  0x7 (7)|  [C:0xDD9D4878] (
         |    [C:0xDD9D4878] next = 0xC125FEB8,
         |    [C:0xDD9D487C] prev = 0xDDA1F078),

아래 코드를 잘 보면, struct tty_driver란 구조체의 tty_drivers란 멤버 변수로 tty_drivers.next 멤버가 등록이 되잖아요.
int tty_register_driver(struct tty_driver *driver)
{
int error;
int i;
// ...생략...
mutex_lock(&tty_mutex);
list_add(&driver->tty_drivers, &tty_drivers);  //<<--


아래 방법으로 container_of 매크로를 쓰면,
(http://rousalome.egloos.com/9963702)

가장 첫 번째로 등록된 tty driver를 확인할 수 있어요. 이름이 "ttyGS" 이 놈이네요.
v.v %s %t container_of(0xDC8A9578,struct tty_driver,tty_drivers)
  (struct tty_driver *) container_of(0xDC8A9578,struct tty_driver,tty_drivers) =
    (int) magic = 21506,
    (struct kref) kref = ((atomic_t) refcount = ((int) counter = 3)),
    (struct cdev *) cdevs = 0xDC885500,
    (struct module *) owner = 0x0,
    (char *) driver_name = 0xC10661B8 -> "g_serial",
    (char *) name = 0xC10661C4 -> "ttyGS",
    (int) name_base = 0,
    (int) major = 229,
    (int) minor_start = 0,
    (unsigned int) num = 5,
    (short int) type = 3,
    (short int) subtype = 1,
    (struct ktermios) init_termios = ((tcflag_t) c_iflag = 1280, (tcflag_t) c_of
    (long unsigned int) flags = 13,
    (struct proc_dir_entry *) proc_entry = 0x0,
    (struct tty_driver *) other = 0x0,
    (struct tty_struct * *) ttys = 0xDC8ADD80,
    (struct tty_port * *) ports = 0xDC8AD540,
    (struct ktermios * *) termios = 0xDC8AD3C0,
    (void *) driver_state = 0x0,
    (struct tty_operations *) ops = 0xC0C14708,
    (struct list_head) tty_drivers = ((struct list_head *) next = 0xDC8A0678, (s

(where)
  0x0 (0)|  [C:0xC125FEB8] (
         |    [C:0xC125FEB8] next = 0xDC8A9578,  //<<--
         |    [C:0xC125FEBC] prev = 0xDD9D4878),
  0x1 (1)|  [C:0xDC8A9578] (
         |    [C:0xDC8A9578] next = 0xDC8A0678,
         |    [C:0xDC8A957C] prev = 0xC125FEB8),
  0x2 (2)|  [C:0xDC8A0678] (
         |    [C:0xDC8A0678] next = 0xDC896378,
         |    [C:0xDC8A067C] prev = 0xDC8A9578),

두 번째는? "ttyUSB"이군요.
v.v %s %t container_of(0xDC8A0678,struct tty_driver,tty_drivers)
  (struct tty_driver *) container_of(0xDC8A0678,struct tty_driver,tty_drivers) =
    (int) magic = 21506,
    (struct kref) kref = ((atomic_t) refcount = ((int) counter = 1)),
    (struct cdev *) cdevs = 0xDC8C0000,
    (struct module *) owner = 0x0,
    (char *) driver_name = 0xC106345C -> "usbserial",
    (char *) name = 0xC1063468 -> "ttyUSB",
    (int) name_base = 0,
    (int) major = 188,
    (int) minor_start = 1,
    (unsigned int) num = 512,
    (short int) type = 3,
    (short int) subtype = 1,
    (struct ktermios) init_termios = ((tcflag_t) c_iflag = 1280, (tcflag_t) c_of
    (long unsigned int) flags = 13,
    (struct proc_dir_entry *) proc_entry = 0xDC8A0700,
    (struct tty_driver *) other = 0x0,
    (struct tty_struct * *) ttys = 0xDC8A5000,
    (struct tty_port * *) ports = 0xDC8A7000,
    (struct ktermios * *) termios = 0xDC8A6000,
    (void *) driver_state = 0x0,
    (struct tty_operations *) ops = 0xC0C0EAF4,
    (struct list_head) tty_drivers = ((struct list_head *) next = 0xDC896378, (s

덧글

댓글 입력 영역