《Unix高级编程学习笔记》 1git
POSIX、API、C库和syscall之间的关系 github
long
类型的返回值(为与64位的硬件体系结构保持兼容)errno
全局变量,经过perror()库函数翻译成用户理解的错误字符串。SYSCALL_DEFINE0(###)
//定义内核中的系统调用getpid()的实现
//展开前
SYSCALL_DEFINE0(getpid)
{
return task_tgidvnr(current); //return current->tgid
}
//展开后
asmlinkage long sys_getpid(void){
return task_tgidvnr(current); //return current->tgid
}
复制代码
用例:编程
//定义内核中的系统调用bar()的实现
//展开前
SYSCALL_DEFINE0(bar)
//展开后
asmlinkage long sys_bar()
复制代码
注:用户空间返回int
,内核空间返回long
安全
用于关联系统调用。用户进程空间的进程执行一个系统调用时,使用系统调用号指明到底执行哪一个系统调用,且不会说起系统调用的名称。bash
sys_ni_syscall()
返回-ENOSYS
,专门填补无效系统调用;x86-64
中,定义于arch/i386/kernel/syscall_64.c
中,并为每一个系统调用指定惟一的系统调用号很高:上下文切换时间短,进出内核被优化得简洁高效,系统调用处理程序和系统调用简洁函数
告诉内核须要切换到内核态,让内核表明应用程序在内核空间执行系统调用 实现机制: 系统调用处理程序:引起一个异常促使系统谢欢到内核态去执行异常处理程序,叫syscall_call()性能
system_call()
NR_syscalls
相比较,大于等于NR_syscalls则返回-ENOSYS,不然执行相应的系统调用call *sys_call_table(,%eax, 8)
//8表明系统调用表中表项以64位类型存放,则结果等于 系统调用号×4 用于查询系统调用位置。
//x86-32则用4代替8
复制代码
x86-32
系统中前五个参数放置在ebx, ecx, edx, esi和edi
中编写完一个系统调用后,将其注册诚正式的系统调用学习
<asm/unistd.h>
中一般,系统调用靠C库支持,若是仅仅写出系统调用,glibc库并不支持,怎么办呢 答:宏_syscalln()
,其中n范围为0~6表明传递给系统调用的参数个数,功能为设置好寄存器并调用陷入指令 例子:优化
//open()系统调用定义
long open(const char* filename, int flags, int mode)
复制代码
不靠库支持,直接调用此系统调用的宏形式ui
#define NR_open 5
_syscall3(long, open, const char*, filename, int, flags, int, mode)
复制代码
在Android系统中,_syscall()
被syscall()
替代,且每一种Android支持的系统调用的参数形式都在Android源码中被SYSCALLS.txt记录,咱们能够根据系统调用的知识,并结合SYSCALLS.txt,能够很轻易地写出本身对应的的syscall()。