曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6673|回复: 0
打印 上一主题 下一主题

使用 Linux 系统调用

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2010-8-22 10:40:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在汇编的最后,经常会看到:

movl $1, %eax
movl $0, %ebx
int $0x80

这实际上是调用了 Linux 的第 1 号系统调用 exit 函数。movl $1, %eax 中的 1 表示 1 号系统调用;0 表示传递给 exit 的参数。int $0x80 是调用中断 0x80 。

系统调用号可以在 /usr/include/asm/unistd.h 中找到。在较新的 Linux 发行版中,32 位系统和 64 位系统的调用号文件可能还会分别放在 /usr/include/asm/unistd_32.h 和 /usr/include/asm/unistd_64.h 中。这个文件的前几行为:
[C++] 纯文本查看 复制代码
#ifndef _ASM_X86_UNISTD_32_H 
#define _ASM_X86_UNISTD_32_H 

/* 
* This file contains the system call numbers. 
*/ 

#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 

常用内存访问内核系统调用
系统调用
描述
brk
改变数据段长度
mlock
禁止对内存部分进行分页
mlockall
禁止对调用进程进行分页
mmap
把文件或者设备映射到内存中
mprotect
控制对内存区域的许可访问
mremap
重新映射虚拟内存地址
msync
同步文件和内存映射
munlock
允许对内存部分进行分页
munlockall
允许对调用进程进行分页
munmap
取消文件或者设备在内存中的映射

常用设备访问内核系统调用
系统调用
描述
access
检查设备权限
chmod
改变设备的权限
chown
改变设备的所有关系
close
关闭设备文件描述符
dup
复制设备文件描述符
fcntl
操作设备描述符
fstat
获得设备的状态
ioctl
控制设备的参数
link
把新的名称分配给设备描述符
lseek
重新定位读取/写入文件偏移量
mknod
为设备创建新的文件描述符
open
为设备或文件打开/创建文件描述符
read
读取设备文件描述符
write
写入设备文件描述符

常用文件系统系统调用
系统调用
描述
chdir
改变工作目录
chroot
改变根目录
flock
在打开的文件上应用或者删除建议锁(advisory lock)
statfs
获得文件系统的统计数据
getcwd
获得当前工作目录
mkdir
创建目录
rmdir
删除目录
symlink
生成文件的新名称
umask
设置文件创建掩码
mount
挂载和卸载文件系统
swapon
开始内存和文件系统的交换
swapoff
停止内存和文件系统的交换

常用进程系统调用
系统调用
描述
acct
打开或者关闭进程计数
capget
获得进程功能
capset
设置进程功能
clone
创建子进程
execve
执行程序
exit
终止当前进程
fork
创建子进程
getgid
获得组标识
getgrp
获得/设置进程组
getppid
获得进程标识
getpriority
获得程序调度优先权
getuid
获得用户标识
kill
发送信号杀死进程
nice
改变进程优先级
vfork
创建子进程并且阻塞父进程

给系统调用传递参数
如果只使用寄存器来传递参数,那么系统调用期望的输入参数顺序如下:
      EBX (第 1 个参数)
      ECX (第 2 个参数)
      EDX (第 3 个参数)
      ESI   (第 4 个参数)
      EDI   (第 5 个参数)
需要超过 6 个输入参数的系统调用使用不同的方法把参数传递给系统调用。EBX 寄存器用于保存指向输入参数的内存位置的指针,输入参数按照连续的顺序存储。系统调用使用这个指针访问内存位置以便读取参数。

测试程序:
.section .data
output:
     .ascii "This is a test message.\n"
output_end:
     .equ len, output_end - output

.section .text
.global _start
_start:
     movl $4, %eax
     movl $1, %ebx
     movl $output, %ecx
     movl $len, %edx
     int $0x80
     
     movl $1, %eax
     movl $0, %ebx
     int $0x80

运行与输出:
$ ./syscall
This is a test message.

说明:
1. .equ 伪指令用来为符号赋值,这个值可以是绝对值也可以是相对值。它可以对一个符号使用一次到多次,使用一次则改变一次符号值。上面程序中,没有给字符串指定一个长度,而是利用 .equ 动态获得。在 .ascii 命令后面马上使用另外一个标签 output_end ,这个位置中什么都没有存储,它实际指向字符串末尾,通过两个标签的相减,从而获得了字符串的长度。

2. 程序中,我们调用的是 write() 这个系统调用,其原型是:
write (int fd, const void *buf, size_t count);
从左到右,它的 3 个参数依次放入上面所述的寄存器(EBX, ECX, EDX)中。
EBX : 文件描述符。这里是标准输出 STDOUT ,值为 1。
ECX : 指向要写入的字符串的指针。
EDX : 要写入的字符串长度。

系统调用返回值
系统的返回值存放在 EAX 寄存器中。一定要了解返回值的类型,一些系统调用会返回怪异的数据类型。如上面的 write(),返回 ssize_t 。实际上,ssize_t 不是标准汇编语言数据类型,它本身由 typedef 定义,实际上是个整型数据。

下面程序分别获取 getpid, getuid, getgid 这 3 个系统调用的返回值,这 3 个系统调用所对应的系统调用号分别为20,24,47。下面时测试代码:
.section .bss
     .lcomm pid, 4
     .lcomm uid, 4
     .lcomm gid, 4

.section .text
.global _start
_start:
     movl $20, %eax
     int $0x80
     movl %eax, pid

     movl $24, %eax
     int $0x80
     movl %eax, uid

     movl $47, %eax
     int $0x80
     movl %eax, gid

end:
     movl $1, %eax
     movl $0, %ebx
     int $0x80

在调试器中观察:
(gdb) x/d &pid
0x80490a4 <pid>:    3347
(gdb) x/d &uid
0x80490a8 <uid>:    1000
(gdb) x/d &gid
0x80490ac <gid>:    1000


复杂的系统调用返回值
有时候系统调用返回涉及 C 样式数据结构的复杂数据.
下面测试 sysinfo 这个系统调用的返回信息。sysinfo() 返回系统如何配置以及有什么可用资源的信息。man 一下,可以看到它的原型为:
#include <sys/sysinfo.h>
int sysinfo (struct sysinfo *info);

它只有一个指向 struct sysinfo 结构体的指针。当函数成功返回时,它会将系统的相关值返回到结构体的特定成员中。所以,我们在汇编里也要相应的创建这个结构。这个结构定义如下:
[C++] 纯文本查看 复制代码
struct sysinfo { 
               long uptime;             /* Seconds since boot */ 
               unsigned long loads[3];  /* 1, 5, and 15 minute load averages */ 
               unsigned long totalram;  /* Total usable main memory size */ 
               unsigned long freeram;   /* Available memory size */ 
               unsigned long sharedram; /* Amount of shared memory */ 
               unsigned long bufferram; /* Memory used by buffers */ 
               unsigned long totalswap; /* Total swap space size */ 
               unsigned long freeswap;  /* swap space still available */ 
               unsigned short procs;    /* Number of current processes */ 
               unsigned long totalhigh; /* Total high memory size */ 
               unsigned long freehigh;  /* Available high memory size */ 
               unsigned int mem_unit;   /* Memory unit size in bytes */ 
               char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for libc5 */ 
           }; 

测试程序:
.section .data
result:
uptime:
     .int 0
loads1:
     .int 0
loads2:
     .int 0
loads3:
     .int 0
totalram:
     .int 0
freeram:
     .int 0
sharedram:
     .int 0
bufferram:
     .int 0
totalswap:
     .int 0
freeswap:
     .int 0
procs:
     .byte 0x00, 0x00
totalhigh:
     .int 0
freehigh:
     .int 0
memunit:
     .int 0
charf:
     .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
retu:
     .int 0

.section .text
.global _start
_start:
     nop
     movl $result, %ebx
     movl $116, %eax
     int $0x80
     
     movl $0, %ebx
     movl $1, %eax
     int $0x80
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-4-29 12:02 , Processed in 0.065474 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表