⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printk.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
字号:
/* *  linux/kernel/printk.c * *  Copyright (C) 1991, 1992  Linus Torvalds * * Modified to make sys_syslog() more flexible: added commands to * return the last 4k of kernel messages, regardless of whether * they've been read or not.  Added option to suppress kernel printk's * to the console.  Added hook for sending the console messages * elsewhere, in preparation for a serial line console (someday). * Ted Ts'o, 2/11/93. */#include <stdarg.h>#include <asm/segment.h>#include <asm/system.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/tty_driver.h>#define LOG_BUF_LEN	8192static char buf[1024];extern void console_print(const char *);/* printk's without a loglevel use this.. */#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING *//* We show everything that is MORE important than this.. */#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */unsigned long log_size = 0;struct wait_queue * log_wait = NULL;int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;static void (*console_print_proc)(const char *) = 0;static char log_buf[LOG_BUF_LEN];static unsigned long log_start = 0;static unsigned long logged_chars = 0;/* * Commands to sys_syslog: * * 	0 -- Close the log.  Currently a NOP. * 	1 -- Open the log. Currently a NOP. * 	2 -- Read from the log. * 	3 -- Read up to the last 4k of messages in the ring buffer. * 	4 -- Read and clear last 4k of messages in the ring buffer * 	5 -- Clear ring buffer. * 	6 -- Disable printk's to console * 	7 -- Enable printk's to console *	8 -- Set level of messages printed to console */asmlinkage int sys_syslog(int type, char * buf, int len){	unsigned long i, j, count;	int do_clear = 0;	char c;	int error;	if ((type != 3) && !suser())		return -EPERM;	switch (type) {		case 0:		/* Close log */			return 0;		case 1:		/* Open log */			return 0;		case 2:		/* Read from log */			if (!buf || len < 0)				return -EINVAL;			if (!len)				return 0;			error = verify_area(VERIFY_WRITE,buf,len);			if (error)				return error;			cli();			while (!log_size) {				if (current->signal & ~current->blocked) {					sti();					return -ERESTARTSYS;				}				interruptible_sleep_on(&log_wait);			}			i = 0;			while (log_size && i < len) {				c = *((char *) log_buf+log_start);				log_start++;				log_size--;				log_start &= LOG_BUF_LEN-1;				sti();				put_user(c,buf);				buf++;				i++;				cli();			}			sti();			return i;		case 4:		/* Read/clear last kernel messages */			do_clear = 1; 			/* FALL THRU */		case 3:		/* Read last kernel messages */			if (!buf || len < 0)				return -EINVAL;			if (!len)				return 0;			error = verify_area(VERIFY_WRITE,buf,len);			if (error)				return error;			count = len;			if (count > LOG_BUF_LEN)				count = LOG_BUF_LEN;			if (count > logged_chars)				count = logged_chars;			j = log_start + log_size - count;			for (i = 0; i < count; i++) {				c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));				put_user(c, buf++);			}			if (do_clear)				logged_chars = 0;			return i;		case 5:		/* Clear ring buffer */			logged_chars = 0;			return 0;		case 6:		/* Disable logging to console */			console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;			return 0;		case 7:		/* Enable logging to console */			console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;			return 0;		case 8:			if (len < 1 || len > 8)				return -EINVAL;			if (len < MINIMUM_CONSOLE_LOGLEVEL)				len = MINIMUM_CONSOLE_LOGLEVEL;			console_loglevel = len;			return 0;	}	return -EINVAL;}asmlinkage int printk(const char *fmt, ...){	va_list args;	int i;	char *msg, *p, *buf_end;	static char msg_level = -1;	long flags;	save_flags(flags);	cli();	va_start(args, fmt);	i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */	buf_end = buf + 3 + i;	va_end(args);	for (p = buf + 3; p < buf_end; p++) {		msg = p;		if (msg_level < 0) {			if (				p[0] != '<' ||				p[1] < '0' || 				p[1] > '7' ||				p[2] != '>'			) {				p -= 3;				p[0] = '<';				p[1] = DEFAULT_MESSAGE_LOGLEVEL + '0';				p[2] = '>';			} else				msg += 3;			msg_level = p[1] - '0';		}		for (; p < buf_end; p++) {			log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = *p;			if (log_size < LOG_BUF_LEN)				log_size++;			else {				log_start++;				log_start &= LOG_BUF_LEN-1;			}			logged_chars++;			if (*p == '\n')				break;		}		if (msg_level < console_loglevel && console_print_proc) {			char tmp = p[1];			p[1] = '\0';			(*console_print_proc)(msg);			p[1] = tmp;		}		if (*p == '\n')			msg_level = -1;	}	restore_flags(flags);	wake_up_interruptible(&log_wait);	return i;}/* * The console driver calls this routine during kernel initialization * to register the console printing procedure with printk() and to * print any messages that were printed by the kernel before the * console driver was initialized. */void register_console(void (*proc)(const char *)){	int	i,j;	int	p = log_start;	char	buf[16];	char	msg_level = -1;	char	*q;	console_print_proc = proc;	for (i=0,j=0; i < log_size; i++) {		buf[j++] = log_buf[p];		p++; p &= LOG_BUF_LEN-1;		if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)			continue;		buf[j] = 0;		q = buf;		if (msg_level < 0) {			msg_level = buf[1] - '0';			q = buf + 3;		}		if (msg_level < console_loglevel)			(*proc)(q);		if (buf[j-1] == '\n')			msg_level = -1;		j = 0;	}}/* * Write a message to a certain tty, not just the console. This is used for * messages that need to be redirected to a specific tty. * We don't put it into the syslog queue right now maybe in the future if * really needed. */void tty_write_message(struct tty_struct *tty, char *msg){	if (tty && tty->driver.write)		tty->driver.write(tty, 0, msg, strlen(msg));	return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -