写自己的函数直接调用Linux system call
来源:互联网 发布:国产耽美电视剧网络剧 编辑:程序博客网 时间:2024/05/17 23:53
众所周知,Linux系统调用是访问Linux内核的必经之路。作为上层软件开发着来说,一般无须考虑自己的程序是如何通过Linuxkernel system call层,因为这是libc的任务,程序员只需要知道libc提供的接口就可以了。但是,有时候为了定制或实现新的LibC一类的需要调用systemcall的软件包或这软件,了解如何写自己的可以直接调用Linux系统调用的函数是必要的。在这篇文章中,给出了一个简单的调用write()系统调用的汇编代码和C中嵌入汇编两种方法实现的软件。
预备知识:
软件中断的产生。首先是通过“int 0x80”指令产生0x80号软件中断。Linux规定了0x80号中断是内核系统调用的中断门。当然,操作系统设计人员在设计系统时,可以更改该中断号。
系统调用号。每一个系统调用都分配了唯一的一个系统调用号,该调用号可以通过访问include/asm-i386/unistd.h文件
#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_lchown 16
#define __NR_break 17
#define __NR_oldstat 18
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
#define __NR_oldfstat 28
..........
例如write()函数的系统调用号是4(#define __NR_write 4)
确定函数参数。在调用系统调用之前,要确定相应系统调用函数的个数,意义。通常,函数的参数分别通过不同寄存器传递。以X86为例,在linux-2.6.17中,ebx, ecx, edx 分别代表第1,2,3个参数。由于Linux kenel不同,其函数参数的传递通常有其对应的compiler确定。函数参数个数的去定可以通过搜索: sys_syscall_name()函数。以write为例:
asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count);
现在你已经了解基本的概念和技术,现在看一下下面两个简单的程序,他们是将“hello world”输出到屏幕。当然是同多调用write 系统调用完成的。
/* write.S*/
.text
.globl _start, _exit, message
.align 4
_start:
/* Reseting EFLAGS */
pushl $0
popf
push %eax /* Save the register value*/
push %ebx
push %ecx
push %edx
mov $4, %eax /* system call number, write_sys() */
mov $1, %ebx /* file description */
mov $message, %ecx /* message address */
mov $14, %edx /* message size */
int $0x80 ;
pop %edx /* Restore the resigter value*/
pop %ecx
pop %ebx
pop %eax
_exit:
mov $1, %eax
int $0x80
message:
.asciz "hello world./n" ;
/* write.c*/
static char message[]={"hello world!/n"};
int main(int argc, char *argvs)
{
int size;
asm volatile( /
"int $0x80" /
: "=a"(size)
: "0"(4), "b"(1), "c"(message), "d"(13));
return 0;
}
有兴趣的可以用反汇编看一下二者经过编译后有什么区别。
预备知识:
软件中断的产生。首先是通过“int 0x80”指令产生0x80号软件中断。Linux规定了0x80号中断是内核系统调用的中断门。当然,操作系统设计人员在设计系统时,可以更改该中断号。
系统调用号。每一个系统调用都分配了唯一的一个系统调用号,该调用号可以通过访问include/asm-i386/unistd.h文件
#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_lchown 16
#define __NR_break 17
#define __NR_oldstat 18
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
#define __NR_oldfstat 28
..........
例如write()函数的系统调用号是4(#define __NR_write 4)
确定函数参数。在调用系统调用之前,要确定相应系统调用函数的个数,意义。通常,函数的参数分别通过不同寄存器传递。以X86为例,在linux-2.6.17中,ebx, ecx, edx 分别代表第1,2,3个参数。由于Linux kenel不同,其函数参数的传递通常有其对应的compiler确定。函数参数个数的去定可以通过搜索: sys_syscall_name()函数。以write为例:
asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count);
现在你已经了解基本的概念和技术,现在看一下下面两个简单的程序,他们是将“hello world”输出到屏幕。当然是同多调用write 系统调用完成的。
/* write.S*/
.text
.globl _start, _exit, message
.align 4
_start:
/* Reseting EFLAGS */
pushl $0
popf
push %eax /* Save the register value*/
push %ebx
push %ecx
push %edx
mov $4, %eax /* system call number, write_sys() */
mov $1, %ebx /* file description */
mov $message, %ecx /* message address */
mov $14, %edx /* message size */
int $0x80 ;
pop %edx /* Restore the resigter value*/
pop %ecx
pop %ebx
pop %eax
_exit:
mov $1, %eax
int $0x80
message:
.asciz "hello world./n" ;
/* write.c*/
static char message[]={"hello world!/n"};
int main(int argc, char *argvs)
{
int size;
asm volatile( /
"int $0x80" /
: "=a"(size)
: "0"(4), "b"(1), "c"(message), "d"(13));
return 0;
}
有兴趣的可以用反汇编看一下二者经过编译后有什么区别。
- 写自己的函数直接调用Linux system call
- linux 系统调用system call
- 如何调用自己写的python函数?
- Mydate97 onpicked 调用自己写的函数
- linux系统调用表(system call table)
- Linux下c++调用自己编写的matlab函数:通过shell script system command实现
- 自己写一个linux的系统调用
- C/C++中调用直接用汇编写的函数
- 系统调用system call
- NSIS使用System::Call调用自定义dll中的导出函数
- 如何使自己写的OnDraw函数被调用
- Python中如何调用自己写的函数
- 直接调用函数的函数
- Linux system call的来龙去脉浅析
- VB调用VC写的DLL导出函数出现“Bad DLL call convention”的解决
- 自己写的一个mail发送组件,可以直接在程序中调用。
- linux 隐式调用 自己写的动态库
- linux 显式调用 自己写的动态库
- RegisterStartupScript和RegisterClientScriptBlock输出位置的区别(转)
- HTML optgroup 标签和fieldset 标签(被遗忘的标签)
- 在Linux中创建静态库和动态库
- FMS中的各种类
- ODBC在ACCESS 中存取二进制
- 写自己的函数直接调用Linux system call
- VS2005 文件编码
- c++中的list用法
- 网络硬盘盒的使用
- 五行棋(五兽棋) V2.0
- netbean不能导入中文的路径有乱码的问题
- 彻底删除SQL Server 2005
- 你过你的幸福,我漂我的江湖
- Prevention Magazine August 2008..