当前位置:首页 » 操作系统 » 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层)所用.

热点内容
php微信支付教程视频教程 发布:2025-05-14 08:59:59 浏览:201
存储服务器分类 发布:2025-05-14 08:39:01 浏览:645
xz文件解压软件 发布:2025-05-14 08:28:43 浏览:969
lua脚本学习 发布:2025-05-14 08:20:55 浏览:713
python文件删除一行 发布:2025-05-14 08:06:58 浏览:721
如何下载奥特曼高级化3安卓版 发布:2025-05-14 07:47:31 浏览:346
qml文件修改后编译未生效 发布:2025-05-14 07:31:00 浏览:331
内到内算法 发布:2025-05-14 07:29:11 浏览:34
文件夹名字不显示 发布:2025-05-14 07:27:47 浏览:775
oracle的数据库驱动jar 发布:2025-05-14 07:23:20 浏览:556