[英]Writing my own init executable
I wanted to create my own init and some Linux fun for a snowy weekend. 我想在一个下雪的周末创建自己的init和一些Linux乐趣。 I know, kernel boots with rootfs and gives the flow to /sbin/init after some driver loading and disk mounting. 我知道,内核使用rootfs启动,并在一些驱动程序加载和磁盘安装后将流程提供给/ sbin / init。 I downloaded ubuntu cloud image and tried direct kernel boot with kvm as follows: 我下载了ubuntu云映像并尝试使用kvm直接进行内核启动,如下所示:
kvm -m 1G -nographic -kernel vmlinuz-3.19.0-32-generic -initrd initrd.img-3.19.0-32-generic -append "console=ttyS0 root=/dev/sda1 rw init=/myinit" -hda mydisk.img
It works somewhat fine with trusty-server-cloudimg-amd64-disk1.img (if you don't mind hanging at cloud-init), then I proceeded to copy it and delete its content. 使用trusty-server-cloudimg-amd64-disk1.img(如果你不介意挂在cloud-init上)它运行得有点好,然后我继续复制它并删除它的内容。
modprobe nbd
qemu-nbd -c /dev/nbd0 mydisk.img
fdisk -l /dev/nbd0 # confirm partition
mount /dev/nbd0p1 disk/
# Delete all files with myinit.c and myinit
And here is my magical init: 这是我的魔法初学者:
int main(){
printf("Welcome to my kernel\n");
printf("Welcome to my kernel\n");
printf("Welcome to my kernel\n");
while(1);
}
I compile it with gcc -static myinit.c -o myinit
. 我用gcc -static myinit.c -o myinit
编译它。 However a kernel panic occurs because of my init. 但是由于我的init,因此发生内核恐慌。 I verified it by renaming myinit to myinit2 and kernel could not find it, and it did not crash. 我通过将myinit重命名为myinit2并且内核无法找到它来验证它,并且它没有崩溃。 I know writing init cannot be as simple as the above, but what are the steps required for it? 我知道编写init不能像上面这么简单,但它需要的步骤是什么? I am reading upstart source code 我正在阅读新手的源代码
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... [ 1.460164] tsc: Refined TSC clocksource calibration: 2394.558 MHz
[ 1.866560] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3
done.
[ 6.251763] EXT4-fs (sda1): recovery complete
[ 6.253623] EXT4-fs (sda1): mounted filesystem with ordered data mode. Opts: (null)
Begin: Running /scripts/local-bottom ... done.
done.
Begin: Running /scripts/init-bottom ... mount: mounting /dev on /root/dev failed: No such file or directory
done.
mount: mounting /sys on /root/sys failed: No such file or directory
mount: mounting /proc on /root/proc failed: No such file or directory
[ 6.299404] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000200
[ 6.299404]
[ 6.300013] CPU: 0 PID: 1 Comm: init Not tainted 3.19.0-32-generic #37~14.04.1-Ubuntu
[ 6.300013] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
[ 6.300013] ffff88003c118700 ffff88003dee7e38 ffffffff817af41b 00000000000017d6
[ 6.300013] ffffffff81a90be8 ffff88003dee7eb8 ffffffff817a925b ffff88003dee8000
[ 6.300013] ffffffff00000010 ffff88003dee7ec8 ffff88003dee7e68 ffffffff81c5ee20
[ 6.300013] Call Trace:
[ 6.300013] [<ffffffff817af41b>] dump_stack+0x45/0x57
[ 6.300013] [<ffffffff817a925b>] panic+0xc1/0x1f5
[ 6.300013] [<ffffffff81077b01>] do_exit+0xa11/0xb00
[ 6.300013] [<ffffffff811ec53c>] ? vfs_write+0x15c/0x1f0
[ 6.300013] [<ffffffff81077c7f>] do_group_exit+0x3f/0xa0
[ 6.300013] [<ffffffff81077cf4>] SyS_exit_group+0x14/0x20
[ 6.300013] [<ffffffff817b6dcd>] system_call_fastpath+0x16/0x1b
[ 6.300013] Kernel Offset: 0x0 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[ 6.300013] drm_kms_helper: panic occurred, switching back to text console
[ 6.300013] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000200
[ 6.300013]
I know myinit is completely static: 我知道myinit是完全静态的:
# ldd disk/myinit
not a dynamic executable
So it should not depend anything else, I guess. 所以它不应该依赖别的东西,我想。 But what am I doing wrong and why is kernel panicking? 但是我做错了什么,为什么内核恐慌? (Kernel panicks without printfs too) (没有printfs的内核恐慌)
I am reading sysvinit source (it should be simpler then upstart & systemd & openrc) but its too long, but the main idea of init is to own the processes and it rests in while(1) loop too. 我正在阅读sysvinit源代码(它应该比upstart和systemd&openrc更简单)但是它太长了,但init的主要思想是拥有进程并且它依赖于while(1)循环。
Your stdin
, stdout
and stderr
might not be connected when your init
starts. init
启动时,您的stdin
, stdout
和stderr
可能无法连接。 It's common to see a sequence similar to the following at the start of an init
program: 在init
程序开始时看到类似于以下的序列是很常见的:
int onefd = open("/dev/console", O_RDONLY, 0);
dup2(onefd, 0); // stdin
int twofd = open("/dev/console", O_RDWR, 0);
dup2(twofd, 1); // stdout
dup2(twofd, 2); // stderr
if (onefd > 2) close(onefd);
if (twofd > 2) close(twofd);
This ensures that stdin
, stdout
and stderr
are connected to the system console. 这可确保stdin
, stdout
和stderr
连接到系统控制台。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.