Chinaunix首页 | 论坛 | 博客
  • 博客访问: 284824
  • 博文数量: 58
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 600
  • 用 户 组: 普通用户
  • 注册时间: 2015-11-27 08:37
个人简介

从linux了解世界

文章分类
文章存档

2017年(5)

2016年(51)

2015年(2)

我的朋友

分类: 嵌入式

2015-12-04 22:34:05

折腾了一个星期,终于能做到mini2440上的东西都是自己做的或者配置的了。
只记录一下流程,具体细节都可以在网上找到资料
创建最小文件系统:
用的交叉编译器是友善的4.4.3,因为编译最新版busybox1.24.1有错
util-linux/umount.c: In function 'umount_main':
util-linux/umount.c:87: error: 'MNT_DETACH' undeclared (first use in this function)
util-linux/umount.c:87: error: (Each undeclared identifier is reported only once
util-linux/umount.c:87: error: for each function it appears in.),上网查找原因是交叉编译的glibc太老,又不能不用umount这个命令,所以用14年的busybox1.22.1重新编译可以使用,首先也是修改顶层makefile中的arch和cross_compile(make menuconfig中也可以配置cross_compile),然后make再make install就会生成在_INSTALL下的文件系统。
内核最终会跳入start_kernel()函数,并开始执行init(系统的第一个进程),如果bootloader传入参数有init=xxx则执行xxx否则执行/bin/init,/sbin/init等,用busybox的init则是init=/linuxrc,init会按照/etc/inittab文件的内容执行程序,inittab文件格式这里不说了,可以通过find -name查找busybox中的inittab文档,也可以看网上的资料。还要有/dev/console和/dev/null,用mknod命令生成,主次设备号可以看pc机下的console和null,前者是5,1后者是1,3都是字符设备c。然后可以用udev机制自动创建/dev下设备(bosybox有文档,网上资料也很多),设置fstab这个mount需要的配置文件。因为busybox选择的动态编译,因此要把PC上交叉编译的用到库拷到最小文件系统下,这样一个最小文件系统就差不多了。
配置内核支持yaffs文件系统(探索最新内核4.3)
内核在里程碑的2.6之后已经收录了mini2440的配置文件,因此只要make mini2440_defconfig就可以完成配置,因此不用修改时钟mtd分区了,唯一要做的就是设置内核支持yaffs文件系统。

linux内核并没有自带支持yaffs,所以上yaffs官网下载源码,阅读里面的README得知在yaffs源码目录下执行./patch-ker.sh  c m $linux内核目录,会修改makefile和kconfig,make menuconfig会在文件系统中发现yaffs这项新选项,选中了之后使用默认配置即可(2K大页)。
最开始我使用最新的4.3内核进行配置出现:
fs/yaffs2/yaffs_vfs.c:286: error: 'struct file' has no member named 'f_dentry'
fs/yaffs2/yaffs_vfs.c:779: error: 'do_sync_read' undeclared here (not in a function)
fs/yaffs2/yaffs_vfs.c:780: error: 'do_sync_write' undeclared here (not in a function)
fs/yaffs2/yaffs_vfs.c:781: error: unknown field 'aio_read' specified in initializer
fs/yaffs2/yaffs_vfs.c:781: error: 'generic_file_aio_read' undeclared here (not in a function)
fs/yaffs2/yaffs_vfs.c:782: error: unknown field 'aio_write' specified in initializer
fs/yaffs2/yaffs_vfs.c:782: error: 'generic_file_aio_write' undeclared here (not in a function)
fs/yaffs2/yaffs_vfs.c:787: error: 'generic_file_splice_write' undeclared here (not in a function)
fs/yaffs2/yaffs_vfs.c:1067: error: implicit declaration of function 'nd_set_link'
第一个错误经过对比新老内核发现,在新内核的fs.h中的file结构体中少了#define f_dentry    f_path.dentry
之后的错误都是内核中采用了新函数或者新结构,参照新内核的nfs和jffs源码修改(注释的是原版):
static const struct file_operations yaffs_file_operations = {
    .read = seq_read或者new_sync_read(不确定是哪个),//do_sync_read,
    .write = seq_write或者new_sync_write(不确定是哪个),//do_sync_write,
    .read_iter = generic_file_read_iter,//.aio_read = generic_file_aio_read,
    .write_iter = generic_file_write_ite,r//.aio_write = generic_file_aio_write,
    .mmap = generic_file_mmap,
    .flush = yaffs_file_flush,
    .fsync = yaffs_sync_object,
    .splice_read = generic_file_splice_read,
    .splice_write = iter_file_splice_write,//generic_file_splice_write,
    .llseek = generic_file_llseek,
};

最后一个错误nd_set_link这个函数已经没有了,在老内核中找到源码:
static inline void nd_set_link(struct nameidata *nd, char *path)
{
    nd->saved_names[nd->depth] = path;
}

但是4.3内核中对nameidata机构体的定义变了,没有办法直接用。原来是:
struct nameidata {
    struct path    path;
    struct qstr    last;
    struct path    root;
    unsigned int    flags;
    int        last_type;
    unsigned    depth;
    char *saved_names[MAX_NESTED_LINKS + 1];

    /* Intent data */
    union {
        struct open_intent open;
    } intent;
}
现在是:
struct nameidata {
    struct path    path;
    struct qstr    last;
    struct path    root;
    struct inode    *inode; /* path.dentry.d_inode */
    unsigned int    flags;
    unsigned    seq, m_seq;
    int        last_type;
    unsigned    depth;
    int        total_link_count;
    struct saved {
        struct path link;
        void *cookie;
        const char *name;
        struct inode *inode;
        unsigned seq;
    } *stack, internal[EMBEDDED_LEVELS];
    struct filename    *name;
    struct nameidata *saved;
    unsigned    root_seq;
    int        dfd;
}
对比新老版本内核的nfs和jffs文件系统中链接文件的实现,发现nd_set_link()并不是简单地被新内核中的新函数代替了,而是引入了cookie变量实现链接,我实在是黔驴技穷了。。
最后用了3.x版本内核的最新一个3.18.24,配置和之前一样,make zImage后出现:
fs/yaffs2/yaffs_vfs.c:781: error: 'generic_file_aio_read' undeclared here (not in a function)
fs/yaffs2/yaffs_vfs.c:782: error: 'generic_file_aio_write' undeclared here (not in a function)
fs/yaffs2/yaffs_vfs.c:787: error: 'generic_file_splice_write' undeclared here (not in a function)
有了之前经验,很好解决(注释掉的是原版)
static const struct file_operations yaffs_file_operations = {
        .read = new_sync_read,//do_sync_read
        .write = new_sync_write,//do_sync_write
        .read_iter = generic_file_read_iter,//.aio_read = generic_file_aio_read
        .write_iter = generic_file_write_iter,//.aio_write = generic_file_aio_write
        .mmap = generic_file_mmap,
        .flush = yaffs_file_flush,
        .fsync = yaffs_sync_object,
        .splice_read = generic_file_splice_read,
        .splice_write = iter_file_splice_write,//generic_file_splice_write
        .llseek = generic_file_llseek,
}
这里要说一下read和write,其实在3.18.24内核中是有do_sync_read和do_sync_write的,但是这样生成的内核烧到板子会显示:
Unable to handle kernel NULL pointer dereference at virtual address 00000000
LR is at do_sync_read
所以我猜测是do_sync_read函数有问题,再fs.h中发现do_sync_read()声明的下面有一个new_sync_read(),并且其他文件系统就是用的这个函数,尝试了一下板子果然可以正常启动。但是会显示:
random: nonblocking pool is initialized  希望有大侠可以帮助解决
至此,板子上的引导是自己写的,内核是站在巨人肩膀修改的,文件系统是自己配置的。终于对嵌入式linux系统开发有了总体的认识,暂时不准备深入挖掘内核,下一步学习嵌入式linux的应用开发,但是对linux的热情和探索热情不会减~

阅读(5107) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~