2.3 向内核添加自定义系统调用并测试
0.
[root@localhost uea_drv]# ls
Kconfig Makefile rain.c syscall.c
[root@localhost uea_drv]# vim Makefile
![]()
笔记:
obj-y:打个比方,我要编译的是hello.c这个文件,obj-y就会把hello.c或者hello.c编译生成的hello.s文件链接到内核中去。
obj-m:打个比方,我要编译的是hello.c这个文件,obj-m则是编译成hello.ko,在系统启动的时候,需要手动insmod进行加载,才能加载到内核里面去。
除了以上两种方式,其余的obj-xxx的形式不会被编译。
1.
[root@localhost uea_drv]# vim rain.c
1 #include <linux/init.h>
2 #include <module.h>
3 #define LINENUM 213
4
5 static int __init demo_init(void)
6 {
7 int i = 0;
8 u32 cpsr;
9 __asm__ __volatile__(
10 "mrs %[cpsr], cpsr\n\t" //指令域
11 :[cpsr]"=&r"(cpsr) //输出变量声明域
12 );
13 while(i < LINENUM) {
14 printk("*****gemeng is handsome!*********%#x*************\n",cpsr&0x1f);
15 //取低5位可查看模式:supervisor svc 10011
16 //重新编译/加载内核到第二分区看启动信息,打印213个0x13
17 i++;
18 }
19 return 0;
20 }
21
22 module_init(demo_init);
23 MODULE_LICENSE("GPL");
2.
[root@localhost linux-3.5]# vim arch/arm/include/asm/unistd.h //3.5内核有378个系统调用号
[root@localhost linux-3.5]# vim arch/arm/kernel/calls.S //一一对应, 可以添加系统调用函数(返回值为long型)

[root@localhost uea_drv]# vim syscall.c
1 /*
2 * 自己做一个系统调用函数ledcontrol,加载到内核中,用一个app.c来测试
3 */
4 #include<linux/syscalls.h>
5 //asmlinkage long sys_ledcontrol(int num, int cmd)
6 SYSCALL_DEFINEE2(ledcontrol, int, num, int, cmd)
7 {
8 if(num<1 || num>4) {
9 return -EINVAL; //代码须作错误处理。
10 }
11
12 if((cmd != 1) && (cmd !=0)) {
13 return -EINVAL;
14 }
15
16 printk("[kernel]:led %d is %s!\n",num,cmd ?"on":"off");
17 return 0;
18 }
3.
[root@localhost linux-3.5]# make //重新编译,生成新内核。

[root@localhost uea_drv]# ls
built-in.o Makefile modules.order rain.o syscall.o
Kconfig modules.builtin rain.c syscall.c
4.
/*将内核zImage烧写(放置)到EMMC的第二分区*/
PC端: ARM端:
a. ls /dev/mmcblk0p* //EMMC的分区对应设备文件/dev/mmcblk0p1 2 3 4
b.cp zImage /rootfs/ c.mount /dev/mmcblk0p2 /mnt/
d.cp zImage /mnt/
e.umount /mnt/
![]()

[millet9527@/]reboot //重启开发板就可以看到现象(rain)了。(界面是四只企鹅的新界面)
。。。。。。
5.写app来测试自定义的系统调用。
/*PC端写app*/
[root@localhost syscall_app]# ls /*PC端写app*/
syscall_app.c
[root@localhost syscall_app]# arm-linux-gc
arm-linux-gcc arm-linux-gcc-4.5.1 arm-linux-gccbug arm-linux-gcov
[root@localhost syscall_app]# arm-linux-gcc syscall_app.c -o syscall_app
[root@localhost syscall_app]# cp syscall_app /rootfs
/*arm开发板端测试*/

=============================================================
[root@localhost fs]# vim read_write.c //举例
460 SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) //追 38
vim /linuxtags/include/linux/syscalls.h
系统调用函数机制之
自己制作/封装mill_read.c mill_fork.c
//去实现系统调用(使用原来的系统调用号)
[root@localhost app]# arm-linux-gcc mill_fork.c
[root@localhost app]# cp a.out /rootfs
[millet9527@/]#./a.out
this is 153parent!
this is 154child!
[root@localhost app]# arm-linux-gcc mill_fork.c -E
void func_aaaaa(void) { printf("info:%s\n","aaaaa"); };
void func_bbbbb(void) { printf("info:%s\n","bbbbb"); };
应用层通过执行svc指令来调用系统调用函数(有编号)
内存管理进行 自动切换内存模式
手册:异常、软中断:B1.8.1 1167页; B1.9.4
## 预处理时实现字符拼接
# 字符串

浙公网安备 33010602011771号