glibc的写入是如何工作的?

2023-12-31

我尝试编译一个简单的程序,名为write with -nostdlib,但我收到错误:

/path/to/file:3: undefined reference to `write'

我想write是 Unix 的东西并且一直存在,但显然不是,事实证明 libc 有write功能。我找到了源代码:

/* Write NBYTES of BUF to FD.  Return the number written, or -1.  */
ssize_t
__libc_write (int fd, const void *buf, size_t nbytes)
{
    if (nbytes == 0)
        return 0;
    if (fd < 0)
    {
        __set_errno (EBADF);
        return -1;
    }
    if (buf == NULL)
    {
        __set_errno (EINVAL);
        return -1;
    }

    __set_errno (ENOSYS);
    return -1;
}
libc_hidden_def (__libc_write)
stub_warning (write)

weak_alias (__libc_write, __write)
libc_hidden_weak (__write)
weak_alias (__libc_write, write)

这一切似乎正在做的是设置errno。如何__libc_write写入文件描述符?


你对这件事有一些误解C and unix.

我想write是 Unix 的东西

确实,write is a syscall https://en.wikipedia.org/wiki/System_call这是POSIX https://en.wikipedia.org/wiki/POSIX标准。POSIX是一个兼容的标准unix(一个非常古老的操作系统)。

这意味着syscall called write存在于任何 Unix 或 POSIX 兼容(如 Linux)操作系统中。但是,如果您没有 C 标准库的实现(例如 Linux 中的 glibc 或 Android 中的 bionic),您将如何进行系统调用(即要求操作系统内核执行某些操作)?系统调用依赖于体系结构(SPARC、Intel、ARM、PowerPC 等将有不同的实现) - 并且由 C 标准库实现。如果您没有(例如,当您遵守-nostdlib你特别要求没有 C 标准库) - 你不能调用write,该函数不存在。但是,您可以使用汇编自行实现它。

您提供的代码用于__libc_write,这与write。两者之间正在发生一些巫术glibc and gcc在这里,有一些与存根有关的东西,我不完全理解它。

简单的实现是这样的:

ssize_t write(int fd, const void *buf, size_t count)
{
    return __set_errno(syscall(__NR_write, fd, buf, count));
}

(In bionic,Android的libc实现,你可以在这里查看源码https://searchcode.com/codesearch/view/34924443/ https://searchcode.com/codesearch/view/34924443/- 看到它是在汇编中实现的)

The syscall函数是在汇编中实现的glibc(以及其他任何地方):http://code.metager.de/source/xref/gnu/glibc/sysdeps/unix/sysv/linux/x86_64/syscall.S http://code.metager.de/source/xref/gnu/glibc/sysdeps/unix/sysv/linux/x86_64/syscall.S(对于 x86_64)

但是,如果您必须真正了解正在发生的事情glibc你打电话时write- 这有点复杂。据我了解,它称为_IO_new_file_write(实施的here http://code.metager.de/source/xref/gnu/glibc/libio/fileops.c#1255). _IO_new_file_write使用write_not_cancel宏定义here http://code.metager.de/source/xref/gnu/glibc/sysdeps/unix/sysv/linux/not-cancel.h#73这是一个宏 http://code.metager.de/source/xref/gnu/glibc/sysdeps/unix/sysv/linux/not-cancel.h#46 INLINE_SYSCALL (write, 3, fd, buf, len),即实施 http://code.metager.de/source/xref/gnu/glibc/sysdeps/unix/sysv/linux/x86_64/sysdep.h#194用于调用系统调用并设置 errno。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

glibc的写入是如何工作的? 的相关文章

随机推荐