linux的核心日誌系統

2021-09-21 05:38:48 字數 3050 閱讀 4392

在linux中,syslogd是使用者空間的乙個守護程序,所有的需要記錄日誌的別的程序可以和這個守護程序通訊,可以委託這個守護程序幫助記錄日誌,為何不自己記錄呢,那是因為syslogd非常的專業,可以將日誌記錄到很細的地步,可以看etc/下面的配置檔案,既然所有的程序都可以委託syslogd記錄日誌,那麼就涉及到了程序間通訊,這就是linux中另外一大塊的內容了,這裡就不談了,linux善於使用小的程式組合成大的機制,linux善於分布式的思想而不是集中的,但是為何將日誌都委託給乙個守護程序呢,這不就集中了嗎?其實這難道不是各司其職嗎?因此這還是乙個邊界的問題。syslogd之外還有乙個klogd,這兩個其實不是乙個層次的,syslogd是個總的日誌記錄器,而klogd僅僅是乙個syslogd的客戶端罷了,和很多需要記錄日誌的程序的級別一樣,在需要記錄日誌的程序裡,可以呼叫syslog函式將日誌傳送給syslogd守護程序,可是核心並不是乙個程序,那麼它的日誌就有必要專門設定乙個使用者程序負責傳給syslogd,這個程序就是klogd,至於klogd如何從核心得到核心日誌資訊,這就是它自己的事情了,其實核心專門留下了兩個日誌介面,乙個是sys_syslog系統呼叫(注意不要和syslog函式混淆,syslog系統呼叫是和核心通訊的,而syslog函式是和syslogd通訊的),另乙個是/proc/kmsg檔案,klogd使用的是後者,當然也可以直接使用ksyslog系統呼叫。這裡首先看一下核心日誌的一些結構,首先核心日誌大多數由printk產生,你也可以認為完全由printk產生,但是我們知道,printk將資訊列印到了螢幕,並沒有別的什麼***,實際上並不是僅僅發生了我們看到的事情,實際上printk並不是將資訊直接寫入了標準輸出檔案,而僅僅將資訊塞入了乙個環形緩衝區,,然後至於這個緩衝區的內容什麼時候顯示到標準輸出,那就是另外乙個事情了,而核心日誌就是存在於這個環形緩衝區,列印到螢幕的僅僅是乙個緩衝區副本,真正的資料還在緩衝區保留,只有到了klogd或者別的什麼呼叫syslog系統呼叫將資訊讀出時或者緩衝區滿了(環形緩衝區首尾相接)的時候才會清除部分資料或者全部資料,剛才說了有兩種方式來得到核心日誌,乙個是/proc/kmsg。乙個是系統呼叫,幸運的是,這兩個都是呼叫了do_syslog核心函式:

int do_syslog(int type, char __user * buf, int len)

spin_unlock_irq(&logbuf_lock);

... }

我們看一下printk呼叫的vprintk核心函式:

asmlinkage int vprintk(const char *fmt, va_list args)

log_level_unknown = 0; }

emit_log_char(*p);

if (*p == '/n')

log_level_unknown = 1; }

if (!cpu_online(smp_processor_id()) && system_state != system_running)

if (!down_trylock(&console_sem)) else

out:

return printed_len; }

核心的環形緩衝有兩個用途,乙個是直接列印在螢幕上,還有乙個就是可能使用者空間的核心日誌程式正在執行,因此這個函式完成了兩個作用:

void release_console_sem(void)

console_locked = 0;

console_may_schedule = 0;

up(&console_sem);

spin_unlock_irqrestore(&logbuf_lock, flags);

if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait)) //如果核心喚醒緩衝中有資料,那麼就喚醒睡眠佇列

wake_up_interruptible(&log_wait); }

最後我們看一下procfs匯出的kmsg介面的read函式,其實也是呼叫了do_syslog函式:

static ssize_t kmsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)

這裡我覺得有乙個問題,就是在printk的時候,如果我們恰好可以得到裝置的訊號量,那麼就必須等到資訊完全顯示到裝置上時呼叫棧才可以返回,也就是說,最好不要在核心大量呼叫printk函式,另外,在多處理器上這也是很不利的,以前的處理器少,因此問題不大,現在都是多處理器了,效能就可能受printk的影響了,我覺得可以為每乙個cpu準備乙個環形緩衝區,然後在拼接這些緩衝區的時候進行控制,比如在使用者空間讀每個cpu的緩衝區,只不過將它們作為乙個整體去理解,這個我感覺可以用檔案系統實現。在任何程式中頻繁呼叫列印都是不妙的,因為列印涉及裝置操作,想想看,外設相比cpu多麼慢,而且對於機器中的唯一裝置,而且是每個程序幾乎都在用的裝置,我們花在打架上的時間又是何等的長。

回歸同事問我的那個問題,在linux上怎麼列印資訊,其實,只要你不關閉,每個程式都會預設開啟0,1,2三個檔案描述符,這三個描述符在start_kernel中呼叫的kernel_init程序(最終成為/sbin/init)中被初始化,也就是在下面的**:

if (sys_open((const char __user *) "/dev/console", o_rdwr, 0) < 0)

printk(kern_warning "warning: unable to open an initial console./n");

(void) sys_dup(0);

(void) sys_dup(0);

在這裡,sys_open開啟了/dev/console,將其作為標準輸出,其實也就是我們的終端,當前終端,在sys_open中會自動將檔案描述符0分配給這個終端檔案,然後緊接著的sys_dup相當於複製了這個終端檔案描述符代表的檔案給了新的描述符1和2,這樣的話實際上0,1,2代表的是同乙個東西,都是指當前的終端,這也就是為什麼你往標準錯誤裡面寫東西也不會錯的道理,實際上標準輸入,輸出,錯誤都是給使用者程序用的,對於核心,它們是乙個東西。因為linux程序都是fork出來的,根源就是這個kernel_init程序,於是每個程序都會預設複製父程序的0,1,2檔案描述符(如果父程序沒有關閉它們的話)。

LINUX核心日誌介紹。

var log vmkernel.log 存放vmkernel生成的日誌 var log vmkwarning.log 只保留vmkernel日誌中的警告和系統告警事件 var log vpxa.log vcenter 日誌,vcenter server通過程序名為vpxa的vcenter serv...

Linux核心日誌開關

linux核心日誌開關 1 讓pr debug能輸出 a kernel printk printk.c b kernel printk printk.c 59,7 59,7 we show everything that is moreimportant than this.define minim...

linux的日誌系統

linux 的日誌系統 作為一名系統管理員,我們不可能時時刻刻都在伺服器旁邊,而且也不可能為了保證伺服器不被攻擊,這時系統的日誌就顯得很重要了,可以通過分析日子檢查系統的漏洞,提前預防和事後的修復。系統在正常執行的日誌主要有 syslog 程序來提供,syslog 又有syslogd 和klogd ...