c - 什么是 __stdinp?

标签 c macos

我正在尝试在微内核 seL4 上实现一个最小的 scanf,仅具有读取字符串的功能。因此,我试图通过阅读 musllibc 来找到一些线索实现其 scanf

我发现,在 stdio.hstdin 映射到 __stdinp:

#define stdin   __stdinp
#define stdout  __stdoutp
#define stderr  __stderrp

但是,我不明白 __stdinp 来自哪里。

例如,musllibc实现scanf通过调用函数vscanfvscanf.c内容如下:

#include <stdio.h>
#include <stdarg.h>
#include "libc.h"

int vscanf(const char *restrict fmt, va_list ap)
{
    return vfscanf(stdin, fmt, ap);
}

weak_alias(vscanf,__isoc99_vscanf);

由于我使用的是 MacOS,所以这里的 stdin 映射到 __stdinp;据我所知。 stdin 接下来如何工作,以及它如何引导到实际的 stdin 端口以读取标准输入?

最佳答案

我认为您看错了地方,即您做出了错误的假设:

#include <stdio.h>

这行看起来可能包含苹果的 libc header stdio.h 但可以使用 -I 更改系统 header 包括搜索路径(musllibc 的 Makefile 会这样做) )。

所以苹果的stdio.h与这段代码完全无关。

如果您深入 musllibc 存储库,您会发现他们的 stdio.h 版本文件如下所示:

/* ... */
extern FILE *const stdin;
extern FILE *const stdout;
extern FILE *const stderr;

#define stdin  (stdin)
#define stdout (stdout)
#define stderr (stderr)
/* ... */

按照定义你会发现FILE *const stdin定义在/src/stdio/stdin.c中:

#include "stdio_impl.h"

static unsigned char buf[BUFSIZ+UNGET];
static FILE f = {
    .buf = buf+UNGET,
    .buf_size = sizeof buf-UNGET,
    .fd = 0,
    .flags = F_PERM | F_NOWR,
    .read = __stdio_read,
    .seek = __stdio_seek,
    .close = __stdio_close,
    .lock = -1,
};
FILE *const stdin = &f;
FILE *volatile __stdin_used = &f;

正如预期的那样,__stdio_read 使用 system call阅读:

#include "stdio_impl.h"
#include <sys/uio.h>

size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
{
    struct iovec iov[2] = {
        { .iov_base = buf, .iov_len = len - !!f->buf_size },
        { .iov_base = f->buf, .iov_len = f->buf_size }
    };
    ssize_t cnt;

    // the actual reading takes place here
    // system call takes place here
    cnt = syscall(SYS_readv, f->fd, iov, 2);
    if (cnt <= 0) {
        f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt);
        return cnt;
    }
    if (cnt <= iov[0].iov_len) return cnt;
    cnt -= iov[0].iov_len;
    f->rpos = f->buf;
    f->rend = f->buf + cnt;
    if (f->buf_size) buf[len-1] = *f->rpos++;
    return len;
}

系统调用提供应用程序和底层内核之间的接口(interface)。

关于c - 什么是 __stdinp?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76832533/

相关文章:

c - 在结构中使用 pthread 条件变量数组

编译器不允许我编辑传递的字符串

ruby-on-rails - 升级到 OSX 10.7 Lion 后修复 Postgresql

objective-c - NSTableView 在失去焦点时无需按 Enter 键即可保存值

c - 在 C 中,*、=、++、<< |运算符(operator)

c - 我不需要 malloc() 这个数组吗?

python - 设置 python emacs 环境 mac os x

java - 编程新手,JDK 与 Android Studio 2.2 Preview 1 捆绑在一起?

css - 表单字段概述

C 中的检查循环 - scan() 未在第二次运行时运行