ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
在从Logger日志驱动程序读取或者写入日志记录之前,首先要调用函数open来打开对应的日志设备文件。在Logger日志驱动程序中,日志设备文件的打开函数定义为logger_open,它的实现如下所示。 **kernel/goldfish/drivers/staging/android/logger.c** ~~~ /* * logger_open - the log's open() file operation * * Note how near a no-op this is in the write-only case. Keep it that way! */ static int logger_open(struct inode *inode, struct file *file) { struct logger_log *log; int ret; ret = nonseekable_open(inode, file); if (ret) return ret; log = get_log_from_minor(MINOR(inode->i_rdev)); if (!log) return -ENODEV; if (file->f_mode & FMODE_READ) { struct logger_reader *reader; reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL); if (!reader) return -ENOMEM; reader->log = log; INIT_LIST_HEAD(&reader->list); mutex_lock(&log->mutex); reader->r_off = log->head; list_add_tail(&reader->list, &log->readers); mutex_unlock(&log->mutex); file->private_data = reader; } else file->private_data = log; return 0; } ~~~ 函数第11行调用函数nonseekable_open将相应的设备文件设置为不可随机访问,即不可以调用函数lseek来设置设备文件的当前读写位置,因为日志记录的读取或者写入都必须按顺序来进行。 函数第15行调用函数get_log_from_minor根据从设备号获得要操作的日志缓冲区结构体。 **kernel/goldfish/drivers/staging/android/logger.c** ~~~ static struct logger_log * get_log_from_minor(int minor) { if (log_main.misc.minor == minor) return &log_main; if (log_events.misc.minor == minor) return &log_events; if (log_radio.misc.minor == minor) return &log_radio; return NULL; } ~~~ 回到函数logger_open中,对于以写模式打开日志设备的情况,函数logger_open只是把前面获得的日志缓冲区结构体log保存在参数file的成员变量private_data中就结束了;而对于以读模式打开日志设备的情况,函数logger_open的处理就相对复杂一些。函数logger_open首先会为当前进程创建一个logger_reader结构体reader,并且对它进行初始化,其中,最重要的是第30行告诉该进程从log->head位置开始读取日志记录,然后把前面获得的日志缓冲区结构体log保存在结构体reader的成员变量log中,并且把结构体reader保存在参数file的成员变量private_data中。