• Linux系统调用及测试


    1.系统调用
    • 查询syscall用法:man 2 syscall
    • 系统调用:上层应用程序调用的API
      • eg:printf() --> glibc write() --> kernel write()
    • 系统调用和计算机的体系结构相关
    • 系统调用的指令
      • syscall和init
      • syscall是64bit机器的指令,init是32bit机器的指令
    • 系统调用的返回值
      • 返回值:rax、rdx寄存器
    • 系统调用的参数
      • 支持6个参数,分别对应6个寄存器
    2.demo程序
    /************************************************************************
        > File Name: test_syscall.c
        > Author: CurryCoder
        > Mail: 1217096231@qq.com 
        > Created Time: 2022年09月18日 星期日 09时42分51秒
    ************************************************************************/
    
    #include 
    #include 
    #include 
    
    int main(){
    	int pid = syscall(39); // 39为getpid的系统调用号
    	printf("pid=%d\n",pid);
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    3.系统调用相关的代码位置
    • 不同体系结构有不同的系统调用
      • arch/x86/entry/syscalls/syscall_64.tbl
    • 系统调用属于内核的一部分,不能作为模块进行编译
      • 对系统调用的修改需要重新编译内核
    • 宏__NR_syscalls
      • 系统调用的个数
      • arch/x86/include/generated/uapi/asm/unistd_64.h
      • 注意:系统调用的编号从0开始的
    4.实例:添加系统调用(获取cpu的个数)
    • (1).注册系统调用号
      • arch/x86/entry/syscalls/syscall_64.tbl文件中,eg: 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();
      }
      
      • 1
      • 2
      • 3
    5.测试系统调用
    • (1).重新编译内核
    • (2).使用busybox制作initramfs
    #!/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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • (3).本地静态编译测试代码gcc -static get_cpu.c -o get_cpu,打包进initramfs
    /************************************************************************
        > File Name: get_cpu.c
        > Author: CurryCoder
        > Mail: 1217096231@qq.com 
        > Created Time: 2022年09月18日 星期日 09时42分51秒
    ************************************************************************/
    
    #include 
    #include 
    #include 
    
    int main(){
    	int pid = syscall(39);
    	printf("pid=%d\n",pid);
    
    	int cpu_number = syscall(451); // 451为get_cpu_number的系统调用号
    	printf("cpus=%d\n",cpu_number);
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • (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"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • (5).用QEMU模拟,可以调整-smp参数观察效果
  • 相关阅读:
    3.2 Redis的持久化机制-RDB
    Java-Redis-Redisson配置
    Jmeter接口测试——使用教程(上)
    torch.hub 记录
    有趣的设计模式——解救抓狂的商场收银员
    ElasticSearch总结
    利用快速排序的思想寻找第k小的元素
    MySQL的多表查询
    QT实现TCP服务器客户端的实现
    nvm管理多个node版本,快速来回切换node版本
  • 原文地址:https://blog.csdn.net/cdlwhm1217096231/article/details/126918760