用户空间和 __NR 常量
注意清单 6 中提供了 __NR 符号常量。您可以在 /usr/include/asm/unistd.h 中找到它们(对于标准系统调用来说)。
_syscall 宏最多可定义 6 个参数(不过此处只显示了 3 个)。
现在,让我们来看一下如何使用 _syscall 宏来使新系统调用对于用户空间可见。清单 6 显示的应用程序使用了 _syscall 宏定义的所有系统调用。
清单 6. 将 _syscall 宏 用于用户空间应用程序开发
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#define __NR_getjiffies 320
#define __NR_diffjiffies 321
#define __NR_pdiffjiffies 322
_syscall0( long, getjiffies );
_syscall1( long, diffjiffies, long, ujiffies );
_syscall2( long, pdiffjiffies, long, ujiffies, long*, presult );
int main()
{
long jifs, result;
int err;
jifs = getjiffies();
printf( "difference is %lx\n", diffjiffies(jifs) );
err = pdiffjiffies( jifs, &result );
if (!err) {
printf( "difference is %lx\n", result );
} else {
printf( "error\n" );
}
return 0;
}
注意 __NR 索引在这个应用程序中是必需的,因为 _syscall 宏使用了 func-name 来构造 __NR 索引(getjiffies -> __NR_getjiffies)。其结果是您可以使用它们的名字来调用内核函数,就像其他任何系统调用一样。
上一页 [1] [2] [3] [4] 下一页
用户/内核交互的其他选择
系统调用是请求内核中服务的一种有效方法。使用这种方法的最大问题就是它是一个标准接口,很难将新的系统调用增加到内核中,因此可以通过其他方法来实现类似服务。如果您无意将自己的系统调用加入公共的 Linux 内核中,那么系统调用就是将内核服务提供给用户空间的一种方便而且有效的方法。
让您的服务对用户空间可见的另外一种方法是通过 /proc 文件系统。/proc 文件系统是一个虚拟文件系统,您可以通过它来向用户提供一个目录和文件,然后通过文件系统接口(读、写等)在内核中为新服务提供一个接口。
使用 strace 跟踪系统调用
Linux 内核提供了一种非常有用的方法来跟踪某个进程所调用的系统调用(以及该进程所接收到的信号)。这个工具就是 strace,它可以在命令行中执行,使用希望跟踪的应用程序作为参数。例如,如果您希望了解在执行 date 命令时都执行了哪些系统调用,可以键入下面的命令:
strace date
结果会产生大量信息,显示在执行 date 命令过程中所执行的各个系统调用。您会看到加载共享库、映射内存,最后跟踪到的是在标准输出中生成日期信息:
...
write(1, "Fri Feb 9 23:06:41 MST 2007\n", 29Fri Feb 9 23:06:41 MST 2007) = 29
munmap(0xb747a000, 4096) = 0
exit_group(0) = ?
$
当当前系统调用请求具有一个名为 syscall_trace 的特定字段集(它导致 do_syscall_trace 函数的调用)时,将在内核中完成跟踪。您还可以看到跟踪调用是 ./linux/arch/i386/kernel/entry.S 中系统调用请求的一部分(请参看 syscall_trace_entry)。
结束语
系统调用是穿越用户空间和内核空间,请求内核空间服务的一种有效方法。不过对这种方法的控制也很严格,更简单的方式是增加一个新的 /proc 文件系统项来提供用户/内核间的交互。不过当速度因素非常重要时,系统调用则是使应用程序获得最佳性能的理想方法。 上一页 [1] [2] [3] [4] 上一页 [1] [2] [3] [4]
|