Logger详解(二)
本文编辑整理自: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 'SIZ
·
在
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 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.
更多推荐
已为社区贡献5条内容
所有评论(0)