Printf and standard output
The parameter transfer that was written to the main function last time. Continue now. I 've been busy with lab work recently. I 've read the article for a week and haven't made any progress. I'll write a technical post on the weekend to relax :-)
After entering the main function, you need to call printf ("Hello world! /N "); By The Way, pass the C language parameter to mention. String" Hello world! /N "is processed by the compiler as a String constant. Although printf is called internally in main," Hello world! /N "is not placed in the main stack, and The String constant must at least be placed in. the data segment is put in the read-only data segment. rodata, I verified one on the workstation. assume that the edited file name is hello. c. compile and generate the ELF binary file GCC hello. c-O hello, and then run the command objdump-s hello-s to dump all the segment information. you will see "Hello world! /N "is located in the. rodata segment.
Printf () is a standard C library function. although the function is simple, it is not easy to implement. this is a platform-related function. in PC, printf output is output to the terminal screen. On embedded devices, generally printf () is output to the serial port. similarly, when printf () is called, the final output devices are different. intuitively, the underlying layer of printf () is related to the platform. so how is printf () implemented?
Let's take a look at the code of the C library program. Here we use uclibc as an example.
Int printf (const char * _ restrict format ,...)
{
Va_list ARG;
Int RV;
Va_start (ARG, format );
Rv = vfprintf (stdout, format, ARG );
Va_end (ARG );
Return RV;
}
Printf supports string formatting and output. The specific parameter processing is not mentioned here. we can see that printf () calls vfprintf (). The first parameter of vfprintf () is stdout, which is a standard output device. the standard output device is a struct. The most important member is its descriptor. Its value is 1.
Follow up with the vfprintf () function, it is complicated parameter processing, because the parameter format of printf () is flexible, so in vfprintf () to form the final output format. if you are interested, you can take a look at it and use it to implement your own printf () function on a platform without an operating system. in this way, it is more convenient for you to output debugging information when you increase the program on bare metal (in fact, uClinux printk does this ).
Vfprintf () is output after parameter processing. The output calls putc (), enters putc (), and then follows up with several layers of functions, it is found that write () is called in Linux (). Yes, the output is completed by operating system code. Before writing, all the code is the code of the C library, which is unrelated to the platform. When it comes to specific output, you need to call the interface provided by the operating system. The principle of system calling is to enter the kernel space of the operating system by some means (usually trap) and call the operating system code to complete some tasks.
Linux system calling has different implementation methods for different platforms. I will talk about this later. After calling write (), enter the kernel space. sys_write () is first introduced. The function code is located in FS/read_write.c. When you enter sys_write (), you must find the corresponding file structure based on the uploaded FD descriptor. For standard output, FD = 1, each process's process control block has an array of open files. The file structure is to find the corresponding structure in the Array Based on FD. After the structure is found, file-> write () is called to output data externally. The output depends on the device driver corresponding to the file structure. Generally, the embedded system can output information from the serial port. The bottom layer of file-> write () Is the function similar to transmit_char that is called by the serial port driver.
There are many books about Linux device drivers. The entire driver structure is very complicated and I do not need to mention it here. as for how the terminal device hangs in the driver queue, how to find the appropriate driver structure according to the standard output Descriptor and look at the kernel printf () function, which contains complex parameter processing, because the parameter format of printf () is flexible, the transmitted parameters must be parsed in vfprintf () to form the final output format. if you are interested, you can take a look at it and use it to implement your own printf () function on a platform without an operating system. in this way, it is more convenient for you to output debugging information when you increase the program on bare metal (in fact, uClinux printk does this ).
Vfprintf () is output after parameter processing. The output calls putc (), enters putc (), and then follows up with several layers of functions, it is found that write () is called in Linux (). Yes, the output is completed by operating system code. Before writing, all the code is the code of the C library, which is unrelated to the platform. When it comes to specific output, you need to call the interface provided by the operating system. The principle of system calling is to enter the kernel space of the operating system by some means (usually trap) and call the operating system code to complete some tasks.
Linux system calling has different implementation methods for different platforms. I will talk about this later. After calling write (), enter the kernel space. sys_write () is first introduced. The function code is located in FS/read_write.c. When you enter sys_write (), you must find the corresponding file structure based on the uploaded FD descriptor. For standard output, FD = 1, each process's process control block has an array of open files. The file structure is to find the corresponding structure in the Array Based on FD. After the structure is found, file-> write () is called to output data externally. The output depends on the device driver corresponding to the file structure. Generally, the embedded system can output information from the serial port. The bottom layer of file-> write () Is the function similar to transmit_char that is called by the serial port driver.
There are many books about Linux device drivers. The entire driver structure is very complicated and I do not need to mention it here. for more information about how terminal devices are mounted to the driver queue and how to find the driver structure based on the standard output descriptor, see related materials.