stdout设备文件

初始化

既然stdout设备是设备文件系统的文件,自然有自己的inode结构。在系统初始化时,即只需如下处理过程

  1. kern_init-->fs_init-->dev_init-->dev_init_stdout --> dev_create_inode
  2. --> stdout_device_init
  3. --> vfs_add_dev

在dev_init_stdout中完成了对stdout设备文件的初始化。即首先创建了一个inode,然后通过stdout_device_init完成对inode中的成员变量inode->__device_info进行初始:

这里的stdout设备文件实际上就是指的console外设(它其实是串口、并口和CGA的组合型外设)。这个设备文件是一个只写设备,如果读这个设备,就会出错。接下来我们看看stdout设备的相关处理过程。

初始化

stdout设备文件的初始化过程主要由stdout_device_init完成,其具体实现如下:

  1. static void
  2. stdout_device_init(struct device *dev) {
  3. dev->d_blocks = 0;
  4. dev->d_blocksize = 1;
  5. dev->d_open = stdout_open;
  6. dev->d_close = stdout_close;
  7. dev->d_io = stdout_io;
  8. dev->d_ioctl = stdout_ioctl;
  9. }

可以看到,stdout_open函数完成设备文件打开工作,如果发现用户进程调用open函数的参数flags不是只写(O_WRONLY),则会报错。

访问操作实现

stdout_io函数完成设备的写操作工作,具体实现如下:

  1. static int
  2. stdout_io(struct device *dev, struct iobuf *iob, bool write) {
  3. if (write) {
  4. char *data = iob->io_base;
  5. for (; iob->io_resid != 0; iob->io_resid --) {
  6. cputchar(*data ++);
  7. }
  8. return 0;
  9. }
  10. return -E_INVAL;
  11. }

可以看到,要写的数据放在iob->io_base所指的内存区域,一直写到iob->io_resid的值为0为止。每次写操作都是通过cputchar来完成的,此函数最终将通过console外设驱动来完成把数据输出到串口、并口和CGA显示器上过程。另外,也可以注意到,如果用户想执行读操作,则stdout_io函数直接返回错误值-E_INVAL。