是否有系统调用函数,其定义调用另一个系统调用函数?

时间:2018-04-26 13:06:45

标签: c linux system-calls

在Linux中,是否有系统调用函数,其定义调用另一个系统调用函数?

或者所有系统调用函数是否相互独占,因为任何系统调用函数都不会调用另一个系统调用函数?

或者系统调用函数主要在上述意义上是否相互支持?

感谢。

3 个答案:

答案 0 :(得分:4)

作为一个例子,我们来看看如何在Linux中实现C函数write()

C库实现基本上是:

ssize_t write(int fd, const void *buf, size_t count)
{
    long retval;

    retval = syscall(__NR_write, fd, buf, count);
    if (retval < 0) {
        errno = -retval;
        return -1;
    } else
        return retval;
}

syscall()函数特定于每个硬件体系结构,操作系统和内核。它通常用汇编语言编写。它将参数加载到特定寄存器(根据使用的内核调用约定),并调用内核。

此时,跨越安全边界,执行移动到内核空间。

内核中的write()系统调用实现本身使用调用进程的文件描述表来查找特定于该文件或套接字的一组文件操作;确切的代码路径取决于文件描述符是文件(在这种情况下,它所驻留的文件系统),管道,套接字,字符设备还是块设备。

几乎所有的系统调用都会返回一个非负值以便成功,而一个负错误代码会返回错误。

在Linux内核中,系统调用实现很少调用另一个实现系统调用的函数。相反,公共部分是系统调用实现函数调用的内核内部函数的因素。这使维护更容易。

如果我们看一下Linux内核如何实现faccessat()access()系统调用,我们会看到它们都只调用内核函数do_faccessat()

答案 1 :(得分:4)

好吧,对于每个系统调用,只生成一个陷阱,但有些调用共享代码,例如sys_epoll_create(),一旦处于内核模式,调用sys_epoll_create1()(请参阅eventpoll.c kernell 2.6.35):

SYSCALL_DEFINE1(epoll_create, int, size)
{
    if (size <= 0)
        return -EINVAL;

    return sys_epoll_create1(0);
}

在最近的kernelk(4.17-rc2)中,相同的函数share code

SYSCALL_DEFINE1(epoll_create1, int, flags)
{
    return do_epoll_create(flags);
}

SYSCALL_DEFINE1(epoll_create, int, size)
{
    if (size <= 0)
        return -EINVAL;

    return do_epoll_create(0);
}

所以问题的答案是肯定的,但这取决于内核版本......

答案 2 :(得分:4)

这取决于您对系统调用的定义。

我没有意识到任何系统调用陷阱,一旦进入内核,就会故意造成另一个系统调用陷阱。

但是一些系统调用的实现 - 内核中的sys_xxx函数 - 最终可能会使用其他系统调用的实现。

这方面的一个例子是creat,除了调用sys_open函数 - open系统调用的实现 - 除了一些特定的参数外什么都不做:

/*
 * For backward compatibility?  Maybe this should be moved
 * into arch/i386 instead?
 */
SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode)
{
    return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
}