当前位置: 首页 > 面试题库 >

C写调用和Go syscall.Write之间的区别

寿亦
2023-03-14
问题内容

syscall write返回-1,而set errno是一个简单的情况。我对errnoC
write调用返回零或正的状态感兴趣。该包装syscall.Write在围棋简单的返回err,如果errno不是任何情况下,其中还包括的零的情况下write调用返回正数。

https://github.com/golang/go/blob/3cb64ea39e0d71fe2af554cbf4e99d14bc08d41b/src/syscall/zsyscall_linux_386.go#L1007

然而,的C man页面write调用大致介绍了errno 可能 ,如果我们写零长度的缓冲区没有解释任何细节也可以设置,但不确定。

因此,以下情况似乎不清楚:

  1. errno如果write针对文件,非阻塞套接字或阻塞套接字的调用返回0 的状态是什么?
  2. 什么时候以及如何write调用返回0而errno不是0?
  3. errnoif write通话返回正数的状态如何?会否定的?
  4. 还有其他系统调用可能会遇到相同的情况吗?

我认为以上描述指出了C writecall和Go 之间的区别syscall.Write,这对于开发人员尚不清楚,这是我的想法:

根据手册页,在write对文件和非阻塞套接字的C
调用中明确定义了返回零,但是尚不清楚阻塞套接字是否存在非错误条件,这将导致write()未阻塞,返回0,并且(大概)可能会在以后重试时成功。

实际上,Go直接包装系统调用write。但是,以下代码段似乎并不安全,因为written等于零的情况可能会触发,err但我们不想中断循环:

func writeAll(fd int, buffer []byte) bool {
    length := len(buffer)
    for length > 0 {
        written, err := syscall.Write(fd, buffer)
        if err != nil { // here
            return false
        }
        length -= written
        buffer = buffer[written:]
    }
    return true
}

我的怀疑有什么不对吗?


问题答案:

使用write,只有两种情况需要考虑:

  1. 如果失败,则结果为-1并被errno设置。
  2. 如果成功,则结果为0或更大errno且未设置。

除非您对历史上的Unix实现感兴趣,否则没有其他情况可以考虑。

write可能返回0 的原因是因为输入缓冲区可能为空。

然而,C的手册页write呼叫大致介绍了errno 可能 ,如果我们写零长度的缓冲区没有解释任何细节也可以设置,但不确定。

所有这一切意味着0长度写入可能会失败。如果失败,则返回-1并设置errno。如果成功,则返回0且不设置errno。手册页中刚刚提到了这与其他任何写入操作相同的行为,因为人们可能会惊讶地发现0长度写入可能会失败。

errno如果write针对文件,非阻塞套接字或阻塞套接字的调用返回0 的状态是什么?

在这种情况下,errno未设置,因为write没有失败。仅当输入缓冲区为零字节时才会发生这种情况。

什么时候以及如何write调用返回0而errno不是0?

这不会发生。errno设置要么返回值为-1,要么errno未设置返回值为0或更大。

errnoif write通话返回正数的状态如何?会否定的?

errno值将不会被设置。它的值将与write调用前相同。

还有其他系统调用可能会遇到相同的情况吗?

通常,系统调用将返回错误 成功。他们不会两者兼而有之。查看其他手册页的“返回值”部分,您将发现它们与大致相同write

此代码是安全的。

func writeAll(fd int, buffer []byte) bool {
    length := len(buffer)
    for length > 0 {
        written, err := syscall.Write(fd, buffer)
        if err != nil { // here
            return false
        }
        length -= written
        buffer = buffer[written:]
    }
    return true
}

请注意,这有点多余,我们可以这样做:

func writeAll(fd int, buf []byte) bool {
    for len(buf) > 0 {
        n, err := syscall.Write(fd, buf)
        if err != nil {
            return false
        }
        buf = buf[n:]
    }
    return true
}

关于C的注释

从技术上讲,write它既是系统调用又是C函数(至少在许多系统上)。但是,C函数只是一个调用系统调用的存根。Go不会调用此存根,而是直接调用系统调用,这意味着此处不涉及C(嗯,直到您进入内核为止)。

手册页显示了C存根的调用约定和行为write。Go选择将其行为复制到自己的存根中syscall.Write。实际的系统调用本身仅具有汇编语言界面。



 类似资料:
  • 问题内容: 我只是在阅读一些Java书籍并制作一些小程序进行练习,我创建了一个小代码来获取有关所输入路径的信息,该代码为: 现在在输入对话框中,当我输入时,结果是,但是当我输入C:/时,它将显示C中目录和文件的完整列表。 奇怪的是,D驱动器和其他驱动器不会发生这种情况(即D:/和D:的结果是相同的),这是怎么回事? 更新 使用C#在WPF中也会发生同样的情况! 问题答案: 表示“驱动器上当前选择的

  • 本文向大家介绍C和Python之间的区别,包括了C和Python之间的区别的使用技巧和注意事项,需要的朋友参考一下 C和Python都是主要使用的编程语言。各种特性使它们在程序设计领域流行。根据这些特征,我们可以区分C和Python。 以下是C和Python之间的重要区别。 序号 键 C语言 Python语言 定义 Python是一种通用的解释型,交互式,面向对象的高级编程语言。 类型 另一方面,

  • 本文向大家介绍Go和C ++之间的区别。,包括了Go和C ++之间的区别。的使用技巧和注意事项,需要的朋友参考一下 走 Go是一种过程编程语言。程序是使用程序包组装的。它支持类似于动态语言的环境采用模式。 C ++ C ++是一种面向对象的编程语言。C ++安静,快速,可靠且安全。它也是最广泛使用的语言。 以下是Go和C ++之间的重要区别。 序号 键 走 C ++ 1 类型 Go是一种过程编程语

  • 问题内容: 以下调用之间有区别吗? 与 应该首选哪一个? 问题答案: 这两个函数以截然不同的方式处理段。只会将它与前一个参数连接起来,但是会将其视为根目录,并忽略所有先前的路径- 将其视为与每个参数一起执行的结果: 要注意的另一件事是,它将始终产生绝对URL,并且将使用您的工作目录作为解析此路径的基础。但是,无论如何,这都是一条绝对路径,这对您而言并不重要。 对于您应该使用哪一个,答案是:这取决于

  • 问题内容: 是图像文件的字符串。 我在C#中具有以下代码: 和Java中的代码如下: 结果是不同的。 有人说是因为 Java字节:-128至127 C#字节:0到255 但是我该如何解决呢?如何在Java中实现C#?通过使用Java,我需要与C#中相同的结果。 问题答案: 您正在对 字符串进行 base64编码吗?你想做什么?您首先需要将字符串转换为字节序列,然后选择一种编码,例如UTF-8或UT

  • 问题内容: 我知道在Java中,我们使用*(星号)将所有内容导入包中 那么为什么不在C#中使用相同的*(星号)来导入所有内容,有没有像Java中那样的方法来导入所有内容。之间有什么区别 和 问题答案: Java 所做的.NET称为引用- 在.NET中添加对程序集的 引用 ,使您可以使用该程序集中定义的(公共)类型。 C#指令只是一种无需输入整个名称空间即可访问这些类型的方法。 您还 可以 使用指令