免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5244 | 回复: 13

[文件系统] 有关linux文件系统/dev目录相关问题 [复制链接]

论坛徽章:
0
发表于 2015-04-27 22:14 |显示全部楼层
第一个疑问:在文件系统启动的时候一般会把基于内存的虚拟文件系统挂载到/dev,可能是写在fstab,也可能是在rcS中实现,但为什么要这么做?我不进行挂载,直接把字符设备节点存于flash中也是正常的啊
第二个疑问:我把/dev/console删除之后也能正常启动,只是会在启动的时候打印”Warning: unable to open an initial console.“。对应的内核中的源码:
static noinline int init_post(void)
        __releases(kernel_lock)
    if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
                printk(KERN_WARNING "Warning: unable to open an initial console.\n");
每一个制作根文件系统的教程中都要求在/dev下建立两个节点,console和null,为什么没有也能启动,这个节点具体是怎么用到的,我知道是和串口相关,但不知道是什么时候打开,怎么用它注册的函数进行字符传输的。
请大神们释疑,感激不尽!

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2015-04-28 09:37 |显示全部楼层
第一个问题,瞎猜的,是不是多数初始化脚本都假设常见字符设备都放在/dev/目录下(不知道是不是什么规范的要求)。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2015-04-28 09:40 |显示全部楼层
第二个,猜是在init(1)准备文件描述符0/1/2吧。

没有的话也没什么问题,就是init(及其派生脚本)有打印话,没办法在console上看到而已。

论坛徽章:
0
发表于 2015-04-28 15:00 |显示全部楼层
回复 2# nswcfd
谢谢仁兄……字符设备节点一般是存于/dev中,但/dev的内容是从内存挂载的,不是我们制作文件系统创建的,为什么要这么干呢

   

论坛徽章:
0
发表于 2015-04-28 15:07 |显示全部楼层
回复 3# nswcfd
init(1)指的是第一个用户程序吗?
就算我的根文件系统里不在dev下创建console,系统启动之后,也会创建这个节点。而且无论根文件系统是否存在console,系统启动之后,都可以根据console的创建时间判断这个节点是系统启动时创建的,应该是“mdev -s”干的

   

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2015-04-28 21:19 |显示全部楼层
本帖最后由 nswcfd 于 2015-04-28 21:30 编辑

就是指在init_post里面启动的1号进程,init(1)是我个人的表达方式,不太严谨

根据楼上的描述,看起来即使在启动init之前/dev/console不存在,init派生的脚本也会创建并打开这个文件的,
这样的话,就不会有“就是init(及其派生脚本)有打印话,没办法在console上看到而已”的问题。

论坛徽章:
0
发表于 2015-04-29 20:21 |显示全部楼层
关于第一个疑问,可能和mdev有关,以下摘自busybox-1.23.1 mdev.txt:
------------- MDEV Primer
-------------
For those of us who know how to use mdev, a primer might seem lame.  For everyone else, mdev is a weird black box that they hear is awesome, but can't seem to get their head around how it works.  Thus, a primer.
----------- Basic Use
-----------
Mdev has two primary uses: initial population and dynamic updates.  Both require sysfs support in the kernel and have it mounted at /sys.  For dynamic updates, you also need to have hotplugging enabled in your kernel.
Here's a typical code snippet from the init script: [0] mount -t proc proc /proc [1] mount -t sysfs sysfs /sys [2] echo /sbin/mdev > /proc/sys/kernel/hotplug [3] mdev -s
Alternatively, without procfs the above becomes: [1] mount -t sysfs sysfs /sys [2] sysctl -w kernel.hotplug=/sbin/mdev [3] mdev -s
Of course, a more "full" setup would entail executing this before the previous code snippet: [4] mount -t tmpfs -o size=64k,mode=0755 tmpfs /dev [5] mkdir /dev/pts [6] mount -t devpts devpts /dev/pts
The simple explanation here is that [1] you need to have /sys mounted before executing mdev.  Then you [2] instruct the kernel to execute /sbin/mdev whenever a device is added or removed so that the device node can be created or destroyed.  Then you [3] seed /dev with all the device nodes that were created while the system was booting.
For the "full" setup, you want to [4] make sure /dev is a tmpfs filesystem (assuming you're running out of flash).  Then you want to [5] create the /dev/pts mount point and finally [6] mount the devpts filesystem on it.

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:58:11
发表于 2015-05-01 15:11 |显示全部楼层
本帖最后由 arm-linux-gcc 于 2015-05-01 15:14 编辑


写flash,会损耗flash,所以/dev/一般都用devtmpfs或tmpfs或ramfs。
如果非要把/dev放在flash里也是可以的,为了避免损耗flash,此时需要保证:
1,不用udev mdev devtmpfs;
2,你制作根文件系统时就必须要所有需要的结点创建好,不仅仅是console和null这两个,而是所有的。
这样不但避免了损耗flash,而且还省去了创建结点的开销,启动要快一些(因为使用devtmpfs,或者使用tmpfs/ramfs搭配udev/mdev时,每次开机都得创建很多很多的结点,需要不少时间)





内核启动时,先会将一个ramfs作为rootfs
start_kernel()
    vfs_caches_init()
        mnt_init()
            init_rootfs()
                register_filesystem(rootfs_fs_type)       
            init_mount_tree()
               do_kern_mount("rootfs", 0, "rootfs", NULL);
到这里就将ramfs作为rootfs给mount起来了,要注意此时这个rootfs中还是空的,什么都没有



接下来就有点复杂了,分为好几种情况
CONFIG_BLK_DEV_INITRD,这个选项决定了是使用noinitramfs.c还是initramfs.c

a,如果使用noinitramfs.c,那么有
default_rootfs()
    sys_mkdir((const char __user __force *) "/dev", 0755);
    sys_mknod((const char __user __force *) "/dev/console", S_IFCHR | S_IRUSR | S_IWUSR, new_encode_dev(MKDEV(5, 1)));
    sys_mkdir((const char __user __force *) "/root", 0700);
于是rootfs中就有了/dev/console了,这里的default_rootfs是被包在rootfs_initcall中的,因此是在do_initcalls中被调用的,所以创建console是在sys_open("/dev/console")之前就做了,这种情况下,绝对不会open失败



b,如果使用initramfs.c,又分了两种情况
i)
设置了CONFIG_INITRAMFS_SOURCE,指向你制作根文件系统的源文件路径
你自己制作的根文件系统将会被打包到内核中
populate_rootfs会将打包在内核中的文件系统解压,于是你自己制作的根文件系统就以ramfs的形式存在了
在这种情况下,如果你自己做的根文件系统中没有/dev/console,那么sys_open(/dev/console)就会失败

ii)
没设置CONFIG_INITRAMFS_SOURCE
内核编译的时候会创建一个默认的initramfs_data.cpio,位置在usr/initramfs_data.cpio
你将其解包,可以看到有/dev/console,这种情况下,sys_open(/dev/console)也不可能会失败

论坛徽章:
0
发表于 2015-05-01 18:33 |显示全部楼层
回复 8# arm-linux-gcc
谢谢仁兄,我还没达到发短消息的等级


较新一点的内核好像都是用tmpfs搭配mdev,放到flash里节省启动时间确实会的,但对于损耗flash空间是什么意思啊,放到内存里也会损耗内存空间啊,而且内存空间比flash空间更珍贵吧。而且我试了一下,存在于flash上也可以用mdev正常创建节点。busybox关于mdev的说明有提到/dev要挂载成tmpfs系统,但好像也不是必须的,只是一般会这么做。猜想另一个原因是不是存在内存里便于管理,因为每次重启都不存在了,存在于flash会一直存在


内核启动的时候是会创建rootfs虚拟文件系统,我的内核没有配置CONFIG_BLK_DEV_INITRD,所以会调用default_rootfs,创建/dev/console和/root,但是这些都是存在于rootfs中的
kernel_init
    do_basic_setup();

    prepare_namespace();
         mount_root();
         sys_mount(".", "/", NULL, MS_MOVE, NULL);
         sys_chroot(".");

    init_post();
        if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
                printk(KERN_WARNING "Warning: unable to open an initial console.\n");

        run_init_process("/sbin/init");

在prepare_namespace中会先通过mount_root挂载根文件系统,然后会切换到根文件系统,这个时候rootfs相当于不可见了吧,然后在接下来的init_post才会调用
sys_open((const char __user *) "/dev/console", O_RDWR, 0),而且如果制作的根文件系统里不存在/dev/console时,确实会打印Warning: unable to open an initial console,
然后/sbin/init接管,启动根文件系统,在根文件系统开始,就把tmpfs挂载到了/dev,后来我们看到的console是mdev -s创建的,所以没看出我们制作根文件系统时console存在的必要啊

   

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:58:11
发表于 2015-05-01 20:39 |显示全部楼层
回复 9# 枫露清愁


    你的代码版本太老了,所以才有这个问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP