• 在内核中添加系统调用


    前面我们学习了在内核中添加自己的代码,这次我们在内核中添加一个自己的系统调用,就像open/close一样的函数!

    当我们应用程序调用open close函数时: open close函数是经过libc.so 库调用syscall函数,然后syscall函数再经过SWI调用内核的系统调用的;

    所有我们写了一个系统调用之后,也要实现这样一个过程,才能让应用层正常调用系统调用.

      vim  calls.S  为自己的函数注册系统调用号378

    385                 CALL(sys_syncfs)
    386                 CALL(sys_sendmmsg)
    387 /* 375 */       CALL(sys_setns)
    388                 CALL(sys_process_vm_readv)
    389                 CALL(sys_process_vm_writev)
    390 /* 378 */       CALL(sys_my_add)
    391 #ifndef syscalls_counted
    392 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
    393 #define syscalls_counted
    394 #endif
    395 .rept syscalls_padding
    396                 CALL(sys_ni_syscall)
    397 .endr

       vim arch/arm/include/asm/unistd.h 声明自己的系统调用函数 407行

    403 #define __NR_sendmmsg                   (__NR_SYSCALL_BASE+374)
    404 #define __NR_setns                      (__NR_SYSCALL_BASE+375)
    405 #define __NR_process_vm_readv           (__NR_SYSCALL_BASE+376)
    406 #define __NR_process_vm_writev          (__NR_SYSCALL_BASE+377)
    407 #define __NR_my_add                     (__NR_SYSCALL_BASE+378)
    408 
    409 /*
    410  * The following SWIs are ARM private.
    411  */
    412 #define __ARM_NR_BASE                   (__NR_SYSCALL_BASE+0x0f0000)
    413 #define __ARM_NR_breakpoint             (__ARM_NR_BASE+1)
    414 #define __ARM_NR_cacheflush             (__ARM_NR_BASE+2)
    415 #define __ARM_NR_usr26                  (__ARM_NR_BASE+3)

      在 arch/arm/kernel目录下创建一个mysyscall文件夹: 并在文件夹内:touch mysyscall.c mysyscall.h Makefile三个文件,写入如下代码,然后编译内核,并刷机,这样就把自己的syscall编译到内核了.

      mysyscall.c

      

      1 #include <linux/init.h>
      2 #include <linux/sched.h>
      3 #include <linux/module.h>
      4 #include "mysyscall.h"
      5 /* asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
      6                                       loff_t offset, loff_t len)
      7  {
      8          return sys_fadvise64_64(fd, offset, len, advice);
      9  }                                                          */
     10 //asmlinkage:表示将来这段代码是要由汇编来调用的。
     11  asmlinkage long sys_my_add(int a,int b)
     12  {
     13         printk("this is liuye's syscall!
    ");
     14          return a+b;
     15  }
     16 
     17 //module_init(sys_my_add);
     18 MODULE_LICENSE("GPL");

      mysyscall.h

      1 #ifndef __MYSYSCALL_H_
      2 #define __MYSYSCALL_H_
      3 
      4  asmlinkage long sys_my_add(int a,int b);
      5 
      6 
      7 #endif

      makefile

      1 obj-y += mysyscall.o

      vim ../Makefile

     74 AFLAGS_iwmmxt.o                 := -Wa,-mcpu=iwmmxt
     75 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
     76 # 在这层malefile中添加下一曾Makefile路径
     77 obj-y  += mysyscall/
     78 

      之后 make -j4 利用SD卡刷机 系统调用添加到内核中了;

      然后我们要制作一个包含mysyscall的库:在PC机上随便找一个文件夹:touch my_add.c my_add.h 写入如下代码.并编译成动态库:

      vim my_add.c

      1 //这三行是为了调用syscall而包含的头文件和宏定义:可以man syscall查看
      2 #define _GNU_SOURCE         /* See feature_test_macros(7) */
      3 #include <unistd.h>
      4 #include <sys/syscall.h>   /* For SYS_xxx definitions */
      5 #include <stdio.h>
      6 int my_add(int a ,int b)
      7 {
      8         printf("this is liuye's app
    ");
      9         return  syscall(378,a,b);
     10 
     11 }

      vim my_add.h

      1 #ifndef __MY_ADD_H_
      2 #define __MY_ADD_H_
      3 
      4 extern int my_add(int a, int b);
      5 
      6 #endif

      把上面的my_add.c my_add.h制作成动态库:生成libadd.so

    [liuye@LiuYe 01syscall]$>arm-linux-gcc -fPIC -c -o my_add.o my_add.c
    [liuye@LiuYe 01syscall]$>arm-linux-gcc my_add.o -shared -o libadd.so

      然后写一个应用程序来调用下我们系统调用:touch test.c

      vim test.c

      1 #include <stdio.h>
      2 #include "my_add.h"
      3 //#include <my_add.h>
      4 int main(void)
      5 {
      6         int sum;
      7         sum = my_add(1,2);
      8         printf("sum = %d
    ",sum);
      9         return 0;
     10 }
    77     使用arm-linux-gcc编译test.c代码,需要链接动态库 -L指定路径  -l指定库名
    78     生成可执行文件:arm-linux-gcc test.c -o test -L./ -ladd
    79     复制库文件和可执行文件到共享文件夹:cp libadd.so test /myroot
    81     把新编译的内核copy到SD卡,刷机;
    82     PC端:1 开启共享服务
    83           2 minicom链接开发板
    84             mount -t nfs -o nolock,rw 192.168.1.10:/myroot /mnt
    85             cd /mnt
    86             cp libadd.so /lib/ 放到根下lib下,在运行的时候不用指定路径
    87             ./test  运行即
    root@board liuye_dir#./test 
    this is liuye's app
    [ 1817.020000] this is liuye's syscall!
    sum = 3
    root@board liuye_dir#

      以上就完成了一个系统调用的全过程,相信同学们即学会了如何在内核中添加一个系统调用,也学会了应用程序调用系统调用的全过程了,是不是觉得很赞?!!!!!!!!!!哈哈哈哈反正我觉得是有收获的!

    有时候,不小心知道了一些事,才发现自己所在乎的事是那么可笑。
  • 相关阅读:
    Leetcode: Summary Ranges
    Leetcode: Kth Smallest Element in a BST
    Leetcode: Basic Calculator II
    Leetcode: Basic Calculator
    Leetcode: Count Complete Tree Nodes
    Leetcode: Implement Stack using Queues
    Leetcode: Maximal Square
    Leetcode: Contains Duplicate III
    Leetcode: Invert Binary Tree
    Leetcode: The Skyline Problem
  • 原文地址:https://www.cnblogs.com/axjlxy/p/8964389.html
Copyright © 2020-2023  润新知