添加Linux系统调用与利用QEMU测试

嵌入式技术

1343人已加入

描述

1.编译内核

(1).源码下载链接

(2).查看本机配置参数命令:screenfetch;

(3).三种编译方式进行内核编译配置

make menuconfig

 make xconfig

 make gconfig(需要安装GTK Package)

(4).查看内核配置文件: ll -a | grep config;

(5).清除上一次构建生成的config文件:make mrproper;

(6).编译内核:make -jn 可以加快内核编译,n为线程数,编译时间与电脑配置有关;

(7).清除上一次内核编译过程生成的文件:make clean;

(8).编译结果内核镜像文件生成路径:linux-5.19.4/arch/x86/boot/bzImage;

Linux

内核编译

Linux

内核镜像文件

2.编译命令行工具集合busyBox

(1).busyBox源码下载链接

(2).解压源码后,进行make menuconfig配置编译选项。开启静态编译Build Static;binary(no shared libs)选项;

(3).编译busyBox源码:make -j4;

(4).编译完成后进行安装:make install;

(5).命令行工具安装在路径:busybox-1.35.0/_install/bin/;

(6).在命令行工具安装路径下执行可执行程序./busybox --help可以查询当前所有可用的命令;

(7).在命令行工具安装路径下执行可执行程序./busybox sh可以进入shell环境;

Linux

busybox编译

3.使用busybox制作initramfs

(1).在home目录下创建initramfs/bin文件夹;

(2).从已经编译并安装好的busybox目录busybox-1.35.0/_install/bin/下将可执行程序busybox拷贝到initramfs/bin目录下;

(3).在initramfs目录下创建文件init, 并修改其权限为可执行chmod +x init

(4).切换到目录initramfs下,执行find . -print0 | cpio -ov --null --format=newc | gzip -9 > initramfs.img命令将该目录下的所有文件使用cpio命令归档并使用gzip进行压缩,生成initramfs.img文件;

#!/bin/busybox sh


/bin/busybox mkdir -p /proc && /bin/busybox mount -t proc none /proc


/bin/busybox echo "Hello Syscall"


export 'PS1=(kernel) = >'
/bin/busybox sh

4.系统调用

(1).查询syscall用法:man 2 syscall

(2).系统调用:上层应用程序调用的API

举例:C库中的printf() --> glibc 库中的write() --> kernel中的write()

(3).系统调用和计算机的体系结构相关

(4).系统调用的指令

syscall和init

     syscall是64bit机器的指令,init是32bit机器的指令

(5).系统调用的返回值

返回值存储在rax、rdx寄存器中

(6).系统调用的参数

支持6个参数,分别对应6个寄存器

5.系统调用相关的代码位置

(1).不同体系结构有不同的系统调用
arch/x86/entry/syscalls/syscall_64.tbl
(2).系统调用属于内核的一部分,不能作为模块进行编译
对系统调用的修改需要重新编译内核
(3).宏__NR_syscalls
系统调用的个数
arch/x86/include/generated/uapi/asm/unistd_64.h
注意:系统调用的编号从0开始的

6.实例:添加新的系统调用(获取cpu的个数)

(1).注册系统调用号
arch/x86/entry/syscalls/syscall_64.tbl文件中,例如 :添加451 common get_cpu_number sys_get_cpu_number

(2).声明系统调用函数
在include/linux/syscalls.h文件中,添加声明asmlinkage long sys_get_cpu_number(void)
(3).实现系统调用
在kernel/sys.c文件中实现系统调用,具体代码如下:

SYSCALL_DEFINE0(get_cpu_number){
        return num_present_cpus();
    }

7.使用QEMU测试新的系统调用

(1).重新编译内核,具体见第1小节;

(2).使用busybox制作initramfs,具体见第3小节;

(3).本地静态编译测试代码gcc -static get_cpu.c -o get_cpu,将编译生成的可执行文件get_cpu拷贝进initramfs文件夹中,进行打包;

/************************************************************************
    > File Name: get_cpu.c
    > Author: CurryCoder
    > Mail: 1217096231@qq.com 
    > Created Time: 2022年09月18日 星期日 09时42分51秒
************************************************************************/


#include < stdio.h >
#include < unistd.h >
#include < sys/syscall.h >


int main(){
  int pid = syscall(39);
  printf("pid=%dn",pid);


  int cpu_number = syscall(451); // 451为get_cpu_number的系统调用号
  printf("cpus=%dn",cpu_number);

  return 0;
}

(4).编写Makefile文件

.PHONY: clean initramfs run


${shell mkdir -p build}


initramfs:
  cd initramfs && find . -print0 | cpio -ov --null -H newc | gzip -9 > ../build/initramfs.img


clean:
  rm -rf build


run:
  qemu-system-x86_64 
    -kernel bzImage 
    -m 256M 
    -smp 4 
    -nographic 
    -initrd build/initramfs.img 
    -append "init=/init earlyprintk=serial,ttyS0 console=ttyS0"

Linux

整个目录结构

(5).启动QEMU模拟内核启动,可以调整-smp参数观察效果

Linux

启动QEMU

Linux

测试结果

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分