Ядро Linux в комментариях

       

Kernel/printk.c


25610 /* 25611 * linux/kernel/printk.c 25612 * 25613 * Copyright (C) 1991, 1992 Linus Torvalds 25614 * 25615 * Modified to make sys_syslog() more flexible: added 25616 * commands to return the last 4k of kernel messages, 25617 * regardless of whether they've been read or not. Added 25618 * option to suppress kernel printk's to the console. 25619 * Added hook for sending the console messages elsewhere, 25620 * in preparation for a serial line console (someday). 25621 * Ted Ts'o, 2/11/93. 25622 * Modified for sysctl support, 1/8/97, Chris Horn. 25623 */ 25624 #include <linux/mm.h> 25625 #include <linux/tty_driver.h> 25626 #include <linux/smp_lock.h> 25627 #include <linux/console.h> 25628 #include <linux/init.h> 25629 25630 #include <asm/uaccess.h> 25631 25632 #define LOG_BUF_LEN (16384) 25633 25634 static char buf[1024]; 25635 25636 /* printk's without a loglevel use this.. */ 25637 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */ 25638 25639 /* We show everything that is MORE important than 25640 * this.. */ 25641 /* Minimum loglevel we let people use */ 25642 #define MINIMUM_CONSOLE_LOGLEVEL 1 25643 /* anything MORE serious than KERN_DEBUG */ 25644 #define DEFAULT_CONSOLE_LOGLEVEL 7 25645 25646 unsigned long log_size = 0; 25647 struct wait_queue * log_wait = NULL; 25648 25649 /* Keep together for sysctl support */ 25650 int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; 25651 int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL; 25652 int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL; 25653 int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; 25654 25655 struct console *console_drivers = NULL; 25656 static char log_buf[LOG_BUF_LEN]; 25657 static unsigned long log_start = 0; 25658 static unsigned long logged_chars = 0; 25659 struct console_cmdline 25660 console_cmdline[MAX_CMDLINECONSOLES]; 25661 static int preferred_console = -1; 25662 25663 /* Setup a list of consoles. Called from init/main.c */ 25664 void __init console_setup(char *str, int *ints) 25665 { 25666 struct console_cmdline *c; 25667 char name[sizeof(c->name)]; 25668 char *s, *options; 25669 int i, idx; 25670 25671 /* Decode str into name, index, options. */ 25672 if (str[0] >= '0' && str[0] <= '9') { 25673 strcpy(name, "ttyS"); 25674 strncpy(name + 4, str, sizeof(name) - 5); 25675 } else 25676 strncpy(name, str, sizeof(name) - 1); 25677 name[sizeof(name) - 1] = 0; 25678 if ((options = strchr(str, ',')) != NULL) 25679 *(options++) = 0; 25680 #ifdef __sparc__ 25681 if (!strcmp(str, "ttya")) 25682 strcpy(name, "ttyS0"); 25683 if (!strcmp(str, "ttyb")) 25684 strcpy(name, "ttyS1"); 25685 #endif 25686 for(s = name; *s; s++) 25687 if (*s >= '0' && *s <= '9') 25688 break; 25689 idx = simple_strtoul(s, NULL, 10); 25690 *s = 0; 25691 25692 /* See if this tty is not yet registered, and if we 25693 * have a slot free. */ 25694 for(i = 0; i < MAX_CMDLINECONSOLES && 25695 console_cmdline[i].name[0]; i++) 25696 if (strcmp(console_cmdline[i].name, name) == 0 && 25697 console_cmdline[i].index == idx) { 25698 preferred_console = i; 25699 return; 25700 } 25701 if (i == MAX_CMDLINECONSOLES) 25702 return; 25703 preferred_console = i; 25704 c = &console_cmdline[i]; 25705 memcpy(c->name, name, sizeof(c->name)); 25706 c->options = options; 25707 c->index = idx; 25708 } 25709 25710 /* Commands to do_syslog: 25711 * 25712 * 0 -- Close the log. Currently a NOP. 25713 * 1 -- Open the log. Currently a NOP. 25714 * 2 -- Read from the log. 25715 * 3 -- Read up to the last 4k of messages in the 25716 * ring buffer. 25717 * 4 -- Read and clear last 4k of messages in the 25718 * ring buffer. 25719 * 5 -- Clear ring buffer. 25720 * 6 -- Disable printk's to console 25721 * 7 -- Enable printk's to console 25722 * 8 -- Set level of messages printed to console 25723 */ 25724 int do_syslog(int type, char * buf, int len) 25725 { 25726 unsigned long i, j, count, flags; 25727 int do_clear = 0; 25728 char c; 25729 int error = -EPERM; 25730 25731 lock_kernel(); 25732 error = 0; 25733 switch (type) { 25734 case 0: /* Close log */ 25735 break; 25736 case 1: /* Open log */ 25737 break; 25738 case 2: /* Read from log */ 25739 error = -EINVAL; 25740 if (!buf len < 0) 25741 goto out; 25742 error = 0; 25743 if (!len) 25744 goto out; 25745 error = verify_area(VERIFY_WRITE,buf,len); 25746 if (error) 25747 goto out; 25748 error = wait_event_interruptible(log_wait, log_size); 25749 if (error) 25750 goto out; 25751 i = 0; 25752 while (log_size && i < len) { 25753 c = *((char *) log_buf+log_start); 25754 log_start++; 25755 log_size--; 25756 log_start &= LOG_BUF_LEN-1; 25757 sti(); 25758 __put_user(c,buf); 25759 buf++; 25760 i++; 25761 cli(); 25762 } 25763 sti(); 25764 error = i; 25765 break; 25766 case 4: /* Read/clear last kernel messages */ 25767 do_clear = 1; 25768 /* FALL THRU */ 25769 case 3: /* Read last kernel messages */ 25770 error = -EINVAL; 25771 if (!buf len < 0) 25772 goto out; 25773 error = 0; 25774 if (!len) 25775 goto out; 25776 error = verify_area(VERIFY_WRITE,buf,len); 25777 if (error) 25778 goto out; 25779 /* The logged_chars, log_start, and log_size values 25780 * may change from an interrupt, so we disable 25781 * interrupts. */ 25782 __save_flags(flags); 25783 __cli(); 25784 count = len; 25785 if (count > LOG_BUF_LEN) 25786 count = LOG_BUF_LEN; 25787 if (count > logged_chars) 25788 count = logged_chars; 25789 j = log_start + log_size - count; 25790 __restore_flags(flags); 25791 for (i = 0; i < count; i++) { 25792 c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1))); 25793 __put_user(c, buf++); 25794 } 25795 if (do_clear) 25796 logged_chars = 0; 25797 error = i; 25798 break; 25799 case 5: /* Clear ring buffer */ 25800 logged_chars = 0; 25801 break; 25802 case 6: /* Disable logging to console */ 25803 console_loglevel = minimum_console_loglevel; 25804 break; 25805 case 7: /* Enable logging to console */ 25806 console_loglevel = default_console_loglevel; 25807 break; 25808 case 8: 25809 error = -EINVAL; 25810 if (len < 1 len > 8) 25811 goto out; 25812 if (len < minimum_console_loglevel) 25813 len = minimum_console_loglevel; 25814 console_loglevel = len; 25815 error = 0; 25816 break; 25817 default: 25818 error = -EINVAL; 25819 break; 25820 } 25821 out: 25822 unlock_kernel(); 25823 return error; 25824 } 25825 25826 asmlinkage int sys_syslog(int type, char * buf, int len) 25827 { 25828 if ((type != 3) && !capable(CAP_SYS_ADMIN)) 25829 return -EPERM; 25830 return do_syslog(type, buf, len); 25831 } 25832 25833 25834 spinlock_t console_lock; 25835


25836 asmlinkage int printk(const char *fmt, ...) 25837 { 25838 va_list args; 25839 int i; 25840 char *msg, *p, *buf_end; 25841 int line_feed; 25842 static signed char msg_level = -1; 25843 long flags; 25844 25845 spin_lock_irqsave(&console_lock, flags); 25846 va_start(args, fmt); 25847 /* hopefully i < sizeof(buf)-4 */ 25848 i = vsprintf(buf + 3, fmt, args); 25849 buf_end = buf + 3 + i; 25850 va_end(args); 25851 for (p = buf + 3; p < buf_end; p++) { 25852 msg = p; 25853 if (msg_level < 0) { 25854 if ( 25855 p[0] != '<' 25856 p[1] < '0' 25857 p[1] > '7' 25858 p[2] != '>' 25859 ) { 25860 p -= 3; 25861 p[0] = '<'; 25862 p[1] = default_message_loglevel + '0'; 25863 p[2] = '>'; 25864 } else 25865 msg += 3; 25866 msg_level = p[1] - '0'; 25867 } 25868 line_feed = 0; 25869 for (; p < buf_end; p++) { 25870 log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] 25871 = *p; 25872 if (log_size < LOG_BUF_LEN) 25873 log_size++; 25874 else { 25875 log_start++; 25876 log_start &= LOG_BUF_LEN-1; 25877 } 25878 logged_chars++; 25879 if (*p == '\n') { 25880 line_feed = 1; 25881 break; 25882 } 25883 } 25884 if (msg_level < console_loglevel && console_drivers){ 25885 struct console *c = console_drivers; 25886 while(c) { 25887 if ((c->flags & CON_ENABLED) && c->write) 25888 c->write(c, msg, p - msg + line_feed); 25889 c = c->next; 25890 } 25891 } 25892 if (line_feed) 25893 msg_level = -1; 25894 } 25895 spin_unlock_irqrestore(&console_lock, flags); 25896 wake_up_interruptible(&log_wait); 25897 return i; 25898 } 25899 25900 void console_print(const char *s) 25901 { 25902 struct console *c = console_drivers; 25903 int len = strlen(s); 25904 25905 while(c) { 25906 if ((c->flags & CON_ENABLED) && c->write) 25907 c->write(c, s, len); 25908 c = c->next; 25909 } 25910 } 25911 25912 void unblank_console(void) 25913 { 25914 struct console *c = console_drivers; 25915 while(c) { 25916 if ((c->flags & CON_ENABLED) && c->unblank) 25917 c->unblank(); 25918 c = c->next; 25919 } 25920 } 25921 25922 /* The console driver calls this routine during kernel 25923 * initialization to register the console printing 25924 * procedure with printk() and to print any messages that 25925 * were printed by the kernel before the console driver 25926 * was initialized. */ 25927 void register_console(struct console * console) 25928 { 25929 int i,j,len; 25930 int p = log_start; 25931 char buf[16]; 25932 signed char msg_level = -1; 25933 char *q; 25934 25935 /* See if we want to use this console driver. If we 25936 * didn't select a console we take the first one that 25937 * registers here. */ 25938 if (preferred_console < 0) { 25939 if (console->index < 0) 25940 console->index = 0; 25941 if (console->setup == NULL 25942 console->setup(console, NULL) == 0) { 25943 console->flags |= CON_ENABLED | CON_CONSDEV; 25944 preferred_console = 0; 25945 } 25946 } 25947 25948 /* See if this console matches one we selected on the 25949 * command line. */ 25950 for (i = 0; 25951 i < MAX_CMDLINECONSOLES && 25952 console_cmdline[i].name[0]; 25953 i++) { 25954 if (strcmp(console_cmdline[i].name, console->name)) 25955 continue; 25956 if (console->index >= 0 && 25957 console->index != console_cmdline[i].index) 25958 continue; 25959 if (console->index < 0) 25960 console->index = console_cmdline[i].index; 25961 if (console->setup && 25962 console->setup(console, 25963 console_cmdline[i].options) != 0) 25964 break; 25965 console->flags |= CON_ENABLED; 25966 console->index = console_cmdline[i].index; 25967 if (i == preferred_console) 25968 console->flags |= CON_CONSDEV; 25969 break; 25970 } 25971 25972 if (!(console->flags & CON_ENABLED)) 25973 return; 25974 25975 /* Put this console in the list - keep the preferred 25976 * driver at the head of the list. */ 25977 if ((console->flags & CON_CONSDEV) 25978 console_drivers == NULL) { 25979 console->next = console_drivers; 25980 console_drivers = console; 25981 } else { 25982 console->next = console_drivers->next; 25983 console_drivers->next = console; 25984 } 25985 if ((console->flags & CON_PRINTBUFFER) == 0) return; 25986 25987 /* Print out buffered log messages. */ 25988 for (i=0,j=0; i < log_size; i++) { 25989 buf[j++] = log_buf[p]; 25990 p++; p &= LOG_BUF_LEN-1; 25991 if (buf[j-1] != '\n' && i < log_size - 1 && 25992 j < sizeof(buf)-1) 25993 continue; 25994 buf[j] = 0; 25995 q = buf; 25996 len = j; 25997 if (msg_level < 0) { 25998 msg_level = buf[1] - '0'; 25999 q = buf + 3; 26000 len -= 3; 26001 } 26002 if (msg_level < console_loglevel) 26003 console->write(console, q, len); 26004 if (buf[j-1] == '\n') 26005 msg_level = -1; 26006 j = 0; 26007 } 26008 } 26009 26010 26011 int unregister_console(struct console * console) 26012 { 26013 struct console *a,*b; 26014 26015 if (console_drivers == console) { 26016 console_drivers=console->next; 26017 return (0); 26018 } 26019 for (a = console_drivers->next, b = console_drivers; 26020 a; b = a, a = b->next) { 26021 if (a == console) { 26022 b->next = a->next; 26023 return 0; 26024 } 26025 } 26026 26027 return (1); 26028 } 26029 26030 /* Write a message to a certain tty, not just the 26031 * console. This is used for messages that need to be 26032 * redirected to a specific tty. We don't put it into 26033 * the syslog queue right now maybe in the future if 26034 * really needed. */ 26035 void tty_write_message(struct tty_struct *tty, char *msg) 26036 { 26037 if (tty && tty->driver.write) 26038 tty->driver.write(tty, 0, msg, strlen(msg)); 26039 return; 26040 }


Содержание раздела