注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

民主与科学

独立之人格,自由之思想

 
 
 

日志

 
 

Logger详解(二)  

2011-10-10 17:04:51|  分类: 深入研究 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
三、 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(log_radio, LOGGER_LOG_RADIO, 64*1024)  
DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 64*1024
     上面的代码创建了log_mainlog_events,log_systemlog_radio这4个logger_log结构体,名称分别LOGGER_LOG_MAINLOGGER_LOG_EVENTS,LOGGER_LOG_SYSTEMLOGGER_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;
    int 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.
  评论这张
 
阅读(1095)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017