Linux系统是一种非常流行并且广泛使用的操作系统,它提供了强大的功能和灵活性,可以在各种不同的设备上使用。在Linux系统中,内核是整个系统的核心,并且是系统启动时更先加载的组件。在本文中,我们将深入探讨过程,了解它的所有步骤和阶段。
1. 引导加载程序
在任何操作系统的启动过程中,之一步始终是启动引导加载程序。引导加载程序负责在计算机启动时加载操作系统的内核,并且它通常存储在计算机的启动磁盘驱动器中。在Linux系统中,引导加载程序通常是grub(GRand Unified Bootloader)。
2. 初始化内核
启动引导加载程序之后,计算机将开始初始化操作系统内核。这是一个非常关键的步骤,因为它将为系统中的其他组件提供必要的基础设施,并确保内核能够正常工作。在Linux系统中,内核初始化包括以下步骤:
– 计算机检测硬件。
– 内核加载相应的驱动程序以支持硬件设备。
– 内核初始化内存管理子系统、进程管理子系统和文件系统子系统。
– 内核启动守护程序,并设置其他系统设置。
3. 用户空间初始化
完成内核初始化后,Linux系统将开始用户空间初始化。用户空间是一个操作系统中的一部分,它是用户和应用程序运行的地方。在Linux系统中,用户空间初始化包括以下步骤:
– 管理用户和用户组。
– 初始化系统服务和设置程序,以便它们可以正常运行。
– 启动登录管理器(如GDM或KDM),以便用户可以登录到系统。
4. shell启动
一旦用户空间初始化完成,Linux系统将启动shell。shell是一个命令行界面,它允许用户与操作系统交互。在Linux系统中,有多个shell可供选择,例如bash和zsh。
5. 启动应用程序和服务
在完成用户空间初始化和shell启动之后,Linux系统将启动应用程序和服务。这些应用程序和服务可能是从命令行启动的,也可能是在系统启动时自动启动的,以确保它们一直在后台运行。
过程是一个非常复杂和精细的过程。没有引导加载程序和内核初始化,操作系统无法正常运行。通过深入了解过程,我们可以更好地理解操作系统的工作原理,并且可以进行调试和优化,使其更加高效和可靠。
相关问题拓展阅读:
linux kernel 没有输出信息 怎么调试
最近工作在调试u虚拟串口,让其作为kernel启动的调试串口老埋,以及user空间的输入输出控制台。
利用这个机会,学习下printk如何选择往哪个console输出以及user空间下控制台如何选择,记录与此,与大家共享,也尺含绝方便自己以后翻阅。
Kernel版本号:3.4.55
依照我的思路(还是时间顺序)分了4部分,指定kernel调试console , kernel下printk console的选择 ,kernel下console的注册,user空间console的选陵姿择。
一 指定kernel调试console
首先看kernel启动时如何获取和处理指定的console参数。
kernel的启动参数cmdline可以指定调试console,如指定‘console=ttyS0,115200’,
kernel如何解析cmdline,我之前写了一篇博文如下:
根据之前的分析,cmdline中有console=xxx,start_kernel中parse_args遍历.init.setup段所有obs_kernel_param。
kernel/printk.c中注册了‘console=’的解析函数console_setup(注册了obs_kernel_param),所以匹配成功,会调用console_setup来解析,如下:
view plain copy
static int __init console_setup(char *str)
char buf.name) + 4>; /* 4 for index */
char *s, *options, *brl_options = NULL;
#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
if (!memcmp(str, “brl,”, 4)) {
brl_options = “”;
} else if (!memcmp(str, “brl=”, 4)) {
brl_options = str + 4;
str = strchr(brl_options, ‘,’);
printk(KERN_ERR “need port name after brl=\n”);
*(str++) = 0;
* Decode str into name, index, options.
if (str >= ‘0’ && str = ‘0’ && *s name, name, sizeof(c->name));
c->options = options;
#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
c->brl_options = brl_options;
c->index = idx;
kernel利用结构体数组console_cmdline,最多可支持8个cmdline传入的console参数。
__add_preferred_console将name idx options保存到数组下一个成员console_cmdline结构体中,如果数组中已有重名,则不添加,并置selected_console为最新添加的console_cmdline的下标号。
比如cmdline中有“console=ttyS0,console=ttyS1,9600”
则在console_cmdline数组中console_cmdline代表ttyS0,console_cmdline代表ttyS1,而selected_console=1.
二 kernel下printk console的选择
kernel下调试信息是通过printk输出,如果要kernel正常打印,则需要搞明白printk怎么选择输出的设备。
关于printk的实现原理,我在刚工作的时候写过一篇博文,kernel版本是2.6.21的,但是原理还是一致的,可供参考:
printk首先将输出内容添加到一个kernel缓冲区中,叫log_buf,log_buf相关代码如下:
view plain copy
#define MAX_CMDLINECONSOLES 8

static struct console_cmdline console_cmdline;
static int selected_console = -1;
static int preferred_console = -1;
int console_set_on_cmdline;
EXPORT_SYMBOL(console_set_on_cmdline);
/* Flag: console code may call schedule() */
static int console_may_schedule;
#ifdef CONFIG_PRINTK
static char __log_buf;
static char *log_buf = __log_buf;
static int log_buf_len = __LOG_BUF_LEN;
static unsigned logged_chars; /* Number of chars produced since last read+clear operation */
static int saved_console_loglevel = -1;
log_buf的大小由kernel menuconfig配置,我配置的CONFIG_LOG_BUF_SHIFT为17,则log_buf为128k。
printk内容会一直存在log_buf中,log_buf满了之后则会从头在开始存,覆盖掉原来的数据。
根据printk的实现原理,printk最后调用console_unlock实现log_buf数据刷出到指定设备。
这里先不关心printk如何处理log buf数据(比如添加内容级别),只关心printk如何一步步找到指定的输出设备,根据printk.c代码,可以找到如下线索。
printk->vprintk->console_unlock->call_console_drivers->_call_console_drivers->_call_console_drivers->__call_console_drivers
看线索更底层__call_console_drivers代码。如下:
view plain copy
* Call the console drivers on a range of log_buf
static void __call_console_drivers(unsigned start, unsigned end)
struct console *con;
for_each_console(con) {
if (exclusive_console && con != exclusive_console)
if ((con->flags & CON_ENABLED) && con->write &&
(cpu_online(p_processor_id()) ||
(con->flags & CON_ANYTIME)))
con->write(con, &LOG_BUF(start), end – start);
for_each_console定义如下:
view plain copy
* for_each_console() allows you to iterate on each console
#define for_each_console(con) \
for (con = console_drivers; con != NULL; con = con->next)
遍历console_drivers链表所有console struct,如果有exclusive_console,则调用与exclusive_console一致console的write,
如果exclusive_console为NULL,则调用所有ENABLE的console的write方法将log buf中start到end的内容发出。
可以看出,EXEclusive_console来指定printk输出唯一console,如果未指定,则向所有enable的console写。
默认情况下execlusive_console=NULL,所以printk默认是向所有enable的console写!
只有一种情况是指定execlusive_console,就是在console注册时,下面会讲到。
到这里就很明了了,kernel下每次printk打印,首先存log_buf,然后遍历console_drivers,找到合适console(execlusive_console或所有enable的),刷出log。
console_drivers链表的成员是哪里来的,谁会指定execulsive_console?接着来看下一部分,kernel下console的注册
linux start kernel的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux start kernel,Linux系统的内核启动,linux kernel 没有输出信息 怎么调试的信息别忘了在本站进行查找喔。
香港服务器首选树叶云,2H2G首月10元开通。树叶云(shuyeidc.com)提供简单好用,价格厚道的香港/美国云 服务器 和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。
LINUX操作系统的启动过程
一、启动内核 首先介绍启动内核部分。 电脑启动时,BIOS装载MBR,然后从当前活动分区启动,LILO获得引 导过程的控制权后,会显示LILO提示符。 此时如果用户不进行任何操作,LILO将在等待制定 时间后自动引导默认的操作系统,而如果在此期间按下TAB键,则可以看到一个可引导的操作 系统列表,选择相应的操作系统名称就能进入相应的操作系统。 当用户选择启动LINUX操作系统时,LILO就会根据事先设置好的信息从ROOT文件系统所在的分 区读取LINUX映象,然后装入内核映象并将控制权交给LINUX内核。 LINUX内核获得控制权后, 以如下步骤继续引导系统: 1. LINUX内核一般是压缩保存的,因此,它首先要进行自身的解压缩。 内核映象前面的一些 代码完成解压缩。 2. 如果系统中安装有可支持特殊文本模式的、且LINUX可识别的SVGA卡,LINUX会提示用户 选择适当的文本显示模式。 但如果在内核的编译过程中预先设置了文本模式,则不会提示选 择显示模式。 该显示模式可通过LILO或RDEV工具程序设置。 3. 内核接下来检测其他的硬件设备,例如硬盘、软盘和网卡等,并对相应的设备驱动程序 进行配置。 这时,显示器上出现内核运行输出的一些硬件信息。 4. 接下来,内核装载ROOT文件系统。 ROOT文件系统的位置可在编译内核时指定,也可通过 LILO或RDEV指定。 文件系统的类型可自动检测。 如果由于某些原因装载失败,则内核启动 失败,最终会终止系统。 二、执行init程序 其次介绍init程序,利用init程序可以方便地定制启动其间装入哪些程序。 init的任务是 启动新进程和退出时重新启动其它进程。 例如,在大多数Linux系统中,启动时最初装入 六个虚拟的控制台进程,退出控制台窗口时,进程死亡,然后init启动新的虚拟登录控制台, 因而总是提供六个虚拟登陆控控制台进程。 控制init程序操作的规则存放在文件/etc/inittab中。 Red Hat Linux缺省的inittab文 件如下: # #inittab This file describes how the INIT process should set up the system in a certain #run-level. # # #Default runlevels used by RHS are: #0-halt(Do NOT set initdefault to this) #1-Single user mode #2-Multiuser,without NFS(the same as 3,if you do not have networking) #3-Full multiuser mode #4-unused #5-X11 #6-reboot(Do NOT set initdefault to this) # id:3:initdefault: #system initialization si::sysinit:/etc/rc.d/ 10:0:wait:/etc/rc.d/rc 0 11:1:wait:/etc/rc.d/rc 1 12:2:wait:/etc/rc.d/rc 2 13:3:wait:/etc/rc.d/rc 3 14:4:wait:/etc/rc.d/rc 4 15:5:wait:/etc/rc.d/rc 5 16:6:wait:/etc/rc.d/rc 6 #Things to run in every runlevel ud:once:/sbin/update #Trap CTRL-ALT-DELETE ca::ctrlaltdel:/sbin/shutdown -t3 -r now #When our UPS tells us power has failed,assume we have a few minutes of power a #shutdown for 2 minutes From now. #This does,of course,assume you have powered installed and your UPS connected and working #correctly. pf::powerfail:/sbin/shutdown -f -h +2 Power Restored;Shutdown Cancelled #Run gettys in standard runlevels 1:respawn:/sbin/minggetty tty1 2:2345:respawn:/sbin/minggetty tty2 3:2345:respawn:/sbin/minggetty tty3 4:2345:respawn:/sbin/minggetty tty4 5:2345:respawn:/sbin/minggetty tty5 6:2345:respawn:/sbin/minggetty tty6 #Run xdm in runlevel 5 x:5:respawn:/usr/bin/X11/xdm -nodaemon Linux有个运行级系统,运行级是表示系统当前状态和init应运行哪个进程并保持在这种 系统状态中运行的数字。 在inittab文件中,第一个项目指定启动时装入的缺省运行级。 上例中是个多用户控制台方式,运行级为3。 然后,inittab文件中每个项目指定第二个 字段的项目用哪种运行级(每个字段用冒号分开)。 因此,对运行级3,下列行是相关的: 13:3:wait:/etc/rc.d/rc 3 1:respawn:/sbin/minggetty tty1 2:2345:respawn:/sbin/minggetty tty2 3:2345:respawn:/sbin/minggetty tty3 4:2345:respawn:/sbin/minggetty tty4 5:2345:respawn:/sbin/minggetty tty5 6:2345:respawn:/sbin/minggetty tty6 最后六行建立Linux提供的六个虚拟控制台。 第一行运行启动脚本/etc/rc.d/ rc 3; 这将运行目录/etc/ rc.d/rc3.d中包含的所有脚本,这些脚本表示系统初始化时要启动的程序。 一般来说, 这些脚本不需要编辑或改变,是系统缺省的。
linux系统启动出现 Kernel panic: No init found. Try passing init=option to kernel怎解决?求详细教程
:No init found ,Try passing init =option to kernel 问题补充:高手能...你应该是在电脑上对立安装linux的吧,在xp下用虚拟机装就没事了,可能是你...
Linux环境变量顺序是什么?
路径排前面的优先。 比如 $JAVA_HOME/bin和/usr/bin下面都有java。 PATH=$JAVA_HOME/bin:$PATH 时,执行 java的时候是$JAVA_HOME/bin/java,如果没有再执行/usr/bin/java PATH=$PATH:$JAVA_HOME/bin 时,执行 java的时候是/usr/bin/java。 一般用户设定都是为了特殊用途,使用方式2没什么意义,所以方式1多些。 内核启动的时候,各个驱动初始化的工作在文件init/main.c中的do_basic_setup()函数中做.
发表评论