我尝试使用write
编译一个名为-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
如何写入文件描述符?
答案 0 :(得分:7)
您对C
和unix
有一些误解。
我认为
write
是一个Unix的东西
当然,write
是syscall,它是POSIX标准的一部分。 POSIX
是与unix
(一个非常古老的操作系统)兼容的标准。
这意味着名为write
的 syscall 存在于任何符合Unix或POSIX的操作系统(如Linux)中。但是,如果您没有C标准库的实现(如Linux中的glibc或Android中的bionic) - 您将如何进行系统调用(即要求操作系统内核执行某些操作)? Syscalls依赖于体系结构(SPARC,Intel,ARM,PowerPC等将具有不同的实现) - 并且由C标准库实现。如果你没有(例如,当你与-nostdlib
一致时,你明确要求不要有一个C标准库) - 你不能调用write
,该函数不存在。但是,您可以使用程序集自己实现它。
您提供的代码适用于__libc_write
,与write
不同。在glibc
和gcc
之间有一些巫术,这与存根有关,我不完全理解它。
琐碎的实现是这样的:
ssize_t write(int fd, const void *buf, size_t count)
{
return __set_errno(syscall(__NR_write, fd, buf, count));
}
(在bionic
,Android的libc实现中,您可以看到这里的来源https://searchcode.com/codesearch/view/34924443/ - 看看它是在汇编中实现的)
syscall
函数在glibc
(以及其他任何地方)的汇编中实现: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)。 _IO_new_file_write
使用write_not_cancel
定义的here a macro for INLINE_SYSCALL (write, 3, fd, buf, len)
,the implementation来调用系统调用并设置errno。