Logger详解(二)
16lz
2021-01-24
本文编辑整理自: http://www.linuxidc.com/Linux/2011-07/38987.htm 三、 Logger初始化过程分析。 在 kernel/drivers/staging/Android/logger.c 文件,定义了四个日志设备: /* * Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which * must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than * LONG_MAX minus LOGGER_ENTRY_MAX_LEN. */ #define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \ static unsigned char _buf_ ## VAR[SIZE]; \ static struct logger_log VAR = { \ .buffer = _buf_ ## VAR, \ .misc = { \ .minor = MISC_DYNAMIC_MINOR, \ .name = NAME, \ . fops = &logger_fops, \ .parent = NULL, \ }, \ .wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \ .readers = LIST_HEAD_INIT(VAR .readers), \ .mutex = __MUTEX_INITIALIZER(VAR .mutex), \ .w_off = 0, \ .head = 0, \ .size = SIZE, \ }; DEFINE_LOGGER_DEVICE( log_main , LOGGER_LOG_MAIN , 64*1024) DEFINE_LOGGER_DEVICE( log_events , LOGGER_LOG_EVENTS , 256*1024) DEFINE_LOGGER_DEVICE(l og_radio , LOGGER_LOG_RADIO , 64*1024) DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 64*1024 上面的代码创建了 log_main 、 log_events,log_system 和 log_radio 这4个logger_log结构体,名称分别 LOGGER_LOG_MAIN 、 LOGGER_LOG_EVENTS,LOGGER_LOG_SYSTEM 和 LOGGER_LOG_RADIO ,它们的次设备号为MISC_DYNAMIC_MINOR,即为在注册时动态分配。在 logger.h 文件中,这三个宏的定义如下: #define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */ #define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */ #define LOGGER_LOG_SYSTEM "log_system" /* system/framework message*/ #define LOGGER_LOG_MAIN "log_main" /* everything else */ 注册的日志设备文件操作方法为 logger_fops: static struct file_operations logger_fops = { .owner = THIS_MODULE, .read = logger_read, .aio_write = logger_aio_write, .poll = logger_poll, .unlocked_ioctl = logger_ioctl, .compat_ioctl = logger_ioctl, .open = logger_open, .release = logger_release, }; 日志驱动程序模块的初始化函数为logger_init: static int __init logger_init(void) { int ret; ret = init_log(&log_main); if (unlikely(ret)) goto out; ret = init_log(&log_events); if (unlikely(ret)) goto out; ret = init_log(&log_radio); if (unlikely(ret)) goto out; ret = init_log(&log_system); if (unlikely(ret)) goto out; out: return ret; } device_initcall( logger_init );
logger_init 函数通过调用 init_log 函数来初始化了上述提到的4个日志设备. 关于 static int __init logger_init(void) 中 __init的意义请参照《 linux代码中的__init和__exit宏》 关于 device_initcall( logger_init ); 请参考《 Linux内核中的xx_initcall》 static int __init init_log(struct logger_log *log) { int ret; ret = misc_register (&log->misc); if (unlikely(ret)) { printk(KERN_ERR "logger: failed to register misc " "device for log '%s'!\n", log->misc.name); return ret; } printk(KERN_INFO "logger: created %luK log '%s'\n", (unsigned long) log->size >> 10, log->misc.name); return 0; } init_log 函数主要调用了 misc_register 函数来注册misc设备, misc_register 函数定义在 kernel/common/drivers/char/misc.c 文件中: /** * misc_register - register a miscellaneous device * @misc: device structure * * Register a miscellaneous device with the kernel. If the minor * number is set to %MISC_DYNAMIC_MINOR a minor number is assigned * and placed in the minor field of the structure. For other cases * the minor number requested is used. * * The structure passed is linked into the kernel and may not be * destroyed until it has been unregistered. * * A zero is returned on success and a negative errno code for * failure. */ int misc_register(struct miscdevice * misc) { struct miscdevice *c; dev_t dev; int err = 0; INIT_LIST_HEAD(&misc->list); mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { if (c->minor == misc->minor) { mutex_unlock(&misc_mtx); return -EBUSY; } } if (misc->minor == MISC_DYNAMIC_MINOR) { int i = DYNAMIC_MINORS; while (--i >= 0) if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) break; if (i<0) { mutex_unlock(&misc_mtx); return -EBUSY; } misc->minor = i; } if (misc->minor < DYNAMIC_MINORS) misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); dev = MKDEV(MISC_MAJOR, misc->minor); misc->this_device = device_create(misc_class, misc->parent, dev, NULL, "%s", misc->name); if (IS_ERR(misc->this_device)) { err = PTR_ERR(misc->this_device); goto out; } /* * Add it to the front, so that later devices can "override" * earlier defaults */ list_add(&misc->list, &misc_list); out: mutex_unlock(&misc_mtx); return err; } 注册完成后,通过device_create创建设备文件节点。 这样将创建 /sys/class/misc/log_radion , /sys/class/misc/log_events , /sys/class/misc/log_system , /sys/class/misc/log_main 这 四个设备节点文件。 我们一般是通过读写这四个文件的映射文件来进行交互。映射文件分别为 /dev/log/radio , /dev/log/events , /dev/log/system , /dev/log/main 。 应用init层之后init进程 在system/core/init/devices.c中device_init()->coldboot()->do_coldboot()->handle_device_fd()->handle_device_event() static void handle_device_event(struct uevent *uevent) { char devpath[96]; char *base, *name; i nt block;
/* if it's not a /dev device, nothing to do */ if((uevent->major < 0) || (uevent->minor < 0)) return;
/* do we have a name? */ name = strrchr(uevent->path, '/'); if(!name) return; name++;
/* too-long names would overrun our buffer */ if(strlen(name) > 64) return;
/* are we block or char? where should we live? */ if(!strncmp(uevent->path, "/block", 6)) { block = 1; base = "/dev/block/"; mkdir(base, 0755); } else { block = 0; /* this should probably be configurable somehow */ if(!strncmp(uevent->path, "/class/graphics/", 16)) { base = "/dev/graphics/"; mkdir(base, 0755); } else if (!strncmp(uevent->path, "/class/oncrpc/", 14)) { base = "/dev/oncrpc/"; mkdir(base, 0755); } else if (!strncmp(uevent->path, "/class/adsp/", 12)) { base = "/dev/adsp/"; mkdir(base, 0755); } else if(!strncmp(uevent->path, "/class/input/", 13)) { base = "/dev/input/"; mkdir(base, 0755); } else if(!strncmp(uevent->path, "/class/mtd/", 11)) { base = "/dev/mtd/"; mkdir(base, 0755); } else if(!strncmp(uevent->path, "/class/misc/", 12) && !strncmp(name, " log_", 4)) { base = " /dev/log/"; mkdir(base, 0755); name += 4; } else base = "/dev/"; }
snprintf(devpath, sizeof(devpath), "%s%s", base, name);
if(!strcmp(uevent->action, "add")) { make_device(devpath, block, uevent->major, uevent->minor); return; }
if(!strcmp(uevent->action, "remove")) { unlink(devpath); return; } } 这样将日志的四个设备节点文件映射为以下4个文件/dev/log/radio,/dev/log/events,/dev/log/system,/dev/log/main.
logger_init 函数通过调用 init_log 函数来初始化了上述提到的4个日志设备. 关于 static int __init logger_init(void) 中 __init的意义请参照《 linux代码中的__init和__exit宏》 关于 device_initcall( logger_init ); 请参考《 Linux内核中的xx_initcall》 static int __init init_log(struct logger_log *log) { int ret; ret = misc_register (&log->misc); if (unlikely(ret)) { printk(KERN_ERR "logger: failed to register misc " "device for log '%s'!\n", log->misc.name); return ret; } printk(KERN_INFO "logger: created %luK log '%s'\n", (unsigned long) log->size >> 10, log->misc.name); return 0; } init_log 函数主要调用了 misc_register 函数来注册misc设备, misc_register 函数定义在 kernel/common/drivers/char/misc.c 文件中: /** * misc_register - register a miscellaneous device * @misc: device structure * * Register a miscellaneous device with the kernel. If the minor * number is set to %MISC_DYNAMIC_MINOR a minor number is assigned * and placed in the minor field of the structure. For other cases * the minor number requested is used. * * The structure passed is linked into the kernel and may not be * destroyed until it has been unregistered. * * A zero is returned on success and a negative errno code for * failure. */ int misc_register(struct miscdevice * misc) { struct miscdevice *c; dev_t dev; int err = 0; INIT_LIST_HEAD(&misc->list); mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { if (c->minor == misc->minor) { mutex_unlock(&misc_mtx); return -EBUSY; } } if (misc->minor == MISC_DYNAMIC_MINOR) { int i = DYNAMIC_MINORS; while (--i >= 0) if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) break; if (i<0) { mutex_unlock(&misc_mtx); return -EBUSY; } misc->minor = i; } if (misc->minor < DYNAMIC_MINORS) misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); dev = MKDEV(MISC_MAJOR, misc->minor); misc->this_device = device_create(misc_class, misc->parent, dev, NULL, "%s", misc->name); if (IS_ERR(misc->this_device)) { err = PTR_ERR(misc->this_device); goto out; } /* * Add it to the front, so that later devices can "override" * earlier defaults */ list_add(&misc->list, &misc_list); out: mutex_unlock(&misc_mtx); return err; } 注册完成后,通过device_create创建设备文件节点。 这样将创建 /sys/class/misc/log_radion , /sys/class/misc/log_events , /sys/class/misc/log_system , /sys/class/misc/log_main 这 四个设备节点文件。 我们一般是通过读写这四个文件的映射文件来进行交互。映射文件分别为 /dev/log/radio , /dev/log/events , /dev/log/system , /dev/log/main 。 应用init层之后init进程 在system/core/init/devices.c中device_init()->coldboot()->do_coldboot()->handle_device_fd()->handle_device_event() static void handle_device_event(struct uevent *uevent) { char devpath[96]; char *base, *name; i nt block;
/* if it's not a /dev device, nothing to do */ if((uevent->major < 0) || (uevent->minor < 0)) return;
/* do we have a name? */ name = strrchr(uevent->path, '/'); if(!name) return; name++;
/* too-long names would overrun our buffer */ if(strlen(name) > 64) return;
/* are we block or char? where should we live? */ if(!strncmp(uevent->path, "/block", 6)) { block = 1; base = "/dev/block/"; mkdir(base, 0755); } else { block = 0; /* this should probably be configurable somehow */ if(!strncmp(uevent->path, "/class/graphics/", 16)) { base = "/dev/graphics/"; mkdir(base, 0755); } else if (!strncmp(uevent->path, "/class/oncrpc/", 14)) { base = "/dev/oncrpc/"; mkdir(base, 0755); } else if (!strncmp(uevent->path, "/class/adsp/", 12)) { base = "/dev/adsp/"; mkdir(base, 0755); } else if(!strncmp(uevent->path, "/class/input/", 13)) { base = "/dev/input/"; mkdir(base, 0755); } else if(!strncmp(uevent->path, "/class/mtd/", 11)) { base = "/dev/mtd/"; mkdir(base, 0755); } else if(!strncmp(uevent->path, "/class/misc/", 12) && !strncmp(name, " log_", 4)) { base = " /dev/log/"; mkdir(base, 0755); name += 4; } else base = "/dev/"; }
snprintf(devpath, sizeof(devpath), "%s%s", base, name);
if(!strcmp(uevent->action, "add")) { make_device(devpath, block, uevent->major, uevent->minor); return; }
if(!strcmp(uevent->action, "remove")) { unlink(devpath); return; } } 这样将日志的四个设备节点文件映射为以下4个文件/dev/log/radio,/dev/log/events,/dev/log/system,/dev/log/main.
更多相关文章
- C语言函数的递归(上)
- CM13.0代码下载
- Android(安卓)笔记
- Ubuntu 编译Android若干错误及解决方法(转)
- Android(安卓)MediaPlayer基本使用方式
- android miscdevice(混杂设备)驱动编写注意
- Android(安卓)读取内存文件返回byte数组
- PackageManagerService(Android5.1)深入分析(四)安装应用
- mac版 android破解软件下载安装