曲径通幽论坛

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

使用 Linux 系统调用

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34399
跳转到指定楼层
楼主
发表于 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, 2026-10-11 13:25 , Processed in 0.071117 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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