當前位置:首頁 » 操作系統 » linux啟動分析

linux啟動分析

發布時間: 2022-10-25 03:15:49

1. 怎樣分析linux的性能指標

LR

監控

UNIX/Linux

系統方法

一、准備工作:

1.

可以通過兩種方法驗證伺服器上是否配置

rstatd

守護程序:

①使用

rup

命令,它用於報告計算機的各種統計信息,其中就包括

rstatd

的配置信息。使用命



rup

10.130.61.203,

此處

10.130.61.203

是要監視的

linux/Unix

伺服器的

IP

,如果該命令返回相關的

統計信息。則表示已經配置並且激活了

rstatd

守護進程;若未返回有意義的統計信息,或者出現一

條錯誤報告,則表示

rstatd

守護進程尚未被配置或有問題。

②使用

find

命令

#find / -name rpc.rstatd,

該命令用於查找系統中是否存在

rpc.rstatd

文件,如果沒有,說明系統沒

有安裝

rstatd

守護程序。

2



linux

需要下載

3

個包:



1



rpc.rstatd-4.0.1.tar.gz



2



rsh-0.17-14.i386.rpm



3



rsh-server-0.17-14.i386.rpm

3

.下載並安裝

rstatd

如果伺服器上沒有安裝

rstatd

程序(一般來說

LINUX

都沒有安裝)

,需要下載一個包才有這個服



,









rpc.rstatd-4.0.1.tar.gz.













,









,











rstatd









http://sourceforge.net/projects/rstatd

這個地址下載)下載後,開始安裝,安裝步驟如下:

tar -xzvf rpc.rstatd-4.0.1.tar.gz

cd rpc.rstatd-4.0.1/

./configure

—配置操作

make

—進行編譯

make install

—開始安裝

rpc.rstatd

—啟動

rstatd

進程



rpcinfo -p

」命令來查看當前系統是否已經啟動了

rstatd

守護進程

只要保證

Linux

機器上的進程里有

rstatd



xinetd

這二個服務就可以用

LR

去監視了,通過以下

兩點可以檢查是否啟動:

1

)檢查是否啟動

: rsh server

監聽的

TCP



514



[root@mg04 root]# netstat -an |grep 514

tcp 0 0 0.0.0.0:514 0.0.0.0:* LISTEN

如果能看到

514

在監聽說明

rsh

伺服器已經啟動。

2

)檢查是否啟動

: rstatd

輸入命令

: rpcinfo -p

如果能看到類似如下信息:

程序版本協議埠

100001

5

udp

937

rstatd

100001

4

udp

937

rstatd

100001

3

udp

937

rstatd

100001

2

udp

937

rstatd

100001

1

udp

937

rstatd

那就說明

rstatd

服務啟動了

,(

當然這里也可以用

ps ax

代替

)

4

.安裝

rsh



rsh-server

兩個服務包方法

a.

卸載

rsh

# rpm



q

rsh----------

查看版本號

# rpm

-e

版本號

---------

卸載該版本。

b

.安裝

# rpm



ivh rsh-0.17-14.i386.rpm rsh-server-0.17-14.i386.rpm

在啟動

rpc.rstatd

時,

會報錯



Cannot register service: RPC: Unable to receive; errno = Ction refused





解決方法如下:

# /etc/init.d/portmap start

# /etc/init.d/nfs start

然後再次啟動

rpc.rstatd

就好了。

5

.安裝

xinetd

方法:

①查看

xinetd

服務:

[root@localhost ~]# rpm -q xinetd

xinetd-2.3.14-10.el5

②安裝

xinetd

服務:

[root@localhost ~]# yum install xinetd

如果安裝不起

xinetd

服務,執行下列操作命令後再次執行

yum install xinetd

命令進行安裝:

yum clean packages

清除緩存目錄下的軟體包

yum clean headers

清除緩存目錄下的

headers

yum clean oldheaders

清除緩存目錄下舊的

headers

yum clean, yum clean all (= yum clean packages; yum clean oldheaders)

清除緩存目錄下的軟體包

及舊的

headers



6

.啟動

xinetd

服務:

在有的系統中,通過如下命令重啟:

# service xinetd reload

# /sbin/service xinetd rstart



suse linux

中如下操作:

cd /etc/init.d/xinetd restart

2



安裝完成後配置

rstatd

目標守護進程

xinetd,

它的主配置文件是

/etc/xinetd.conf ,

它裡面內容是

一些如下的基本信息:

#

# xinetd.conf

#

# Copyright (c) 1998-2001 SuSE GmbH Nuernberg, Germany.

# Copyright (c) 2002 SuSE Linux AG, Nuernberg, Germany.

#

defaults

{

log_type

= FILE /var/log/xinetd.log

log_on_success = HOST EXIT DURATION

log_on_failure = HOST ATTEMPT

#

only_from

= localhost

instances

= 30

cps

= 50 10

#

# The specification of an interface is interesting, if we are on a firewall.

# For example, if you only want to provide services from an internal

# network interface, you may specify your internal interfaces IP-Address.

#

#

interface

= 127.0.0.1

}

includedir /etc/xinetd.d

我們這里需要修改的是

/etc/xinetd.d/

下的三個

conf

文件

rlogin

,rsh,rexec

這三個配置文件

,

打這

三個文件里的

disable = yes

都改成

disable = no ( disabled

用在默認的

{}

中禁止服務

)

或是把

# default:

off

都設置成

on

這個的意思就是在

xinetd

啟動的時候默認都啟動上面的三個服務

!

說明:我自己在配置時,沒有

disable = yes

這項,我就將

# default: off

改為:

default: on

,重啟後

(cd /etc/init.d/./xinetd restart

)通過

netstat -an |grep 514

查看,沒有返回。然後,我就手動在三個文

件中最後一行加入

disable

=

no

,再重啟

xinetd

,再使用

netstat

-an

|grep

514

查看,得到

tcp

0

0

0.0.0.0:514 0.0.0.0:* LISTEN

結果,表明

rsh

伺服器已經啟動。

看到網上有的地方說使用如下命令:

# service xinetd reload

# /sbin/service xinetd rstart

不知道是在什麼系統用的。

二、監控

linux

資源:



controller

中,將

System resource Graphs

中的

Unix resources

拖到右側的監控區域中,並單擊

滑鼠右鍵選擇「

Add

Measurements



,

在彈出的對話框中輸入被監控的

linux

系統的

IP

地址,然後選

擇需要監控的性能指標,並點擊「確定」

,出現如下結果:

Monitor name :UNIX Resources. Cannot initialize the monitoring on 10.10.15.62.

Error while creating the RPC client. Ensure that the machine can be connected and that it runs the

rstat daemon (use rpcinfo utility for this verification).

Detailed error: RPC: Failed to create RPC client.

RPC-TCP: Failed to establish RPC server address.

RPC-TCP: Failed to communicate with the portmapper on host '10.10.15.62'.

RPC: RPC call failed.

RPC-TCP: recv()/recvfrom() failed.

RPC-TCP: Timeout reached. (entry point: CFactory::Initialize). [MsgId: MMSG-47190]

檢查原因,發現是

Linux

系統中的防火牆開啟了並且阻擋了

LoadRunner

監控

Linux

系統的資源,

因此要將防火牆關閉。

關閉防火牆:

[root@localhost ~]# /etc/init.d/iptables stop;

三、監控

UNIX

lr

監控

UNIX



UNIX

先啟動一

rstatd

服務

以下是在

IBM AIX

系統中啟動

rstatd

服務的方法:

1

.使用

telnet



root

用戶的身份登錄入

AIX

系統

2

.在命令行提示符下輸入:

vi /etc/inetd.conf

3

.查找

rstatd

,找到

#rstatd

sunrpc_udp

udp

wait

root /usr/sbin/rpc.rstatd rstatd 100001 1-3

4

、將

#

去掉

5



:wq

保存修改結果

6

、命令提示符下輸入:

refresh



s inetd

重新啟動服務。

這樣使用

loadrunner

就可以監視

AIX

系統的性能情況了。

註:在

HP UNIX

系統上編輯完

inetd.conf

後,重啟

inetd

服務需要輸入

inetd -c

UNIX

上也可以用

rup

命令查看

rstatd

程序是否被配置並激活



rstatd

程序已經運行,

重啟時,

先查看進程

ps -ef |grep inet



然後殺掉進程,



refresh



s inetd

進行重啟。

2. 請幫忙分析Linux下mysql啟動不起來的原因

以下錯誤日誌提示,都是查看 MySQL 錯誤日誌得到,查看方法如下:
查看下 MySQL 配置文件 my.cnf 中有記錄,日誌記錄在/log/mysql/error.log下
?MySQL 配置文件 my.cnf 許可權問題導致無法啟動,錯誤提示:World-writable config file 『/etc/my.cnf』 is ignored
?Binlog 丟失導致無法啟動,錯誤日誌: File 『./mysql-bin.000001』 not found
?Binlog 無法讀取導致無法啟動,錯誤日誌:Failed to open log (file 『./mysql-bin.000001』, errno 13)
?不能創建 PID 導致無法啟動,錯誤日誌:Can』t start server: can』t create PID file: No such file or directory
?不能創建臨時文件導致無法啟動,錯誤日誌:mysqld: Can』t create/write to file 『/tmp/ibfguTtC』 (Errcode: 13)
?MySQL 服務無法識別導致無法啟動,錯誤提示:mysqld: unrecognized service
?MySQL 配置了過大的內存導致無法啟動,錯誤日誌:InnoDB: Cannot allocate memory for the buffer pool
?MySQL 啟動參數過多導致無法啟動,錯誤提示:Too many arguments (first extra is 『start』)
?MySQL 目錄許可權問題導致無法啟動,錯誤日誌:File 『./mysql-bin.index』 not found (Errcode:13 – Permission denied)
?MySQL 未初始化導致無法啟動,錯誤提示:can』t open the mysql.plugin table
?MySQL 啟動成功但未監聽埠
?MySQL ibdata1許可權問題導致無法啟動,錯誤日誌:InnoDB Operating system error number 13 in a file operation
?磁碟空間滿導致 MySQL 無法啟動
?進程殘留導致 MySQL 無法啟動
?MySQL 服務自動停止
這些是錯誤提示你對照去找你的原因就這么多了

3. 啟動linux(xubuntu)時在[ok] reached target sound card不動了

啟動linux(xubuntu)時在[ok] reached target sound card不動了
[OK] Reached initrd target default target
這個是在剛才編輯/etc/selinux/config這個文件里,重啟後出現的錯誤。
結果呢, [OK] Reached initrd target default target
在啟動里能看到,到了這兒,就再也進行不下去了。
分析加GOOGLE後,
在啟動是選擇e 進入到命令行編輯模式, 在倒數第二行 加上 selinux=0
然後能正常啟動中。
編輯上面提到的文件, 恢復原來的設置 selinux=targeted 。

4. 求Linux系統啟動過程分析

google , 下Linux系統啟動過程 你會得到一大堆的, 這個東西在基本的教科書上都有描述

http://publish.it168.com/2005/0825/20050825123701.shtml

很詳細的描述, 就不了,

沒必要也不值得為這個打一大段

5. linux dhcp啟動 失敗 求 高人分析下

出現問題的可能有以下幾個可能:
1. 配置文件有問題。
1.1 內容不符合語法結構,例如,少個分號;
1.2 聲明的子網和子網掩碼不符合;
2. 主機IP地址和聲明的子網不在同一網段。
3. 主機沒有配置IP地址。
4. 配置文件路徑出問題,比如在RHEL6以下的版本中,配置文件保存在了/etc/dhcpd.conf,但是在rhel6及以上版本中,卻保存在了/etc/dhcp/dhcpd.conf。
你檢查一下吧。

6. Linux 高級分析手段有哪些

高級分析手段如OProfile、gprof。
OProfile可以幫助用戶識別諸如模塊的佔用時間、循環的展開、高速緩存的使用率低、低效的類型轉換和冗餘操作、錯誤預測轉移等問題。它收集有關處理器事件的信息,其中包括TLB的故障、停機、存儲訪問以及緩存命中和未命中的指令的攫取數量。
OProfile支持兩種采樣方式:基於事件的采樣(Event Based)和基於時間的采樣(Time Based)。基於事件的采樣是OProfile只記錄特定事件(比如L2緩存未命中)的發生次數,當達到用戶設定的定值時Oprofile就記錄一下(采一個樣)。這種方式需要CPU內部有性能計數器(Performace Counter)。基於時間的采樣是OProfile藉助OS時鍾中斷的機制,在每個時鍾中斷,OProfile都會記錄一次(采一次樣)。引入它的目的在於,提供對沒有性能計數器的CPU的支持,其精度相對於基於事件的采樣要低,因為要藉助OS時鍾中斷的支持,對於禁用中斷的代碼,OProfile不能對其進行分析。
OProfile在Linux上分兩部分,一個是內核模塊( oprofile.ko),另一個是用戶空間的守護進程( oprofiled)。前者負責訪問性能計數器或者注冊基於時間采樣的函數,並將采樣值置於內核的緩沖區內。後者在後台運行,負責從內核空間收集數據,寫入文件。其運行步驟如下。
1)初始化opcontrol--init
2)配置opcontrol--setup--event=...
3)啟動opcontrol--start
4)運行待分析的程序xxx
5)取出數據
opcontrol--mp
6)分析結果opreport-1./xxx
用GNU gprof可以列印出程序運行中各個函數消耗的時間,以幫助程序員找出眾多函數中耗時最多的函數;還可產生程序運行時的函數調用關系,包括調用次數,以幫助程序員分析程序的運行流程。GNU gprof的實現原理:在編譯和鏈接程序的時候〈使用-pg編譯和鏈接選項),gcc在應用程序的每個函數中都加入名為mcount (_mcount或_mcount,依賴於編譯器或操作系統)的函數,也就是說應用程序里的每一個函數都會調用mcount,而mcount會在內存中保存一張函數調用圖,並通過函數調用堆棧的形式查找子函數和父函數的地址。這張調用圖也保存了所有與函數相關的調用時間、調用次數等的所有信息。

7. Linux systemd 自啟動腳本無法正常運行(求助分析方向)

chmod +X /etc/rc.d/rc.local

8. linux kernel啟動失敗,如何分析問題所在

kernel可是linux內核,這個出問題了估計會比較麻煩。
undefined instruction

未定義的指令。

9. linux 啟動時何時初始化console,串口等

1、LINUX下TTY、CONSOLE、串口之間是怎樣的層次關系?具體的函數介面是怎樣的?串口是如何被調用的?


2、printk函數是把信息發送到控制台上吧?如何讓PRINTK把信息通過串口送出?或者說系統在什麼地方來決定是將信息送到顯示器還是串口?


3、start_kernel中一開始就用到了printk函數(好象是printk(linux_banner什麼的),在 這個時候整個內核還沒跑起來呢那這時候的printk是如何被調用的?在我們的系統中,系統啟動是用的現代公司的BOOTLOADER程序,後來好象跳到了LINUX下的head-armv.s, 然後跳到start_kernel,在bootloader 里串口已經是可用的了,那麼在進入內核後是不是要重新設置?


以上問題可能問的比較亂,因為我自己腦子里也比較亂,主要還是對tty,console,serial之間的關系,特別是串口是如何被調用的沒搞清這方面的資料又比較少(就情景分析中講了一點),希望高手能指點一二,非常謝!

我最近也在搞這方面的東西,也是寫一個串口設備的驅動

搞了將近一個月了,其中上網找資料,看源代碼,什麼都做了

但還是一蹋糊塗的,有些問題還是不明白,希望一起討論討論


在/proc/device(沒記錯應該是這個文件)

裡面有一個叫serial的驅動,其主設備號是4,次設備號是64-12X(沒記錯應該是這個范圍)

大家都知道,串口的次設備號是從64開始的,串口1 /dev/ttyS0就對應次設備號64,串口2就對應65

問題是現在我機上只有兩個串口,它注冊這么多次設備號來干什麼?


對於一個接在串口1的設備,在我注冊驅動的時候

我是需要自己找一個主設備號呢?

還是就用主設備號4,次設備號從上面12X的後面選?

還是就用主設備號4,次設備號64?


在linux的內核中有一個tty層,我看好像有些串口驅動是從這里開始的

例如調用tty_register_driver()來注冊驅動

就像在pci子系統里調用pci_register_driver()那樣的

那麼,用這種機制來注冊的驅動,

它是直接對串口的埠操作呢(例如用inb(),outb()....之類的)

還是某些更底層的驅動介面呢?


這些問題纏了我很久都沒解決,搞得最後不得不放棄

現在轉向用戶空間的應用程序,看能不能有些更高效的方法來實現

(在用戶空間只能用open("/dev/ttyS0", O_RDWR)來實現了)

另外還有,系統里已經為我們實現了串口的驅動

所以我們在用戶空間的程序里直接open("/dev/ttyS0")就可用了

但是現在要寫的是接在串口上的設備的驅動

在內核模塊中可不可以包含某個頭文件,然後就可以直接用串口驅動中的介面呢?

看到你們的問題後,感覺很有典型性,因此花了點工夫看了一下,做了一些心得貼在這里,歡迎討論並指正:

1、LINUX下TTY、CONSOLE、串口之間是怎樣的層次關系?具體的函數介面是怎樣的?串口是如何被調用的?

tty和console這些概念主要是一些虛設備的概念,而串口更多的是指一個真正的設備驅動Tty實際是一類終端I/O設備的抽象,它實際上更多的是一個管理的概念,它和tty_ldisc(行規程)和tty_driver(真實設備驅動)組合在一起,目的是向上層的VFS提供一個統一的介面通過file_operations結構中的tty_ioctl可以對其進行配置。查tty_driver,你將得到n個結果,實際都是相關晶元的驅動因此,可以得到的結論是(實際情況比這復雜得多):每個描述tty設備的tty_struct在初始化時必然掛如了某個具體晶元的字元設備驅動(不一定是字元設備驅動),可以是很多,包括顯卡或串口chip不知道你的ARM Soc是那一款,不過看情況你們應該用的是常見的chip,這些驅動實際上都有而console是一個緩沖的概念,它的目的有一點類似於tty實際上console不僅和tty連在一起,還和framebuffer連在一起,具體的原因看下面的鍵盤的中斷處理過程Tty的一個子集需要使用console(典型的如主設備號4,次設備號1―64),但是要注意的是沒有console的tty是存在的

而串口則指的是tty_driver舉個典型的例子:

分析一下鍵盤的中斷處理過程:

keyboard_interrupt―>handle_kbd_event―>handle_keyboard_event―>handle_scancode

void handle_scancode(unsigned char scancode, int down)

{

……..

tty = ttytab? ttytab[fg_console]: NULL;

if (tty && (!tty->driver_data)) {

……………

tty = NULL;

}

………….

schele_console_callback();

}

這段代碼中的兩個地方很值得注意,也就是除了獲得tty外(通過全局量tty記錄),還進行了console 回顯schele_console_callbackTty和console的關系在此已經很明了!!!


2、printk函數是把信息發送到控制台上吧?如何讓PRINTK把信息通過串口送出?或者說系統在什麼地方來決定是將信息送到顯示器還是串口?

具體看一下printk函數的實現就知道了,printk不一定是將信息往控制台上輸出,設置kernel的啟動參數可能可以打到將信息送到顯示器的效果。函數前有一段英文,很有意思:

/*This is printk. It can be called from any context. We want it to work.

*

* We try to grab the console_sem. If we succeed, it's easy - we log the output and

* call the console drivers. If we fail to get the semaphore we place the output

* into the log buffer and return. The current holder of the console_sem will

* notice the new output in release_console_sem() and will send it to the

* consoles before releasing the semaphore.

*

* One effect of this deferred printing is that code which calls printk() and

* then changes console_loglevel may break. This is because console_loglevel

* is inspected when the actual printing occurs.

*/

這段英文的要點:要想對console進行操作,必須先要獲得console_sem信號量如果獲得console_sem信號量,則可以「log the output and call the console drivers」,反之,則「place the output into the log buffer and return」,實際上,在代碼:

asmlinkage int printk(const char *fmt, ...)

{

va_list args;

unsigned long flags;

int printed_len;

char *p;

static char printk_buf[1024];

static int log_level_unknown = 1;

if (oops_in_progress) { /*如果為1情況下,必然是系統發生crush*/

/* If a crash is occurring, make sure we can't deadlock */

spin_lock_init(&logbuf_lock);

/* And make sure that we print immediately */

init_MUTEX(&console_sem);

}

/* This stops the holder of console_sem just where we want him */

spin_lock_irqsave(&logbuf_lock, flags);

/* Emit the output into the temporary buffer */

va_start(args, fmt);

printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);/*對傳入的buffer進行處理,注意還不是

真正的對終端寫,只是對傳入的string進行格式解析*/

va_end(args);

/*Copy the output into log_buf. If the caller didn't provide appropriate log level tags, we insert them here*/

/*注釋很清楚*/

for (p = printk_buf; *p; p++) {

if (log_level_unknown) {

if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {

emit_log_char('<');

emit_log_char(default_message_loglevel + '0');

emit_log_char('>');

}

log_level_unknown = 0;

}

emit_log_char(*p);

if (*p == ' ')

log_level_unknown = 1;

}

if (!arch_consoles_callable()) {

/*On some architectures, the consoles are not usable on secondary CPUs early in the boot process.*/

spin_unlock_irqrestore(&logbuf_lock, flags);

goto out;

}

if (!down_trylock(&console_sem)) {

/*We own the drivers. We can drop the spinlock and let release_console_sem() print the text*/

spin_unlock_irqrestore(&logbuf_lock, flags);

console_may_schele = 0;

release_console_sem();

} else {

/*Someone else owns the drivers. We drop the spinlock, which allows the semaphore holder to

proceed and to call the console drivers with the output which we just proced.*/

spin_unlock_irqrestore(&logbuf_lock, flags);

}

out:

return printed_len;

}

實際上printk是將format後的string放到了一個buffer中,在適當的時候再加以show,這也回答了在start_kernel中一開始就用到了printk函數的原因


3、start_kernel中一開始就用到了printk函數(好象是printk(linux_banner什麼的),在這個時候整個內核還沒跑起來呢。那這時候的printk是如何被調用的?在我們的系統中,系統啟動是用的現代公司的BOOTLOADER程序,後來好象跳到了LINUX下的head-armv.s, 然後跳到start_kernel,在bootloader 里串口已經是可用的了,那麼在進入內核後是不是要重新設置?

Bootloader一般會做一些基本的初始化,將kernel拷貝物理空間,然後再跳到kernel去執行。可以肯定的是kernel肯定要對串口進行重新設置,原因是Bootloader有很多種,有些不一定對串口進行設置,內核不能依賴於bootloader而存在。


多謝樓上大俠,分析的很精闢。我正在看printk函數。


我們用的CPU是hynix的hms7202。在評估板上是用串口0作

控制台,所有啟動過程中的信息都是通過該串口送出的。

在bootloader中定義了函數ser_printf通過串口進行交互。


但我還是沒想明白在跳轉到linux內核而console和串口尚未

初始化時printk是如何能夠工作的?我看了start_kernel

的過程(並通過超級終端作了一些跟蹤),console的初始化

是在console_init函數里,而串口的初始化實際上是在1號

進程里(init->do_basic_setup->do_initcalls->rs_init),

那麼在串口沒有初始化以前prink是如何工作的?特別的,在

start_kernel一開始就有printk(linux_banner),而這時候

串口和console都尚未初始化呢。

  1. 在start_kernel一開始就有printk(linux_banner),而這時候串口和console都尚未初始化?

  2. 仔細分析printk可以對該問題進行解答代碼中的:

  3. /* Emit the output into the temporary buffer */

  4. va_start(args, fmt);

  5. printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);

  6. va_end(args);

  7. 將輸入放到了printk_buf中,接下來的

  8. for (p = printk_buf; *p; p++) {

  9. if (log_level_unknown) {

  10. if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {

  11. emit_log_char('<');

  12. emit_log_char(default_message_loglevel + '0');

  13. emit_log_char('>');

  14. }

  15. log_level_unknown = 0;

  16. }

  17. emit_log_char(*p);

  18. if (*p == ' ')

  19. log_level_unknown = 1;

  20. }

  21. 則將printk_buf中的內容進行解析並放到全局的log_buf(在emit_log_char函數)中if (!down_trylock(&console_sem)) {

  22. /*

  23. * We own the drivers. We can drop the spinlock and let

  24. * release_console_sem() print the text

  25. */

  26. spin_unlock_irqrestore(&logbuf_lock, flags);

  27. console_may_schele = 0;

  28. release_console_sem();

  29. } else {

  30. /*

  31. * Someone else owns the drivers. We drop the spinlock, which

  32. * allows the semaphore holder to proceed and to call the

  33. * console drivers with the output which we just proced.

  34. */

  35. spin_unlock_irqrestore(&logbuf_lock, flags);

  36. }

  37. 則是根據down_trylock(&console_sem)的結果調用release_console_sem(),在release_console_sem()中才真正的對全局的log_buf中的內容相應的console設備驅動進行處理。至此,可以得到如下的一些結論:

  38. (1)printk的主操作實際上還是針對一個buffer(log_buf),該buffer中的內容是否顯示(或者說向終端輸出),則要看是否可以獲得console_sem(2)printk所在的文件為printk.c,是和體系結構無關的,因此對任何平台都一樣。 可以推測的結論是:

  39. (1)kernel在初始化時將console_sem標為了locked,因此在start_kernel一開始的printk(linux_banner)中實際只將輸入寫入了緩沖,等在串口和console初始化後,對printk的調用才一次將緩沖中的內容向串口和console輸出。 (2)在串口和console的初始化過程中,必然有對console_sem的up操作。

  40. (3)因此,在embedded的調試中,如果在console的初始化之前系統出了問題,不會有任何的輸出。 唯一可以使用的只能是led或jtag了。(4)因此,你的問題可以看出解答。2.console的初始化.

  41. 不知道你用的是那一個內核版本,在我看的2.4.18和2.4.19中,都是在start_kernel中就對console進行的初始化。從前面的分析來看,console的初始化不應該太晚,否則log_buf有可能溢出。

  42. 多謝樓上,分析的很精彩!

我們用的內核版本是2.4.18,console的初始化確實是在

start_kernel->console->init。關於tty和串口,我這里還想再問一下tty設備的操作的總入口


static struct file_operations tty_fops = {

llseek: no_llseek,

read: tty_read,

write: tty_write,

poll: tty_poll,

ioctl: tty_ioctl,

open: tty_open,

release: tty_release,

fasync: tty_fasync,

};


而對串口的操作定義在:


static struct tty_driver serial_driver 這個結構中

serial.c中的多數函數都是填充serial_driver中的函數指針

那麼在對串口操作時,應該是先調用tty_fops中的操作(比如

tty_open等),然後再分流到具體的串口操作(rs_open等)吧?

但tty_driver(對串口就是serial_driver)中有很多函數指針

並不跟file_operations中的函數指針對應,不知道這些對應

不上的操作是如何被執行的?比如put_char,flush_char,read_proc,

write_proc,start,stop等。

以下是我對這個問題的一些理解:

這實際上還是回到原先的老問題,即tty和tty_driver之間的關系。從實現上看,tty_driver實際上是tty機制的實現組件之一,借用面向對象設計中的常用例子,這時的tty_driver就象是tty這部汽車的輪胎,tty這部汽車要正常運行,還要tty_ldisc(行規程),termios,甚至struct tq_struct tq_hangup(看tty_struct)等基礎設施。它們之間的關系並非繼承。至於tty_driver中的函數指針,再打個C++中的比喻,它們實際上很象虛函數,也就是說,可以定義它們,但並不一定實現它們、實際上還不用說tty_driver,只要查一下serial_driver都會發現n多個具體的實現,但對各個具體的設備,其tty_driver中的函數不一定全部實現、所以put_char,flush_char,read_proc, write_proc,start,stop這些函數的情況是有可能實現,也有可能不實現 即使被實現,也不一定為上層(VFS層)所用.

熱點內容
lua腳本linux 發布:2025-07-08 01:20:57 瀏覽:218
平板如何關掉appstore密碼 發布:2025-07-08 00:59:17 瀏覽:405
安卓版軒轅劍劍之源哪裡下載 發布:2025-07-08 00:55:06 瀏覽:675
安卓的軟體怎麼關閉 發布:2025-07-08 00:53:38 瀏覽:777
html5整站源碼 發布:2025-07-08 00:36:01 瀏覽:943
sql創建鏈接 發布:2025-07-08 00:08:38 瀏覽:398
ftp上傳中斷 發布:2025-07-08 00:08:37 瀏覽:641
linux雲計算課程 發布:2025-07-08 00:07:23 瀏覽:23
安卓網易雲怎麼發布歌曲 發布:2025-07-07 23:42:29 瀏覽:626
安卓內存讀取腳本 發布:2025-07-07 23:42:19 瀏覽:872