Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在最小的linux内核环境中启动进程?_C_Linux_Bash_Linux Kernel_Qemu - Fatal编程技术网

C 如何在最小的linux内核环境中启动进程?

C 如何在最小的linux内核环境中启动进程?,c,linux,bash,linux-kernel,qemu,C,Linux,Bash,Linux Kernel,Qemu,是否可以在裸linux内核上运行通用C程序 我使用的是带有Qemu的虚拟化linux最小系统,在这里我加载了自定义内核和根文件系统,但显然无法运行我的用户空间hello world程序 编辑1:我已经更新了问题,使其更加详细。以下是我遵循的步骤: 1] 我已在主机上使用以下命令编译hello_world程序: gcc hello_world.c -o hello_world 源代码如下所示: #include <stdio.h> int main(int argc, char c

是否可以在裸linux内核上运行通用C程序

我使用的是带有Qemu的虚拟化linux最小系统,在这里我加载了自定义内核和根文件系统,但显然无法运行我的用户空间hello world程序

编辑1:我已经更新了问题,使其更加详细。以下是我遵循的步骤:

1] 我已在主机上使用以下命令编译hello_world程序:

gcc hello_world.c -o hello_world
源代码如下所示:

#include <stdio.h>

int main(int argc, char const *argv[]) {
  printf("Hello world!\n");
  return 0;
}
    $ ldd hello_world
    linux-vdso.so.1 =>  (0x00007ffc0dfc8000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007efd90658000)
    /lib64/ld-linux-x86-64.so.2 (0x000055a57447f000)
2] 我已经通过执行buildroot构建了根文件系统,它默认来自。我已经编译了linux内核并获得了相应的bzImage

3] 我安装了根文件系统,并将编译后的程序复制到其中,如下所示:

sudo mount -t ext2 rootfs.ext2 /home/andreww/Desktop/mountfile/
sudo cp hello_world /home/andreww/Desktop/mountfile/
sudo umount /home/andreww/Desktop/mountfile/
这感觉不对,我这么做是因为我还没有找到一种直接在客户机内部编译C程序的方法。 在来宾计算机上,我没有gcc,事实上,如果我尝试调用它,我会得到:

 # -sh: gcc: not found
4] 我已经用命令启动了模拟系统

qemu-system-x86_64 \
    -M pc \
    -append 'root=/dev/vda $extra_append' \
    -drive file=${images_dir}/rootfs.ext2,if=virtio,format=raw \
    -kernel ${images_dir}/bzImage \
    -m 256M \
    -net nic,model=virtio \
    -net user \
    -enable-kvm \
    -cpu host \
    -smp threads=4
这是我从你那里拿走的。 ext2是系统启动时所针对的根文件系统,bzImage是我将启动来宾机的内核映像

5] 来宾计算机在shell中进行仿真。这正是我所期望的,因为我只虚拟了裸内核,而不是整个操作系统映像

显示buildroot登录,我以root身份登录并运行以下命令:

当我尝试运行hello程序时,会显示以下消息:

-sh: ./hello_world: not found
我假设我的程序从未执行过,即使我通过调试看到它作为elf文件加载到系统中

如果我键入一个不存在的随机命令,我会得到相同的错误

目标是让hello_world程序在用户空间中运行,在内核之上,我不希望它成为它的一部分


我同意你们的观点,我可能缺少一些库或一些基本的东西,但我不知道该怎么做。

如果你打算这样做,你基本上可以运行一个进程而不是init。要运行进程而不是systems init应用程序,可以替换原始init,或者将init=/path/To/you/application作为内核参数传递给VM

但有几件事你应该记住:

所有库都需要存在于VM中,与构建应用程序的系统上的位置相同。这还包括它所基于的基本c库。您可以使用

ldd hello_world
例如,如果您编译以下程序

#include <stdio.h>

int main(int argc, char** argv) {
  printf("hello world!\n");
  return 0;
}
如果替换init进程,则需要处理控制台中断并正确处理它们。如果您不这样做,您将面临严重的系统崩溃风险。因此,如果您不知道自己在做什么,最好保留一个init进程并让该进程启动应用程序

我在过去看到过你命令的输出。您是否使用shell脚本启动应用程序?如果是这样,则可能表明您当前缺少虚拟环境中的某些库

编辑:

也许您可以创建一个静态链接的应用程序,这意味着将所有库编译到同一个文件中。在gcc上,您可以使用-static开关来实现这一点。请看区别:

$ gcc -o test test.c
$ ldd test
    linux-vdso.so.1 =>  (0x00007ffcd1f22000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f088d43a000)
    /lib64/ld-linux-x86-64.so.2 (0x00005580f8a2b000)
$ gcc -static -o test test.c
$ ldd test
    not a dynamic executable
如前所述,您可以使用ldd查找所需的库。我通常使用的另一个选项是objdump,因为输出更详细

因此,对于我的应用程序,这意味着类似这样的内容(我已将输出缩短到相关部分):

在我的例子中,这就是libc.So.6,我需要将主机上的/lib/x86_64-linux-gnu/libc.So.6复制到虚拟机中的/lib/x86_64-linux-gnu/libc.So.6


希望有帮助。

您应该检查文件上的执行标志。默认的输出文件是./a.out,使用-o,您可以更改输出文件。
rootfs.ext2
来自哪里?你是如何编写你的“hello world”程序的?如果要构建动态二进制文件,则需要确保虚拟环境包含与构建环境相同的
ld.so
和其他库。如果您正在构建一个静态二进制文件,这不会是一个问题。
init
是由裸内核启动的用户空间程序。你可以用你想要的任何东西来代替它。在您的例子中,您正在启动一个shell
sh
。当您尝试在shell下运行程序时,它会告诉您没有在正确的目录中。@stark,这是一条有点混乱的错误消息,我认为上面的larsks是对的,它是关于库和加载程序的。谢谢大家的建议!为了更精确,我修改了这个问题!我正在使用shell脚本来启动Qemu。我认为您关于缺少库的说法是对的,可能在虚拟化系统中,我缺少了所有东西,因为它只使用最少的内核代码,而没有其他任何东西。你知道我如何添加这些最小的功能,让我的hello_程序运行吗?为了更准确,我在问题中添加了更多的信息。我扩展了我的答案。我建议您在应用程序上使用ldd或objdump或其他工具来列出所需的库。另一个(可能更容易)的选择是静态链接它。我用-static标志重新编译了我的程序,现在它在客户机上正确运行。我还检查了来宾计算机中的/lib文件夹以及所需的.so文件,以便正确运行该程序。非常感谢!
$ gcc -o test test.c
$ ldd test
    linux-vdso.so.1 =>  (0x00007ffcd1f22000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f088d43a000)
    /lib64/ld-linux-x86-64.so.2 (0x00005580f8a2b000)
$ gcc -static -o test test.c
$ ldd test
    not a dynamic executable
$ objdump -p test

test:     file format elf64-x86-64

[...]

Dynamic Section:
  NEEDED               libc.so.6
  INIT                 0x00000000004003c8
  FINI                 0x00000000004005c4
  INIT_ARRAY           0x0000000000600e10
  INIT_ARRAYSZ         0x0000000000000008
  FINI_ARRAY           0x0000000000600e18
  FINI_ARRAYSZ         0x0000000000000008
[...]