Unix write()和printf()之间的区别
最近我在学习操作系统。我只想知道:Unix write()和printf()之间的区别,unix,io,operating-system,system-calls,Unix,Io,Operating System,System Calls,最近我在学习操作系统。我只想知道: 系统调用(如write())和标准库函数(如printf())之间有什么区别?系统调用由操作系统实现,并在内核模式下运行。库函数是在用户模式下实现的,就像应用程序代码一样。库函数可能调用系统调用(例如,printf最终调用write),但这取决于库函数的用途(数学函数通常不需要使用内核)。操作系统中的系统调用用于与操作系统交互。例如,Write()可以用于系统或程序中 虽然标准库函数是特定于程序的,例如printf()将打印出一些内容,但它仅在GUI/命令行中
系统调用(如write())和标准库函数(如printf())之间有什么区别?系统调用由操作系统实现,并在内核模式下运行。库函数是在用户模式下实现的,就像应用程序代码一样。库函数可能调用系统调用(例如,
printf
最终调用write
),但这取决于库函数的用途(数学函数通常不需要使用内核)。操作系统中的系统调用用于与操作系统交互。例如,Write()可以用于系统或程序中
虽然标准库函数是特定于程序的,例如printf()将打印出一些内容,但它仅在GUI/命令行中,不会影响系统
对不起,我无法发表评论,因为我需要50%的声誉才能发表评论
编辑:Barmar有很好的答案系统调用是对一个函数的调用,该函数不是应用程序的一部分,而是在内核中。内核是一个软件层,它为您提供一些基本功能来抽象硬件。粗略地说,内核是将硬件转化为软件的东西 您最终总是使用
write()write()
被设计成只写一个字节序列,仅此而已。但是由于write()
被认为太基本了(您可能希望以十为基础编写一个整数,或者以科学记数法编写一个浮点数,等等),不同类型的编程环境为您提供了不同的库以方便您
例如,C编程语言为您提供了printf()
,允许您以多种不同的格式编写数据。因此,您可以将printf()
理解为一个函数,它将数据转换为格式化的字节序列,并调用write()
将这些字节写入输出。但是C++给了你<代码> cOUT <代码>;JavaSystem.out.println
,等等。这些函数中的每一个都以调用write()
(至少在POSIX系统上)结束
需要知道的一件事(重要的)是,这样的系统调用代价高昂!这不是一个简单的函数调用,因为您需要调用自己代码之外的东西,并且系统必须确保您没有尝试做令人讨厌的事情,等等。因此,在高级打印类函数中,内置一些缓冲是非常常见的;这样就不总是调用write,但您的数据被保存在某种隐藏的结构中,只有在确实需要或必要时(缓冲区已满或您确实希望看到打印结果)才被写入
这正是当你管理你的钱时发生的事情。如果很多人每人给你5美元,你就不会把每个人都存入银行!您可以将它们放在您的钱包中(这是打印件),直到钱包已满或您不想再保存它们为止。然后你去银行存了一大笔钱(这是写的)。你知道,把5美元放进钱包比去银行存款快得多。银行是内核/OS。我正在写一个小程序。目前,它只是从标准输入中读取每一行并将其打印到标准输出。我可以添加一个在循环中写入的调用,它会在每行末尾添加几个字符。但是当我改用printf时,所有额外的字符都会聚集在一起,并一次全部出现,而不是出现在每一行上
似乎使用printf会导致stderr被缓冲。添加fflush(stdout)调用printf后,code>修复了输出中的差异 我想提到另一点,stdio
缓冲区保存在进程的用户空间内存中,而系统调用write
将数据直接传输到内核缓冲区。这意味着,如果在write
和printf
调用之后fork
一个进程,刷新可能会导致输出三次,并受到行缓冲和块缓冲的影响,其中两个属于printf
调用,因为stdio
缓冲区是通过fork
在子级中复制的printf()
是向用户空间公开的用于从C库调用函数的API或接口之一
printf()
实际使用write()
系统调用。write()
系统调用实际上负责将数据发送到输出。因此write()
每5美元直接存入银行,而printf()
则等待缓冲区收集到很多东西。这就是为什么当父进程和子进程试图在外围设备上打印内容时,printf()
可能会产生奇怪的输出。是吗?没错!你理解得很好。最后一段实际上很好地解释了非缓冲和缓冲之间区别的一般概念。我正在为嵌入式设备编程。我将交叉编译的c代码闪存到没有操作系统的设备上。调用write函数是否会导致设备上出现未定义的行为?@mercury0114不一定,如果代码中有write函数,则会调用它。