Lab6 : Linux系統(tǒng)調(diào)用 - 嵌入式與操作系統(tǒng)實(shí)驗(yàn)

前言

本次實(shí)驗(yàn)和某操作系統(tǒng)實(shí)驗(yàn)課好像啊,我又回憶起了那幾次被Linux支配著的恐懼。

本次試驗(yàn)使用Ubuntu 14.04 LTS 64 bits進(jìn)行交叉編譯,下位機(jī)是Raspberry Pi 2,編譯的內(nèi)核版本是3.18.16-v7,而下載鏈接中提供的Raspbian-Wheezy-2015-02-17的內(nèi)核也是3.18。編譯基本按照樹(shù)莓派官方文檔進(jìn)行。

我本次實(shí)驗(yàn)的整體思路是先在SD card上燒錄好打包好的系統(tǒng)鏡像,而之后編譯的內(nèi)核可以直接放進(jìn)去而不用重建整個(gè)根目錄。如果鏡像內(nèi)核版本和編譯內(nèi)核版本差別過(guò)大的話容易出問(wèn)題。而我選擇的這個(gè)3.18版本和我原來(lái)操作系統(tǒng)實(shí)驗(yàn)所用的版本也比較接近,所以基本步驟可以通用。

如果按照教程跑,而且選擇交叉編譯的話,那么推薦編譯安裝的時(shí)候選擇一個(gè)能夠直接接觸到樹(shù)莓派SD卡的電腦,各種遠(yuǎn)程服務(wù)器以及虛擬機(jī)在編譯內(nèi)核模塊的時(shí)候如果出了我文中的那個(gè)問(wèn)題可能會(huì)比較難受?;蛘哒f(shuō)其實(shí)是我方法有問(wèn)題?(Update: 這幾天想了想,感覺(jué)自己好蠢啊,可以交叉編譯好了再scp過(guò)去,(:з」∠)

最后一節(jié)是我折騰Acadia的從入門到放棄之路,希望能對(duì)大家有些幫助。(翁老大說(shuō)Acadia直接放棄好了,不需要入門)

試編譯

其實(shí)如果熟悉的話,直接在文件目錄底下改文件即可,本步驟不是必要的。

但是,拿到不會(huì)的東西不得先點(diǎn)個(gè)燈?

首先從git上把項(xiàng)目拽下來(lái),解壓之后文件夾結(jié)構(gòu)大概長(zhǎng)這樣。

推薦所有的操作均在linux下完成。因?yàn)槿绻麎嚎s包內(nèi)有一些軟鏈接什么的在windows底下會(huì)出問(wèn)題,而在linux下才會(huì)被正確解析。

而如果在mac上姿勢(shì)不對(duì)也是會(huì)出問(wèn)題的,比如說(shuō)使用的文件系統(tǒng)是大小寫不敏感的,那這會(huì)導(dǎo)致到后面編譯的時(shí)候缺少某些文件或者缺少某個(gè)宏定義等等。文件系統(tǒng)大小寫問(wèn)題的解決方案戳這位同學(xué)的在mac os x上進(jìn)行嵌入式linux開(kāi)發(fā)[編譯linux kernel]

文件夾結(jié)構(gòu)

然后是安裝交叉編譯工具,在Lab2中已經(jīng)下載過(guò),直接拿來(lái)使用即可。

編譯器們

還有還有,編譯之前有一些依賴,別忘記裝了,ubuntu還是可以apt-get大法拿下來(lái)的。

sudo apt-get install bc

樹(shù)莓派1和2之間的操作還是有一些區(qū)別的,注意看好型號(hào),樹(shù)莓派1直接去找官方文檔順著做就好了。

準(zhǔn)備好之后,就可以開(kāi)始編譯了。

首先是config文件,可以使用現(xiàn)在樹(shù)莓派上使用的config文件進(jìn)行編譯,樹(shù)莓派上的配置文件是/proc/config.gz,使用zcat命令可以直接查看。

而按照官方教程,源碼包內(nèi)有相關(guān)配置可以直接拿來(lái)使用。

KERNEL=kernel7
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig

使用上述命令選擇好項(xiàng)目配置即可。我選擇使用的是源碼包內(nèi)和我樹(shù)莓派對(duì)應(yīng)的那個(gè)配置(官方的教程寫的就是這個(gè))。

configuration

而后準(zhǔn)備好之后就可以直接開(kāi)始編譯了

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

少女祈禱中………………

反正又是一段漫長(zhǎng)的編譯之旅。

如果編譯中間有問(wèn)題,一般來(lái)說(shuō)先考慮是不是依賴沒(méi)有滿足,而后如果再有什么file missing之類的錯(cuò)誤我傾向于是源碼包有問(wèn)題。

總體編譯過(guò)程蠻順利的。不像某Acadia……一定是因?yàn)闃?shù)莓派長(zhǎng)得更像我熟知的Linux……

編譯完成后文件結(jié)構(gòu)

編譯完成之后就是安裝,如果燒錄了樹(shù)莓派官方給出的SDcard鏡像,那么現(xiàn)在你的SD卡分區(qū)長(zhǎng)這樣。SDcard使用讀卡器接入電腦。

/dev/sdd
    /dev/sdd1 fat32 boot  啟動(dòng)分區(qū)
    /dev/sdd2 ext4 /  根目錄

由于目錄與教程一致,所以就直接按照步驟執(zhí)行一遍即可。

# 建立掛載點(diǎn)
mkdir /mnt/fat32
mkdir /mnt/ext4

# 掛載
# fat32掛載boot
sudo mount -t vfat /dev/sdd1 /mnt/fat32
# ext4掛載根文件夾
sudo mount -t ext4 /dev/sdd2 /mnt/ext4

# 在文件系統(tǒng)中安裝編譯出來(lái)的模塊
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/mnt/ext4 modules_install

# 備份原來(lái)的系統(tǒng)鏡像,其中$KERNEL在編譯前進(jìn)行過(guò)設(shè)置,此時(shí)值為kernel7
sudo cp /mnt/fat32/$KERNEL.img /mnt/fat32/$KERNEL-backup.img
sudo scripts/mkknlimg arch/arm/boot/zImage /mnt/fat32/$KERNEL.img

# 將其他我不認(rèn)識(shí)的文件拷到我不認(rèn)識(shí)的地方
sudo cp arch/arm/boot/dts/*.dtb /mnt/fat32/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /mnt/fat32/overlays/
sudo cp arch/arm/boot/dts/overlays/README /mnt/fat32/overlays/

# 卸載
sudo umount /mnt/fat32
sudo umount /mnt/ext4

這個(gè)時(shí)候直接將SDcard插到樹(shù)莓派上,上電就可以啟動(dòng)了。

修改系統(tǒng)調(diào)用

本節(jié)可以結(jié)合操作系統(tǒng)實(shí)驗(yàn)2的實(shí)驗(yàn)指導(dǎo)一起食用。

系統(tǒng)調(diào)用實(shí)際上是調(diào)用內(nèi)核某個(gè)函數(shù)的過(guò)程。所以,為了告訴操作系統(tǒng)什么時(shí)候該用什么函數(shù),需要在內(nèi)核中進(jìn)行一些修改。

首先,你需要在內(nèi)核中有一個(gè)這樣的可執(zhí)行的函數(shù)。在arch/arm/kernel中新建一個(gè)sys_mysyscall.c文件,只包含一個(gè)函數(shù),其作用為在運(yùn)行后輸出一條內(nèi)核日志。

sys_mysyscall.c

而后,修改Makefile中的obj-y字段,將sys_mysyscall.o加入目標(biāo)文件中。即將該函數(shù)納入系統(tǒng)的編譯進(jìn)程。

Makefile

而后,你需要讓操作系統(tǒng)知道這個(gè)函數(shù)是處理某個(gè)系統(tǒng)調(diào)用的函數(shù)。此時(shí),需要修改系統(tǒng)的中斷向量表。此時(shí)需要修改arch/arm/kernel/calls.S文件。

按照操作系統(tǒng)實(shí)驗(yàn)的教程,選擇223號(hào)調(diào)用進(jìn)行替換。223號(hào)調(diào)用在x86體系架構(gòu)的系統(tǒng)上是沒(méi)有使用的,而arm的似乎這么替換也沒(méi)有問(wèn)題?不是很懂,不過(guò)這么替換沒(méi)有遇到坑。

系統(tǒng)中斷向量表 call.S

在include/uapi/asm-generic/unistd.h頭文件中將223號(hào)調(diào)用與某個(gè)宏進(jìn)行關(guān)聯(lián),在syscall()中注冊(cè)一個(gè)位置,方便調(diào)用。

unistd.h

然后接下來(lái)就是又一次的編譯了,不過(guò)此次由于改的東西比較少,編譯會(huì)快一些。

將鏡像載入到SDcard之后,開(kāi)始編寫使用系統(tǒng)調(diào)用的程序。如下兩個(gè)分別使用了匯編的方式以及系統(tǒng)提供的syscall方式調(diào)用系統(tǒng)調(diào)用。

#include <stdio.h>
#define sys_call() {__asm__ __volatile__ ("swi 0x900000+223\n\t");} while(0)
 
int main(void) {
    sys_call();
    printf("Type \"dmesg | tail\" to see the result.\n");
 
    return 0;
}
#include <linux/unistd.h>
#include <sys/syscall.h>

int main(){
    syscall(223);
    return 0;
}
運(yùn)行結(jié)果

內(nèi)核模塊

首先需要寫一個(gè)內(nèi)核模塊,我就偷懶直接使用當(dāng)時(shí)操作系統(tǒng)實(shí)驗(yàn)中寫的系統(tǒng)進(jìn)程統(tǒng)計(jì)的程序了。

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/uaccess.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("lmzqwer2 <lmzqwerty@163.com>");
MODULE_DESCRIPTION("In-kernel processors infomation detector.");

#define show(id,arr,x) printk(KERN_INFO "%s%s %d\n", id, #x, arr[x]);
#define clean(arr,x) arr[x] = 0
#ifndef IDENTIFIER
    #define IDENTIFIER aaaadfa
#endif

static int processorDetector_read(struct file *file, char __user *out,
                                    size_t size, loff_t *off){
    // identifier用于每次調(diào)用的輸出,每行的輸出均帶有此標(biāo)識(shí)符,而后用戶程序在讀取系統(tǒng)日志的時(shí)候只識(shí)別帶有該標(biāo)識(shí)符的日志。
    static char identifier[] = "IDENTIFIER";

    // 系統(tǒng)init進(jìn)程指針,使用該指針可以將整個(gè)系統(tǒng)的所有進(jìn)程遍歷一遍
    struct task_struct *task = &init_task;

    int i, taskTotal = 0;

    // 用于統(tǒng)計(jì)每個(gè)狀態(tài)的進(jìn)程的個(gè)數(shù),開(kāi)大數(shù)組為了能少寫點(diǎn)代碼……寫法比較蠢
    static int stateCollection[2049];

    // 每次進(jìn)調(diào)用需要清除上一次的結(jié)果
    clean(stateCollection, TASK_RUNNING);
    clean(stateCollection, TASK_INTERRUPTIBLE);
    clean(stateCollection, TASK_UNINTERRUPTIBLE);
    clean(stateCollection, __TASK_STOPPED);
    clean(stateCollection, __TASK_TRACED);
    clean(stateCollection, EXIT_DEAD);
    clean(stateCollection, EXIT_ZOMBIE);
    clean(stateCollection, EXIT_TRACE);
    clean(stateCollection, TASK_DEAD);
    clean(stateCollection, TASK_WAKEKILL);
    clean(stateCollection, TASK_WAKING);
    clean(stateCollection, TASK_PARKED);
    clean(stateCollection, TASK_STATE_MAX);

    // 修改identifier,使每次讀取該設(shè)備的時(shí)候返回的值均不同。
    identifier[0]++;
    i = 0;
    while (identifier[i] == 'z'+1){
        identifier[i++] = 'a';
        if (i < sizeof(identifier)){
            identifier[i]++;
        }else
            break;
    }

    // 遍歷系統(tǒng)的進(jìn)程,有宏next_task進(jìn)行進(jìn)程之間的跳轉(zhuǎn)
    // linux的進(jìn)程使用環(huán)形鏈表,從init_task到init_task即完成了一次遍歷
    do{
        printk(KERN_INFO "%s%s %d %ld %s\n", identifier, task->comm, task->pid, task->state, task->parent->comm);
        stateCollection[task->state]++;
        taskTotal++;
        task = next_task(task);
    }while (task != &init_task);

    // 輸出遍歷之后的統(tǒng)計(jì)信息
    printk(KERN_INFO "%sThere is %d processes in system.", identifier, taskTotal);
    show(identifier, stateCollection, TASK_RUNNING);
    show(identifier, stateCollection, TASK_INTERRUPTIBLE);
    show(identifier, stateCollection, TASK_UNINTERRUPTIBLE);
    show(identifier, stateCollection, __TASK_STOPPED);
    show(identifier, stateCollection, __TASK_TRACED);
    show(identifier, stateCollection, EXIT_DEAD);
    show(identifier, stateCollection, EXIT_ZOMBIE);
    show(identifier, stateCollection, EXIT_TRACE);
    show(identifier, stateCollection, TASK_DEAD);
    show(identifier, stateCollection, TASK_WAKEKILL);
    show(identifier, stateCollection, TASK_WAKING);
    show(identifier, stateCollection, TASK_PARKED);
    show(identifier, stateCollection, TASK_STATE_MAX);

    // 將標(biāo)識(shí)符拷貝給用戶
    copy_to_user(out, identifier, sizeof(identifier));
    return 0;
}

// 只實(shí)現(xiàn)了讀取指令,返回identifier
static struct file_operations processorDetector_fops = {
    .owner = THIS_MODULE,
    .read = processorDetector_read,
    .llseek = noop_llseek
};

// 模塊名為processorDetector
static struct miscdevice processorDetector_misc_device = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "processorDetector",
    .fops = &processorDetector_fops
};


// insmod的時(shí)候調(diào)用該函數(shù)進(jìn)行一些處理
static int __init processorDetector_init(void){
    // create a device file at "/dev/"
    // named "processorDetector"
    misc_register(&processorDetector_misc_device);
    printk(KERN_INFO
            "processorDetector device has been registed.\n");
    return 0;
}

// rmmod的時(shí)候調(diào)用該函數(shù)進(jìn)行一些清理
static void __exit processorDetector_exit(void){
    misc_deregister(&processorDetector_misc_device);
    printk(KERN_INFO
            "processorDetector device has been unregisted.\n");
}

// 注冊(cè)模塊的init & exit函數(shù)
module_init(processorDetector_init);
module_exit(processorDetector_exit);

該內(nèi)核模塊還需要一個(gè)使用者進(jìn)行使用。

#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <fcntl.h>

char identifier[100];
char buf[100000];

int inner(char* a, char* b){
    while (*a++ == *b++);
    return *a==0;
}

int main(int argc, char* argv[]){
    // 這個(gè)fd打開(kāi)的是上面編譯的內(nèi)核模塊
    int fd = open("/dev/processorDetector", O_RDWR);

    // 這個(gè)FILE*打開(kāi)的是系統(tǒng)log
    FILE* log = fopen("/var/log/kern.log", "r");
    int i, len, buflen;

    // 首先從內(nèi)核模塊中獲取輸出標(biāo)識(shí)符
    read(fd, identifier, sizeof(identifier));
    printf("Identifier: %s\n", identifier);

    // 為了方便以后性能優(yōu)化,先睡個(gè)2s先
    sleep(2);

    // 讀取系統(tǒng)日志,判斷標(biāo)識(shí)符后輸出
    len = strlen(identifier);
    while (!feof(log)){
        fgets(buf, sizeof(buf), log);
        buflen = strlen(buf);
        i = 0;

        // 不要吐槽暴力枚舉
        while (i + len < buflen && !inner(identifier, buf+i)){
            i++;
        }
        if (!feof(log) && i + len < buflen - 1){
            printf("%s", buf+i+len);
        }
    }
    return 0;
}

好了,現(xiàn)在有了內(nèi)核模塊,也有了對(duì)應(yīng)的的用戶程序。那么就是編譯運(yùn)行了。

我所想的內(nèi)核模塊編譯進(jìn)程是這樣的,一切順利。

操作系統(tǒng)實(shí)驗(yàn)中的內(nèi)核模塊編譯

然后就崩了。一定是代碼又過(guò)保質(zhì)期了……

既然崩了就解決嘍。

錯(cuò)誤信息提示的是找不到build文件夾,原來(lái)還以為是安裝的時(shí)候沒(méi)有帶上,然后發(fā)現(xiàn)就是安裝的時(shí)候沒(méi)有帶上。但是這錯(cuò)誤和我預(yù)想的不一樣……

編譯錯(cuò)誤

我就一臉懵逼得看著這個(gè)錯(cuò)誤。這個(gè) build -> /home/lmuser/tmp/linux 的意思是它在安裝的時(shí)候只是送了一個(gè)軟鏈接過(guò)去?竟然沒(méi)有直接拷貝……

不過(guò)仔細(xì)一想可能是SDcard上沒(méi)有這么大的空間把整個(gè)項(xiàng)目拷貝進(jìn)去,所以就使用了軟鏈接。

但是,但是,但是!現(xiàn)在SDcard在樹(shù)莓派上,并沒(méi)有/home/lmuser/這種東西。經(jīng)過(guò)我一番深思熟慮,我決定——內(nèi)核模塊也用交叉編譯。

既然要交叉編譯,那么makefile自然就不能像原來(lái)的那樣簡(jiǎn)單了。手動(dòng)加的特技有點(diǎn)多。主要是指定編譯文件夾以及指定編譯的參數(shù)等。

obj-m := processorDetector.o
# 其實(shí)不需要這么多特技,直接定位/home/lmuser/tmp/linux即可
KERNEL_VER := 3.18.16-v7
KERNEL_DIR := /media/lmuser/f24a4949-f4b2-4cad-a780-a138695079ec/lib/modules/$(KERNEL_VER)/build

PWD := $(shell pwd)
ARGS := ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
all:
    make -C $(KERNEL_DIR) SUBDIRS=$(PWD) $(ARGS) modules
clean:
    rm *.o *.ko *.mod.c
.PHONY:clean

感覺(jué)好蠢啊……一點(diǎn)都不優(yōu)雅。不過(guò)還是好用的……

然后將樹(shù)莓派關(guān)機(jī),拔出SDcard,讀卡器,cd,make,彈出SDcard,樹(shù)莓派開(kāi)機(jī)。

編譯期報(bào)了個(gè)warning,華麗麗無(wú)視之。

接下來(lái)就是驗(yàn)證成果的時(shí)候了,果斷運(yùn)行之。

內(nèi)核模塊運(yùn)行結(jié)果

成功把整個(gè)操作系統(tǒng)當(dāng)前運(yùn)行的所有進(jìn)程都輸出出來(lái)了。

撒花,慶祝!

關(guān)于Acadia

最終我使用樹(shù)莓派而不是Acadia完成了實(shí)驗(yàn),原因主要是因?yàn)闃?shù)莓派在網(wǎng)上的教程比較多,而且樹(shù)莓派看上去整個(gè)文件結(jié)構(gòu)什么的就比較像我熟悉的Linux。(主要是因?yàn)槲液虯cadia相性不合,折騰不出來(lái))

而且沒(méi)有樹(shù)莓派沒(méi)有板載的存儲(chǔ)設(shè)備,SDcard直接作為系統(tǒng)存儲(chǔ),插拔讀取修改操作都很方便。最關(guān)鍵的是不用擔(dān)心刷機(jī)刷壞了,刷壞了再燒一個(gè)就是了,Acadia有板載的存儲(chǔ)不是很敢亂玩。

以下的實(shí)驗(yàn)步驟我編譯成功進(jìn)入過(guò)一次系統(tǒng),只有一次。之后不管怎么操作都進(jìn)不去,可能是那一步中間有啥特殊的地方我沒(méi)注意到吧。

實(shí)驗(yàn)一開(kāi)始就不順利。雖然pcDuino/kernel.git這個(gè)git倉(cāng)庫(kù)比較小,但是linux-sunxi這個(gè)倉(cāng)庫(kù)大啊,1.6G啊,500W+的文件啊。

每次git到1W+的時(shí)候就clone不下去了。后來(lái)解決方案是使用服務(wù)器git clone --recursive下載完全之后,tar -czvf一次性打個(gè)包,再wget / Thunder到本地,再丟給虛擬機(jī)linux中就可以進(jìn)行編譯了。

拿下來(lái)之后就是開(kāi)始編譯了,按照官方教程,一步一步跑下來(lái)。似乎也沒(méi)有叫我配置什么config之類的。_(:з」∠)_

然后編譯報(bào)了個(gè)錯(cuò)。

arm-linux-gnueabihf-ld.bfd: error: required section '.rel.plt' not found in the linker script

網(wǎng)上找了一些資料,說(shuō)是要下載這個(gè)包。

sudo apt-get install ia32-libs

然而我并沒(méi)能成功找到這個(gè)包,搜索了半天,最終結(jié)果是使用下面這個(gè)包進(jìn)行替換。

sudo apt-get install gcc-multilib

編譯繼續(xù)。

fs/btrfs/ctree.c:26:21: fatal error: locking.h: No such file or directory
 #include "locking.h"

這個(gè)fs找不到頭文件啊,拿很難辦啊,反正不認(rèn)識(shí),config里面去掉好了。編譯繼續(xù)。

而后,又報(bào)了個(gè)錯(cuò)。

fel.c:21:20: fatal error: libusb.h: No such file or directory
#include <libusb.h>

網(wǎng)上找說(shuō)是缺這個(gè),

sudo apt-get install libusb-1.0-0-dev

但是還是找不到,最終發(fā)現(xiàn)少了一個(gè)配置類型的程序。

sudo apt-get install pkg-config

下下來(lái)之后就可以繼續(xù)編譯了。

然后就又編譯不下去了。

Make sys configs: /home/linux/kernel/allwinner-tools/livesuit/default/sys_config_linux.fex
/home/linux/kernel/allwinner-tools/bins/script: 1: /home/linux/kernel/allwinner-tools/bins/script: Syntax error: end of file unexpected

先用file看了一下這個(gè)文件,并看不出什么。

linux@linux-VBox:~/kernel/allwinner-tools/bins$ file script 
script: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, BuildID[sha1]=7ce8c666545525b7459addd15d8d7b91c4e70009, not stripped

百度了一下發(fā)現(xiàn)這樣一句話


[【轉(zhuǎn)】有關(guān)pcduino 內(nèi)核編譯問(wèn)題](http://www.pcduino.org/forum.php?mod=viewthread&tid=147)

誒,然后發(fā)現(xiàn)確實(shí)是生成了hwpack這個(gè)文件,我就當(dāng)是編譯成功沒(méi)再管了。(說(shuō)不定就是這個(gè)問(wèn)題)

接下來(lái)就是如何將其安裝到Acadia了。

首先解包,有如下文件結(jié)構(gòu)。

文件結(jié)構(gòu)

Acadia有一個(gè)板載的系統(tǒng)以及倆SDcard插槽,通過(guò)配置可以從中任意選一個(gè)進(jìn)行啟動(dòng)。

Acadia Boot開(kāi)關(guān)選擇

我首先選擇使用SD1進(jìn)行啟動(dòng)。啟動(dòng)的方式也很保守,使用的是官方給的鏡像,然后似乎是沒(méi)啟動(dòng)起來(lái)還是怎么回事,反正最終我放棄了從SDcard直接啟動(dòng)。

而如果要從板子啟動(dòng),由于有板子自帶存儲(chǔ)器,沒(méi)辦法備份,我選擇慫。

要把剛才那個(gè)hwpack中的文件全部放入系統(tǒng),那么需要考慮一些東西。首先,板載系統(tǒng)自帶bootloader,那么bootloader這個(gè)文件夾應(yīng)該是不用去管的。而rootfs是放系統(tǒng)模塊的,仔細(xì)看了一下,和原版系統(tǒng)沒(méi)有沖突,直接拷貝之。而kernel比較尷尬,想要無(wú)沖突解決的話得加一些特技。

比如說(shuō)使用bootloader的的一些命令,將內(nèi)核手動(dòng)載入系統(tǒng)。

首先還是得把系統(tǒng)燒入SDcard,使用以下命令即可,注意seek是后續(xù)載入系統(tǒng)的時(shí)候的參數(shù)之一,要前后一致。

sudo dd if=uImage of=/dev/sdd bs=512 seek=2048
sync

sync了之后,把SDcard從電腦上轉(zhuǎn)到Acadia上,從emmc啟動(dòng),進(jìn)入bootloader。

# 設(shè)置了一些控制臺(tái)的參數(shù)
setenv bootargs_base 'setenv bootargs console=ttymxc0,115200'

# 控制文件系統(tǒng)的位置,使用的root位置為emmc即可
setenv bootargs_mmc 'setenv bootargs ${bootargs} root=/dev/mmcblk0p1 rootwait rw'

# 載入系統(tǒng)內(nèi)核,
# 表示讀取SDcard1的
# 地址為0x800后續(xù)0x2000的內(nèi)容
# 讀入位置為$(loadaddr),即后續(xù)bootm所用的地址
setenv bootcmd_mmc 'run bootargs_base bootargs_mmc; mmc dev 1; mmc read ${loadaddr} 0x800 0x2000; bootm'

# 開(kāi)始引導(dǎo)
setenv bootcmd 'run bootcmd_mmc'
boot

然后,接下來(lái)出現(xiàn)了三種錯(cuò)誤。

  • 第一種是根本讀不到

    比較少見(jiàn),重啟可破。

  • 第二種是CRC校驗(yàn)失敗

    可以使用命令強(qiáng)行扭過(guò)去。

setenv verify no


不過(guò)這種方法基本上是會(huì)進(jìn)第三種錯(cuò)誤的。校驗(yàn)本來(lái)就是為了能夠保證東西是對(duì)的。

未解決!

* 第三種是輸出了 Starting kernel ... 之后,完全沒(méi)有反應(yīng)

這句話是bootloader輸出的最后一句話,在此之后,控制權(quán)轉(zhuǎn)交給內(nèi)核。

然而內(nèi)核一點(diǎn)反應(yīng)都沒(méi)有,那這就很尷尬了。原因有很多,沒(méi)有再折騰了。

未解決。

最終我的Acadia之路在某次順利從編譯出的內(nèi)核啟動(dòng)之后,就停留在了那個(gè)尷尬的階段。

Starting kernel ...


總的來(lái)說(shuō),沒(méi)做出來(lái)可能的原因有幾點(diǎn);

1. make沒(méi)有make完畢
2. make前沒(méi)有做相關(guān)的配置
3. 沒(méi)有直接燒錄板子,太慫
4. 虛擬機(jī)有毒
5. 和Acadia相性不合
6. 我太蠢

反正就是撲街了,哪來(lái)這么多原因……

#參考資料

* [git clone 一個(gè)比較大的 repo 出錯(cuò), 糾結(jié)我 1 天了, 求助](https://segmentfault.com/q/1010000000637171)

樹(shù)莓派相關(guān)

* [Raspberry Pi documentation: KERNEL BUILDING](https://www.raspberrypi.org/documentation/linux/kernel/building.md)
* [驅(qū)動(dòng)開(kāi)發(fā)的一些錯(cuò)誤解決方法](http://blog.chinaunix.net/uid-24456535-id-2606924.html)
* [樹(shù)莓派開(kāi)發(fā)系列教程8——樹(shù)莓派內(nèi)核編譯與固件升級(jí)](http://blog.csdn.net/xdw1985829/article/details/39077611)
* [樹(shù)莓派上為內(nèi)核添加系統(tǒng)調(diào)用](http://blog.csdn.net/rk2900/article/details/8848093)
* [在mac os x上進(jìn)行嵌入式linux開(kāi)發(fā)[編譯linux kernel]](http://es.hzypp.me/zai-mac-os-xshang-jin-xing-qian-ru-shi-linuxkai-fa-bian-yi-linux-kernel/)

Acadia相關(guān)

* [Cross build pcDuino kernel on X86-64 machine](http://learn.linksprite.com/pcduino/a10-based-pcduino1pcduino2pcduino-litepcduino-lite-wifi/how-to-cross-build-pcduino-kernel-on-x86-64-machine/)
* [Tutorial on Flashing LinkSprite Acadia](http://learn.linksprite.com/acadia/tutorial-on-flashing-linksprite-acadia/)
* [pcDuino的Linux移植心得筆記](méi)(http://www.linuxidc.com/Linux/2013-04/83606.htm)
* [pcDuino: How to compile Kernel for pcDuino](http://blog.chinaunix.net/uid-23381466-id-3821540.html)
* [How to build linux images by yourself for pcDuino?](http://learn.linksprite.com/?p=1048)
* [pcDuino無(wú)顯示器刷機(jī)與使用](http://www.cnblogs.com/damir/p/3200558.html)
* [【轉(zhuǎn)】有關(guān)pcduino 內(nèi)核編譯問(wèn)題](http://www.pcduino.org/forum.php?mod=viewthread&tid=147)
* [I.MX6Q(TQIMX6Q/TQE9)學(xué)習(xí)筆記——內(nèi)核啟動(dòng)與文件系統(tǒng)掛載](http://blog.csdn.net/girlkoo/article/details/44626011)
* [Get stuck at "Starting kernel ..." using imx-3.10.17-1.0.1_ga](https://community.nxp.com/thread/329129)

# 下載鏈接

樹(shù)莓派相關(guān)

* [raspberrypi / linux](https://github.com/raspberrypi/linux)

  整個(gè)項(xiàng)目大概git clone下來(lái)至少有1G。用校內(nèi)的小水管慢慢跑簡(jiǎn)直難受。
  我選擇的版本是rpi-3.18.y。如果有服務(wù)器直接git clone了之后git checkout到這個(gè)tag了之后,.git文件夾的歷史使命就結(jié)束了。
  此時(shí)將.git文件夾直接刪了就可以了。大概整個(gè)目錄就剩下100多Mb了,這就能下載了。
  當(dāng)然,如果有別人下載好了你直接拷貝也是極好的。

  官方文檔提供了這樣一個(gè)命令,也是能減少git文件夾的。

git clone --depth=1 https://github.com/raspberrypi/linux


* [raspbian-2015-02-17/](https://downloads.raspberrypi.org/raspbian/images/raspbian-2015-02-17/)

Acadia相關(guān)

* [Github: pcduino / kernel](https://github.com/pcduino/kernel)
* [Image for Acadia](http://www.linksprite.com/image-for-acadia/)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 我們說(shuō)的Linux其實(shí)指的就是 內(nèi)核(kernel)而已。這個(gè)內(nèi)核控制你主機(jī)的所有硬件并提供系統(tǒng)所有的功能,所以它...
    Zhang21閱讀 7,696評(píng)論 0 18
  • Linux系統(tǒng)一般有4個(gè)主要部分: 內(nèi)核、shell、文件系統(tǒng)和應(yīng)用程序。內(nèi)核、shell和文件系統(tǒng)一起形成了基本...
    偷風(fēng)箏的人_閱讀 3,396評(píng)論 1 17
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯(cuò)誤還是無(wú)法避免 以后資料會(huì)慢慢更新 大...
    數(shù)據(jù)革命閱讀 13,334評(píng)論 2 33
  • 【同讀一本書(shū).王紀(jì)云】2016-3-2-052:《談話的力量》 正文:83% “支援不被緊張所累,你冒的風(fēng)險(xiǎn)越大,...
    AA王紀(jì)云閱讀 526評(píng)論 4 0
  • 觀棋一語(yǔ)閱讀 186評(píng)論 0 0

友情鏈接更多精彩內(nèi)容