console 的定位

原创 2007年10月12日 08:59:00

首先在init/main.c的init函数中建立了系统的stdin和stdout
 if (open("/dev/null", O_RDWR, 0) < 0)
  printk("Warning: unable to open an initial console./n");
 (void) dup(0);
 (void) dup(0);
打开的/dev/null设备,这也是导致busybox开始printf不能显示的原因。
而且显然在busybox中重新建立了stdin和stdout,于是我在busybox源码的
init/init.c的init_main函数中找到了以下代码
 /* Figure out where the default console should be */
 console_init();
 /* Close whatever files are open, and reset the console. */
 close(0);
 close(1);
 close(2);
 if (device_open(console, O_RDWR | O_NOCTTY) == 0) {
  set_term(0);
  close(0);
 } //这里好像没有建立stdin和stdout啊,反正肯定有新建的
改成打开/dev/console设备,就可以在busybox中添加打印语句察看流程了。
只是不知道哪里出了问题,我这里用reboot重启就会死掉,所以还是改回/dev/null了,
等有空再仔细看看busybox了,这里先介绍内核是怎样把console定位到ttyS0的,
因为我们真正的控制台设备是ttyS0。
找到drivers/char/mem.c中的chr_dev_init函数,是用__initcall(chr_dev_init)注册使其
在初始化的时候运行的。该函数注册了大部分的字符设备,null,mem,console,tty等等
它tty_init()(drivers/char/tty_io.c)来注册tty和console等设备,代码如下
 memset(&dev_tty_driver, 0, sizeof(struct tty_driver));
 dev_tty_driver.magic = TTY_DRIVER_MAGIC;
 dev_tty_driver.driver_name = "/dev/tty";
 dev_tty_driver.name = dev_tty_driver.driver_name + 5;
 dev_tty_driver.name_base = 0;
 dev_tty_driver.major = TTYAUX_MAJOR;
 dev_tty_driver.minor_start = 0;
 dev_tty_driver.num = 1;
 dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
 dev_tty_driver.subtype = SYSTEM_TYPE_TTY;
 
 if (tty_register_driver(&dev_tty_driver))
  panic("Couldn't register /dev/tty driver/n");

 dev_syscons_driver = dev_tty_driver;
 dev_syscons_driver.driver_name = "/dev/console";
 dev_syscons_driver.name = dev_syscons_driver.driver_name + 5;
 dev_syscons_driver.major = TTYAUX_MAJOR;
 dev_syscons_driver.minor_start = 1;
 dev_syscons_driver.type = TTY_DRIVER_TYPE_SYSTEM;
 dev_syscons_driver.subtype = SYSTEM_TYPE_SYSCONS;

 if (tty_register_driver(&dev_syscons_driver))
  panic("Couldn't register /dev/console driver/n");

tty      设备   major=5  minor=0
consle  设备 major=5  minor=1

看一下它调用的tty_register_driver函数
int tty_register_driver(struct tty_driver *driver)
{
 int error;
        int i;

 if (driver->flags & TTY_DRIVER_INSTALLED)
  return 0;

 error = devfs_register_chrdev(driver->major, driver->name, &tty_fops);
 if (error < 0)
  return error;
 else if(driver->major == 0)
  driver->major = error;

 if (!driver->put_char)
  driver->put_char = tty_default_put_char;
 
 driver->prev = 0;
 driver->next = tty_drivers;
 if (tty_drivers) tty_drivers->prev = driver;
 tty_drivers = driver;
 
 if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
  for(i = 0; i < driver->num; i++)
      tty_register_devfs(driver, 0, driver->minor_start + i);
 }
 proc_tty_register_driver(driver);
 return error;
}

使用了devfs_register_chrdev来注册设备,而下来又用tty_register_devfs又一次注册设备
还是先来看看这两个函数吧
int devfs_register_chrdev (unsigned int major, const char *name,
      struct file_operations *fops)
{
    if (boot_options & OPTION_ONLY) return 0;
    return register_chrdev (major, name, fops);

这个函数很简单,其实就是调用了register_chrdev来注册设备,而用register_chrdev来注册
设备是需要使用mknod来建立节点的,看看register_chrdev函数,其实只是对一个全局的
chrdevs结构赋值而已。
void tty_register_devfs (struct tty_driver *driver, unsigned int flags, unsigned minor)
{
#ifdef CONFIG_DEVFS_FS
 umode_t mode = S_IFCHR | S_IRUSR | S_IWUSR;
 kdev_t device = MKDEV (driver->major, minor);
 int idx = minor - driver->minor_start;
 char buf[32];

 switch (device) {
  case TTY_DEV:
  case PTMX_DEV:
   mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
   break;
  default:
   if (driver->major == PTY_MASTER_MAJOR)
    mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
   break;
 }
 if ( (minor <  driver->minor_start) ||
      (minor >= driver->minor_start + driver->num) ) {
  printk(KERN_ERR "Attempt to register invalid minor number "
         "with devfs (%d:%d)./n", (int)driver->major,(int)minor);
  return;
 }
#  ifdef CONFIG_UNIX98_PTYS
 if ( (driver->major >= UNIX98_PTY_SLAVE_MAJOR) &&
      (driver->major < UNIX98_PTY_SLAVE_MAJOR + UNIX98_NR_MAJORS) )
  flags |= DEVFS_FL_CURRENT_OWNER;
#  endif
 sprintf(buf, driver->name, idx + driver->name_base);
 devfs_register (NULL, buf, flags | DEVFS_FL_DEFAULT,
   driver->major, minor, mode, &tty_fops, NULL);
#endif /* CONFIG_DEVFS_FS */
}
对于tty_register_devfs函数则需要定义CONFIG_DEVFS_FS宏才有意义,这意味着内核支持
devfs设备文件系统。使用devfs_register注册设备同时在/dev建立相应的节点。
只要没有使用mknod建立节点,就不会和devfs_register产生冲突,而我实际使用的都是
devfs_register注册产生的设备。

关键要考虑的还是tty_fops这个结构中的设备方法
static struct file_operations tty_fops = {
 llseek:  no_llseek,
 read:  tty_read,
 write:  tty_write,
 poll:  tty_poll,
 ioctl:  tty_ioctl,
 open:  tty_open,
 release: tty_release,
 fasync:  tty_fasync,
};

看看tty_open方法,在其中能看到对不同设备的处理方法,重点还是看console的
        device = inode->i_rdev;
 if (device == SYSCONS_DEV) {
  struct console *c = console_drivers;
  while(c && !c->device)
   c = c->next;
  if (!c)
                        return -ENODEV;
                device = c->device(c);
  filp->f_flags |= O_NONBLOCK; /* Don't let /dev/console block */
  noctty = 1;
 }
 retval = init_dev(device, &tty);
 filp->private_data = tty;
 if (tty->driver.open)
  retval = tty->driver.open(tty, filp);
console_drivers就是前一片文章介绍过的全局变量,存放着真正控制台ttyS0的信息,在这里并没有把file结构中的f_pos重新赋值,而是让filp->private_data赋值为tty结构然后通过tty->driver.open去打开真正的控制台设备。同时在tty_read,tty_write方法中也是通过这个tty结构实现对真正控制台设备的读写的。如果定义了CONFIG_VT宏,就是make menuconfig,在Character devices中选中Virtual terminal,而且关闭串口控制台,这样就会把显示器还有键盘做为默认的控制台设备,在console drivers下可以看到VGA text console被选中。希望以后可以加上usb键盘和液晶屏作为控制台吧。

JavaScript调试技巧之:快速定位

赶紧总结一下JavaScript的调试技巧,这次首先是“快速定位”篇。 快速定位,其实就是快速定位程序的错误,所以也算是调试。这个在实际的码代码时往往比较实用。大多数情况下,你的js代码不多(少于1...
  • ladycode
  • ladycode
  • 2016年04月29日 11:01
  • 1674

Unity Editor Console Pro 扩展点击定位到外部工程

以 C# 源码形式放在 Unity 工程中,那么打印日志的时候,双击 Console 窗口里面的日志行信息,就会自动定位到 Visual Studio 所在的文件和行数。但是,以 DLL 形式放在 U...
  • akof1314
  • akof1314
  • 2016年11月19日 18:55
  • 3045

解决IE浏览器不支持console,报错未定义问题

问题产生:   前端开发调试经常用到console.info进行打印信息,前几天调试的时候Google功能完全OK,但是IE8浏览器点设置按钮完全没反应,看了修改的代码貌似没看出什么存在浏览器兼容性问...
  • yinxiangzhongqing
  • yinxiangzhongqing
  • 2017年01月10日 11:12
  • 7365

Eclipse多个console的使用

 Eclipse多个console的使用 发布于14-04-16 被阅读 65 次 评论 0 条 我们在使用Eclipse开发服务器端和客户端时,经常需要同时运行服务器端和客户端,...
  • dieziyangfei
  • dieziyangfei
  • 2014年05月06日 17:49
  • 2699

[Unity]console中定位lua文件并在sublime中打开

在雨松MOMO的微博上发现可以传入lua文件路径和行数,在sublime中直接定位 由于最近一直在写lua, 也苦于开发工具的匮乏,所以就捣鼓了一下: 下面可以看到lua代码输出的内容,双击这一条...
  • RICKShaozhiheng
  • RICKShaozhiheng
  • 2017年03月08日 22:09
  • 1057

console驱动

  • 2018年01月04日 13:28
  • 3.65MB
  • 下载

Editor Console Pro

  • 2017年11月29日 11:02
  • 182KB
  • 下载

rocketmq-console

  • 2017年12月02日 09:30
  • 208KB
  • 下载

rocketmq-console-ng

  • 2017年11月19日 17:23
  • 28.26MB
  • 下载

cb_console_runner

  • 2014年08月16日 23:18
  • 21KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:console 的定位
举报原因:
原因补充:

(最多只允许输入30个字)