善有善报背后的printf用C? [英] What goes behind printf in C?

查看:100
本文介绍了善有善报背后的printf用C?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:结果
  了解printf的

我不是在寻找的printf 函数的实现,但我想知道,什么都发生在调用的printf 在C做?
什么活动都发生在软件和硬件水平。

I am not looking for the implementation of printf function but I want to know, what all happens when the call to printf is made in C? What all activities take place at the software and hardware level.

这是我的想法
PrintfCAll - > KernelModeOn - > SystemCallMade - >把输出缓冲器某种形式的数据 - >输出要倾倒在一些控制的缓冲区 - >控制器转储它放在监视器 - >中断CPU话说,工作就完成了。

This is what I think PrintfCAll -> KernelModeOn -> SystemCallMade -> Data Put On Output Buffer Of Some Sort -> Output To Be Dumped On Some Controller's Buffer -> Controller Dumps It On The Monitor -> Interrupts CPU saying That work is done.

如何正确我是谁?
谢谢你。

How correct am I? Thanks.

编辑:Unix的可采取作为一个平台。说Ubuntu Linux系统。
并能有人告诉,我在哪里,将数据从监视器流出,是否有任何控制器吗?到什么程度高于psented时间轴$ P $是正确的?

Unix Can be taken as a platform. say ubuntu. And can someone tell, me where the data flows out from, and is there any controller for the monitor too? and to what extent is the timeline presented above is correct?

推荐答案

下面是一个总体描述和总结的基础上,在一般的编程概念,而不是任何具体实施。

The following is a general description and summary, based on programming concepts in general rather than any specific implementation.

的printf 到通话开始于一个普通的子程序调用;不涉及内核模式。在很大程度上,的printf 是普通code,可能用C编写的的printf $的大部分C $ C本身涉及跨preting格式字符串,转换参数字符串写入,写这些字符串输出文件。这项工作大部分将通过子程序来完成的的printf 调用,如子程序转换数字(对象,如 INT 浮动)以数字(即重新present数字)字符的字符串。

The call to printf starts with an ordinary subroutine call; kernel mode is not involved. In large part, printf is ordinary code and may be written in C. The bulk of the printf code itself is concerned with interpreting the format string, converting the arguments to strings to be written, and writing those strings to the output file. Much of this work will be done through subroutines that printf calls, such as subroutines to convert numbers (objects like int or float) to numerals (strings of characters that represent the numbers).

的printf 也有可能调用的malloc 或相关程序来获得内存在那里prepares缓冲区字符串。我将避免描述这个答案的的malloc 电话。

printf also likely calls malloc or a related routine to get memory for a buffer where it prepares the strings. I will refrain from describing the malloc call in this answer.

所有跨preting格式字符串,转换参数,并写入可以在C做preparing字符串的工作,但高质量的库,可使用多种特定目标的优化包括汇编语言,速度和效率。

All of the work of interpreting the format string, converting the arguments, and preparing strings to be written can be done in C, although high-quality libraries may use a variety of target-specific optimizations, including assembly language, for speed or efficiency.

在某些时候,当的printf 有一个字符串进行打印时,它会调用一个子程序写入字符串标准输出。这可能是 FWRITE 或一些类似的子程序。为了讨论,我会想这是 FWRITE

At some point, when printf has a string to print, it will call a routine to write the string to stdout. This may be fwrite or some similar subroutine. For discussion, I will suppose it is fwrite.

通常,流缓冲。所以,当的printf 要求 FWRITE FWRITE 检查是否完整它的缓冲区。如果从新字符串的printf 安装到缓冲区中, FWRITE 只是将字符串到缓冲区,然后返回。如果缓冲区已满,则 FWRITE 调用其他程序中的缓冲区的内容实际写入文件。 (通常,这包括填充缓冲区与进入的字符串的一部分,写入缓冲器到文件[和标记的缓冲器空],然后传入串的其余部分复制到新的空缓冲器。)某些其他东西也可能触发写缓冲器,如输入字符串中检测一个新行字符,视情况而定。

Usually, streams are buffered. So, when printf calls fwrite, fwrite checks how full its buffer is. If the new string from printf fits into the buffer, fwrite merely adds the string to the buffer and returns. If the buffer is full, then fwrite calls another routine to actually write the buffer contents to a file. (Typically, this involves filling the buffer with part of the incoming string, writing the buffer to a file [and marking the buffer empty], and then copying the rest of the incoming string into the newly empty buffer.) Certain other things might also trigger writing the buffer, such as detecting a newline character in the incoming string, depending on circumstances.

让我们说,写缓冲, FWRITE 调用系统例行程序。面对是一个库程序; FWRITE 执行一个普通的子程序调用调用。系统程序将有一些部分是一个普通的子程序,但是,当他们需要做的基本事实的工作,有某种系统调用指令(有时称为陷阱)的。

Let’s say that, to write the buffer, fwrite calls the system routine write. The face of write is a library routine; fwrite performs an ordinary subroutine call to call write. System routines will have some portion that is an ordinary subroutine, but, when they need to do the nitty-gritty work, there is some sort of system-call instruction (sometimes called a trap).

当您执行系统调用指令,处理器做几件事情。它节省了处理器寄存器中指定的位置。这既包括通用寄存器和描述该用​​户进程的状态的特殊寄存器。那么处理器切换到内核模式,通常涉及设置位,表明新的执行状态是特权(允许更改特殊处理器寄存器,执行特殊指令,等等),并从其他位置加载寄存器,或者将它们设置为已知值。具体地,程序计数器(其中,所述处理器读出指令来执行的位置)被设置为指向一个特定的地方,这里的操作系统有code键处理的系统调用。

When you execute a system-call instruction, the processor does several things. It saves processor registers in specified locations. This includes both general registers and special registers that describe the state of the user process. Then the processor switches to kernel mode, which typically involves setting bits to indicate the new execute state is privileged (allowed to change special processor registers, execute special instructions, et cetera) and loading the registers from some other location, or setting them to known values. In particular, the program counter (the location where the processor reads instructions to execute) is set to point to a particular place, where the operating system has code to handle system calls.

现在处理器在内核模式下执行。通常,在这一点上,处理器的工作是摆脱内核模式的尽快,以便它可以继续分时进程之间和被准备其他工作。此外,还有许多层,以现代操作系统,所以很难说precisely什么此时发生的情况。

Now the processor is executing in kernel mode. Usually, the job of the processor at this point is to get out of kernel mode as quickly as possible, so that it can resume time-sharing between processes and being ready for other work. Additionally, there are many layers to modern operating systems, so it is difficult to say precisely what happens at this point.

的一种情况是,该系统调用句柄(当一个系统呼叫时被调用的软件)读取保存的寄存器和用户进程的存储器,以确定哪些过程要求。在每个系统中,被指定传递参数到系统调用的一些方法。例如,某寄存器可能包含一个数字,指示该请求是什么(0表示写,1装置读出,2装置获得当前时间,3方式改变存储器映象,等等),并且每个请求将在通过某些参数其它寄存器或存储器(一个寄存器可能包含在存储器中的地址,而另一个包含写的长度)

One scenario is that the system call handler (the software that is called when a system call occurs) reads the saved registers and memory of the user process to determine what the process asked for. On each system, some method of passing parameters to a system call is specified. For example, a certain register might contain a number that indicates what the request is (0 means write, 1 means read, 2 means get current time, 3 means change memory map, et cetera), and each request will have certain parameters passed in other registers or in memory (one register might contain an address in memory, while another contains the length to write).

所以,系统调用处理程序计算出要求正在做什么,并分派到code来处理。这可能涉及搜集参数的请求,并将它们成型为工作的一个描述要完成的,然后把一个队列的工作和离开系统调用句柄

So, the system call handler figures out what request is being made and dispatches to code to handle that. This might involve collecting parameters for the request and forming them into a description of the work to be done, then putting that work on a queue and leaving the system call handler.

虽然有工作要做,操作系统很可能不会返回到用户进程。正如我前面提到的,有现代的操作系统很多层。有设备驱动程序,内核扩展,微内核,操作系统内的软件库,等等。然而操作系统被组织,在一段时间后,它决定做由系统调用所请求的工作

While there is work to be done, the operating system probably does not return to a user process. As I mentioned before, there are many layers in modern operating systems. There are device drivers, kernel extensions, microkernels, libraries of software within the operating system, and more. However the operating system is organized, at some time, it decides to do the work requested by the system call.

在标准输出的写入的情况下,工作被发送到设备驱动器,这是一个名字为处理对装置的工作的软件。最初,设备是连接到系统的硬件的各个部分。的设备驱动器将命令中的数据复制到被写入存储器中的特殊的地方,并发出到设备(使用特殊说明)来读取存储器的数据,并将其发送到哪里的设备发送它(终端,磁盘驱动器, 随你)。设备驱动程序的另一部分将是一个当工作完成时调用程序。 (这个调用类似于一个系统呼叫,但通常被称为一个中断。)当工作完成后,设备驱动器将传递一个消息返回给操作系统的其他部分,并最终信息有关系统调用的结果将被写入到用户进程将被重新启动的存储器或一个用户进程的寄存器和执行

In the case of a write to standard output, the work is sent to a "device driver", which is a name for software that handles the work for "device". Originally, devices were pieces of hardware connected to the system. A device driver would copy the data to be written to a special place in memory and issue a command to the device (using special instructions) to read that data from memory and send it to wherever the device sends it (a terminal, a disk drive, whatever). Another part of the device driver would be a routine that is called when the work is done. (This call is similar to a system call but is usually called an interrupt.) When the work is done, the device driver would pass a message back to other parts of the operating system, and eventually information about the result of the system call would be written into the memory or registers of a user process, and execution of the user process would be restarted.

今天,许多的设备是实现虚拟设备软件。一个用户进程的标准输出可能是某种伪终端。由于该伪终端有没有实际的硬件终端,它通过询问其他软件来帮助处理写入请求。

Today, many "devices" are software that implement virtual devices. The standard output of a user process is likely some sort of pseudo-terminal. Since that pseudo-terminal has no actual hardware terminal, it has to handle write requests by asking other software to help.

当的伪终端是一个图形显示器上的终端窗口的一部分,有一些实现终端窗口的软件。该软件接受文本被写到标准输出,决定凡在窗口应将其放置,并呼吁其他软件中的字符转换为变化像素的窗口。即,一些软件读取的字符,在一些表和其他数据(字体的说明等)仰视它们的描述,并且在图像缓冲器绘制这些字符。

When the pseudo-terminal is part of a terminal window on a graphic display, there is some software that implements the terminal window. That software accepts text being written to standard output, decides where in the window it should be placed, and calls other software to convert the characters into changes in pixels in the window. That is, some software is reading the characters, looking up descriptions of them in some tables and other data (descriptions of the typeface and so on), and drawing those characters in an image buffer.

在图像缓冲器已准备好,更软件被称为写入图像缓冲器到显示器。再次,这涉及将数据传递到其他装置的驱动程序。最终,它达到一个实际的硬件设备,这需要的数据,并使其出现在显示屏上。

When the image buffer is ready, more software is called to write the image buffer to the display. Again, this involves passing data to another device driver. Ultimately, it reaches an actual hardware device, which takes the data and makes it appear on the display.

要包裹起来,有一个巨大的事件链。数据上升和下降,通过多层次,可能涉及到几个不同的用户进程和几个不同的设备驱动程序,和许多软件库。这是很难得的全过程的COM prehensive视图。通常情况下,人们不会想尝试一次全部了解整个过程,但会分别了解每个步骤。例如,在我的职业生涯时,我不得不处理一个系统调用指令的微小细节。但是,想我的整个系统是如何工作的时候,我想到了较大级别进程相互通信,无需考虑这些的通讯是如何作出的工作细节。

To wrap up, there is a huge chain of events. Data goes up and down through multiple layers, likely involving several different user processes and several different device drivers, and many software libraries. It is difficult to get a comprehensive view of the entire process. Generally, one would not want to try to understand the entire process all at once but would learn separately about each of the steps. For example, at times in my career, I have had to deal with the minute details of a system call instruction. But, when thinking about how my entire system is working, I think about larger-level processes communicating with each other, without thinking about the details of how those communications are made to work.

这篇关于善有善报背后的printf用C?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆