linux 操作系统启动过程和内核参数修改添加方法

linux 操作系统启动过程和内核参数修改添加方法

操作系统启动过程

操作系统启动过程一般分为五个阶段:(centos7为例)

  1. BIOS初始化
  2. 加载MBR到内存
  3. GRUB阶段
  4. 加载内核和initramfs模块
  5. systemd阶段

BIOS初始化

上电后,主板BIOS运行POST(Power on self test)代码,进行开机自检,检查硬件:CPU、内存、显卡、硬盘、CD-ROM、串口、并口、软驱等。

加载MBR到内存

自检硬件没有问题时候,这里以BIOS为例,BIOS将会直接找硬盘的第一个扇区,找到前446字节,将MBR加载到内存中,MBR将告诉程序下一阶段去哪里找系统的grub引导。此阶段属于grub第1阶段。grub还有1.5阶段和2阶段。

GRUB阶段

主要操作是装载stage1,装载stage1.5,装载stage2。
然后读取/boot/grub.conf文件显示启动菜单,装载所选的kernel和initrd文件到内存中。
grub启动三阶段:

stage1: 引导安装在MBR中的引导程序(bootloader)
stage1.5: mbr之后的扇区,让stage1中的bootloader能识别stage2所在的分区上的文件系统;
stage2:读取存放在磁盘上的grub(存放位置:/boot/grub),grub的配置文件:/boot/grub/grub.conf,在etc目录下有此文件的连接文件:/etc/grub.conf

加载内核和initramfs模块

加载内核,核心开始解压,启动一些最核心的程序。

为了让内核足够的轻小,硬件驱动并没放在内核文件里面。

kernel内核开始初始化,用systemd来代替centos6以前的init程序
先执行initrd.target
包括挂载/etc/fstab文件中系统,挂载之后,就可以切换到根目录。

从initramfs根文件系统切换到磁盘的根目录
systemd执行默认target配置
centos7表面有“运行级别”这个概念,实际是为了兼容以前的系统,每个所谓“运行级别”都有对应的软连接指向,默认的启动级别/etc/systemd/system/default.target,根据它的指向可以找到系统要进入到哪个模式。

模式:

0 ==> runlevel0.target, poweroff.target
1 ==> runlevel1.target, rescue.target
2 ==> runlevel2.target, multi-user.target
3 ==> runlevel3.target, multi-user.target
4 ==> runlevel4.target, multi-user.target
5 ==> runlevel5.target, graphical.target
6 ==> runlevel6.target, reboot.target

systemd阶段

systemd执行sysinit.target
systemd启动multi-user.target下的本机与服务器服务
systemd执行multi-user.target下面的/etc/rc.d/rc.local
systemd执行multi-user.target下的getty.target及登录服务
getty.target是启动终端的systemd对象。如果到此步骤,系统没有指定启动图形桌面,到此就可以结束,如果需要启动图形界面,要在此基础上启动桌面程序。

systemd执行graphical图形化需要的服务
至此系统启动完成,可以正常使用。

 

内核参数

修改内核参数

内核命令行参数(也称为内核参数)仅用于在引导时自定义Linux的行为。
内核命令行参数保存在boot/grub/grub.cfg配置文件中,该文件为 由GRUB2引导加载程序生成。不要编辑此配置文件。仅对该文件所做的更改,由配置脚本制作。

  1. 使用纯文本编辑器(例如vim或Gedit)以root身份打开/etc/default/grub配置文件。
  2. 在此文件中,找到以GRUB_CMDLINE_LINUX开头的行,如下所示:
    GRUB_CMDLINE_LINUX =“ rd.lvm.lv=rhel/swap crashkernel=auto rd.lvm.lv= rhel/root rhgb quiet”
  3. 更改所需的内核命令行参数的值。然后,保存文件并退出编辑器。
  4. 使用编辑后的默认文件重新生成GRUB2配置。如果您的系统使用BIOS固件,执行以下命令:
    #grub2-mkconfig -o /boot/grub2/grub.cfg
    在具有UEFI固件的系统上,改为执行以下操作:
    #grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
    完成上述步骤后,将重新配置引导加载程序,并在下次重新引导后应用您在其配置文件中指定的内核命令行参数

修改内核可调参数

内核可调参数用于在引导时或在系统运行时按需自定义Linux的行为。 一些硬件参数仅在引导时指定,并且一旦系统运行就无法更改,但是大多数硬件参数可以根据需要进行更改,并在下次引导时永久设置。

使用sysctl命令
sysctl命令用于列出,读取和设置内核可调参数。 当列出或读取或临时设置或永久设置可调参数时,它可以过滤可调参数。

  1. 列出变量
    #sysctl -a
  2. 读取变量
    #sysctl kernel.version +
    kernel.version =#1 SMP 2018年1月19日星期五13:19:54
  3. 临时写变量
    #sysctl .=
  4. 永久写入变量
    #sysctl -w .= >> /etc/sysctl.conf

要在引导时覆盖默认值,还可以在/etc/sysctl.d中手动填充文件。

  1. 在/etc/sysctl.d中创建一个新文件
    #vim /etc/sysctl.d/99-custom.conf
  2. 包含您要设置的变量,每行一个,格式如下
    . = +
    . =
  3. 保存文件
  4. 重新引导计算机以使更改生效,或执行sysctl -p /etc/sysctl.d/99-custom.conf以应用更改而无需重新引导。

编写添加内核参数

在Linux系统下,使用sysctl命令可以查看和修改系统参数,添加一个系统参数的方法:

在ctl_table中注册内核参数

在source/net/ipv4/sysctl_net_ipv4.c文件中有这样一个结构体数组

static struct ctl_table ipv4-table[] = {
    ......
},
{
    ......
}
......

在目录/proc/sys/net/ipv4/下面所有的系统参数都得先到这里注册,下面给出一个具体例子。

{ 
	.procname = "tcp_vegas_alpha",
	.data     = &sysctl_tcp_vegas_alpha,
	.maxlen   = sizeof(int),
	.mode     = 0644,
	.proc_handler  = proc_dointvec
},
{
	.procname = "tcp_vegas_beta",
	.data     = &sysctl_tcp_vegas_alpha,
	.maxlen   = sizeof(int),
	.mode     = 0644,
	.proc_handler  = proc_dointvec

}

这两个参数是拥塞控制算法Vegas在拥塞控制阶段调节cwnd用的。
这里是struct ctl_table的具体定义。

/* 结构位置:include/linux/sysctl.h */
struct ctl_table
{
    const char    *procname;    /* Text ID for /proc/sys, or zero */
    void          *data;
    int           maxlen;
    umode_t       mode;
    struct        ctl_table *child;  /* Deprecated */
    proc_handler  *proc_handler;     /* Callback for text formatting */
    struct ctl_tabel_poll *poll;
    void *extral;
    void *extra2;
};

现在简单介绍一下这些结构体成员变量。
*procname 表示在/proc/sys/下显示的文件名称,
*data 表示对应于内核中的变量名称,
maxlen 表示允许的最大长度,
mode 表示访问权限,
proc_handler表示回调函数,有一些常用取值:
porc_dointvec 读写包含一个或多个整数的数组,
proc_dostring 读写一个字符串,
proc_dointvec_minmax 写的整数必须在min~max范围内。

声明内核参数

用于TCP的内核参数在source/include/net/tcp.h声明。

/* 进入tcp.h文件可以看到大量的变量声明,这里只列出上文提及到的两个变量 */
...
extern int sysctl_tcp_vegas_alpha;
extern int sysctl_tcp_vegas_beta
...

定义内核参数

内核参数的定义可能在不同的文件中,这个根据内核参数的用途而定。
systcl_tcp_vegas_alpha和sysctl_tcp_vegas_beta这两个变量的定义位置:
source/net/ipv4/tcp_retrans.c

int sysctl_tcp_vegas_alpha = 2;
int sysctl_tcp_vegas_beta = 4;

经过上面这些步骤,内核参数就添加成功了,当我们编译重启系统后,就会发现在目录:/proc/sys/net/ipv4/下有两个文件分别是tcp_vegas_alpha和tcp_vegas_beta,以后就可以通过echo命令动态修改这两个值。

常用的内核参数

下列文件所在目录:/proc/sys/net/ipv4/

名称 默认值 描述
tcp_syn_retries 5 对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,是由tcp_retries1决定的)
tcp_synack_retries 5 对于远端的连接请求SYN,内核会发送SYN + ACK数据报,以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。不应该大于255,默认值是5,对应于180秒左右时间。
tcp_keepalive_time 7200 TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效。防止两边建立连接但不发送数据的攻击
tcp_keepalive_probes 9 TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效。
tcp_keepalive_intvl 75 探测消息未获得响应时,重发该消息的间隔时间(秒)。默认值为75秒。 (对于普通应用来说,这个值有一些偏大,可以根据需要改小.特别是web类服务器需要改小该值,15是个比较合适的值)
tcp_retries1 3 放弃回应一个TCP连接请求前﹐需要进行多少次重试。RFC规定最低的数值是3
tcp_retries2 15 在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15,根据RTO的值来决定,相当于13-30分钟(RFC1122规定,必须大于100秒).(这个值根据目前的网络设置,可以适当地改小)
tcp_orphan_retries 7 在近端丢弃TCP连接之前﹐要进行多少次重试。默认值是7个﹐相当于 50秒 - 16分钟﹐视 RTO 而定。如果您的系统是负载很大的web服务器﹐那么也许需要降低该值﹐这类 sockets 可能会耗费大量的资源。另外参的考tcp_max_orphans。(事实上做NAT的时候,降低该值也是好处显著的)
tcp_fin_timeout 60 对于本端断开的socket连接,TCP保持在FIN-WAIT-2状态的时间。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。默认值为 60 秒
tcp_max_tw_buckets 180000 系统在同时所处理的最大 timewait sockets 数目。如果超过此数的话﹐time-wait socket 会被立即砍除并且显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐不过﹐如果网络条件需要比默认值更多﹐则可以提高它(或许还要增加内存)。(事实上做NAT的时候最好可以适当地增加该值)
tcp_tw_recycle 0 打开快速 TIME-WAIT sockets 回收。除非得到技术专家的建议或要求﹐请不要随意修改这个值。(做NAT的时候,建议打开它)
tcp_tw_reuse 8192 系统所能处理不属于任何进程的TCP sockets最大数量。假如超过这个数量﹐那么不属于任何进程的连接会被立即reset,并同时显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐千万不要依赖这个或是人为的降低这个限制。如果内存大更应该增加这个值。(这个值Redhat AS版本中设置为32768,但是很多防火墙修改的时候,建议该值修改为2000)
tcp_abort_on_overflow 0 当守护进程太忙而不能接受新的连接,就象对方发送reset消息,默认值是false。这意味着当溢出的原因是因为一个偶然的猝发,那么连接将恢复状态。只有在你确信守护进程真的不能完成连接请求时才打开该选项,该选项会影响客户的使用。(对待已经满载的sendmail,apache这类服务的时候,这个可以很快让客户端终止连接,可以给予服务程序处理已有连接的缓冲机会,所以很多防火墙上推荐打开它)
tcp_syncookies 0 只有在内核编译时选择了CONFIG_SYNCOOKIES时才会发生作用。当出现syn等候队列出现溢出时象对方发送syncookies。目的是为了防止syn flood攻击。
tcp_stdurg 0 使用 TCP urg pointer 字段中的主机请求解释功能。大部份的主机都使用老旧的 BSD解释,因此如果您在 Linux打开它﹐或会导致不能和它们正确沟通。

等等。

所处目录/proc/sys/net/ipv4/netfilter/
文件需要打开防火墙才会存在

名称 默认值 描述
ip_conntrack_max 65536 系统支持的最大ipv4连接数,默认65536(事实上这也是理论最大值),同时这个值和你的内存大小有关,如果内存128M,这个值最大8192,1G以上内存这个值都是默认65536,这个值受/proc/sys/net/ipv4/ip_conntrack_max限制
ip_conntrack_tcp_timeout_established 432000 已建立的tcp连接的超时时间,默认432000,也就是5天。影响:这个值过大将导致一些可能已经不用的连接常驻于内存中,占用大量链接资源,从而可能导致NAT ip_conntrack: table full的问题。建议:对于NAT负载相对本机的 NAT表大小很紧张的时候,可能需要考虑缩小这个值,以尽早清除连接,保证有可用的连接资源;如果不紧张,不必修改
ip_conntrack_tcp_timeout_time_wait 120 time_wait状态超时时间,超过该时间就清除该连接
ip_conntrack_tcp_timeout_close_wait 60 close_wait状态超时时间,超过该时间就清除该连接
ip_conntrack_tcp_timeout_fin_wait 120 fin_wait状态超时时间,超过该时间就清除该连接

等等。

文件所处目录/proc/sys/net/core/

名称 默认值 描述
netdev_max_backlog 1024 每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目,对重负载服务器而言,该值需要调高一点。
somaxconn 128 用来限制监听(LISTEN)队列最大数据包的数量,超过这个数量就会导致链接超时或者触发重传机制。web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值。对繁忙的服务器,增加该值有助于网络性能
wmem_default 129024 默认的发送窗口大小(以字节为单位)
rmem_default 129024 默认的接收窗口大小(以字节为单位)
rmem_max 129024 最大的TCP数据接收缓冲
wmem_max 129024 最大的TCP数据发送缓冲

等等。

你可能感兴趣的:(linux 操作系统启动过程和内核参数修改添加方法)