Linux移植之內核啟動過程引導階段分析

在Linux移植之make uImage編譯過程分析中已經提到了uImage是一個壓縮的包并且內含壓縮程序,可以進行自解壓。自解壓完成之后內核代碼從物理地址為0x30008000處開始運行。下面分析在進入C之前內核做的一些工作,以下是內核啟動過程中打印出來的信息,其中Uncompressing Linux就是在自解壓代碼。make uImage編譯的最后也給出了鏈接腳本arch/arm/kernel/vmlinux.lds,以及鏈接的順序arch/arm/kernel/head.o?是第一個。

?

分析arch/arm/kernel/vmlinux.lds可以知道程序入口的地址是stext,并且是.text.head段

277    OUTPUT_ARCH(arm)
278    ENTRY(stext)291    . = (0xc0000000) + 0x00008000;
292
293    .text.head : {
294    _stext = .;
295    _sinittext = .;
296    *(.text.head)
297    }

打開arch/arm/kernel/head.s。可見內核運行的第一條代碼就是第79行的代碼,從這條開始分析,首先將CPU設置為管理模式,并且關閉所有中斷;然后獲得CPU的id。

76        .section ".text.head", "ax" //.text.head段
77        .type    stext, %function
78    ENTRY(stext)                    //入口地址stext
79        msr    cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode//確保進入了管理模式
80                            @ and irqs disabled                                     //并且禁止中斷
81        mrc    p15, 0, r9, c0, c0        @ get processor id                               //獲得處理器的CPU id,并且存入 r9中
82        bl    __lookup_processor_type        @ r5=procinfo r9=cpuid           //調用函數,輸入參數r9=cpuid。返回值r5=procinfo
83        movs    r10, r5                @ invalid processor (r5=0)?//如果不支持當前CPU,則r5=0
84        beq    __error_p            @ yes, error 'p'                              //如果r5=0,則打印錯誤
85        bl    __lookup_machine_type        @ r5=machinfo          //調用函數,r5=返回值machinfo
86        movs    r8, r5                @ invalid machine (r5=0)?  //如果不支持當前單板,則返回r5=0
87        beq    __error_a            @ yes, error 'a'               //如果r5=0,則打印錯誤
88        bl    __create_page_tables//創建一級頁表以建立虛擬地址到物理地址的映射關系,后面再研究

接著調用__lookup_processor_type,它位于arch\arm\kernel\head-common.S。它的功能是比較當前CPU的id與內核支持的CPU的id是否相符合。這段代碼在.proc.info.init段中從__proc_info_begin開始到__proc_info_end結束,尋找符合當前CPU的ID號的proc_info_list結構

145        .type    __lookup_processor_type, %function
146    __lookup_processor_type:
147        adr    r3, 3f                        //r3 = 第178行代碼的物理地址
148        ldmda    r3, {r5 - r7}      //將r3地址開始的3個地址的內容賦給 r5、r6、r7 ;r5=__proc_info_begin,r6=__proc_info_end
149        sub    r3, r3, r7            @ get offset between virt&phys//r3=r3-r7,即物理地址與虛擬地址的差值
150        add    r5, r5, r3            @ convert virt addresses to//r5=__proc_info_begind對應的物理地址
151        add    r6, r6, r3            @ physical address space   //r6=__proc_info_end對應的物理地址
152    1:    ldmia    r5, {r3, r4}            @ value, mask//r3、r4等于proc_info_list結構中的cpu_val、cpu_mask
153        and    r4, r4, r9            @ mask wanted bits//r4=r4&r9=cpu_mask&傳入的cpuid
154        teq    r3, r4                                                    //比較
155        beq    2f                                                        //如果相等,則找到對應的proc_info_list結構,跳到160行
156        add    r5, r5, #PROC_INFO_SZ        @ sizeof(proc_info_list)//r5指向下一個proc_info_list結構
157        cmp    r5, r6                                                   //是否已經比較完所有proc_info_list
158        blo    1b                                                       //沒有則繼續比較
159        mov    r5, #0                @ unknown processor//比較完畢,但是沒有找到匹配的proc_info_list結構,r5=0
160    2:    mov    pc, lr//返回,返回的值為r5=proc_info_list176        .long    __proc_info_begin
177        .long    __proc_info_end
178    3:    .long    .//.表示當前這條代碼鏈接后的虛擬地址
179        .long    __arch_info_begin
180        .long    __arch_info_end

其中__proc_info_begin、__proc_info_end被定義在arch\arm\kernel\vmlinux.lds中,它的意思是內核源碼中有被定義為.proc.info.init的內容,它的起始地址是__proc_info_begin,結束地址為__proc_info_end。

299     .init : { /* Init code and data        */
230       *(.init.text)
231      _einittext = .;
232      __proc_info_begin = .;
233       *(.proc.info.init)
234      __proc_info_end = .;

接著看到proc_info_list結構的內容,它被定義在include\asm-arm\Procinfo.h中

29    struct proc_info_list {
30        unsigned int        cpu_val;      
31        unsigned int        cpu_mask;
32        unsigned long        __cpu_mm_mmu_flags;    /* used by head.S */
33        unsigned long        __cpu_io_mmu_flags;    /* used by head.S */
34        unsigned long        __cpu_flush;        /* used by head.S */
35        const char        *arch_name;
36        const char        *elf_name;
37        unsigned int        elf_hwcap;
38        const char        *cpu_name;
39        struct processor    *proc;
40        struct cpu_tlb_fns    *tlb;
41        struct cpu_user_fns    *user;
42        struct cpu_cache_fns    *cache;
43    };

接著找到對于當前內核支持的proc_info_list 定義,它在arch\arm\mm\proc-arm920.S 中。對于S3C2410、S3C2440芯片來說CPU ID都是0x41129200。cpu_val的值為0x41009200、cpu_mask的值為0xff00fff0,剛好匹配。

    .section ".proc.info.init", #alloc, #execinstr448        .type    __arm920_proc_info,#object
449    __arm920_proc_info:
450        .long    0x41009200//cpu_val值
451        .long    0xff00fff0//cpu_mask值
452        .long   PMD_TYPE_SECT | \
453            PMD_SECT_BUFFERABLE | \
454            PMD_SECT_CACHEABLE | \
455            PMD_BIT4 | \
456            PMD_SECT_AP_WRITE | \
457            PMD_SECT_AP_READ
458        .long   PMD_TYPE_SECT | \
459            PMD_BIT4 | \
460            PMD_SECT_AP_WRITE | \
461            PMD_SECT_AP_READ
462        b    __arm920_setup
463        .long    cpu_arch_name
464        .long    cpu_elf_name
465        .long    HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
466        .long    cpu_arm920_name
467        .long    arm920_processor_functions
468        .long    v4wbi_tlb_fns
469        .long    v4wb_user_fns
470    #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
471        .long    arm920_cache_fns
472    #else
473        .long    v4wt_cache_fns
474    #endif
475        .size    __arm920_proc_info, . - __arm920_proc_info

繼續回到arch/arm/kernel/head.s往下分析,看到第83行,調用完__lookup_processor_type后r5的值變為執向找到的proc_info_list 結構的地址。所以第83行與第84行比較r5是否為0,如果為0說明沒有找到符合當前CPU的ID號,則打印錯誤。接著到85行,調用__lookup_machine_type,它同樣位于arch\arm\kernel\head-common.S中,它的功能是比較當前單板的id與內核支持的單板的id是否相符合。這段代碼在.arch.info.init段中從__arch_info_begin開始到__arch_info_end結束,尋找符合當前單板的ID號的machine_desc結構

176        .long    __proc_info_begin
177        .long    __proc_info_end
178    3:    .long    .//.表示當前這條代碼鏈接后的虛擬地址
179        .long    __arch_info_begin
180        .long    __arch_info_end193        .type    __lookup_machine_type, %function
194    __lookup_machine_type:
195        adr    r3, 3b                   //r3=第178行的物理地址
196        ldmia    r3, {r4, r5, r6}     //r4=r3。r5=__proc_info_end,r6=__proc_info_begin,取得的是虛擬地址
197        sub    r3, r3, r4            @ get offset between virt&phys//r3=r3-r4,取得物理地址與虛擬地址的偏差
198        add    r5, r5, r3            @ convert virt addresses to//r5=r5+r3,取得物理地址__proc_info_end
199        add    r6, r6, r3            @ physical address space   //r6=r6+r3,取得物理地址__proc_info_begin
200    1:    ldr    r3, [r5, #MACHINFO_TYPE]    @ get machine type //r3=取得單板的編號
201        teq    r3, r1                @ matches loader number?//比較r3與r1是否相等,即linux是否支持uboot傳入的單板
202        beq    2f                @ found                     //如果相等,則跳到207行,找到支持的單板,返回
203        add    r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc//r5執向下一個machine_desc結構
204        cmp    r5, r6                                             //是否已經比較完machine_desc結構?
205        blo    1b                                                 //如果沒有比較完,則跳到200行繼續比較
206        mov    r5, #0                @ unknown machine              //如果所有machine_desc都比較完了,r5=0
207    2:    mov    pc, lr                                             //返回

其中__arch_info_begin、__arch_info_end被定義在arch\arm\kernel\vmlinux.lds中,它的意思是內核源碼中有被定義為.arch.info.init的內容,它的起始地址是__arch_info_begin,結束地址為__arch_info_end。

305      __arch_info_begin = .;
306       *(.arch.info.init)
307      __arch_info_end = .;

接著看到machine_desc結構的內容,它被定義在include\asm-arm\mach\Arch.h?中

17    struct machine_desc {
18        /*
19         * Note! The first four elements are used
20         * by assembler code in head-armv.S
21         */
22        unsigned int        nr;        /* architecture number    */     //單板的編號,是從內核傳過來的編號  r1
23        unsigned int        phys_io;    /* start of physical io    */
24        unsigned int        io_pg_offst;    /* byte offset for io 
25                             * page tabe entry    */
26
27        const char        *name;        /* architecture name    */
28        unsigned long        boot_params;    /* tagged list        *///boo傳過來的tag標記的位置,也是從內核傳過來的 r2
29
30        unsigned int        video_start;    /* start of video RAM    */
31        unsigned int        video_end;    /* end of video RAM    */
32
33        unsigned int        reserve_lp0 :1;    /* never has lp0    */
34        unsigned int        reserve_lp1 :1;    /* never has lp1    */
35        unsigned int        reserve_lp2 :1;    /* never has lp2    */
36        unsigned int        soft_reboot :1;    /* soft reboot        */
37        void            (*fixup)(struct machine_desc *,
38                         struct tag *, char **,
39                         struct meminfo *);
40        void            (*map_io)(void);/* IO mapping function    *///IO映射函數,移植時需要關注
41        void            (*init_irq)(void);
42        struct sys_timer    *timer;        /* system tick timer    */
43        void            (*init_machine)(void);
44    };

接著需要找到對于當前內核支持的machine_desc定義,在include\asm-arm\mach\Arch.h 中有如下宏定義,它表示在.arch.info.init段存入一個machine_desc 的結構體,名稱為

__mach_desc_type,結構體內.nr、.name初始化為MACH_TYPE_type、_name
50    #define MACHINE_START(_type,_name)            \
51    static const struct machine_desc __mach_desc_##_type    \
52     __used                            \
53     __attribute__((__section__(".arch.info.init"))) = {    \
54        .nr        = MACH_TYPE_##_type,        \
55        .name        = _name,
56    
57    #define MACHINE_END                \
58    };

接著找調用MACHINE_START這個宏的文件,在arch\arm\mach-s3c2440\Mach-smdk2440.c 找到了,所以單板的ID為MACH_TYPE_S3C2440,它被定義在include\asm-arm\Mach-types.h中

#define MACH_TYPE_S3C2440? ? ? ? ? ? ? 362。與UBOOT傳入的參數相符合。

339    MACHINE_START(S3C2440, "SMDK2440")
340        /* Maintainer: Ben Dooks <ben@fluff.org> */
341        .phys_io    = S3C2410_PA_UART,
342        .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
343        .boot_params    = S3C2410_SDRAM_PA + 0x100,
344
345        .init_irq    = s3c24xx_init_irq,
346        .map_io        = smdk2440_map_io,
347        .init_machine    = smdk2440_machine_init,
348        .timer        = &s3c24xx_timer,
349    MACHINE_END

繼續來看MACHINE_START(S3C2440, "SMDK2440")這個宏,在里面有許多和開發板相關的設置,比如說smdk2440_map_io,它被定義在arch\arm\mach-s3c2440\Mach-smdk2440.c中,在Linux移植之移植步驟中提到過想要移植成功,必須修改327行代碼,將晶振的設置改為12000000。還有其它的一些配置就不一一列舉了。

324    static void __init smdk2440_map_io(void)
325    {
326        s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
327        s3c24xx_init_clocks(12000000);//根據開發板合適的晶振配置
328        s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
329    }

回到arch/arm/kernel/head.s接著往下看,86、87行判斷__lookup_machine_type是否成功找到支持單板的machine_desc結構,如果沒找到則打印錯誤,88行是用來創建一級頁表以建立虛擬地址到物理地址的映射關系,這里不詳細分析。

繼續往下看,看到100行,其中r10的值為__arm920_proc_info所在地址,PROCINFO_INITFUNC為proc_info_list結構體的偏移量,具體為__cpu_flush,對應到__arm920_proc_info結構體內,pc的值就是b __arm920_setup這條語句所在地址,即執行b?__arm920_setup這條指令,__arm920_setup做一些MMU相關的初始化,在arch\arm\mm\proc-arm920.S中,這里不做細究。

97    ldr    r13, __switch_data        @ address to jump to after//r13是堆棧寄存器sp
98                            @ mmu has been enabled
99    adr    lr, __enable_mmu        @ return (PIC) address //100行設置完成之后在使能MMU
100   add    pc, r10, #PROCINFO_INITFUNC//調用__arm920_setup函數,應該跟MMU相關,后面再研究

b?__arm920_setup執行完畢返回之后執行的是arch/arm/kernel/head.s下的__enable_mmu 。

152        .type    __enable_mmu, %function
153    __enable_mmu:
.....
174        b    __turn_mmu_on187        .align    5
188        .type    __turn_mmu_on, %function
189    __turn_mmu_on:
190        mov    r0, r0
191        mrc    p15, 0, r3, c0, c0, 0        @ read id reg
192        mov    r3, r3
193        mov    r3, r3
194        mov    pc, r13//設置完MMU之后跳轉到__switch_data執行

__enable_mmu 執行完之后進入__switch_data執行,注意這時候的運行地址已經是初始化MMU之后的虛擬地址了。從15-24行可以看出pc=__mmap_switched,__mmap_switched的主要工作是將processor_id與__machine_arch_type初始化為當前MCU的編號與單板的編號

14        .type    __switch_data, %object
15    __switch_data:
16        .long    __mmap_switched
17        .long    __data_loc            @ r4
18        .long    __data_start            @ r5
19        .long    __bss_start            @ r6
20        .long    _end                @ r7
21        .long    processor_id            @ r4//之前找到的符合當前MCU的__arm920_proc_info結構體
22        .long    __machine_arch_type        @ r5//之前找到的符合單板的__mach_desc_S3C2440結構體
23        .long    cr_alignment            @ r6
24        .long    init_thread_union + THREAD_START_SP @ sp
25
26    /*
27     * The following fragment of code is executed with the MMU on in MMU mode,
28     * and uses absolute addresses; this is not position independent.
29     *
30     *  r0  = cp#15 control register
31     *  r1  = machine ID
32     *  r9  = processor ID
33     */
34        .type    __mmap_switched, %function
35    __mmap_switched://虛擬地址已經可以使用
36        adr    r3, __switch_data + 4//r3=__data_loc所在的地址
37
38        ldmia    r3!, {r4, r5, r6, r7}//r4=__data_loc所在地址;r5=__data_start所在地址依次類推 r3=__switch_data+4*4
39        cmp    r4, r5                @ Copy data segment if needed //檢查是否有__data_loc段r4=r5說明沒有__data_loc
40    1:    cmpne    r5, r6          
41        ldrne    fp, [r4], #4
42        strne    fp, [r5], #4
43        bne    1b
44
45        mov    fp, #0                @ Clear BSS (and zero fp)//清0BSS段
46    1:    cmp    r6, r7
47        strcc    fp, [r6],#4
48        bcc    1b
49
50        ldmia    r3, {r4, r5, r6, sp}//r4=processor_id、r5=__machine_arch_type、r6=cr_alignment、sp=init_thread_union + THREAD_START_SP
51        str    r9, [r4]            @ Save processor ID//processor_id=r9 = proc_info_list.cpu_val = 0x41009200
52        str    r1, [r5]            @ Save machine type//__machine_arch_type=r1 = machine_desc .nr =  MACH_TYPE_S3C2440 = 362
53        bic    r4, r0, #CR_A            @ Clear 'A' bit
54        stmia    r6, {r0, r4}            @ Save control register values
55        b    start_kernel//跳轉到start_kernel C函數

最終執行b start_kernel,跳到C函數,這是第二階段的內容。

?

轉載于:https://www.cnblogs.com/andyfly/p/9404198.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279720.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279720.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279720.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

阿里開源HTML5小游戲開發框架Hilo實戰教程

前言 開發基于Html5的小游戲并不困難&#xff0c;基本思路就是使用Html5的canvas進行游戲圖像繪制&#xff0c;通過監聽Dom元素的touch事件并觸發相應的動畫&#xff0c;來實現游戲的交互。難在于解決開發后面臨的不同設備游戲畫面、音效等兼容性問題。 使用Hilo可以幫助我們解…

outlook附件大小限制_如何在Outlook中調整大圖片附件的大小

outlook附件大小限制When you have to send someone a large image file through email, it’s a good idea to resize the image file to make it smaller before sending it. Outlook makes this easy and allows you to resize the image file as it’s sent. 當您必須通過電…

bzoj2460: [BeiJing2011]元素

怕不是學了個假的線性基。。。一直以為要高位到低位插入&#xff0c;結果那個是高斯消元的線性基。。。 那么直接排序權值就行了。 #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<…

西湖論劍WP

先水幾句&#xff0c;這次的題確實難啊&#xff0c;動用洪荒之力了&#xff0c;第一名的神仙也沒有全部做完。 官方說這次的題目有兩道沒被做出來&#xff0c;我猜應該是PWN和RE吧 本來我們是45名的&#xff0c;最后5分鐘那幫人啊&#xff0c;硬生生給我們擠出前50&#xff0c;…

vm macos 啟用3d_如何在macOS中啟用夜班以減輕眼睛疲勞

vm macos 啟用3dNight Shift is a new feature introduced in macOS Sierra 10.12.4, and you might already be familiar with it if you’re an iOS user. Here’s how to enable it and set it up on your Mac. Night Shift是macOS Sierra 10.12.4中引入的新功能&#xff0c…

hdu3072 Intelligence System (最小樹形圖?)

題意&#xff1a;給一個有向圖&#xff0c;問要從0號點能到達所有點所需要經過路徑的最小權值和是多少&#xff0c;然而&#xff0c;若兩點強聯通&#xff0c;則這兩點互相到達不需要花費。保證0號點能到達所有點 tarjan縮點以后直接取每個點入邊中花費最小的即可。 1 #include…

如何在Windows 7、8、10,Vista或XP中刪除Windows服務

If you are a fan of tweaking your system and disabling services, you might find that over time your Windows Services list becomes large and unwieldy. It’s easy enough to delete a Windows service using the Command Prompt. 如果您喜歡調整系統并禁用服務&#…

縮點(有向圖的強連通分量)學習筆記

縮點(有向圖的強連通分量)學習筆記 1.什么是強連通分量&#xff1f;&#xff1a; 有向圖強連通分量:在有向圖G中&#xff0c;如果兩個頂點vi,vj間(vi>vj)有一條從vi到vj的有向路徑&#xff0c;同時還有一條從vj到vi的有向路徑&#xff0c;則稱兩個頂點強連通(strongly conne…

mysql多表聯合刪除

文件一&#xff1a;01.txt文件二&#xff1a;02.txt登錄mysql選擇數據庫表user結構表user_depart結構導入數據到表user導入數據到表user_depart聯合刪除查看刪除后user表的數據查看刪除后user_depart表的數據本文轉自 Lee_吉 51CTO博客&#xff0c;原文鏈接:http://blog.51cto.…

Jenkins 隨筆

window是 隨筆 修改端口 &#xff1a; <arguments>-Xrs -Xmx256m -Dhudson.lifecyclehudson.lifecycle.WindowsServiceLifecycle -jar "%BASE%\jenkins.war" --httpPort8181 --webroot"%BASE%\war"</arguments> 然后重啟服務&#xff08;服務…

centos 初學者_初學者:如何在Outlook 2013中創建和管理任務

centos 初學者If you’re one of those people who has a whiteboard or notepad with an ever-evolving to-do list, or your desk and monitors are adorned with Post-its reminding you of important events, then this the article for you. 如果您是擁有不斷發展的待辦事…

C語言基礎(五)

一、字符串相關函數 1.gets()(輸入字符串) 格式&#xff1a;gets(字符串)&#xff1b; (1)區別&#xff1a;gets(str)與scanf(“%s”,str) gets(str)允許輸入的字符串含有空格 scanf(“%s”,str)不允許含有空格 注意&#xff1a;由于以上無法知道字符串大小&#xff0c;很容易導…

新服務器安裝和配置zabbix的playbook

公司的金山區云服務器是由我負責的&#xff0c;每一次新購買了金山區的服務器都要把這些新服務器添加到zabbix監控里&#xff0c;于是我就編寫了一個ansible的playbook&#xff0c;這樣以后就可以在執行playbook的時候“帶薪拉屎”了。 ansible主機準備&#xff1a; 1&#xff…

15個變態的Google面試題以及答案

在當前經濟形勢不景氣的情況下&#xff0c;谷歌招聘新員工是一件令人振奮的事&#xff0c;特別是對那些在當前金融風暴中渴望找到安全港的年輕經理們和軟件開發商們來說是個好消息。   不過&#xff0c;也不要高興太早&#xff0c;谷歌在招聘新員工時&#xff0c;更加青睞名牌…

小程序禁用ios 左右滑動_如何在使用應用程序時禁用iOS控制中心

小程序禁用ios 左右滑動The Control Center has proven to be a thoughtful and welcome addition to iOS, but it can be annoying sometimes if you’re playing a game or using an app, and you accidentally open it. Here’s how you can disable it in such situations.…

repomd.xml錯誤14 not found

用Centos7最小化安裝了系統&#xff0c;想練練手&#xff0c;可以到換了“搜狐”的YUM源&#xff0c;系統總報錯更新錯誤說找不到repomd.xml。 然后就一直搜解決問題&#xff0c;能用到的都用到了&#xff0c;網上提到的都用到了。浪費了好幾個小時沒解決。正當無語的時候&…

淺談javascript遞歸(白話版)

遞歸 遞歸是一種解決問題的方法&#xff0c;通常我們可以理解成函數調用自身&#xff1b; 什么遞歸&#xff1f;遞歸怎么寫&#xff1f; 首先直接調用自身的方法和函數&#xff0c;他是一個遞歸&#xff0c;我們看代碼&#xff1a; 復制代碼 var recursiveFun function(params…

超鏈接禁用_如何在Microsoft Word中禁用超鏈接

超鏈接禁用When you type a web or email address in Word, you may notice that the program automatically formats it as a live hyperlink. This is a setting in Word’s AutoFormat feature that is on by default but can be easily turned off. 當您在Word中鍵入網站或…

ssh面試題總結

題目1&#xff1a;Hibernate工作原理及為什么要用&#xff1f; 原理&#xff1a; hibernate&#xff0c;通過對jdbc進行封裝&#xff0c;對 java類和 關系數據庫進行mapping&#xff0c;實現了對關系數據庫的面向對象方式的操作&#xff0c;改變了傳統的jdbc sql操作數據的方式…

SaltStack的salt-ssh使用及LAMP狀態設計部署

SaltStack的salt-ssh使用及LAMP狀態設計部署 1、salt-ssh的使用 官方文檔&#xff1a;https://docs.saltstack.com/en/2016.11/topics/ssh/index.html &#xff08;1&#xff09;安裝salt-ssh [rootlinux-node1 ~]# yum install -y salt-ssh&#xff08;2&#xff09;配置salt-…