内核系统调用的过程
系统调用是操作系统提供给用户的一组接口,每个系统调用都有一个对应的系统调用函数来完成相应的工作,用户通过这个接口向操作系统申请服务,如访问硬件资源,管理进程等,但是因为用户运行在用户空间,而系统调用运行在内核空间,因此用户程序不能之间调用函数,我们常见的open,fork,write都不是真正的调用函数,他们都只是c库,他们在函数中执行一个svc指令,使系统进入内核态接着在内核中进行一系类的判断,判断出哪个系统调用,再转到真正的调用函数,完成响应功能
首先我们开内核中的文件
vi inux-3.5/arch/arm/include/asm/unistd.h
#define __NR_OABI_SYSCALL_BASE 0x900000
17
18 #if defined(__thumb__) || defined(__ARM_EABI__)
19 #define __NR_SYSCALL_BASE 0
20 #else
21 #define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE
22 #endif
23
24 /*
25 * This file contains the system call numbers.
26 */
27
28 #define __NR_restart_syscall (__NR_SYSCALL_BASE+ 0)
29 #define __NR_exit (__NR_SYSCALL_BASE+ 1)
30 #define __NR_fork (__NR_SYSCALL_BASE+ 2)
31 #define __NR_read (__NR_SYSCALL_BASE+ 3)
#define __NR_write (__NR_SYSCALL_BASE+ 4)
33 #define __NR_open (__NR_SYSCALL_BASE+ 5)
34 #define __NR_close (__NR_SYSCALL_BASE+ 6)
35 /* 7 was sys_waitpid */
36 #define __NR_creat (__NR_SYSCALL_BASE+ 8)
37 #define __NR_link (__NR_SYSCALL_BASE+ 9)
38 #define __NR_unlink (__NR_SYSCALL_BASE+ 10)
39 #define __NR_execve (__NR_SYSCALL_BASE+ 11)
40 #define __NR_chdir (__NR_SYSCALL_BASE+ 12)
41 #define __NR_time (__NR_SYSCALL_BASE+ 13)
42 #define __NR_mknod (__NR_SYSCALL_BASE+ 14)
43 #define __NR_chmod (__NR_SYSCALL_BASE+ 15)
44 #define __NR_lchown (__NR_SYSCALL_BASE+ 16)
我们可以看到,其实每一个函数都对应一个内核的编号,我在需要的时候可以通过svc指令来进行传参调用(因为我们需要切换CPU的工作模式)
其中我们划分内存,用户的为0-3G,而系统调用在3-4G
测试函数
ssize_t my_read(int fd, void *buf, size_t count)
{
ssize_t ret=0;
__asm__ __volatile__(
"mov r0,%[fd]\n"
"mov r1,%[buf]\n"
"mov r2,%[count]\n"
"svc #(0x900000+3)\n"
"mov %[ret],r0\n"
:[ret]"=&r"(ret)
:[fd]"r"(fd),[buf]"r"(buf),[count]"r"(count)
:"r0","r1","r2"
);
}
ssize_t my_write(int fd, const void *buf, size_t count)
{
ssize_t ret=0;
__asm__ __volatile__(
"mov r0,%[fd]\n"
"mov r1,%[buf]\n"
"mov r2,%[count]\n"
"svc #(0x900000+4)\n"
"mov %[ret],r0\n"
:[ret]"=&r"(ret)
:[fd]"r"(fd),[buf]"r"(buf),[count]"r"(count)
:"r0","r1","r2"
);
}
int main(int argc, char *argv[])
{
if (argc !=3)
{
puts ("a.out [] []");
exit (-1);
}
int fd1,fd2;
char buf[100];
int ret1=0,ret2=0;
fd1 = open (argv[2],O_WRONLY | O_CREAT | O_TRUNC,0664);
if (fd1 <0)
exit(-1);
fd2 = open (argv[1],O_RDONLY |O_NDELAY);
if (fd2 <0)
exit(-1);
while ((ret1 =my_read(fd2,buf,100)>0))
{
ret2 = my_write(fd2,buf,100);
}
return 0;