用户程序调用getuid()
C库给所用系统调用作出了定义,但是自己定义系统调用不想改变库,则在自己mian函数前加入:_syscall0(int, mysyscall )
#include <linux/unistd.h>
int main()
{
int i = getuid();
printf("getuid:%d\n", i);
return 0;
}
getuid经unistd.h宏转换
- getuid变为__NR_getuid
- 这里无参数到寄存器
- 返回类型为int
- __NR_getuid根据宏转换为24
//linux/include/asm-i386/unistd.h
#define __NR_getuid 24
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
__syscall_return(type,__res); \
}
int getuid(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_getuid)); \
__syscall_return(int,__res); \
}
/*
"int $0x80" \
: "=a" (__res) \
: "0" (__NR_getuid)); \
看成一句,进入软中断
*/
进入软中断,执行system_call
- 系统启动时,系统调用的软中断已经在traps.c中注册好
- 发生系统调用软中断自动进入system_call
- 查询sys_call_table找到第24个系统调用sys_setuid16
//linux/arch/i386/kernel/entry.S
ENTRY(system_call)
pushl %eax # save orig_eax
SAVE_ALL
GET_CURRENT(%ebx)
testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS
jne tracesys
cmpl $(NR_syscalls),%eax
jae badsys
call *SYMBOL_NAME(sys_call_table)(,%eax,4)
movl %eax,EAX(%esp) # save the return value
ENTRY(ret_from_sys_call)
cli # need_resched and signals atomic test
cmpl $0,need_resched(%ebx)
jne reschedule
cmpl $0,sigpending(%ebx)
jne signal_return
restore_all:
RESTORE_ALL
//linux/arch/i386/kernel/entry.S
ENTRY(sys_call_table)
.......
.long SYMBOL_NAME(sys_getuid16) /* 24 */
.......
执行/linux/kernel/uid16.c中sys_getuid16
- asmlinkage 是gcc中标志,说明该函数从堆栈中而不是从寄存器中那参数
-asmlinkage 等同于attribute((regparm(0)))
asmlinkage long sys_getuid16(void)
{
return high2lowuid(current->uid);
}
内核空间数据处理
用户空间要传递数据给内核,通过传递指向用户态数据的结构指针。用户态传递给内核是一个指针加一个范围,有可能超过进程地址空间,破坏运行环境。内核总是要对这个地址范围进行检验,包括是否正确,能不能读、写等。
- linux/include/asm-i386/uaccess.h
//copy_to_user中会调用access_ok(type, addr, size)检测
//type:指定检查类型(读、写等)
//后两个参数为范围和长度
copy_from_user(void *to, const *from, int c);
copy_to_user(void *to, const *from, int c);
include/linux/kernel.h
编写内核代码时常用的一个函数,用来大洋信息到console,或者系统日志。比printf(内核中不可用)多一个表示打印级别。级别比console高打印到console,否则打印到系统日志/var/log/message
asmlinkage int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2)));
#define KERN_EMERG "<0>" /* system is unusable */
#define KERN_ALERT "<1>" /* action must be taken immediately */
#define KERN_CRIT "<2>" /* critical conditions */
#define KERN_ERR "<3>" /* error conditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition */
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */
- include/linux/slab.h
//内核编程时分配内存,flags表示分配内存的类型
extern void *kmalloc(size_t size, int flags);
- _ _init表示这个函数使用后就可以丢弃
- _ _exit表示如果不是以模块方式编译这段程序,则后面的函数可以丢弃
int __init init_myf()
{
}
void __exit exit_myf()
{
}