系统启动 之 Linux系统启动概述(2)


博客:http://blog.csdn.net/younger_china/article/details/51615916


Linu系统启动是一个”冗长乏味”的过程,那么我们现就需要去经历一下这个冗长乏味的生活。我们按照如下流程来分析:

 


1. 史前时代:BIOS

计算机在上电那一刻几乎是毫无用处的,此时,RAM中包含的全部是随机数据。

在开始启动时,一个特殊的硬件电路在CPU的一个引脚上产生一个RESET逻辑值,在RESET产生之后,就把处理器的一些寄存器设置成固定的值,并执行在物理地址0xFFFFFFF0处找到的代码(Younger注:该代码我称之为BIOS代码)。硬件会把这个地址映射到某个只读、持久的存储芯片中,该芯片被称为ROM(即:Read-Only Memory)。

Linux一旦进入实模式,就不再使用BIOS,而是linux本身为计算机上的每个硬件设备提供各自的设备驱动程序。实际上,因为BIOS过程必须在实模式下运行,而内核在保护模式下运行,所以即使在二者之间共享函数是有益的,也不能共享。

BIOS是采用实模式寻址的,因为在上电启动时,计算机只能寻址这么大的地址空间(请参阅实模式与保护模式的区别)。实模式地址由一个segment段和一个offset偏移量组成.。相应的物理地址样计算方法:segment*16 + offset。此时,CPU寻址电路不需要全局描述表(GDT)、局部描述表(LDT)和页表(PT)。显然,对GDT,LDT和PT进行初始化的代码必须在实模式下运行。

那么在BIOS阶段,都是做了哪些工作哪?.BIOS启动过程实际上执行一下4个操作:

1. 上电自检:对计算机硬件执行一系列的测试,用来检测现在都有什么设备以及这些设备是否正常工作,这个阶段通常称为POST(上电自检)。这个阶段中,会显示一些信息,如BIOS版本号等。

2. 初始化硬件设备:这个阶段在现代基于PCI的体系机构中相当重要,因为它可以保证所有的硬件设备操作不会引起IRQ线与I/O端口的冲突。在本阶段的最后,会显示系统中所安装的所有PCI设备的一个列表。(实际上,由BIOS扫描的一系列设备数据都会被内存引用,尤其是在PCI扫描的过程,一般只是对 BIOS扫描结果后的一种确认,而内核也一般不需要过多地重新扫描PCI资源)。

3. 搜索一个操作系统来启动:实际上,根据BIOS的设置,这个过程可能要试图访问系统中的软盘,硬盘和CDROM等设备的第一个扇区。

4. 装载代码(引导程序):只要找到一个有效的设备,就把第一个扇区的内容拷贝到RAM中从物理地址0x00007c00(X86)0x00008000(ARM)开始的位置,然后跳转到这个地址处,开始执行刚才转载进来的代码。

head-y          := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o

textofs-y       := 0x00008000

 

2. 远古时代:BootLoader

引导装入程序(Bootloader)是BIOS将操作系统内核映像装载到RAM中执行的第一个程序。

软盘启动与磁盘启动过程稍有不同,仅此处仅仅分析磁盘启动方式。

从硬盘启动时,硬盘的第一个扇区MBR(Master Boot Record)中包含分区表和一小段程序,这段小程序用来装载被启动的操作系统所在分区的第一个扇区的内容。针对Linux系统,第一个扇区中存放的是bootloader,可以允许用户选择要启动的操作系统。

从磁盘启动linux内核,Bootloader通被BIOS加载到RAM的0x00008000处开始执行。

Bootloader的主要执行过程:

1. 初始化 RAM:因为 Linux 内核一般都会在 RAM 中运行,所以在调用 Linux 内核之前 bootloader 必须设置和初始化 RAM,为调用 Linux内核做好准备。初始化 RAM 的任务包括设置CPU 的控制寄存器参数,以便能正常使用 RAM 以及检测RAM 大小等。

2. 初始化串口:串口在 Linux 的启动过程中有着非常重要的作用,它是 Linux内核和用户交互的方式之一。Linux 在启动过程中可以将信息通过串口输出,这样便可清楚的了解 Linux 的启动过程。虽然它并不是 Bootloader 必须要完成的工作,但是通过串口输出信息是调试Bootloader 和Linux 内核的强有力的工具,所以一般的 Bootloader 都会在执行过程中初始化一个串口做为调试端口。

3. 检测处理器类型:Bootloader在调用 Linux内核前必须检测系统的处理器类型,并将其保存到某个常量中提供给 Linux 内核。Linux 内核在启动过程中会根据该处理器类型调用相应的初始化程序。

4. 设置 Linux启动参数:Bootloader在执行过程中必须设置和初始化 Linux 的内核启动参数。

5. 调用 Linux内核映像:Bootloader完成的最后一项工作便是调用 Linux内核。如果 Linux 内核存放在 Flash 中,并且可直接在上面运行(该 Flash 指 Nor Flash),那么可直接跳转到内核中去执行。但由于在 Flash 中执行代码会有种种限制,而且速度也远不及RAM 快,所以一般的嵌入式系统都是将 Linux内核拷贝到 RAM 中,然后跳转到 RAM 中去执行,不论哪种情况,在跳到 Linux 内核执行之前 CPU的寄存器必须满足以下条件:r0=0,r1=处理器类型,r2=标记列表在 RAM中的地址。

 

3. 内核启动

 

3.1            原始时代:加载内核

在 bootloader将 Linux 内核映像拷贝到 RAM 以后,可以通过下例代码启动 Linux 内核: 

call_linux(0, machine_type, kernel_params_base)。 

其中,machine_tpye 是 bootloader检测出来的处理器类型, kernel_params_base 是启动参 数在 RAM 的地址。通过这种方式将 Linux 启动需要的参数从 bootloader传递到内核。 

Linux 内核有两种映像:一种是非压缩内核,叫 Image,另一种是它的压缩版本,叫 zImage。

根据内核映像的不同,Linux 内核的启动在开始阶段也有所不同。zImage 是 Image 经过压缩形成的,所以它的大小比 Image 小。但为了能使用 zImage,必须在它的开头加上解压缩的代码,将 zImage 解压缩之后才能执行,因此它的执行速度比 Image 要慢。但考虑 到嵌入式系统的存储空容量一般比较小,采用 zImage 可以占用较少的存储空间,因此牺牲一点性能上的代价也是值得的。所以一般的嵌入式系统均采用压缩内核的方式。

对于 ARM 系列处理器来说,zImage 的入口程序即为 arch/arm/boot/compressed/head.S。 它依次完成以下工作:开启 MMU 和Cache,调用 decompress_kernel()解压内核,最后通过 调用 call_kernel()进入非压缩内核 Image 的启动。下面将具体分析在此之后 Linux 内核的启 动过程。 

3.2            封建时代:Linux内核入口 

Linux 非压缩内核的入口位于文件/arch/arm/kernel/head-armv.S 中的 stext 段。该段的基 地址就是压缩内核解压后的跳转地址。如果系统中加载的内核是非压缩的 Image,那么 bootloader将内核从 Flash中拷贝到 RAM 后将直接跳到该地址处,从而启动 Linux 内核。 不同体系结构的 Linux 系统的入口文件是不同的,而且因为该文件与具体体系结构有 关,所以一般均用汇编语言编写[3] 。对基于 ARM 处理的 Linux 系统来说,该文件就是 head-armv.S。该程序通过查找处理器内核类型和处理器类型调用相应的初始化函数,再建立页表,最后跳转到 start_kernel()函数开始内核的初始化工作。 

检测处理器内核类型是在汇编子函数__lookup_processor_type中完成的。通过以下代码 可实现对它的调用: bl __lookup_processor_type。 __lookup_processor_type调用结束返回原程序时,会将返回结果保存到寄存器中。其中 r8保存了页表的标志位,r9 保存了处理器的 ID 号,r10 保存了与处理器相关的 stru proc_info_list 结构地址。 检测处理器类型是在汇编子函数 __lookup_architecture_type 中完成的。与 __lookup_processor_type类似,它通过代码:“bl __lookup_processor_type”来实现对它的调 用。该函数返回时,会将返回结构保存在 r5、r6 和 r7 三个寄存器中。其中 r5 保存了 RAM 的起始基地址,r6 保存了 I/O基地址,r7 保存了 I/O的页表偏移地址。 

当检测处理器内核和处理器类型结束后,将调用__create_page_tables 子函数来建立页 表,它所要做的工作就是将RAM 基地址开始的 4M 空间的物理地址映射到 0xC0000000 开 始的虚拟地址处。当所有的初始化结束之后,使用如下代码来跳到C程序的入口函数 start_kernel()处,开始之后的内核初始化工作:

 b SYMBOL_NAME(start_kernel) 

 

3.3            近代:start_kernel函数 

start_kernel是所有 Linux 平台进入系统内核初始化后的入口函数,它主要完成剩余的与 硬件平台相关的初始化工作,在进行一系列与内核相关的初始化后,调用第一个用户进程- init 进程并等待用户进程的执行,这样整个 Linux 内核便启动完毕。该函数所做的具体工作 
有[4][5] : 

1) 调用 setup_arch()函数进行与体系结构相关的第一个初始化工作; 对不同的体系结构来说该函数有不同的定义。对于 ARM 平台而言,该函数定义在 arch/arm/kernel/Setup.c。它首先通过检测出来的处理器类型进行处理器内核的初始化,然后 通过 bootmem_init()函数根据系统定义的 meminfo 结构进行内存结构的初始化,最后调用 paging_init()开启MMU,创建内核页表,映射所有的物理内存和 IO空间。 

2) 创建异常向量表和初始化中断处理函数; 

3) 初始化系统核心进程调度器和时钟中断处理机制;

4) 初始化串口控制台(serial-console); 

ARM-Linux 在初始化过程中一般都会初始化一个串口做为内核的控制台,这样内核在 启动过程中就可以通过串口输出信息以便开发者或用户了解系统的启动进程。 

5) 创建和初始化系统 cache,为各种内存调用机制提供缓存,包括;动态内存分配,虚拟文 件系统(VirtualFile System)及页缓存。 

6) 初始化内存管理,检测内存大小及被内核占用的内存情况;

7) 初始化系统的进程间通信机制(IPC); 

当以上所有的初始化工作结束后,start_kernel()函数会调用 rest_init()函数来进行最后的 

初始化,包括创建系统的第一个进程-init 进程来结束内核的启动。Init 进程首先进行一系列的硬件初始化,然后通过命令行传递过来的参数挂载根文件系统。最后 init 进程会执行用户传递过来的“init=”启动参数执行用户指定的命令,或者执行以下几个进程之一: 

execve("/sbin/init",argv_init,envp_init); 

execve("/etc/init",argv_init,envp_init); 

execve("/bin/init",argv_init,envp_init); 

execve("/bin/sh",argv_init,envp_init)。 

当所有的初始化工作结束后,cpu_idle()函数会被调用来使系统处于闲置(idle)状态并等待用户程序的执行。至此,整个 Linux 内核启动完毕。

 

4.      参考文献

1.  《深入理解linux内核》



 

Linu系统启动是一个冗长乏味的过程,那么我们现就需要去经历一下这个冗长乏味的生活。我们按照如下流程来分析:

 

1. 史前时代:BIOS

计算机在上电那一刻几乎是毫无用处的,此时,RAM中包含的全部是随机数据。

在开始启动时,一个特殊的硬件电路在CPU的一个引脚上产生一个RESET逻辑值,在RESET产生之后,就把处理器的一些寄存器设置成固定的值,并执行在物理地址0xFFFFFFF0处找到的代码(Younger注:该代码我称之为BIOS代码)。硬件会把这个地址映射到某个只读、持久的存储芯片中,该芯片被称为ROM(即:Read-Only Memory)

Linux一旦进入实模式,就不再使用BIOS,而是linux本身为计算机上的每个硬件设备提供各自的设备驱动程序。实际上,因为BIOS过程必须在实模式下运行,而内核在保护模式下运行,所以即使在二者之间共享函数是有益的,也不能共享。

BIOS是采用实模式寻址的,因为在上电启动时,计算机只能寻址这么大的地址空间(请参阅实模式与保护模式的区别)。实模式地址由一个segment段和一个offset偏移量组成.。相应的物理地址样计算方法:segment16 + offset。此时,CPU寻址电路不需要全局描述表(GDT)、局部描述表(LDT)和页表(PT)。显然,对GDT,LDTPT进行初始化的代码必须在实模式下运行。

那么在BIOS阶段,都是做了哪些工作哪?.BIOS启动过程实际上执行一下4个操作:

1. 上电自检:对计算机硬件执行一系列的测试,用来检测现在都有什么设备以及这些设备是否正常工作,这个阶段通常称为POST(上电自检)。这个阶段中,会显示一些信息,如BIOS版本号等。

2. 初始化硬件设备:这个阶段在现代基于PCI的体系机构中相当重要,因为它可以保证所有的硬件设备操作不会引起IRQ线与I/O端口的冲突。在本阶段的最后,会显示系统中所安装的所有PCI设备的一个列表。(实际上,由BIOS扫描的一系列设备数据都会被内存引用,尤其是在PCI扫描的过程,一般只是对 BIOS扫描结果后的一种确认,而内核也一般不需要过多地重新扫描PCI资源)

3. 搜索一个操作系统来启动:实际上,根据BIOS的设置,这个过程可能要试图访问系统中的软盘,硬盘和CDROM等设备的第一个扇区。

4. 装载代码(引导程序)只要找到一个有效的设备,就把第一个扇区的内容拷贝到RAM中从物理地址0x00007c00(X86)0x00008000ARM开始的位置,然后跳转到这个地址处,开始执行刚才转载进来的代码。

head-y          := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o

textofs-y       := 0x00008000

 

2. 远古时代:BootLoader

引导装入程序(Bootloader)是BIOS将操作系统内核映像装载到RAM中执行的第一个程序。

软盘启动与磁盘启动过程稍有不同,仅此处仅仅分析磁盘启动方式。

从硬盘启动时,硬盘的第一个扇区MBRMaster Boot Record)中包含分区表和一小段程序,这段小程序用来装载被启动的操作系统所在分区的第一个扇区的内容。针对Linux系统,第一个扇区中存放的是bootloader,可以允许用户选择要启动的操作系统。

从磁盘启动linux内核,Bootloader通被BIOS加载到RAM0x00008000处开始执行。

Bootloader的主要执行过程:

1. 初始化 RAM因为 Linux 内核一般都会在 RAM 中运行,所以在调用 Linux 内核之前 bootloader 必须设置和初始化 RAM,为调用 Linux内核做好准备。初始化 RAM 的任务包括设置CPU 的控制寄存器参数,以便能正常使用 RAM 以及检测RAM 大小等。

2. 初始化串口:串口在 Linux 的启动过程中有着非常重要的作用,它是 Linux内核和用户交互的方式之一。Linux 在启动过程中可以将信息通过串口输出,这样便可清楚的了解 Linux 的启动过程。虽然它并不是 Bootloader 必须要完成的工作,但是通过串口输出信息是调试Bootloader Linux 内核的强有力的工具,所以一般的 Bootloader 都会在执行过程中初始化一个串口做为调试端口。

3. 检测处理器类型Bootloader在调用 Linux内核前必须检测系统的处理器类型,并将其保存到某个常量中提供给 Linux 内核。Linux 内核在启动过程中会根据该处理器类型调用相应的初始化程序。

4. 设置 Linux启动参数:Bootloader在执行过程中必须设置和初始化 Linux 的内核启动参数。

5. 调用 Linux内核映像:Bootloader完成的最后一项工作便是调用 Linux内核。如果 Linux 内核存放在 Flash 中,并且可直接在上面运行(该 Flash  Nor Flash),那么可直接跳转到内核中去执行。但由于在 Flash 中执行代码会有种种限制,而且速度也远不及RAM 快,所以一般的嵌入式系统都是将 Linux内核拷贝到 RAM 中,然后跳转到 RAM 中去执行,不论哪种情况,在跳到 Linux 内核执行之前 CPU的寄存器必须满足以下条件:r00r1=处理器类型,r2=标记列表在 RAM中的地址。

 

3. 内核启动

 

3.1            原始时代:加载内核

 bootloader Linux 内核映像拷贝到 RAM 以后,可以通过下例代码启动 Linux 内核: 

call_linux(0, machine_type, kernel_params_base) 

其中,machine_tpye  bootloader检测出来的处理器类型, kernel_params_base 是启动参 数在 RAM 的地址。通过这种方式将 Linux 启动需要的参数从 bootloader传递到内核。 

Linux 内核有两种映像:一种是非压缩内核,叫 Image,另一种是它的压缩版本,叫 zImage

根据内核映像的不同,Linux 内核的启动在开始阶段也有所不同。zImage  Image 经过压缩形成的,所以它的大小比 Image 小。但为了能使用 zImage,必须在它的开头加上解压缩的代码,将 zImage 解压缩之后才能执行,因此它的执行速度比 Image 要慢。但考虑 到嵌入式系统的存储空容量一般比较小,采用 zImage 可以占用较少的存储空间,因此牺牲一点性能上的代价也是值得的。所以一般的嵌入式系统均采用压缩内核的方式。

对于 ARM 系列处理器来说,zImage 的入口程序即为 arch/arm/boot/compressed/head.S 它依次完成以下工作:开启 MMU Cache,调用 decompress_kernel()解压内核,最后通过 调用 call_kernel()进入非压缩内核 Image 的启动。下面将具体分析在此之后 Linux 内核的启 动过程。 

3.2            封建时代:Linux内核入口 

Linux 非压缩内核的入口位于文件/arch/arm/kernel/head-armv.S 中的 stext 段。该段的基 地址就是压缩内核解压后的跳转地址。如果系统中加载的内核是非压缩的 Image,那么 bootloader将内核从 Flash中拷贝到 RAM 后将直接跳到该地址处,从而启动 Linux 内核。 不同体系结构的 Linux 系统的入口文件是不同的,而且因为该文件与具体体系结构有 关,所以一般均用汇编语言编写[3] 。对基于 ARM 处理的 Linux 系统来说,该文件就是 head-armv.S。该程序通过查找处理器内核类型和处理器类型调用相应的初始化函数,再建立页表,最后跳转到 start_kernel()函数开始内核的初始化工作。 

检测处理器内核类型是在汇编子函数__lookup_processor_type中完成的。通过以下代码 可实现对它的调用: bl __lookup_processor_type __lookup_processor_type调用结束返回原程序时,会将返回结果保存到寄存器中。其中 r8保存了页表的标志位,r9 保存了处理器的 ID 号,r10 保存了与处理器相关的 stru proc_info_list 结构地址。 检测处理器类型是在汇编子函数 __lookup_architecture_type 中完成的。与 __lookup_processor_type类似,它通过代码:“bl __lookup_processor_type”来实现对它的调 用。该函数返回时,会将返回结构保存在 r5r6  r7 三个寄存器中。其中 r5 保存了 RAM 的起始基地址,r6 保存了 I/O基地址,r7 保存了 I/O的页表偏移地址。 

当检测处理器内核和处理器类型结束后,将调用__create_page_tables 子函数来建立页 表,它所要做的工作就是将RAM 基地址开始的 4M 空间的物理地址映射到 0xC0000000  始的虚拟地址处。当所有的初始化结束之后,使用如下代码来跳到C程序的入口函数 start_kernel()处,开始之后的内核初始化工作:

 b SYMBOL_NAME(start_kernel) 

 

3.3            近代:start_kernel函数 

start_kernel是所有 Linux 平台进入系统内核初始化后的入口函数,它主要完成剩余的与 硬件平台相关的初始化工作,在进行一系列与内核相关的初始化后,调用第一个用户进程- init 进程并等待用户进程的执行,这样整个 Linux 内核便启动完毕。该函数所做的具体工作 
[4][5]  

1) 调用 setup_arch()函数进行与体系结构相关的第一个初始化工作; 对不同的体系结构来说该函数有不同的定义。对于 ARM 平台而言,该函数定义在 arch/arm/kernel/Setup.c。它首先通过检测出来的处理器类型进行处理器内核的初始化,然后 通过 bootmem_init()函数根据系统定义的 meminfo 结构进行内存结构的初始化,最后调用 paging_init()开启MMU,创建内核页表,映射所有的物理内存和 IO空间。 

2) 创建异常向量表和初始化中断处理函数; 

3) 初始化系统核心进程调度器和时钟中断处理机制;

4) 初始化串口控制台(serial-console); 

ARM-Linux 在初始化过程中一般都会初始化一个串口做为内核的控制台,这样内核在 启动过程中就可以通过串口输出信息以便开发者或用户了解系统的启动进程。 

5) 创建和初始化系统 cache,为各种内存调用机制提供缓存,包括;动态内存分配,虚拟文 件系统(VirtualFile System)及页缓存。 

6) 初始化内存管理,检测内存大小及被内核占用的内存情况;

7) 初始化系统的进程间通信机制(IPC); 

当以上所有的初始化工作结束后,start_kernel()函数会调用 rest_init()函数来进行最后的 

初始化,包括创建系统的第一个进程-init 进程来结束内核的启动。Init 进程首先进行一系列的硬件初始化,然后通过命令行传递过来的参数挂载根文件系统。最后 init 进程会执行用户传递过来的“init启动参数执行用户指定的命令,或者执行以下几个进程之一: 

execve("/sbin/init",argv_init,envp_init); 

execve("/etc/init",argv_init,envp_init); 

execve("/bin/init",argv_init,envp_init); 

execve("/bin/sh",argv_init,envp_init) 

当所有的初始化工作结束后,cpu_idle()函数会被调用来使系统处于闲置(idle)状态并等待用户程序的执行。至此,整个 Linux 内核启动完毕。

 

4.      参考文献

1.  《深入理解linux内核》



 

转载于:https://www.cnblogs.com/youngerchina/p/5624441.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573458.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 全文搜索 句子_python新玩法:用python进行文章摘要拿取,只需要一行代码

前言今天为大家介绍一个python算法TextRank,实现从长篇中快速抽取精准摘要。TextRank是一种基于图形的文本处理排序算法。PageRank通常用作其底层的图排序模型。当然,其他的图排序模型也可以与之结合。TextRank算法不需要深入的语言和专业知识,因为它是一…

Django小项目简单BBS论坛

开发一个简单的BBS论坛项目需求:1 整体参考“抽屉新热榜” + “虎嗅网” 2 实现不同论坛版块 3 帖子列表展示 4 帖子评论数、点赞数展示 5 在线用户展示 6 允许登录用户发贴、评论、点赞 7 允许上传文件 8 帖子可被置顶 9 可进行多级评论知识必备&#x…

时间转年月日_编程中常见的时间格式

时间格式前端和后端时经常会遇到各种各样的时间格式,这些格式在编写程序的时候都需要去使用不同的处理方式,这里集中写一下。先说一下各种不同的时间格式。类型名格式说明ISO 8601一般:2020-12-05T05:33:19Z 东八区:2004-05-03T17…

外星人台式机无盘服务器,可以拎走的“台式机” Alienware Area-51m评测

Alienware外星人这个品牌曾经一度是游戏笔记本领域的执牛耳者,自从1996年创立以来,品牌宗旨就是提供最强的PC性能,最有个性的设计和最好的服务。凭借着强悍的配置、创新的黑科技和酷炫的灯效,其一度是业内高端和高品质的代名词。但…

法流程图_世界五大学习方法之西蒙学习法

世界五大学习方法之西蒙学习法摘要:西蒙学习法为6个月可以掌握任何一门学问,它的本质是广义动量定理。广义动量定理通过调整力量、方向、作用点和时间来增加成果。西蒙学习法使用了降低问题难度方法中的一种:拆分。本节分为四个部分&#xff…

生成word_Word如何生成目录?3个步骤轻松掌握!

在使用Word编写长篇文档时,我们经常会给内容生成一个目录,有了目录,无论是阅读还是查找内容,都非常方便。Word生成目录是一项核心功能,这是每个使用Word的人,必须要掌握的一项技巧。如果你还不会这项技巧&a…

启动go服务_内网穿透工具 FRP公网服务端、内网客户端快速配置文件说明

内网穿透工具 FRP 公网服务端、内网客户端 frps.ini 、frpc.ini 配置文件常用设置展示及说明公网服务端 frps.ini 配置文件常用设置公网服务端配置文件:frps.ini[common]bind_port 7000# vhost_http_port 参数来设置 HTTP 访问端口,此处示例&#xff1a…

设置dns_2019让你的网速飞起来,你需要……设置正确DNS服务篇

有时候上网明明网络连接正常,但网页访问却很慢?平时会不会经常听到一些老司机说,网络很慢啊可以修改一下DNS啊!什么是DNS?又为什么会对网速产生影响呢?跟着小编的教程一起来学习一下吧~PART 1 什么是DNS&am…

5 随窗口改变大小_C4D默认界面两个关于坐标轴的窗口有什么区别

前言在一开始学习C4D的时候,就有这个疑问,为什么明明物体的属性都有了一个坐标属性的窗口了,还要有一个和坐标相关的窗口在默认的界面呢,后边在使用的过程中才慢慢理解了额外的坐标管理器窗口的作用,这一篇文章我们来看…

MySQL数据查询新人须知

MySQL 是一个开放源码的小型关系型数据库管理系统。 针对不同的用户,MySQL 一共分为两个不同的版本: MySQL Community Server(社区版服务器)。 MySQL Enterprise Server(企业版服务器)。 目前 Internet …

(硬 核)Navicat for MySQL 介 绍( 入 门 须 知 )

Navicat for MySQL 是一款流行的 MySQL 图形化管理工具以下是 Navicat for MySQL 工作界面使用 Navicat for MySQL 连接 MySQL 服务器鼠标左键单击“连接”按钮,出现“新建连接”窗口。分别输入连接名、MySQL 服务器主机地址、服务 端口号、用户名和密码&#xff0c…

小明一家过桥_【练习】用python解决小明一家过桥问题

import randomlist1[] #存放所有遍历的结果#等待过桥的人员bridge1{小明:1,弟弟:3,爸爸:6,妈妈:8,爷爷:12}#过桥后的人员bridge2{}#判断未过桥的人是否空了(全部过完后,程序停止,看总共用了多长时间)len1len(bridge1)print(len1)#while True:print(初始情…

WGZX:javaScript 学习心得--1

标签: javascriptiframedreamweaver浏览器htmltable2008-09-11 10:50 1071人阅读 评论(0) 收藏 举报分类:UI(21) 1,document.getElementById方法只能获取到一个对象,即使有多个同名的对象,也只取…

PHP----练习-----新闻管理----增删改查

练习-----新闻管理 题目要求如下&#xff1a; 做法&#xff1a; 【1】建数据库 【2】封装类文件--------DBDA.class.php 1 <?php2 class DBDA3 {4 public $fuwuqi"localhost"; //服务器地址5 public $yonghuming"root";//用户名6 public …

mysql query cache 关闭_为什么要关闭MySQL query cache-Fun言

MySQL的query cache大部分情况下其实只是鸡肋而已&#xff0c;建议全面禁用。当然了&#xff0c;或许在你的场景下还是挺好的&#xff0c;还能发挥作用&#xff0c;那就继续使用吧&#xff0c;把本文当做参考就好。不过&#xff0c;可能有的人人为只需要把 query_cache_size 大…

Java 基础之java运算符

运算符&#xff0c;顾名思义就是用于计算的符号。按功能分为&#xff1a;赋值运算符、算术运算符、关系运算符和逻辑运算符按操作数的个数分类&#xff1a;单目运算符、双目运算符、三目运算符运算符的目&#xff1a;运算符能连接操作数的个数称为运算符的目运算符的优先级&…

直流电机调速仿真作业

本次调速仿真采用PID调节。首先要确定PID中的各项设计参数&#xff0c;仿真过程中采用临界比例度法确定了大概的Kp值。在若干次调整的过程中&#xff0c;发现加入微分环节后调整时间略有上升&#xff0c;故采用PI调节。调整参数确定为Kp75,Ki22。控制器部分的程序如下图所示。原…

Java运算符优先级和表达式及数据类型转换

计算机程序在处理数据时会进行大量的计算&#xff0c;而数据的运算则需要借助运算符和表达式来完成。表达式是指由操作数和运算符组成的用于完成某种运算功能的语句子表达式Y X * ( Z 10 ) 表达式 其中Y、X、Z、10 称为操作数&#xff0c;、*、 称为运算符。 在…

Bugtags 2016-06-16 更新内容

增加版本管理功能 随着版本的增多&#xff0c;有些历史的版本不再使用&#xff0c;可将这些版本隐藏起来。操作步骤如下&#xff1a;点击设置 - 版本管理&#xff08;管理员可见&#xff09;- 取消勾选需要隐藏的版本即可。隐藏版本后&#xff0c;版本筛选中将不会显示&#xf…

直通车运营系统优化之账户结构设置

国庆期间&#xff0c;小2哥我好好的享受了好几天的日子&#xff0c;说实话&#xff0c;自从做了淘宝&#xff0c;就很少像这期间一样好好的享受了这段日子 。做淘宝有时候真的很苦逼&#xff0c;每天的工作时间比一个打工的还长&#xff0c;熬夜到凌晨才睡也是家常便饭&#xf…