Linux下printk原理

看下printk的实现

asmlinkage __visible int printk(const char *fmt, ...)
{
	r = vprintk_func(fmt, args);
}
 
__printf(1, 0) int vprintk_func(const char *fmt, va_list args)
{
	return vprintk_default(fmt, args);
}
 
int vprintk_default(const char *fmt, va_list args)
{
	r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args);
}
 
asmlinkage int vprintk_emit(int facility, int level,const char *dict, size_t dictlen,const char *fmt, va_list args)
{
 
	console_unlock();
}
 
void console_unlock(void)
{
 
	call_console_drivers(level, text, len);
}
 
static void call_console_drivers(int level, const char *text, size_t len)
{
	struct console *con;
	
	for_each_console(con) {
		con->write(con, text, len);
	}
}

也就是调用con->write的写接口,把log输出到串口上。

那控制台什么时候注册,以sprd的为例

#define SPRD_TTY_NAME		"ttyS"
static struct console sprd_console = {
	.name = SPRD_TTY_NAME,
	.write = sprd_console_write,
	.device = uart_console_device,
	.setup = sprd_console_setup,
	.flags = CON_PRINTBUFFER,
	.index = -1,
	.data = &sprd_uart_driver,
};

static int __init sprd_serial_console_init(void)
{
	register_console(&sprd_console);
	return 0;
}
console_initcall(sprd_serial_console_init);

控制台注册 

struct console *console_drivers;
EXPORT_SYMBOL_GPL(console_drivers);
void register_console(struct console *newcon)
{
	for (i = 0, c = console_cmdline;i < MAX_CMDLINECONSOLES && c->name[0];i++, c++) {

			if (newcon->index < 0)
				newcon->index = c->index;

			if (newcon->setup &&
			    newcon->setup(newcon, c->options) != 0)
				break;
		}
	}

	if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
		newcon->next = console_drivers;
		console_drivers = newcon;
	} else {

	}
}
EXPORT_SYMBOL(register_console);

 从命令行中获取控制台信息

console=ttyS1,115200n8
static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
static int __add_preferred_console(char *name, int idx, char *options,char *brl_options)
{
	struct console_cmdline *c;
	int i;

	for (i = 0, c = console_cmdline;i < MAX_CMDLINECONSOLES && c->name[0];i++, c++) {
		...
	}
	strlcpy(c->name, name, sizeof(c->name));
	c->options = options;

	c->index = idx;
	return 0;
}
static int __init console_setup(char *str)
{
	
	char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
	strncpy(buf, str, sizeof(buf) - 1);
	options = strchr(str, ',');
	for (s = buf; *s; s++)
		if (isdigit(*s) || *s == ',')
			break;
	idx = simple_strtoul(s, NULL, 10);
	__add_preferred_console(buf, idx, options, brl_options);

}
__setup("console=", console_setup);

 //看下写串口的实现 write = sprd_console_write

static void sprd_console_write(struct console *co, const char *s,
			       unsigned int count)
{
	struct uart_port *port = &sprd_port[co->index]->port;
	uart_console_write(port, s, count, sprd_console_putchar);

	
}

void uart_console_write(struct uart_port *port, const char *s,unsigned int count,void (*putchar)(struct uart_port *, int))
{
	unsigned int i;

	for (i = 0; i < count; i++, s++) {
		if (*s == '\n')
			putchar(port, '\r');
		putchar(port, *s);
	}
}

static void sprd_console_putchar(struct uart_port *port, int ch)
{
	wait_for_xmitr(port);
	serial_out(port, SPRD_TXD, ch);
}

 

你可能感兴趣的:(TTY)