[PATCH 3/3] syslogd: add option to log to Linux kernel printk buffer

Peter Korsgaard jacmet at sunsite.dk
Tue Dec 18 19:49:20 UTC 2012


Why invent our own shared memory circular buffer when the kernel has a
perfectly fine one already?

This can be used as a smaller/simpler alternative to the syslogd IPC support
(as IPC shmem/klogd/logread aren't needed), while also allowing centralised
logging of everything (kernel messages, userspace bootup and syslog)
when used together with ttyprintk.

Notice that kernel 3.5+ is needed to store syslog facility in printk buffer,
otherwise only the priority is stored.

bloat-o-meter compared to IPC+klogd+logread:
function                                             old     new   delta
get_linux_version_code                                 -      84     +84
applet_nameofs                                         8       4      -4
static.stdout@@GLIBC_2                                 8       -      -8
applet_names                                          29      15     -14
bb_msg_standard_output                                16       -     -16
applet_main                                           32      16     -16
init_sem                                              18       -     -18
xatoull_range                                         19       -     -19
overlapping_strcpy                                    21       -     -21
error_exit                                            26       -     -26
sem_up                                                32       -     -32
init_data                                             56      24     -32
interrupted                                           35       -     -35
fflush_stdout_and_exit                                38       -     -38
bb_signals_recursive_norestart                        90       -     -90
timestamp_and_log                                    651     546    -105
syslogd_main                                         798     555    -243
xstrtoull_range_sfx                                  267       -    -267
.rodata                                             1898    1577    -321
logread_main                                         508       -    -508
klogd_main                                           525       -    -525
bb_common_bufsiz1                                   8193       -   -8193
------------------------------------------------------------------------------
(add/remove: 2/17 grow/shrink: 0/7 up/down: 84/-10531)     Total: -10447 bytes

Signed-off-by: Peter Korsgaard <jacmet at sunsite.dk>
---
 sysklogd/Config.src |   16 ++++++++++++++++
 sysklogd/syslogd.c  |   39 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/sysklogd/Config.src b/sysklogd/Config.src
index b7a494e..fcf9930 100644
--- a/sysklogd/Config.src
+++ b/sysklogd/Config.src
@@ -113,6 +113,19 @@ config FEATURE_LOGREAD_REDUCED_LOCKING
 	  from circular buffer, minimizing semaphore
 	  contention at some minor memory expense.
 
+config FEATURE_KMSG_SYSLOG
+	bool "Linux kernel printk buffer support"
+	default y
+	depends on SYSLOGD
+	select PLATFORM_LINUX
+	help
+	  When you enable this feature, the syslogd utility will
+	  write system log message to the Linux kernel's printk buffer.
+	  This can be used as a smaller alternative to the syslogd IPC
+	  support, as klogd and logread aren't needed.
+
+	  NOTICE: Syslog facilities in log entries needs kernel 3.5+.
+
 config KLOGD
 	bool "klogd"
 	default y
@@ -123,6 +136,9 @@ config KLOGD
 	  you wish to record the messages produced by the kernel,
 	  you should enable this option.
 
+comment "klogd should not be used together with syslog to kernel printk buffer"
+	depends on KLOGD && FEATURE_KMSG_SYSLOG
+
 config FEATURE_KLOGD_KLOGCTL
 	bool "Use the klogctl() interface"
 	default y
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index fc380d9..f1d4136 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -43,6 +43,9 @@
 //usage:     "\n	-f FILE		Use FILE as config (default:/etc/syslog.conf)"
 //usage:	)
 /* //usage:  "\n	-m MIN		Minutes between MARK lines (default:20, 0=off)" */
+//usage:	IF_FEATURE_KMSG_SYSLOG(
+//usage:     "\n	-K		Log to kernel printk buffer (use dmesg to read it)"
+//usage:	)
 //usage:
 //usage:#define syslogd_example_usage
 //usage:       "$ syslogd -R masterlog:514\n"
@@ -140,6 +143,9 @@ IF_FEATURE_IPC_SYSLOG( \
 ) \
 IF_FEATURE_SYSLOGD_CFG( \
 	logRule_t *log_rules; \
+) \
+IF_FEATURE_KMSG_SYSLOG( \
+	int kmsgfd; \
 )
 
 struct init_globals {
@@ -212,6 +218,7 @@ enum {
 	IF_FEATURE_IPC_SYSLOG(    OPTBIT_circularlog,)	// -C
 	IF_FEATURE_SYSLOGD_DUP(   OPTBIT_dup        ,)	// -D
 	IF_FEATURE_SYSLOGD_CFG(   OPTBIT_cfg        ,)	// -f
+	IF_FEATURE_KMSG_SYSLOG(   OPTBIT_kmsg       ,)	// -K
 
 	OPT_mark        = 1 << OPTBIT_mark    ,
 	OPT_nofork      = 1 << OPTBIT_nofork  ,
@@ -225,6 +232,8 @@ enum {
 	OPT_circularlog = IF_FEATURE_IPC_SYSLOG(    (1 << OPTBIT_circularlog)) + 0,
 	OPT_dup         = IF_FEATURE_SYSLOGD_DUP(   (1 << OPTBIT_dup        )) + 0,
 	OPT_cfg         = IF_FEATURE_SYSLOGD_CFG(   (1 << OPTBIT_cfg        )) + 0,
+	OPT_kmsg        = IF_FEATURE_KMSG_SYSLOG(   (1 << OPTBIT_kmsg       )) + 0,
+
 };
 #define OPTION_STR "m:nO:l:S" \
 	IF_FEATURE_ROTATE_LOGFILE("s:" ) \
@@ -233,7 +242,8 @@ enum {
 	IF_FEATURE_REMOTE_LOG(    "L"  ) \
 	IF_FEATURE_IPC_SYSLOG(    "C::") \
 	IF_FEATURE_SYSLOGD_DUP(   "D"  ) \
-	IF_FEATURE_SYSLOGD_CFG(   "f:"  )
+	IF_FEATURE_SYSLOGD_CFG(   "f:" ) \
+	IF_FEATURE_KMSG_SYSLOG(   "K"  )
 #define OPTION_DECL *opt_m, *opt_l \
 	IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \
 	IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \
@@ -523,6 +533,23 @@ void ipcsyslog_init(void);
 void log_to_shmem(const char *msg);
 #endif /* FEATURE_IPC_SYSLOG */
 
+#if ENABLE_FEATURE_KMSG_SYSLOG
+/* Write message to /dev/kmsg */
+static void log_to_kmsg(int pri, const char *msg)
+{
+	/*
+	  kernel < 3.5 expects single char printk KERN_* priority prefix,
+	  from 3.5 onwards the full syslog facility/priority format is supported
+	*/
+	if (get_linux_version_code() < KERNEL_VERSION(3,5,0))
+		pri &= LOG_PRIMASK;
+
+	write(G.kmsgfd, G.printbuf, sprintf(G.printbuf, "<%d>%s\n", pri, msg));
+}
+#else
+void log_to_kmsg(int pri, const char *msg);
+#endif /* FEATURE_KMSG_SYSLOG */
+
 /* Print a message to the log file. */
 static void log_locally(time_t now, char *msg, logFile_t *log_file)
 {
@@ -657,6 +684,11 @@ static void timestamp_and_log(int pri, char *msg, int len)
 	}
 	timestamp[15] = '\0';
 
+	if (ENABLE_FEATURE_KMSG_SYSLOG && (option_mask32 & OPT_kmsg)) {
+		log_to_kmsg(pri, msg);
+		return;
+	}
+
 	if (option_mask32 & OPT_small)
 		sprintf(G.printbuf, "%s %s\n", timestamp, msg);
 	else {
@@ -831,6 +863,11 @@ static void do_syslogd(void)
 		ipcsyslog_init();
 	}
 
+#if ENABLE_FEATURE_KMSG_SYSLOG
+	if (option_mask32 & OPT_kmsg)
+		G.kmsgfd = xopen("/dev/kmsg", O_WRONLY);
+#endif
+
 	timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER);
 
 	while (!bb_got_signal) {
-- 
1.7.10.4



More information about the busybox mailing list