IT貓撲網(wǎng):您身邊最放心的安全下載站! 最新更新|軟件分類(lèi)|軟件專題|手機(jī)版|論壇轉(zhuǎn)貼|軟件發(fā)布

您當(dāng)前所在位置:首頁(yè)操作系統(tǒng)LINUX → linux設(shè)備驅(qū)動(dòng)之控制臺(tái)驅(qū)動(dòng)(1)

linux設(shè)備驅(qū)動(dòng)之控制臺(tái)驅(qū)動(dòng)(1)

時(shí)間:2015/6/28來(lái)源:IT貓撲網(wǎng)作者:網(wǎng)管聯(lián)盟我要評(píng)論(0)

  一:前言

  我們?cè)谥胺治鲞^(guò)input子系統(tǒng)和tty設(shè)備驅(qū)動(dòng)架構(gòu).今天需要將兩者結(jié)合起來(lái).看看linux中的控制臺(tái)是怎么樣實(shí)現(xiàn)的.

  二:控制臺(tái)驅(qū)動(dòng)的初始化

  之前在分析tty驅(qū)動(dòng)架構(gòu)的時(shí)候曾分析到.主設(shè)備為4,次設(shè)備為0的設(shè)備節(jié)點(diǎn),即/dev/tty0為當(dāng)前的控制終端.

  有tty_init()中,有以下代碼段:

  static int __init tty_init(void)

  {

  ……

  ……

  #ifdef CONFIG_VT

  cdev_init(&vc0_cdev, &console_fops);

  if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||

  register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)

  panic("Couldn't register /dev/tty0 driver\n");

  device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0");

  vty_init();

  #endif

  return 0;

  }

  CONFIG_VT:是指配置虛擬終端.即我們所說(shuō)的控制臺(tái).在此可以看到TTY_MAJOR(4),0對(duì)應(yīng)的設(shè)備節(jié)點(diǎn)操作集為console_fops.

  繼續(xù)跟進(jìn)vty_init()

  int __init vty_init(void)

  {

  vcs_init();

  console_driver = alloc_tty_driver(MAX_NR_CONSOLES);

  if (!console_driver)

  panic("Couldn't allocate console driver\n");

  console_driver->owner = THIS_MODULE;

  console_driver->name = "tty";

  console_driver->name_base = 1;

  console_driver->major = TTY_MAJOR;

  console_driver->minor_start = 1;

  console_driver->type = TTY_DRIVER_TYPE_CONSOLE;

  console_driver->init_termios = tty_std_termios;

  console_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;

  tty_set_operations(console_driver, &con_ops);

  if (tty_register_driver(console_driver))

  panic("Couldn't register console driver\n");

  kbd_init();

  console_map_init();

  #ifdef CONFIG_PROM_CONSOLE

  prom_con_init();

  #endif

  #ifdef CONFIG_MDA_CONSOLE

  mda_console_init();

  #endif

  return 0;

  }

  經(jīng)過(guò)我們之前的tty驅(qū)動(dòng)架構(gòu)分析,這段代碼看起來(lái)就比較簡(jiǎn)單了,它就是注冊(cè)了一個(gè)tty驅(qū)動(dòng).這個(gè)驅(qū)動(dòng)對(duì)應(yīng)的操作集是位于con_ops里面的.

  仔細(xì)看.在之后還會(huì)調(diào)用kbd_init().顧名思義,這個(gè)是一個(gè)有關(guān)鍵盤(pán)的初始化.控制終端跟鍵盤(pán)有什么關(guān)系呢?在之前分析tty的時(shí)候,曾提到過(guò),. 對(duì)于控制臺(tái)而言,它的輸入設(shè)備是鍵盤(pán)鼠標(biāo),它的輸出設(shè)備是當(dāng)前顯示器.這兩者是怎么關(guān)聯(lián)起來(lái)的呢?不著急.請(qǐng)看下面的分析.

  三:控制臺(tái)的open操作

  在前面分析了,對(duì)應(yīng)console的操作集為con_ops.定義如下:

  static const struct file_operations console_fops = {

  .llseek    = no_llseek,

  .read = tty_read,

  .write      = redirected_tty_write,

  .poll     = tty_poll,

  .ioctl    = tty_ioctl,

  .compat_ioctl    = tty_compat_ioctl,

  .open      = tty_open,

  .release    = tty_release,

  .fasync   = tty_fasync,

  };

  里面的函數(shù)指針值我們都不陌生了,在之前分析的tty驅(qū)動(dòng)中已經(jīng)分析過(guò)了.

  結(jié)合前面的tty驅(qū)動(dòng)分析.我們知道在open的時(shí)候,會(huì)調(diào)用ldisc的open和tty_driver.open.

  對(duì)于ldisc默認(rèn)是tty_ldiscs[0].我們來(lái)看下它的具體賦值.

  console_init():

  void __init console_init(void)

  {

  initcall_t *call;

  /* Setup the default TTY line discipline. */

  (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);

  /*

  * set up the console device so that later boot sequences can

  * inform about problems etc..

  */

  call = __con_initcall_start;

  while (call < __con_initcall_end) {

  (*call)();

  call++;

  }

  }

  在這里,通過(guò)tty_register_ldisc.將tty_ldisc_N_TTY注冊(cè)為了第N_TTY項(xiàng).即第1項(xiàng). tty_ldisc_N_TTY定義如下:

  struct tty_ldisc tty_ldisc_N_TTY = {

  .magic     = TTY_LDISC_MAGIC,

  .name      = "n_tty",

  .open      = n_tty_open,

  .close     = n_tty_close,

  .flush_buffer    = n_tty_flush_buffer,

  .chars_in_buffer = n_tty_chars_in_buffer,

  .read      = read_chan,

  .write     = write_chan,

  .ioctl     = n_tty_ioctl,

  .set_termios     = n_tty_set_termios,

  .poll      = normal_poll,

  .receive_buf     = n_tty_receive_buf,

  .write_wakeup    = n_tty_write_wakeup

  }

  對(duì)應(yīng)的open操作為n_tty_open:

  static int n_tty_open(struct tty_struct *tty)

  {

  if (!tty)

  return -EINVAL;

  /* This one is ugly. Currently a malloc failure here can panic */

  if (!tty->read_buf) {

  tty->read_buf = alloc_buf();

  if (!tty->read_buf)

  return -ENOMEM;

  }

  memset(tty->read_buf, 0, N_TTY_BUF_SIZE);

  reset_._flags(tty);

  tty->column = 0;

  n_tty_set_termios(tty, NULL);

  tty->minimum_to_wake = 1;

  tty->closing = 0;

  return 0;

  }

  它為tty->read_buf分配內(nèi)存.這個(gè)buffer空間大小為N_TTY_BUF_SIZE.read_buf實(shí)際上就是從按鍵的緩存區(qū).然后調(diào)用reset_flags()來(lái)初始化tty中的一些字段:

  static void reset_buffer_flags(struct tty_struct *tty)

  {

  unsigned long flags;

  spin_lock_irqsave(&tty->read_lock, flags);

  tty->read_head = tty->read_tail = tty->read_cnt = 0;

  spin_unlock_irqrestore(&tty->read_lock, flags);

  tty->canon_head = tty->canon_data = tty->erasing = 0;

  memset(&tty->read_flags, 0, sizeof tty->read_flags);

  n_tty_set_room(tty);

  check_unthrottle(tty);

  }

  這里比較簡(jiǎn),不再詳細(xì)分析.在這里要注意幾個(gè)tty成員的含義:

  Tty->read_head, tty->read_tail , tty->read_cnt分別代表read_buf中數(shù)據(jù)的寫(xiě)入位置,讀取位置和數(shù)據(jù)總數(shù).read_buf是一個(gè)環(huán)形緩存區(qū).

  n_tty_set_room()是設(shè)備read_buf中的可用緩存區(qū)

  check_unthrottle():是用來(lái)判斷是否需要打開(kāi)"閥門(mén)",允許輸入數(shù)據(jù)流入

  對(duì)于console tty_driver對(duì)應(yīng)的open函數(shù)如下示:

  static int con_open(struct tty_struct *tty, struct file *filp)

  {

  unsigned int currcons = tty->index;

  int ret = 0;

  acquire_console_sem();

  if (tty->driver_data == NULL) {

  ret = vc_allocate(currcons);

  if (ret == 0) {

  struct vc_data *vc = vc_cons[currcons].d;

  tty->driver_data = vc;

  vc->vc_tty = t

關(guān)鍵詞標(biāo)簽:linux

相關(guān)閱讀

文章評(píng)論
發(fā)表評(píng)論

熱門(mén)文章 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程使用screen管理你的遠(yuǎn)程會(huì)話使用screen管理你的遠(yuǎn)程會(huì)話GNU/Linux安裝vmwareGNU/Linux安裝vmware如何登錄linux vps圖形界面 Linux遠(yuǎn)程桌面連如何登錄linux vps圖形界面 Linux遠(yuǎn)程桌面連

相關(guān)下載

人氣排行 Linux下獲取CPUID、硬盤(pán)序列號(hào)與MAC地址linux tc實(shí)現(xiàn)ip流量限制dmidecode命令查看內(nèi)存型號(hào)linux下解壓rar文件安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程Ubuntu linux 關(guān)機(jī)、重啟、注銷(xiāo) 命令lcx.exe、nc.exe、sc.exe入侵中的使用方法查看linux服務(wù)器硬盤(pán)IO讀寫(xiě)負(fù)載