100% found this document useful (1 vote)
294 views632 pages

Linux Asm CH English

linux asm

Uploaded by

juliusjgunn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
294 views632 pages

Linux Asm CH English

linux asm

Uploaded by

juliusjgunn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 632

Linux kernel entirely Notes

Kernel version 0.11 (0.95)

Revision V1.9.5

Zhao Jiong the

www.oldlinux.org [email protected]
Linux Kernel 0.11 Full comments
A Heavily Commented Linux Kernel Source Code
Linux Version 0.11

Revision 1.9.5
(Revision 1.9.5)

Zhao Zhao

Jiong Jiong

[email protected]

www.plinux.org
www.oldlinux.org

2004-05-21
brief introduction

This book Linux Early operating system kernel ( v0.11) All code files were detailed and comprehensive notes and illustrations, designed to enable the reader to in the shortest possible time Linux The

working mechanism of access to comprehensive and profound understanding for further study and research Linux System lay a solid foundation. Although lower the selected version, but the core has

been able to compile and run properly, which already includes a LINUX The essence of works by reading its source code to quickly complete understanding of the operating mechanism of the kernel. The

book first to Linux Changes in the source code version of the history of the main line, introduced in detail Linux The history of the system, highlighted the important differences and improvements between

the various kernel version, it gives the choice 0.11 (0.95) Version reason as an object of study. Further organizational structure describes the relationship between the core and the source code, and also

describes a method to compile and run the version of the kernel. Then book based on the organizational structure of the kernel source code is commented and detailed description of all core programs

and files. Each chapter arrangement is basically divided into an overview of the research object, the function of each file description, comments within the code, the code and the difficulties related to the

information, the main difference with the current version of the other parts. The last chapter summary introduction to continue to study Linux The method and system start point.

Copyright statement

All rights reserved modification of e-books and formal publication. Readers are free to transmit all chapters of the book and the content, but requires attribution. Due to the current book is still in

draft stage, so there are many errors and deficiencies , I hope that readers will respond well to give criticism or advice you can give me information via e-mail: [email protected] , Or a letter directly to:

Shanghai Tongji University Mechanical and Electronic Engineering Research Institute (Shanghai Siping Road 1239 No, Zip: 200092, China).

© 2002,2003,2004 by Zhao Jiong © 2002,2003,2004 Zhao

Jiong all rights reserved.


"RTFSC - Read The F ** king Source Code ☺! "

- Linus Benedict Torvalds


table of Contents

table of Contents

5.3 M AKEFILE file................................................. .. 98


Preamble ................................................. ............................... 1
5.4 ASM.S program................................................. ....... 100
The main objective of this book ............................................. ........... 1 5.5 TRAPS.C program................................................. .... 106
Existing books shortcomings ............................................ ........ 1 5.6 SYSTEM_CALL.S program........................................ 113
Read the early core of other benefits ........................................ 2 5.7 MKTIME.C program................................................. 123
Read the importance and necessity of the full source code ........................ 2 5.8 SCHED.C program................................................. ... 125
How to choose the version of the kernel code to be read ............................ 3 5.9 SIGNAL.C program................................................. .. 138
Read the book need to have basic knowledge of .................................... 3 5.10 EXIT.C program................................................. .... 147
Use an earlier version of obsolescence? ........................................ 4 E XT 2 File 5.11 FORK.C program................................................. ... 153
system MINIX File system......................... 4 5.12 SYS.C program................................................. ...... 160
5.13 VSPRINTF.C program.............................................. 166
The first 1 chapter Overview ................................................. ................. 5
5.14 PRINTK.C program................................................. 174
1.1 L INUX The birth and development ........................................... 5 5.15 PANIC.C program................................................. .. 175
1.2 The summary of ................................................ ........... 10 5.16 chapter summary................................................ ........ 176
1.3 chapter summary................................................ ........... 14
The first 6 Chapter block device drivers ( BLOCK DRIVER) ......... 177
The first 2 chapter LINUX Core architecture .................................. 15
6.1 Overview ................................................. ................ 177
2.1 L INUX Kernel mode ................................................ . 15 6.2 The overall function ................................................ .......... 177
2.2 L INUX Core system architecture ................................. 16 6.3 M AKEFILE file................................................. 180
2.3 Interrupt mechanism ................................................ ........... 18 6.4 BLK.H file................................................. ....... 182
2.4 System timing ................................................ ........... 19 6.5 HD.C program................................................. ......... 186
2.5 L INUX Process control ................................................ . 20 6.6 LL_RW_BLK.C program........................................... 202
2.6 L INUX Kernel Methods for the use of memory ......................... 26 6.7 RAMDISK.C program................................................ 207
2.7 L INUX The method used in the system stack ......................... 29 6.8 FLOPPY.C program................................................. .. 212
2.8 L INUX Kernel source code directory structure ......................... 32
The first 7 chapter Character device driver ( CHAR DRIVER) ....... 239
2.9 The relationship between user and system kernel program ............................ 38

2.10 LINUX / M AKEFILE file...................................... 39 7.1 Overview ................................................. ................ 239


2.11 chapter summary................................................ .......... 47 7.2 Overall functional description ............................................... ... 239

7.3 M AKEFILE file................................................. 247


The first 3 chapter Boot program ( BOOT ) ............................. 49
7.4 KEYBOARD.S program............................................. 249
3.1 Overview ................................................. .................. 49 7.5 CONSOLE.C program................................................ 267
3.2 The overall function ................................................ ........... 49 7.6 SERIAL.C program................................................. .. 290
3.3 BOOTSECT.S program................................................ 50 7.7 RS_IO.S program................................................. .... 293
3.4 SETUP.S program................................................. ...... 58 7.8 TTY_IO.C program................................................. .. 297
3.5 HEAD.S program................................................. ....... 71 7.9 TTY_IOCTL.C program............................................. 308
3.6 chapter summary................................................ ........... 80
The first 8 Chapter math coprocessor ( MATH) ................................ 317

The first 4 chapter Initialization procedure ( INIT) ......................................... 81


8.1 Overview ................................................. ................ 317
4.1 Overview ................................................. .................. 81 8.2 M AKEFILE file................................................. 317
4.2 MAIN.C program................................................. ....... 81 8.3 MATH-EMULATION.C program.................................. 319
4.3 Environmental initialization ............................................... 91
The first 9 Chapter File System ( FS) ............................................... 321
4.4 chapter summary................................................ ........... 92

9.1 Overview ................................................. ................ 321


The first 5 chapter Kernel code ( KERNEL) ..................................... 95
9.2 Overall functional description ............................................... ... 321
5.1 Overview ................................................. .................. 95 9.3 M AKEFILE file................................................. 327
5.2 Overall functional description ............................................... .... 95

-I-
table of Contents

9.4 BUFFER.C program................................................. . 330 11.27 KERNEL.H file.............................................. 526


9.5 BITMAP.C program................................................. .. 345 11.28 MM.H file................................................. .... 527
9.6 INODE.C program................................................. ... 349 11.29 SCHED.H file................................................ 527
9.7 SUPER.C program................................................. ... 360 11.30 SYS.H file................................................. .... 535
9.8 NAMEI.C program................................................. ... 369 11.31 TTY.H file................................................. .... 537
9.9 FILE_TABLE.C program............................................ 390 11.32 INCLUDE / SYS / Files in the directory ......................... 540

9.10 BLOCK_DEV.C program......................................... 390 11.33 STAT.H file................................................. .. 540


9.11 FILE_DEV.C program.............................................. 394 11.34 TIMES.H file................................................. 541
9.12 PIPE.C program................................................. ..... 397 11.35 TYPES.H file................................................. 542
9.13 CHAR_DEV.C program........................................... 400 11.36 UTSNAME.H file........................................... 543
9.14 READ_WRITE.C program........................................ 403 11.37 WAIT.H file................................................. .. 544
9.15 TRUNCATE.C program............................................ 407
The first 12 Chapter library files ( LIB) ............................................... 547
9.16 OPEN.C program................................................. ... 409
9.17 EXEC.C program................................................. ... 415 12.1 Overview ................................................. .............. 547

9.18 STAT.C program................................................. .... 430 12.2 M AKEFILE file............................................... 548


9.19 FCNTL.C program................................................. . 431 12.3 _ EXIT.C program................................................. .. 550

9.20 IOCTL.C program................................................. .. 434 12.4 CLOSE.C program................................................. . 550


12.5 CTYPE.C program................................................. . 551
The first 10 chapter Memory Management ( MM) .......................................... 437
12.6 DUP.C program................................................. ..... 552
10.1 Overview ................................................. .............. 437 12.7 ERRNO.C program................................................. . 553
10.2 Overall functional description ............................................... 437 12.8 EXECVE.C program................................................ 553
10.3 M AKEFILE file............................................... 442 12.9 MALLOC.C program............................................... 554
10.4 MEMORY.C program............................................... 443 12.10 OPEN.C program................................................. . 562
10.5 PAGE.S program................................................. .... 457 12.11 SETSID.C program................................................ 563
12.12 STRING.C program............................................... 564
The first 11 chapter head File( INCLUDE) ................................... 459
12.13 WAIT.C program................................................. .. 564
11.1 Overview ................................................. .............. 459 12.14 WRITE.C program................................................ 565
11.2 INCLUDE / Files in the directory ................................. 459
The first 13 Chapter build tool ( TOOLS) .................................... 567
11.3 A.OUT.H file................................................. .. 460
11.4 CONST.H file................................................. . 470 13.1 Overview ................................................. .............. 567
11.5 CTYPE.H file................................................. . 471 13.2 BUILD.C program................................................. .. 567
11.6 ERRNO.H file................................................. 472
The first 14 chapter Test environment setup and use ........................ 574
11.7 FCNTL.H file................................................. . 474
11.8 SIGNAL.H file................................................. 476 14.1 Overview ................................................. .............. 574

11.9 STDARG.H file................................................ 478 14.2 B OCHS Simulation System............................................ 574

11.10 STDDEF.H file.............................................. 479 14.3 Create a disk image file ........................................ 578

11.11 STRING.H file............................................... 480 14.4 Access to the disk image file information ........................ 581

11.12 TERMIOS.H file............................................ 490 14.5 Production root file system ............................................ 584

11.13 TIME.H file................................................. .. 497 14.6 in L INUX 0.11 The build system 0.11 Kernel ........... 590

11.14 UNISTD.H file............................................... 498 14.7 in R EDHAT 9 Under the build system L INUX 0.11 Kernel .. 591

11.15 UTIME.H file................................................ 504 14.8 use BOCHS Debugging kernel ................................... 594

11.16 INCLUDE / ASM / Files in the directory ....................... 505


references................................................ .................... 595
11.17 IO.H file................................................. ...... 505
11.18 MEMORY.H file............................................. 506 appendix................................................. ........................... 596

11.19 SEGMENT.H file........................................... 507


appendix 1 The main kernel constant ............................................ 596
11.20 SYSTEM.H file.............................................. 509
appendix 2 Kernel data structures ............................................ 599
11.21 INCLUDE / LINUX / Files in the directory .................... 512
appendix 3 80 X 86 Protection operating mode ................................. 607
11.22 CONFIG.H file............................................... 512
appendix 4 ASCII Stopwatch ................................................ . 617
11.23 FDREG.H head File............................................ 514
11.24 FS.H file................................................. ...... 517 index................................................. ........................... 618

11.25 HDREG.H file................................................ 523


11.26 HEAD.H file................................................. 525

- II -
Preface

Preface

This book is about a Linux The operating system kernel primer on basic working principles.

The main objective of this book

The book's main goal is to use as little space or in a limited space, to complete Linux Kernel source code were dissected in order to obtain a comprehensive understanding

of the basic functions of the operating system and the actual implementation. To do linux Kernel has a complete and profound understanding, linux The basic principle of the

operating system really understand and get started.

Positioning book readers are aware of some Linux General use of the system or have some programming basics, but the relative lack of basic knowledge of reading the

current latest kernel source code, but also eager to further understand UNIX Like operating system kernel and the actual code that implements the principle of enthusiasts. Some

readers of this level should be bound in between the primary and secondary levels. Currently, this part of the readership in Linux The proportion of enthusiasts share is very high,

and for this part of the reader much easier to understand and to explain effective means of core information books.

At the shortcomings of existing books

At present, the description Linux Core books, try to use all the latest Linux Kernel version (eg Redhat 7.0 in use 2.2.16

Stable, etc.) are described, but due to the current Linux The entire size of the kernel source has very very large (e.g. 2.2.20 Version has 268

Million lines of code! ), So these books only to Linux Selectively kernel source principle or illustrated, many implementation details of the system are ignored. And therefore can not

give the reader the actual Linux The core has a clear and complete understanding.

Scott Maxwell With a book. " Linux Kernel source code analysis "(Lu Lina translated) substantially facing Linux Readers intermediate level, requiring more

comprehensive knowledge base to fully understand. And may be due to limited space, the book is not for all Linux Annotate kernel code, many kernel implementation details

are omitted, for example where each kernel headers used (*. h) , Utilities generate code for the kernel image file, each make The role and realize etc files not involved. So read

the book for readers in some difficulties between the intermediate level of it.

Zhejiang University, published " Linux Kernel source code Scenario Analysis, "a book, basically these deficiencies. Even though some have higher Linux Application level of

undergraduate computer system high school students, because the length of the book and the actual implementation only problem selectively explain kernel source code, can not

really thoroughly understand the kernel, which often just start reading to give up. This basic problem will appear in the student teaching process. When the book is just coming to

market, I had tried to persuade the students to read the purchase and investigate the case after two months learning to read, and so there is basically could not stand or can not

understand the problem, most people have given up.

John Lions With the "Leon's UNIX Source code analysis, "a book though is a learning UNIX Like operating system kernel source code is a very good book, but because of

its use is UNIX V6 Part of the code version, in which the system calls is outdated PDP-11 Assembly language series machine, so when reading the hardware portion of the

associated source code will encounter greater difficulties.

ASTanenbaum The book "Operating Systems: Design and Implementation" is a book about the operating system kernel to achieve good introductory book, but the book

as described MINIX System is a kernel implementation of the message passing mechanism, and Linux Kernel implementation differ. Therefore, after studying the book, and not

very successfully instantly begin to learn more newer Linux Kernel source code.

When using these books to learn there will be a "elephant" feeling, not really understand Linux The overall concept of core system to achieve specific, especially for those

who Linux Beginner or just learned how to use the system Linux Those who use the system kernel book learning

-1-
Preface

When the principles, the structure of the overall operation of the kernel and not clearly formed in my mind. This in my years Linux Kernel learning process too deep. in 1991 year 10 month,

Linux Founder Linus Toravlds In the developed Linux 0.03 After the written version of the article also mentioned the same problem. In the article, entitled " LINUX - a free unix-386

kernel "The article, he said:" Developing Linux It is for students who train enthusiasts and operating system use of computer science, learning and entertainment. ... Free Software

Foundation GNU Hurd If the system has been developed becomes too large and not suitable for learning and understanding. " And today Linux System than GNU of Hurd More large

and complex system, and therefore also not suitable as a starting point for entry-learning operating system for beginners. This is also one of the motivations of writing this book.

To fill this gap, the main goal of this book is to use as little space or in a limited space, to complete Linux Kernel source code to conduct a comprehensive anatomy, with a

view to practical implementation of the basic functions and the operating system to get the full range of understanding. To do Linux Kernel has a complete and profound

understanding, Linux The basic principle of the operating system really understand and get started.

Other benefits of early reading kernel

At present, there have been many Based Linux Early kernel developed kernel version specifically for embedded systems, such as DJJ of x86

operating system, Uclinux And so on (in www.linux.org On a dedicated directory), the world there are many people know from an early Linux Benefits kernel source code learning,

currently has some people are organizing manpower comments published books like this one. Thus, by reading Linux

Early versions of the kernel source code, is indeed a learning Linux An effective way systems, and research and application Linux Embedded systems are also a great help.

In the annotation process early kernel source code, the authors found that early kernel source code is almost a streamlined version of the newer kernel currently used.

Which already includes a new version of the current content in almost all of the basic functions of principles. Just as: the author of "Introduction to System Software System

Programming," a book Leland L. Beck Introducing the operating system program and system design, the introduction of a very simple instruction simplified computer ( SIC) System to

illustrate the design and implementation of all principles of system programs, which not only avoids the complexity of the actual computer system, but also a thorough description of

the problem. Select here Linux Early versions of the kernel as a learning object, its guiding ideology and Leland Consistent. This pair Linux Beginners learn the kernel, it is one of the

most ideal choice. Depth understanding can in the shortest possible time Linux The basic principle of the kernel.

For those already familiar with core operating principle, in order to make themselves do not create a sense of castles in the air of the actual workings of the system in

practice, therefore, it is necessary to read the kernel source code.

Of course, as with earlier kernel learning objects also have shortcomings. Chosen Linux Early kernel version does not include the virtual file system VFS Support, support

for network systems support only a.out Executable files and description of other existing complex kernel subsystem. But because the book is as Linux Core operating mechanism

to achieve entry materials, so this choice is also one of the advantages of an early version of the kernel. By studying this book, you can lay a solid foundation for further study of

these advanced content.

Read the importance and necessity of the full source code

Just like Linux Founder of the system on a newsgroup posting said, to understand the true operating mechanism of a software system, be sure to read the source code ( RTFSC

- Read The Fucking Source Code ). The system itself is a complete whole, with many of the seemingly unimportant details exist, but if we ignore these details, it will bring

difficulties to understand the entire system, and can not really understand the ways and means to achieve a practical system.

Although the operating system by reading some classic books principle (eg MJBach of" UNIX Operating System Design ") capable of UNIX

Works like operating systems have some theoretical guidance, but actually understand the true relationship between the composition and internal operating system implemented

is still not very clear. Just like AST Said, "many operating systems textbooks are heavy theory and practice of light", "Most books and courses for scheduling algorithms spend a lot

of time and space and completely ignored I / O In fact, the former is usually less than one code, which often account for a third of the total amount of code for the entire system.

"After the kernel lot of important details were not mentioned. So do not make the reader understand the operating system to achieve a true secret lies only in reading too detailed

full kernel source code, you will have a clear insight of feeling on the system ,Correct

-2-
Preface

The operation of the overall system have a deep understanding. Then, when you choose the latest or newer kernel source code to learn, you will not run into a big problem,

basically able to successfully understand the content of the new code.

How to choose the version of the kernel code to be read

So, how can achieve the above requirements, without being too much content and confuse the mind, to select a suitable Linux Kernel version to learn, to improve the

efficiency of learning it? After the author of a large number of kernel versions to compare and choose, he chose the current Linux

The basic functions of the kernel more similar, and very short 0.11 Kernel version as the best version of entry-learning. Below is some of the major Linux

Statistics version of the kernel line.

100,000,010,000,000

100,010,000,100,000
V1.0
V0.01

V0.11

V0.12

V0.95

V0.97
V0.96a

V1.1.52

V1.2.13

V1.3.95

V2.0.38

V2.2.20

V2.4.17

current Linux Kernel source code amount in the number of millions of rows of extremely large, full versions of these notes, and is almost impossible, and 0.11 Version of

the kernel does not exceed 2 Million lines of code amount, so they could explain clearly and notes in a book. Small but complete.

In addition, this version can avoid using existing newer kernel version has become increasingly complex research was part of the various subsystems (such as virtual file

system VFS , ext2 or ext3 File system, network subsystem, the new complex memory management mechanisms, etc.).

Basics of reading this book should have,

In reading this book, the authors hope that the reader has some basic knowledge of or related reference books at hand. One is about 80x86

Processor architecture and programming knowledge or information. For example, can be downloaded from the Internet 80x86 Programming Manual ( INTEL 80386 Programmer's

Reference Manual ); The other is related to 80x86 Hardware architecture and interface programming knowledge or information. A lot of information in this regard; it should also have

three primary use Linux Simple skill system.

In addition, since Linux System kernel implementation, according to the earliest MJBach of" UNIX The basic principles of operating system design, "a book

-3-
Preface

Development, the source code of many variable or function name comes from the book, so when reading this book, if appropriate reference book, easier to understand the source

code.

Linus In the initial development Linux Operating system, referring to the MINIX operating system. For example, the initial Linux Copying the kernel version MINIX 1.0 File

system. Therefore, when reading this book, ASTanenbaum The book "Operating Systems: Design and Implementation" also has great reference value. but Tanenbaum Book

describes a message passing communication (exchange of information) between each of the core modules, and Linux The working mechanism of the kernel is not the same. You

can only refer to the contents of which operating system works on general chapter and file system implementation.

Use an earlier version of obsolescence?

On the surface this book Linux Early versions of the kernel content like comments Linux When the operating system just released Tanenbaum It is considered outdated ( Linux

is obsolete ) The same idea, but by the content of this book, you will find that the use of book learning Linux Kernel, because the kernel source code quantity short and lean, so

there will be a high learning efficiency, able to do more with less, quick start. And lay a solid foundation for further selection to continue learning new kernel part of the source

code. After learning this postscript, you principle of operation of the system will have a very complete and practical concept, a complete concept that can make people more easily

select and study any part of the new kernel source code, without the need to read a huge amount of code to chew on a new kernel with full source code.

Ext2 File system MINIX File system

Currently Linux The system used Ext2 (Or latest Ext3 ) File system, the kernel is 1.x After the development of the file system, its functionality and its performance is very

detailed and complete stability, it is Linux The default operating system on standard file system. However, as Linux Complete operating system works in getting started section to

be used, in principle, is more streamlined as possible. In order to achieve a complete understanding of the operating system, and can not be overwhelming and excessive

complexity of the details of each subsystem in the choice of study analysis using kernel version, part of the code system can be described as long as the content of the actual work

principle, the simpler the better.

Linux Kernel 0.11 At that time the version contains only the most simple MINIX 1.0 File system, an operating system for understanding the actual file system and working

principle sufficient. This is also the choice Linux One of the main kernel versions earlier study.

After a complete reading this book, I believe you will certainly send out such a sigh: "For Linux Core system, I'm finally a beginning! . "At this point, you should be very

sure to further learn the latest Linux Works and processes in various parts of the kernel.

Tongji University,

Dr. Zhao Jiong

2002.12

--4--
1.1 Linux birth and development

The first 1 Chapter Overview

This chapter first reviews Linux Operating system birth, development and growth process, whereby you can understand why this book would choose Linux

Some earlier versions of the system as a reason for learning object. Then specifically described early selection Linux Kernel version of the advantages and shortcomings of

learning and how to begin further study. Finally, the content of each chapter gives a brief introduction.

1.1 Linux The birth and development

Linux The operating system is UNIX One kind of operating system cloning system. It was born in 1991 Year 10 month 5 Day (this is the first time outside the official

published). Since the aid Internet Network, through the joint efforts of computer enthusiasts around the world, has now become the world's most used one UNIX Like operating

systems, and the number of users is still growing fast.

Linux OS birth, development and growth process relies on the following five pillars: UNIX operating system, MINIX operating system, GNU plan, POSIX Standard and Internet The

internet. This is based on the following five basic clues to pursue it Linux The development process, its brewing process and the initial development experience. First, the four basic

elements introduced therein, and then in accordance with Linux Founder Linus Toravlds From the computer to the computer of interest and self-knowledge, to prepare my heart

began brewing its own operating system, to the original Linux

Kernel 0.01 Since then released version and how the hard way in the world step by step hacker With the help of a relatively complete final launch 1.0

After this time the development version, that is to Linux The early history of the development in detail.

Of course, Linux Kernel version has been developed to 2.5.52 Version. Most Linux The system used by the kernel is stable

2.4.20 Version of the kernel (the first of which 2 If the odd numbers indicates is being developed version, we can not guarantee the stability of the system). for Linux

The general history of many articles and books have introduced, will not repeat here.

1.1.1 UNIX The operating system was born

Linux The operating system is UNIX A clone version of the operating system. UNIX The operating system is the US Bell Labs

Ken.Thompson with Dennis Ritchie to 1969 In the summer DEC PDP-7 Developed on a small computer time-sharing operating system.

Ken Thompson To be able to idle the PDP-7 He runs very much like Star Trek on your computer ( Space travel ) Game, so in 1969 During the summer

vacation back home in California take his wife, developed in a month UNIX Operating system prototype. It was using BCPL Language (Basic programming language

combinations), after Dennis Ritchie to 1972 In a highly portable C

Language has been rewritten so that UNIX System in universities and colleges have been promoted.

1.1.2 MINIX operating system

MINIX The system is composed of Andrew S. Tanenbaum ( AST )developing. AST In the Netherlands Amsterdam of Vrije Mathematics and Computer Science University

system work, is ACM with IEEE Fellow (only a few people around the world also is a senior member of the NPC and CPPCC). A total of 100 Articles, 5 Computer books.

AST Although born in New York, but it is a Dutch nationals ( 1914 In his ancestors came to the United States). His high school in New York, MIT

The university, the University of California Berkeley Campus PhD study. Since reading postdoctoral reason, he came home to the Netherlands. Since then, he remained in touch with

home. Later in Vrije University began teaching, research students. Dutch capital Amsterdam He is a perennial rainy city, but for AST , This is the best, however, because in such an

environment he can often be at home playing with his computer up.

MINIX It's him 1987 In preparation, mainly for students to learn principles of operating systems. To 1991 Versions years 1.5 . Currently there are two versions in use: 1.5 Version

and 2.0 Version. The operating system was used in the university is free, but other uses are not. Head of course

--5--
1.1 Linux birth and development

before MINIX The system is already free from many FTP On the download.

for Linux The system, he later has said its developer Linus Praise. But he believes Linux The development of a large reason is because in order to keep him MINIX Miniaturization,

students will be able to make completion within one semester, so many people around the world did not accept MINIX

The expansion requirements. So inspired in this context Linus write Linux system. of course Linus Also happens to seize this good time.

As an operating system, MINIX Not a good person, but it also provides a C Written language and assembly language source code system. This is the first time so that aspiring

programmer or hacker Be able to read the operating system source code. At the time, the source code is the software vendors have been carefully guarded secret.

1.1.3 GNU plan


GNU Program and the Free Software Foundation FSF (the Free Software Foundation) By Richard M. Stallman to 1984 In single-handedly founded. It aims to develop a

similar UNIX And is a complete operating system free software: GNU system( GNU Yes" GNU's Not Unix " Recursive acronym, it's pronounced " guh-NEW " ). Use a variety of Linux

As the core of GNU The operating system is being widely used. While these systems are generally referred to as " Linux " ,but Stallman Think, strictly speaking, they should be

called GNU / Linux system.

The last century 90 Early years, GNU Project has developed a number of high-quality free software, including the famous emacs Editing system, bash shell program, gcc Series

compiler, gdb Debugger and so on. These software Linux Operating system development has created a suitable environment. this is Linux One of the foundations can be born, so

that many people now will Linux Operating system called " GNU / Linux " operating system.

1.1.4 POSIX standard

POSIX ( Portable Operating System Interface for Computing Systems )By IEEE with ISO / IEC The development of a cluster of standards. The standard is based on the

existing UNIX Practice and experience, describes the operation of the system calls the service interface. Preparation for securing portable applications and can run on multiple

operating systems on the source code level. It is 1980 In early a UNIX user group

(Usr / group) Acquired on the basis of earlier work. That UNIX User group had tried to AT & T of System V Operating system and Berkeley CSRG of BSD The difference between the

operating system call interface re-reconcile integration. And to 1984 In the custom / usr / group standard.

1985 year, IEEE Operating Systems Technical Committee Standards Subcommittee ( TCOS-SS ) In the beginning ANSI With the support of enjoin IEEE

Standards Committee procedures operating system source code portability service interfaces formal standards. Arrived 1986 year 4 month, IEEE Worked out a trial standards. The

first is the formal standard 1988 year 9 Month approved ( IEEE 1003.1-1988 ), Also often referred to both the future

POSIX.1 standard.

To 1989 year, POSIX The work was transferred to ISO / IEC Community by 15 Working Group to continue to develop into ISO standard. To 1990

year, POSIX.1 And has been adopted C Joint language standard, formally approved IEEE 1003.1-1990 (Also ANSI Standard) and ISO / IEC 9945-1: 1990 standard.

POSIX.1 Only provides system services application programming interface ( API ), Only outlines the basic system service standards. The Working Group is expected other

functions of the system are also to develop standards. such IEEE POSIX Work begins launched. At first there are ten approved plan was afoot, nearly 300 People attended a

one-week meeting every quarter. The work that has commands and tools standard ( POSIX.2) Standard test method ( POSIX.3 ),real time API ( POSIX.4 )Wait. Arrived 1990 In the first

half it has been 25 A plan was afoot, and there 16

Working groups participating. At the same time, there are a number of organizations are also developing similar standards, such as X / Open , AT & T , OSF Wait.

in 90 Early years, POSIX Standards are in the final vote, when finalized, it is 1991-1993 Years. It is at this time Linux

Just starting up, this UNIX Standards Linux Providing important information so that Linux It can be developed under the guidance of the standard, and can with

most UNIX Operating systems. In the first Linux Kernel source ( 0.01 Version, 0.11 Version) is already Linux System and POSIX Compatible with standard ready

for work. in Linux 0.01 Version of the kernel / include / unistd.h File already defines several related POSXI Standard symbolic constant, and Linus Already he

wrote in a comment: " OK It may be a joke, but I is studying it yet. "

-6-
1.1 Linux birth and development

1991 year 7 month 3 Day in comp.os.minix Posted on post The already mentioned are gathering POSIX data of. Which revealed he is looking to develop an operating

system, and in the early stage of development and has been thought to be achieved POSIX Compatible problem.

1.1.5 Linux The operating system was born

in 1981 year, IBM The company introduced a world-renowned microcomputer IBM PC . in 1981-1991 Years, MS-DOS Operating system has been dominated by

micro-computer operating system. At this point though declining price of computer hardware, but the software price is still high. then Apple of MACs The operating system can be

said to be the best performance, but its high price makes no one can easily close.

At that time the camp is another computer technology UNIX world. but UNIX The operating system is not only expensive problem. In order to seek high profit

margins, UNIX Dealers to raise prices too high, PC Small users can not close it. Once received Bell Labs

The license can be used for teaching at the university UNIX The source code has been carefully guarded allowed to open. For the majority of PC User, the software industry's large

suppliers were never given an effective means to solve this problem.

At that moment, there was MINIX Operating system, and there is a book that describes the design and implementation of the principles will also be issued. due to AST Of

this writing it is very detailed, and narrated orderly, so almost computer enthusiasts around the world are beginning to look at this book, in order to be able to understand the

workings of the operating system. Which also includes Linux The founder of the system Linus Benedict Torvalds .

then( 1991 year), Linus Benedict Torvalds Is a sophomore at the University of Helsinki Department of Computer Science, is also a self-taught computer hacker . This one twenty

one Young Finnish-year-old likes to tinker with his computer and test computer performance and limitations. But when he lacks is a professional-grade operating system.

During the same year, GNU Program has developed a number of tools. Two of the most anticipated GNU C The compiler has emerged, but have not yet developed free GNU operating

system. Even the use of teaching MINIX Operating system also began to have copyright, need to buy to get the source code. although GNU Operating Systems HURD It has been in

development, but it seems can not be completed within a few years at that time.

In order to better learn computer knowledge (perhaps just for fun ☺ ), Linus Christmas and New Year's money to use the loan to purchase a 386 Compatible computer, and

a set of mail order from the United States MINIX system software. Just wait MINIX During the software, Linus To seriously study the relevant Intel 80386 Hardware knowledge. In

order to pass Modem Dial-up connection to the host school, he used assembly language and use 80386 CPU Multitasking characteristics worked out a terminal emulation program.

Since then copies itself to the software on the old computer to a new computer, he also worked out the appropriate driver for the floppy disk drive, keyboard and other hardware

devices.

By programming practices, and that in the learning process MINIX Many restrictions system ( MINIX Although good, but just a simple operating system for teaching

purposes, rather than a strong practical operating system), and the above practice Linus There have been some similar operating system, hardware device driver code, so he

began to prepare a new operating system ideas. at this time GNU Program has developed a number of software tools, which most expect GNU C The compiler has occurred.

although GNU The free operating system HURD

in development. but Linus He has not wait.

From 1991 year 4 Since May, he by modifying the terminal emulation programs and hardware drivers, started to compile from their own operating system. At first, his

purpose is very simple, just to learn Intel 386 Programming techniques in architecture protected mode operation mode. But then Linux

The development has completely changed his mind. according to Linus in comp.os.minix Published on the newsgroup message, we know that he can gradually learn from MINIX System

development phase to develop their own Linux Process system.

Linus The first 1 Times to comp.os.minix The message is delivered in 1991 year 3 month 29 day. The postings on the topic " gcc on minix-386 does not optimize ", Is about

gcc Compiler MINIX-386 On system operation optimization problem ( MINIX-386 It is made Bruce Evans Improved use Intel 386 Characteristic 32 Place MINIX system). It can be

seen, Linus in 1991 Early years has already begun in-depth study MINIX System, and has improved during this time MINIX Operating system thought. In a further study MINIX After

the system, the idea gradually evolved into a redesign based think Intel 80386 The idea of ​the new operating system architecture.

He was raised in answer MINIX When on a question, said the first sentence is "read source code" ( "RTFSC (Read the F ** ing Source Code :-)" ). He believes the answer lies

in the source. This also shows that the system software for learning, we not only need to understand the basic principles of operation of the system, but also the actual system,

learning the actual implementation of the system. Because, after all, the theory is the theory, which omitted many minor, and these minor issues, although there is not much

theoretical content, but it is a necessary component of the system, like a feather sparrow body.

-7-
1.1 Linux birth and development

From 1991 year 4 The beginning of May, Linus He spent almost all the time to study MINIX-386 system( Hacking the kernel) And try to transplant GNU Software

on the system ( GNU gcc , bash , gdb Wait). And to 4 month 13 Day in comp.os.minix The release said he had successfully bash Ported to MINIX On, and has not put

it down, can not leave this shell Software.

First and Linux In related news 1991 year 7 month 3 Day in comp.os.minix The release (of course, that time does not exist

Linux The name was Linus Had in mind names may be FREAX ☺ , FREAX English meaning is grotesque, monster, whimsical, etc.). Which he revealed his ongoing Linux System

development, and it has been thought to be achieved and POSIX Compatible with the problem.

in Linus Another announcement in ( 1991 year 8 month 25 day comp.os.minix) He all MINIX Users ask " What would you like to see in minix? "( "Do you want the

most MINIX What the system to see? "), He first revealed in the message is developing a (free) 386 (486) Operating system, and said that just a hobby, the code will not be

great, would not like GNU As a professional. For some of the feedback we hope MINIX Features like system which does not like what other information and instructions for

practical and other reasons, the newly developed system beginning with MINIX Much like (and use MINIX The file system). And has successfully bash (1.08

Version) and gcc (1.40 Version) ported to the new system, but in a few months will be practical.

At last, Linus He affirmed that the development of the operating system does not use a line MINIX Source; and the use of the 386 The task switching characteristics, so that

the operating system is not good transplant (not portable), and can only be used AT hard disk. for Linux Portability problems,

Linus I did not consider. But now Linux It can run on almost any hardware architecture.
Arrived 1991 Year 10 month 5 day, Linus in comp.os.minix Post messages on newsgroups, announced outwards Linux The birth of the system kernel ( Free minix-like

kernel sources for 386-AT ). This message may be called Linux The birth of the Declaration, and has been widely circulated. therefore 10 month 5 Day of Linux Community is a

special day, many later Linux The new version released have chosen this day. and so RedHat The company chose this day to release its new system is not accidental.

1.1.6 Linux Operating system version changes

Linux Operating system from birth to 1.0 The official version appeared, it issued a total of table 1 - 1 Some of the major versions shown.

table 1 - 1 The main version of the kernel

version number Release date Explanation

0.00 (1991.2-4) Two processes, are displayed on the screen 'AAA' with 'BBB' .

The first official announcement of outward Linux Kernel version. Multi-threaded file system,
0.01 (1991.8)
segmentation and paging memory management.

0.02 (1991.10.5) This version and 0.03 Version is the build, it has been unable to find the characteristics above.

0.10 (1991.10) by Ted Ts'o Published Linux Kernel version. Increased memory allocation library functions.

0.11 (1991.12.8) The basic version of the kernel can be normal operation. At this point the hard drive and floppy drive.

The main increase in the software simulation program math coprocessor, increasing job control, virtual
0.12 (1992.1.15)
console, file symbolic links and virtual memory swap function.

Join the virtual file system support, increase the login function. Improve the performance of the floppy
0.95 (0.13) (1992.3.8)
disk drivers and the file system. Change the hard drive numbering. stand by CDROM .

Start adding network support. Improve the performance of the serial driver, cache, memory
0.96 (1992.5.12)
management, support dynamic link libraries, and can run X-Windows program.

0.97 (1992.8.1) Adds new SCSI Driver support.

0.98 (1992.9.29) Improved to TCP / IP ( 0.8.1 ) Network support, corrected extfs mistake.

0.99 (1992.12.13) Re-allocation of memory to use the design process, each process has 4G Linear space.

1.0 (1994.3.14) The first official version.

-8-
1.1 Linux birth and development

will Linux system 0.13 Direct renamed version of the kernel 0.95 Version, Linus It does mean that we do not feel isolated 1.0 Version is still far away. At the same time,

from 0.95 Version began, many improvements to the kernel (provided patches) are mainly on other people, and Linus The main task starts to become the kernel decide whether to

adopt a maintenance and patches. Until now, the latest version of the kernel is 2003 year 12 month 18

Announced 2.6.2 Version. Including about 15,000 Files, and use gz Compressed source code package also 40MB about! Until now, the latest version of the Table 1-2

Fig.

table 1-2 New kernel source bytes

Kernel version number Release date Source code size (by gz After compression)

2.4.22 2004.2.4 35MB

2.6.5 2004.4.4 41MB

1.1.7 Linux Origin of the name

Linux Operating system just has not been referred to at the beginning Linux , Linus To his operating system named FREAX , The English meaning of the grotesque,

monster, whimsical and other means. In his new operating system will be uploaded ftp.funet.fi When the server administrator Ari Lemke

Not like this name. He believes that since it is Linus The operating system will take its homophonic Linux As a directory of the operating system of it, so

Linux The name began to spread down.

in Linus Autobiography " Just for Fun "A book, Linus explain 1 : "Frankly, I never thought to use Linux The name of the publication of this operating system,

because the name a little too arrogant. And I am ready for the final release version of what is the name of it? Freax . In fact, some early kernel code Makefile - Used

to describe how to compile the source code file - File already contains " Freax " The name, there is about half a year or so. But this will not matter, do not need a

name at the time, because I have not had anyone to publish kernel code. "

"and Ari Lemke He insisted on his way into the kernel code ftp On the site, and I did not like Freax The name. He insisted on the name now ( Linux)

I admit that I did not argue with him and more. But it is his to take the name. So I can openly say that I'm not conceited, or partially frankly I was not

thinking selfishness. But I think Well, this is a good name, but after this thing I can always convince others, as I now do so. "

1.1.8 Early stage Linux The main contributors to system development

From Linux Early in the source code can be seen, Linux Early in addition to the main developer of the system Linus One except the person, who is most famous Theodore

Ts'o (Ted Ts'o) . He was 1990 He graduated from MIT Computer Science. In college he actively participated in various student activities organized by the school. He likes cooking,

biking, and of course there is the Hacking on Linux . Later, he began to like the sport from amateur radio reported. He is currently in IBM Work in systems programming and other

important matters. He is an international network design, operations, sales organizations and researchers open IETF member.

Linux Popular in the world also has his great credit. already Linux When the operating system has just come out, he was with great enthusiasm linux The

development of a Maillist Almost in Linux At first release since, he has been to Linux make a contribution. He is also the first to Linux Kernel add a program people ( Linux

Kernel 0.10 Virtual disk driver Edition ramdisk.c And kernel memory allocator kmalloc.c) . So far he is still engaged with Linux Related work. He was the first in North

America to set up Linux of

ftp Site ( tsx-11.mit.edu ), But the site is still for the majority Linux Users. He's right Linux One of the biggest contributions is proposed and implemented ext2 File

system. The file system has become Linux The world's de facto standard file system. He recently launched a ext3 File system. The system greatly improves the

stability and efficiency of access to the file system. As respected for his first 97 period( 2002 year 5 Months) Linux Journal Journal of him as a Cover, and interviewed

him. Currently, he is IBM Linux

1 Linus Torvalds "Just for fun" on page 84-88.

-9-
1.2 Summary of contents

Technology Center, and engaged in related Linux Standard Library LSB (Linux Standard Base) Work and other aspects.

Linux Another prominent figure in the community is Alan Cox . He had to work at the University of Wales Swansea ( Swansea University College) . At first he was particularly

fond of playing computer games, especially MUD ( Multi-User Dungeon or Dimension , Multi-user network games). in 90 Early years games.mud Newsgroup posts You can find a lot

of posts he published. He even wrote an article for this purpose MUD The history of the development ( rec.games.mud Newsgroups, 1992 year 3 month 9 day, A history of MUD) .

due to MUD The game is closely related to the network, and slowly he began to computer networks fascinated by them. To play the game and increase the speed and

network transmission speed computer running the game, he needs to choose a most satisfactory platform. So he came into contact with various types of operating systems.

Because of money, even MINIX He could not afford the system. when Linux 0.11 with 386BSD When released, he was considered a long time and finally bought a 386SX computer.

due to 386BSD Need a math coprocessor support, while the use of Intel 386SX CPU The computer is without a math coprocessor, so he installed Linux system. So he began

studying with the free source code Linux And began to Linux

The system generates interest, particularly the achievement of the relevant networks. About the Linux Single-user mode operation issues under discussion, he even praised Linux Achieve

cleverly ( beautifully) .

Linux 0.95 After release, he began Linux Writing system patches (modified program) (remember his first two patches have not been Linus Adoption), and became Linux On

the system TCP / IP One of the first people to use the network code. He later gradually joined the Linux The development team, and become a maintenance Linux One of the main

people responsible for the kernel source code, it can be said to be Linux Associations relay

Linus After the most important figure. after Microsoft The company had invited him to join, but he flatly refused. From 2001 In the beginning, he was responsible for maintenance Linux

Kernel 2.4.x Code. and Linus It is mainly responsible for the development of the latest development version of the kernel development (odd version, such as 2.5.x

Version).

"Kernel Hacker's Handbook" ( The Linux Kernel Hackers' Guide ) Author of the book Michael K. Johnson It is the first contact

Linux One of the operating system of people (from 0.97 Version). He is also famous Linux Documentation Project ( Linux Document Project - LDP ) Is one of the initiators. Once in Linux

Journel Work now RedHat work in company.

Linux The backbone of the system is not only able to develop into what it is today, there are many experts on computer Linux He made a great contribution, not list them

here. Specific can be found in the list of major contributors Linux Kernel CREDITS Files, which are listed in alphabetical order of Linux Make a greater contribution of nearly 400 A list

of list of people, including their email Address and mailing address, home page and the main contribution to the deeds and other information.

Through the above description, we can above Linux The five pillars are summarized as follows:

UNIX operating system - UNIX to 1969 He was born in Bell laboratory. Linux It is UNIX A cloning system. UNIX

The importance goes without saying.

MINIX operating system - MINIX Operating system is UNIX A cloning system, in which 1987 By the famous professor of computer

Andrew S. Tanenbaum Developed. due to MINIX Event of a system and provides the source code (only free for the university) whipped up a study at universities throughout the

world in UNIX Cyclone system. Linux At first reference is MINIX System to 1991 Only began to develop.

GNU Program - Development Linux Operating system, and Linux Most software used on basically come from GNU plan. Linux

Just a kernel of an operating system, no GNU Software environment (for example, bash shell) ,then Linux We will be unable to move.

POSIX standard - The standard push Linux After the operating system plays an important role towards the development of formal way. Yes Linux Forward lighthouse.

INTERNET - if there is not Intenet Net, no computer hackers all over the world countless selfless dedication, then Linux Can only develop to 0.13 (0.95) Version

level.

1.2 Content Summary

This article will focus on Linux Early kernel 0.11 Version of a detailed description and notes. Linux-0.11 Version is 1991 year 12 month 8

--10--
1.2 Summary of contents

Issued. The following files are included in the release:

bootimage.Z - US keyboard has a compression boot code image file;

rootimage.Z - In the compression 1200kB root file system image file;

linux-0.11.tar.Z - kernel source code file. Size is 94KB, 325KB is also just expanded; as86.tar.Z
- Bruce Evans' binaries. It is 16 and the loader assembly;
INSTALL-0.11 - Updated installation information file.

Currently in addition to the original rootimage.Z File, the other four documents can be found. However, the authors have used Internet Resources for

Linux 0.11 Re-create a fully used rootimage-0.11 Root file system. And re-compile their energy in 0.11
Use the environment gcc 1.40 Compiler, configure the available experimental development environment. Currently, these documents are available from oldlinux.org Download on

the website.

In this paper, a detailed analysis of linux-0.11 All of the kernel source code for each source file have carried out detailed notes, including Makefile Annotation files. The

main analysis was performed according to the computer startup process. Therefore, analysis of coherence to the end of the kernel initialization start calling shell So far the

program. Each of the remaining procedures were carried out for its own analysis, there is no continuity, it can be read according to their needs. But in the analysis or provide some

application examples.

All programs in the analysis process if you encounter authors believe is difficult to understand the statement, will give a detailed description of relevant knowledge. For

example, in reading the code the first time encountered C Inline assembly code language, will GNU C Inline assembly language language more detailed description; in the face of the

interrupt controller input / output operations, will Intel Interrupt Controller ( 8259A ) Chip detailed description is given, and lists the commands and the methods used. This will help

deepen the understanding of the code, but also a better understanding of the use of hardware used, the authors believe that this interpretation method than the content listed in a

separate chapter to introduce a much higher overall hardware or other knowledge to efficiency.

take Linux 0.11 Version of the kernel to "cut" in order to improve our understanding of Linux Efficiency operation mechanism. Linux-0.11 Whole kernel source code version

only 325K Bytes, of which the content comprises basically Linux The essence. The latest 2.5.XX Version of the kernel is very large, nearly 188 Megabytes, even if you spend a

lifetime experience may not be able to read all read. Maybe you want to ask "If you want to start from simple, why not analyze smaller Linux 0.01 Version of the kernel source

code? It only 240K Byte about "The main reason is because 0.01

Version of the kernel code has too many shortcomings, not even including the driver of the floppy disk, there is no good to the use of a math coprocessor and a description of

the landing procedure. And its boot program structure with the current version is not the same, and 0.11 Version of the boot and program structure is now basically the same.

Another reason is to be found 0.11 The early version has been compiled to make a good kernel image file ( bootimage) , It can be used to guide the presentation. If matched

with a simple root file system image file ( rootimage) , Then it can be a normal run.

take Linux 0.11 Learning version also has shortcomings. For example, the kernel version is not yet included in the relevant specialized processes waiting queue,

TCP / IP Some very important current code and other aspects of the network, distribution and use of memory with the current kernel is also somewhat different. But the good news

Linux The network code is basically a self-contained, the relationship between the core mechanism is not very big, so you can understand the Linux After analyzing the basic

principle of the code again.

In this paper, Linux All of the kernel code are described. In order to maintain structural integrity, the composition is described structure of the code in the source code of the

kernel carried out, basically each source code directory introduces a chapter. The introduction of the order source files can be found in front of the file list index. entire Linux Kernel

source code directory structure following Table 1.1 Fig. All are based on the directory structure linux For the current directory.

--11--
1.2 Summary of contents

List 1-1 Linux / table of Contents

Name Size The last modification date (GMT) Description

boot / 1991-12-05 22:48:49

fs / 1991-12-08 14:08:27

include / 1991-09-22 19:58:04

init / 1991-12-05 19:59:04

kernel / 1991-12-08 14:08:00

lib / 1991-12-08 14:10:00

mm / 1991-12-08 14:08:21

tools / 1991-12-04 13:11:56


Makefile 2887 bytes 1991-12-06 03:12:46

This book can be divided into three parts. The first 1 The first chapter to 4 Chapter is to describe the kernel and boot 32 Prepared Bit operating mode, as a beginner to

learn the kernel should all be read. A second portion from the first 5 The first chapter to 10 Chapter is the main part of the kernel code. The first of 5

Chapter can be read as part of the subsequent sections of this index. The first 11 The first chapter to 13 The third chapter is part of, the information can be read as a reference to

the second part of the code.

The first 2 Chapter summary description of the Linux Architecture operating system kernel source code file organizational structure and placement of each file function

substantially. Also introduced Linux Use of physical memory allocation, using several stacks and how to use the linear kernel and the virtual address to be allocated. Finally, the

kernel package start comment Linux / The first file in the directory have seen, that the overall kernel code

Makefile Contents of the file. The kernel source file is compiled manage all configuration files for build management tools make use.

The first 3 Chapter detailed notes boot / Three assembler directory, including the disk boot program bootsect.s ,Obtain BIOS Parameters in setup.s Assembler and 32 Bit

run boot code program head.s . This is done three assembler kernel boot loader into the working memory from a block device, and the detection system configuration parameters,

the entry is completed 32 All work before the bit protected mode. For the core system to perform further initialization work ready.

The first 4 Chapter introduces init / Kernel initialization program directory system main.c . It is a key place to do all the kernel initialization and into normal operation. After

completing all of the initialization system, created for shell Process. Introducing the program will need to see it to call other programs, so the order of the following chapters of

reading can be invoked in accordance with this. Since the function of memory management program is widely used in the kernel, so this should be the first chapter Readings.

When you can really understand until main.c When the program until all programs, you should already Linux Kernel have a certain understanding, it can be said to have half a

beginning ☺ But you also need to file systems, system calls, various drivers, etc. deeper reading.

The first 5 Chapter introduces kenel / All program directory. The most important part is the process of scheduling function schedule () , sleep_on ()

Functions and related system calls the program. At this point you should have an understanding of some important program them.

The first 6 Chapter kernel / dev_blk / Block device program directory will be described annotation. This chapter contains drivers for hard drives, floppy disks and other block

device, it is mainly used to deal with the file system and high-speed buffer, containing more content-related hardware. Therefore, when reading this chapter need some hardware

reference material. It is best to first look at the section of the file system.

The first 7 Chapter kernel / dev_chr / Character device driver directory annotation explained. This chapter is mainly involved in the serial line drivers, keyboard drivers, and

display drivers. These drivers make up 0.11 The kernel supports serial terminal console and terminal equipment. Therefore, this chapter also contains more content related to

hardware. In reading about the need to refer to the relevant hardware books.

The first 8 Chapter kernel / math / The simulation program directory math coprocessor. Because this book is annotated version of the kernel, it has not really begun to

support co-processor, and therefore less of this chapter, is relatively simple. Just to have a general understanding.

The first 9 Chapter kernel source code fs / File system program directory, I suggest you can pause to read it while watching this chapter

Andrew S. Tanenbaum "Operating System Design and Implementation," a book about MINIX Section of the file system because the initial Linux

The system is only supported MINIX A document system, Linux 0.11 Version is no exception.

--12--
1.2 Summary of contents

The first 10 Chapter Commentary mm / Memory manager directory. To get a full understanding of the content in this area, the need for Intel 80X86 Protected-mode operating

mode of the microprocessor has enough understanding, so this chapter contains more complete in place concerning 80X86 Description protected-mode operating mode, which

basically can refer to knowledge Intel 80386 Programmer Programming Manual ( Intel 80386 Programmer's Reference Manual) . But in this chapter, to use an example source code

will be explained as an object, you should be able to better understand how it works.

current Linux Kernel analysis books lack a description of the kernel headers, so for a beginner is concerned, at the time of reading the kernel will encounter many

obstacles. The first book 11 Chapter include / All files in a directory header been described in detail, for each substantially define, each have a constant or data structures and

detailed comments. In order to facilitate access to reference when reading this book in the appendix also some important data structures and variables often use the comments

were summarized, but the content actually can be found in this chapter. Although this chapter is primarily for the reader to other sections of reference to use, but if you want a

thorough understanding of core operating mechanism, still need to understand these header files in many of the details.

The first 12 Chapter describes the Linux 0.11 Version of the kernel source code lib / All files in the directory. These documents mainly library functions provides interface

functions to the compiler system, a system program for the future have a greater understanding of the system software help. Due to lower this version, so there's not a lot of

content, you can quickly read. This is why we have chosen 0.11 One of the reasons edition.

The first 13 Chapter tools / Directory build.c program. This program will not be included in the compiled kernel image ( image) File, it is only for the disk boot program

core blocks connected to other modules to form a complete primary kernel kernel image ( kernel image )file.

The first 14 Chapter describes the experimental environment and experimental method when learning the kernel source code. Introduces the Bochs Use and compile

emulation system Linux Kernel methods and the production method of a disk image file. Also explains how to modify Linux 0.11 The syntax of the source code to enable him RedHat

9 The system successfully compile the kernel to correct.

Finally, the appendices and index. Given in the Appendix Linux The basic definition of the constants and the kernel data structure definitions, and a concise description of

the protected mode operating mechanism.

For ease of reference, also in the appendix of this book are listed separately in the kernel to use the relevant PC Information machine hardware. In the references, we

have only given when reading the source code can refer to the information on books, articles, etc., are not all-inclusive complex gives a list of a bunch of messy literature. For

example, in reference Linux Documentation Project LDP ( Linux Document Project When the file), we will clearly list the specific needs Which one HOWTO Article, and not only give LDP

The website address trouble.

Linus In the initial development Linux When the operating system kernel, the main reference 3 Book. One is MJ Bach Significant " UNIX Operating System Design ", the

book describes the UNIX System V Core operating principle and data structures. Linus The book uses a lot of functions in the algorithm, Linux Kernel source code names of many

important functions are taken from the book. Therefore, when reading this book, which is an essential aspect of the kernel works reference books. This is another John H. Crawford

Eds of " Programming the 80386 "Is explained

80x86 Protected mode programming method of the books. There is a Andrew S.Tanenbaum Significant " MINIX The first operating system design and implementation, "a book 1 Version.

Linus The main use described in the book MINIX File system 1.0 Version, but in the early Linux Kernel only supports the file system, so when reading this book a chapter about the

file system, working knowledge of the principles of respect from the file system can Tanenbaum Book available.

At the time of each program explanation, we will describe briefly the main object and purpose of the program, the relationship between input and output parameters, and

other programs, and then list the complete code of the program and in which the code annotation detail, when the original comment program code or text without modification or

delete any aspect, because C Language is an English language class, a small amount of any original program English annotations symbolic constant, variable names, also

provided a lot of useful information. After the code is more in-depth dissection program, some of the language or knowledge of the hardware and code appear explained. If you go

back and look through the program after reading this information, you will have a deeper level of experience.

For some knowledge of the basic concepts introduced in this book required reading are scattered in various sections of the respective places, so was able to easily find,

but when combined with the source code to read, some basic concepts to have a deeper understanding.

Finally, note that when you have fully understood all illustrated herein, does not mean you have become a Linux The expert,

--13--
1.3 Summary

You only just set foot on Linux The journey has to be a certain amount of Linux GURU The preliminary knowledge. Then you should be reading more of the source code, it is best

progressively from 1.0 Until the beginning of the odd-numbered version of the latest version under development. In writing this book the latest Linux The kernel is 2.5.44 Version.

When you can quickly understand the latest versions of these developers are even able to make their own suggestions and patches ( patch ) Program, I also beats the ☺ .

1.3 chapter summary

First elaborated Linux The birth and development of five essential pillars: UNIX The original open-source version Linux The basic theory and algorithm

implementation, Rechard Stallman of GNU Plans for Linux The system provides a rich variety of free and utilities,

POSIX Appear as standard Linux It provides a reference guide to achieve standards-compliant system. AST of MINIX Operating system Linux

The birth played a lack of reference can not be ignored, Internet Yes Linux The necessary environment for growth and expansion. The last chapter provides an overview of the

basic contents of the book.

--14--
2.1 Linux kernel mode

The first 2 chapter Linux Core Architecture

This chapter first provides an overview of Linux Preparation mode kernel and architecture, and is described in detail Linux The main function of each organization, and

code files and subdirectories in the hierarchy of basic calling kernel source directory. Then direct to the point, from the kernel source files Linux / The first file in the directory Makefile

The beginning of each line of code detailed explanatory notes. This chapter can be seen as a summary overview of the kernel source code can be used as reference information

read subsequent chapters.

Available a complete operating system mainly consists of 4 Components: hardware, operating system kernel, operating system services and user applications, see Fig. 2-1 Fig.

User applications are those word processing program, Internet Various applications or user-browser program compiled; operating system services are those services provided to

users of the program is seen as part of the operating system functions. in Linux Operating system, these programs include X Window system, shell Command interpreter system and

those kernel programming interface system program; the operating system kernel that is part of the book is of interest, it is mainly used for the scheduling abstract and access to

hardware resources.

User application

Operating System Services

The operating system kernel

Hardware system

Map 2-1 Operating system components.

Linux The main purpose of the kernel is to perform with the computer hardware interaction programmable control and interface operation of the hardware components,

scheduling access to hardware resources, and provide a high level of execution environment and the virtual interface hardware for the user program on the computer. In this

chapter, we first based Linux 0.11 Version of the source code kernel, concisely describe Linux The basic architecture of the core, constituting the main module. Then several

important data structures occur in the source code will be explained. Finally, it describes the construction Linux 0.11 Methods kernel compile test environment.

2.1 Linux Kernel mode

At present, the structure of the operating system kernel mode can be divided into single monolithic kernel mode and hierarchical micro-kernel mode. The book comments Linux

0.11 Kernel, is the use of single-core mode. The main advantages of the single-core mode structure is compact kernel code, execution speed, the deficiency is primarily structural

level is not strong.

In the system of single-core mode, the operating system for the flow of services provided: application programs are used to specify parameter values ​call instruction

execution system ( int x80) ,Make CPU From the user mode ( User Mode ) Is switched to the core state ( Kernel Model ), Then the operating system service call specific call procedure

according to the specific system parameter values, and these services are programs in accordance with some functions need to support the bottom to accomplish specific functions.

After completion of the required service application, operating system, and from switch back to user mode kernel mode, returns to the application program execution continues

following instructions. Therefore Summary speaking, single-kernel-mode kernel can be roughly divided into three levels: call the main program level services,

--15--
2.2 Linux kernel system architecture

Service layer and the underlying function support system call system call. See Fig. 2-2 Fig.

The main program

system service

Support Functions

Map 2-2 Simple single-core mode structure model

2.2 Linux Core System Architecture

Linux Mainly by the kernel 5 A module configuration, they are: inter-process scheduling module, a memory management module, a file system module, a process

communication module and a network interface module.

Process scheduling module is used to control the process responsible for CPU Use of resources. Scheduling policy adopted by each process can be fair and reasonable

access CPU While ensuring the core can perform hardware operations in a timely manner. Memory management module is used to ensure that all processes can share the

machine's main memory area safely, at the same time, the memory management module also supports virtual memory management, so that Linux Support for the process uses

more memory space than the actual memory capacity. And can not use the file system to the temporary memory block is switched to the external storage device up, and then

switched back when necessary. The file system module for supporting and driving the external storage device. The virtual file system module by providing a common to all of the

external storage device file interface, hiding the details of the various hardware devices. And to provide support for other operating systems are compatible with a variety of file

system formats. Interprocess communication subsystem modules for support information exchange between multiple processes. The network interface module provides access to

a variety of network communication standards and supports many network hardware.

Dependencies between these modules see FIG. 2-3 Fig. Wherein the connection on behalf of dependencies, and an imaginary broken line between them represents the

frame portion Linux 0.11 Section has not been realized (from Linux 0.95 Version gradually began to realize the virtual file system, and support to the network interface 0.96 Version

only).

--16--
2.2 Linux kernel system architecture

Memory Management

Virtual File System

Process Scheduling Interprocess communication


File system

Network Interface

Map 2-3Linux Core system module structure and interdependencies

As can be seen from the figure, all modules are dependencies and process scheduling module. Because they need to rely on the process scheduler to suspend (pause) or

re-run their course. Typically, a module will be suspended while waiting for the hardware to operate, and can continue to run after the operation is completed. For example, when a

process attempts to write a block of data up diskette, floppy disk driver may start the rotation of the floppy disk during the process put on hold waiting state, and in the floppy disk

and then proceeds to the normal speed so that the process can continue run. Other 3 Modules also due to similar reasons and process scheduling module dependencies.

Some few other dependencies less obvious, but equally important. Process scheduling subsystem need to use memory manager to adjust the physical memory space used

by a particular process. Interprocess communication subsystems will need to rely on the memory manager to support shared memory communication mechanism. This

communication mechanism allows two processes to access the same area of ​memory for inter-process exchange of information. The virtual file system will also use the network

interface to support the Network File System ( NFS ), Also can use the memory management subsystem to provide virtual memory disk ( ramdisk )device. And the memory file system

management subsystem is also used to support the switching operations of the memory block.

If the kernel mode from single structural model, we can also according to Linux 0.11 Structure kernel source code kernel module mainly plotted 2-4 Shown in block

diagram.

--17--
2.3 interrupt mechanism

User-level

Kernel-level

System call interface

communication memory management


File subsystem

Process
program
Cache
Control Subsystem Scheduler

Character device block device


Inter-process
Device Drivers

Hardware Control
Kernel-level

Hardware-level
hard Parts library user

Map 2-4 Core structure diagram

Wherein the kernel level of several blocks, in addition to the hardware control block, other blocks correspond to thick line directory organization kernel source.

In addition to the dependency of these figures we have been given, all of which will depend universal resource modules in the kernel. These resources include all

subsystems kernel memory allocation and recovery of function calls will print a warning or error message function and a number of system debugging functions.

2.3 Interrupt mechanism

In use 80X86 consist of PC Machine, using two 8259A Programmable interrupt controller chip. Each piece can be managed 8 Interrupt sources. By cascading multiple sheet

management can constitute up 64 System interrupt vectors. in PC / AT Series compatible, the use of the two 8259A

Chip, a total of management 15 Level interrupt vectors. Which is shown schematically in Figure cascaded 2-5 Fig. From which the chips INT Pin is connected to the main chip

IR2 Pin on. the Lord 8259A Chip is the port address 0x20 From chip 0xA0 .

--18--
2.4 System Timing

clock IRQ0 IR0 IR1


keyboard IRQ1 INT INTR
connected with the serial IR2 IR3 8259A
port 2 IRQ3 int IRQ2 1 IR4 main sheet CPU
IRQ4 serial parallel IR5 IR6 IR7
interface 2 IRQ5 floppy Data D7-D0
IRQ6
parallel port 1 IRQ7

Address 0x20-0x3f A0
CS
CAS2-0

Real-time clock IRQ8 IR0 CAS2-0


INT0AH IRQ9 Reserved IR1 INT
IRQ10 Reserved IRQ12 IR2 IR3 8259A
mouse IRQ11 PS2 hard IR4 from sheet
disk coprocessor IRQ13 IR5 IR6 IR7
IRQ14 IRQ15 reserved

Address 0xA0-0xbf A0
CS

Map 2-5 PC / AT Computer cascading style 8259 Control System

Under control of the bus controller, 8259A Chip may be a programmed state and an operating state. Programming status is CPU use IN or OUT

Instructions 8259A Chip initial programming state. Once the initial programming, i.e. chips into operation, this device has to respond to the interrupt request by the external

apparatus at any time ( IRQ0 - IRQ15 ). By interrupting the arbitration select the chip will select the current highest priority interrupt request as an interrupt service objects, and by CPU

Pin INT Notice CPU The arrival of external interrupt requests, CPU After the response, the data bus from the chip D7-D0 The current service object programmed interrupt number

sent, CPU Thus obtaining the corresponding interrupt vector values, and execute the interrupt service routine.

for Linux Kernel, the interrupt signal is usually divided into two categories: hardware interrupt and software interrupt (abnormal). Each interrupt by 0-255

A number between identified. For interrupt int0 - int31 (0x00--0x1f) Each interrupt function by the Intel The company set a fixed or retained by, It belongs to the software interrupt, but

Intel The company called the exception. Because these interrupts are in CPU When an abnormality is detected due to instruction execution. Typically failure can be divided into ( Fault)

And traps ( traps) Categories. Interrupt int32 - int255 (0x20--0xff) It can be set by the user. in Linux System will int32 - int47 (0x20--0x2f) Corresponds to 8259A Interrupt control chip

emits a hardware interrupt request signal

IRQ0-IRQ15 And programming the system calls made ( system_call) Interruption to int128 (0x80) .

2.4 System Timing

in Linux 0.11 Kernel, PC Machine programmable timer chip Intel 8253 It is set to every 10 Ms to issue a clock interrupt ( IRQ0 )signal. This time to beat is the pulse of the

operation of the system, which we call 1 A system tick. So after each 1 Ticks will be called once the clock interrupt handler ( timer_interrupt ). The handler is mainly used by jiffies Variable

to the cumulative elapsed since the system starts the clock ticks. Whenever the clock interrupt occurs once the value is increased 1 . Then get the current privilege level from the

interrupted program segment selector in CPL As a parameter called do_timer () function.

do_timer () According to the privilege level as a function of the cumulative operating time for the current process. in case CPL = 0 , Then the process is running in kernel

mode is interrupted, so the kernel run-time process statistics stime increase 1 Otherwise, the user mode process run time statistics by 1 . If the program had to add a timer, then the

timer list for processing. If a timer expires (after decreasing equal 0 ), The timer handler is invoked. Then the current process run time to process, the current process run time slice

cut 1 . At this time if the current process

--19--
2.5 Linux Process Control

Sheet and is also greater than 0 , Said its time slice has not run out, so he quit do_timer () Continue the current process. If at this time the process has been decreasing for the time

slice 0 , Indicating that the process has run out of the use of CPU Time slice, the program will then determine further processing according to the level of the interrupted program.

The current process is interrupted if they are greater than the work (privilege level of the user state 0 ),then do_timer () The scheduler will call schedule () Switch to the other

processes to run. If the current process is interrupted the work in kernel mode, that is interrupted program run in the kernel, then do_timer () Eject immediately. Therefore, this

approach decision Linux Runtime system in kernel mode is not switched scheduler. Kernel mode programs can not be preempted, but it can be preempted at run time the user

mode program.

2.5 Linux Process Control

Program is an executable file, and the process ( process ) Is an instance of the program execution. The use of time-sharing technology, Linux

The operating system can simultaneously run multiple processes. The basic principle is to time-sharing technology CPU The running time is divided into a prescribed length of time

one piece, so that each process runs in a time slice. When the process of the system using a time slice expires scheduler switches to another process to run. So in fact, for a

single CPU The machine is only run one at a time process. However, due to time slice for each process running very short (eg 15 Systems ticks = 150 Ms), so the surface it seems

as if all the processes running at the same time.

for Linux 0.11 The kernel is concerned, the system can have up to 64 A process exist. In addition to the first process is outside the "manual" is established, the rest are using

the system calls the process fork The new process is created, the process is created called the child process ( child process ), Creator, called the parent process ( parent process ).

Kernel using the process identification number ( process ID , pid ) To identify each process. A process executable instruction code, data, and stack region. Process code and data

portions respectively corresponding to a code segment file, the data block execution. Each process can only execute code and access their own data and stack area.

Communication between each process needs to be carried out by a system call. For only a CPU The system, at a time only one process is running. By sharing the kernel scheduler

scheduling each process runs.

Linux System, it may be a kernel mode process ( kernel mode ) Or a user state ( user mode ) Under execution, therefore, Linux

Kernel stack and user stack is separated. User stack in user mode processes for temporarily holding the function call parameters, local variables and other data. The kernel stack

contains a kernel program execution information at the time of the function call.

2.5.1 Task data structure

Kernel to manage processes by table, each process occupies an entry in the process table. in Linux Systems, the entry process is a task_struct Task structure pointer.

Task data structure defined in the header file include / linux / sched.h in. Referred to as process control block some books PCB ( Process Control Block ) Or process descriptor PD ( Processor

Descriptor ). Which holds all the information for the control and management processes. State includes the current running process information, signals, process ID, parent process

ID, the cumulative operating time value, the local descriptors, and TSS information file is being used and this task. The configuration shown in the specific meaning of each field is

as follows.

struct task_struct {
long state // task of running state (-1 inoperable, 0 run (ready),> 0 has stopped).
long counter // task running time count (decrement) (ticks), run time slice.
long priority // Run priority number. When the task starts running counter = priority, the greater the long run.

long signal // signal. Bitmap, each bit represents a signal, the signal value of the bit offset value = +1.

struct sigaction sigaction [32] // flag information signal and performs the operation attribute structure, a corresponding signal will be executed. long blocked

// mask process signal (signal corresponding to the bit map).

int exit_code // task exit code execution stops, the parent process will take.

unsigned long start_code // code segment address.

unsigned long end_code // the code length (number of bytes).

unsigned long end_data // the code length + data length (number of bytes).

unsigned long brk // Total length (number of bytes).

unsigned long start_stack // stack segment address.

--20--
2.5 Linux Process Control

long pid // process identification number (process ID).

long father // parent process ID.

long pgrp // parent group number.

long session // session number.

long leader // session leader.


unsigned short uid // user identification number (user id).

unsigned short euid // effective user id.


unsigned short suid // Save the user id.
unsigned short gid // Group ID (group id).
unsigned short egid // effective group id.

unsigned short sgid // set id saved.


long alarm // alarm timer value (number of ticks).

long utime // user mode run time (ticks).


long stime // run time system state (ticks).
long cutime // child process run time user mode.

long cstime // child process state system uptime.

long start_time // process starts running time.


unsigned short used_math // flag: whether to use a coprocessor.
int tty // process uses sub-tty device number. -1 indicates no use.
unsigned short umask // Create a file attribute mask bits.

struct m_inode * pwd // current working directory i-node structure.

struct m_inode * root I // root node structure.


struct m_inode * executable // perform file i-node structure.
Close the file handle bitmap flag // execute unsigned long close_on_exec. (See include / fcntl.h) struct file * filp [NR_OPEN] // file structure
pointer list, a maximum of 32. Entry number that is the value of the file descriptor. struct desc_struct ldt [3] // tasks LDT. 0- empty, 1- snippet
cs, 2- data and stack segments ds & ss. struct tss_struct tss
TSS information structure // process.
};

When a process is executing, CPU State value in the register of all, the contents of the stack and the process is referred to as the process context. When the kernel needs to

switch ( switch ) When to another process, it needs to save all the status of the current process, that is, save the context of the current process, so that when the process is executed

again, the state can be restored when the switch to execute it. in Linux In the context of the current process data are stored in the task structure in the process. When an interrupt

occurs, the kernel in the context of the interrupted process, the execution in kernel mode interrupt service routine. But while retaining all of the necessary resources in order to

resume the interrupted interrupt process executed at the end of the service.

2.5.2 Process running

A process for its lifetime, may be under a different set of states, a process known state. See Fig. 2-6 Fig. Process status in the process saved the task structure state

Field. When the process is waiting for system resources in a wait state, called it in sleep wait state. in Linux System, the state is divided into sleeping wait interruptible

and uninterruptible wait state.

- twenty one -
2.5 Linux Process Control

Users running

state running

Kernel running state


System call or interrupt return
Interrupt, the interrupt return
running

Interruptible sleep state Sleep termination Dead zombie


1 0 3
interruptible state

Sleep Pause

Dispatch
Wake
Uninterruptible Pause state
2 00 4
uninterruptible sleep state stopped
wake carry on

Ready state
running

Map 2-6 State relations and the process of conversion

◆ operating status ( TASK_RUNNING )

When the process is being CPU Perform, or is ready to perform at any time by the scheduler, the process is said to be running ( running ). The process can run in kernel

mode, you can also run in user mode. When the system resources already available, the process will be awakened and ready to operate, the state called the ready state.

The state (FIG middle column) represents the same manner as in the kernel, were to become in a TASK_RUNNING status. ◆ can interrupt sleep state ( TASK_INTERRUPTIBLE

When the process is in an interruptible wait, the system will not schedule the execution. When the system generates an interrupt or release the process is waiting for a

resource or process receives a signal, you can wake up the process of transition to the ready state (running state). ◆ uninterruptible sleep state ( TASK_UNINTERRUPTIBLE )

And can interrupt sleep-like state. But the process in this state is only to be used wake_up () It can be converted to a ready state to run when a clear wake-up function. ◆

suspended state ( TASK_STOPPED )

When the process receives a signal SIGSTOP , SIGTSTP , SIGTTIN or SIGTTOU When it will enter a suspended state. May send

SIGCONT Signal so that the process of shifting to the operation. in Linux 0.11 , The conversion process has not been achieved to the state. The state is in the process will

be terminated as a process to deal with. ◆ dead state ( TASK_ZOMBIE )

When the process has stopped, but the parent process has not asked about their status, the process is said to be in dead state.

When running a process time slice is exhausted, the system will switch to force the scheduler to execute other processes. In addition, if the process executed in the kernel

mode have to wait for a resource system, in which case the process will call sleep_on () or sleep_on_interruptible ()

Voluntarily give up CPU The right to use, and let the scheduler to execute other processes. The process goes to sleep ( TASK_UNINTERRUPTIBLE

or TASK_INTERRUPTIBLE ).

Only when the process is transferred from the "kernel running state" to "sleep", the kernel will carry out the process of switching operations. A process running in another

process can not be preempted kernel mode, but can not change the state of a process to another process. To avoid data errors during the process of switching the kernel, the

kernel when executing a critical section of code disables all interrupts.

- twenty two -
2.5 Linux Process Control

2.5.3 Initialization process

in boot / Directory bootstrap the kernel is loaded from disk into memory, and let the system run in protected mode to enter, they begin to perform system initialization

program init / main.c . The program first to use the system to determine how to allocate physical memory, then calls kernel initialization function of each part separately for memory

management, interrupt handling, block and character devices, process management as well as hard and floppy disk hardware initialization process. After completion of these

operations, the various parts of the system having been in the running state. Since then the program themselves "manual" to the task 0

(process 0 ) Running, and use fork () Calls for the first time create a process 1 . In the process 1 The program will continue with the application environment initialization and execution shell

Login procedure. The original process 0 Scheduling will be performed when the system is idle, then the task 0 Execution only pause () System call, and it will call the dispatch

function.

"Move to the task 0 The implementation of "the process by the macro move_to_user_mode ( include / asm / system.h )carry out. It main.c

The program execution flow from kernel mode (privilege level 0 ) To the user mode (privilege level 3 ) Task 0 Continue to run. Before moving, during initialization of the system

scheduler ( sched_init () ), The first task 0 The operating environment has been set. This includes artificial pre-set task 0 Value data structure of each field ( include / linux / sched.h ),

Insertion of the task in global descriptor table 0 The Task State Segment ( TSS ) And a local descriptor table descriptor ( LDT ) Segment descriptor, and they are loaded into the task

register tr And Local Descriptor Table Register ldtr in.

It should be emphasized that the kernel initialization is a special process, the kernel initialization code that is, the task 0 Code. From the task 0

The initial set data structure can be seen, the task 0 The base address of the code and data segments are 0 , Segment length is limited 640KB . The base address of the kernel

code and data segments are 0 , Segment length is limited 16MB , The task 0 Code and data segments are contained in the kernel code and data segments. Kernel initialization

procedure main.c That is the task 0 Code, just moves on to task 0 Before the system is in a privileged kernel mode

0 Running main.c program. Macros move_to_user_mode The function is to run from privileged kernel mode 0 The user state level conversion

3 Level, but still continue with the original code instruction stream.

In moving to the task 0 Of course, the macro move_to_user_mode Use a method interrupt return instruction caused the privilege level change. The main idea of ​this

method is to build an interrupt return instruction required content in the stack, the return address of the segment selector is set to the task 0 Code segment selector, which is the

privilege level 3 . After the interrupt return instruction iret When will cause the system to CPU From the privileged 0 Jump to the outer layer of the privileged class

3 On the run. Referring to FIG. 2-7 Interrupt stack frame returns schematic privilege level changes as shown.

31 0 SP0 - (TSS in the SS: ESP)


Former SS
Stack extension direction

CS original ESP

Original EFLAGS

Original

Original EIP
SP1 - iret instructions before implementation of the new SS: ESP

Map 2-7 Interrupt stack frame returns schematic changes privileged

Macros move_to_user_mode First to the kernel stack pressed into the task 0 Data segment selector and the kernel stack pointer. Then push the contents of the flag

register. Finally pressed into the task 0 Code segment selector and executing the interrupt execution of the next instruction required offset position upon return. The offset position

is iret An instruction following.

When executed iret Instruction, CPU The return address into CS: EIP While the pop-up flag stack register contents. due to CPU

It is judged that the privilege level of the code segment object is 3 , With the current state of the core 0 Different level. then CPU It will stack the stack segment and stack pointer

selector to pop SS: ESP in. Since a change in privilege level hair segment registers DS , ES , FS with GS The value becomes invalid, this time

CPU These segment registers will be cleared. Therefore, the implementation of the iret After the instruction needs to reload the segment registers. Since then, the system begins

- twenty
- three
2.5 Linux Process Control

To privileged 3 Running in Task 0 Of the code. User mode stack or the stack used originally used before moving. While its kernel mode stack were top of the page where the task

data structure began to specify its ( PAGE_SIZE + (long) & init_task ). Because later when creating a new process, you need to copy the task 0 The task data structures, including

the user stack pointer, thus requiring tasks 0 The user mode stack to create a task 1 (process 1 ) Prior to maintain "clean" state.

2.5.4 Creating a new process

Linux The system creates a new process using fork () System call. All the processes are by copying process 0 Obtained, the process is 0

The child process.

In the process of creating a new process, the system first finds an empty entry (empty slot) that has not yet been used by any process in the task array. If the system already

has 64 A process is running, fork () The system will call the array table because the task is not available empty entry and return an error. Then the application process for the new

system in the main memory area in a memory to store its data structure of the task information, and copy all the contents of the current process task data structure as a template for

a new process task data structure. In order to prevent this process has not been completed the new process is scheduled to perform a function, then the new process should

immediately be unavailable for interruption wait state ( TASK_UNINTERRUPTIBLE ).

Then copy the data structure of the task to be modified. The current process is set to the parent process of the new process, a clear signal and reset for each bit map

statistics new process, and set the initial value of the running time slice 15 Two ticks system ( 150 millisecond). Then set the task state segment based on the current process ( TSS )

The value of each register. Since the new process returns the value creating process should be 0 , You need to set tss.eax = 0 . New process kernel mode stack pointer tss.esp0 The

new process is set to top the task data structure where memory pages, and stack segment tss.ss0 Is provided to the kernel data segment selector. tss.ldt It is set as a local

descriptor table GDT The index value. If the current process uses a co-processor, the state also need to preserve the integrity coprocessor to a new process tss.i387 Structure.

After setting up a new task system code and data segment base address, limit long and copy the current process page table memory paging management. If the parent

process has the file open, it should open the corresponding file number will increase 1 . Followed by GDT Set new tasks TSS with LDT Descriptor entries, wherein the group address

information point to the new progress of the task structure tss with ldt . Then the final set to run a new task state and returns a new process ID.

2.5.5 Process Scheduling

Apparent from the foregoing description, Linux Process is preemptive. Still in the process is preempted TASK_RUNNING State, not just temporary CPU run. Seize processes

occur in the implementation phase process is in user mode, kernel mode at the time of execution can not be preempted.

In order to make the process efficient use of system resources, but also make the process have a fast response time, it is necessary to switch the scheduling process

using certain scheduling policy. in Linux 0.11 It adopted a scheduling policy based on priority queuing.

Scheduler
schedule () The function first scan tasks array. By comparing each ready state ( TASK_RUNNING ) The task of running time tick count is decremented counter The value to

determine which process is currently running a minimum of time. Which is greater, it means that the running time is not long, so they select the process, and use the macro

function task switching process to switch to the run.

If at this time all in TASK_RUNNING State of the process time slice have been exhausted, the system according to the priority value of each process priority Recalculated

for all processes (including the ongoing process of sleep) time slice value of each task needs to run counter . The formula is:

= + priority
counter counter
2

then schdeule () Function rescan all tasks in an array TASK_RUNNING State, repeating the process until a selected process so far. Last call switch_to () The actual

process of performing a switching operation.

If no other process can be run at this time, the system selection process 0 run. for Linux 0.11 , The process 0 Will call pause ()

Himself put to sleep can be interrupted and called again schedule () . But in the scheduling process is running, schedule () And do not care process 0

- twenty four -
2.5 Linux Process Control

In what state. As long as the system is idle on the scheduling process 0 run.

Process switch

The actual process of switching tasks by switch_to () Some assembly code to complete the macro definition. Before the handover is performed, switch_to ()

First check if the process is to be switched to the current process, and if nothing is done, exit. Otherwise, the first kernel global variables current Pointer is set to the new task, the

new task and then jump to the long task state segments TSS Address the composition, resulting in CPU Perform a task switch operation. at this time CPU Will save the state of all

registers to the current task register TR in TSS Select the current process task segment data structure pointed to by the symbol tss Structure, then the new task to select a new task

state segment data structure pointed to by the symbol tss Register information structure is returned to CPU , The system officially began operation of the tasks of the new switch.

This process can be found in FIG. 2-8 Fig.

Original tss 80386 CPU

EAX CS
EBX DS
ECX ES
EDX FS
ESI GS
EDI SS
new table EBP LDTR
ESP
EIP
EFLAGS
CR3

TR

GDT tss

ljmp selector 32-bit offset value


Original TSS descriptor

Useless, ignored
The new TSS descriptor

# Long branch TSS segment selector to cause the CPU to perform a task switch operation

Map 2-8 Illustrating the operation task switching

2.5.6 Terminate the process

When a process is running or terminate the end of the run in the middle, then the kernel will need to free up system resources consumed by the process. This includes

open process runtime files, memory allocation and so on.

When a user calls the program exit () System call will be executed kernel functions do_exit () . This function will first release process code and data segments occupied

memory page, close all open files with the process, the current working directory of the process used, the root directory and run the program i Node synchronization. If Cheng Youzi

into the process, then let init Process as all of its parent process child process. If the process is a process and there will Buddist control terminal, then release the control terminal, all

the processes belonging to the session to send a signal to hang up SIGHUP This will usually terminate all processes in the session. Then the process status to dead state TASK_ZOMBIE

. And sends its former parent process SIGCHLD Signal to notify one of its child processes have terminated. At last do_exit () Call scheduling function to execute other processes.

Whereby

--25--
2.6 Linux kernel's memory usage

See you in the process is terminated, its task data structure still retains. Because the parent process also requires the use of the information therein.

During the execution of the child process, the parent process normally used wait () or waitpid () Function waits for one of its child processes to terminate. When the child

process is terminated and waiting in a dead state, the parent process will handle the processes running time used to accumulate their own process. The final release has been

terminated child process task data structure occupied by the memory page, and set the pointer entry process takes loopholes in the task array.

2.6 Linux Use of the kernel memory

in Linux 0.11 Core, in order to efficiently use the machine physical memory, the memory is divided into several functional areas, as shown below 2-9

Fig.

Kernel Module High-speed buffer Virtual disk The primary bank

0 640K 1M

Memory and BIOS ROM

Map 2-9 Distribution functions of the physical memory usage

among them, Linux Kernel occupies physical memory at the beginning, followed by a high-speed buffer portion for supplying a hard disk or floppy disk block devices. When

a process device data block needs to be read, the system will first to read data in the cache area; when data needs to be written to block up the equipment, the system is first

placed in the data buffer area, and then by the block device drivers written to the device. The last part of the application is available for all programs can use part of the main

memory area at any time. When using the kernel main memory area, too, must first apply to the kernel's memory management module can only be used after the application is

successful. To contain RAM Virtual disk system, the primary bank head also part of the plan to go for the virtual disk to store data.

Because the computer systems contained in the actual physical memory capacity is limited, and therefore CPU Usually it provides memory management mechanism of

memory in the system for effective management. in Intel CPU There is provided two kinds of memory management (conversion) systems: system memory segments ( Segmentation

System ) And paging systems ( Paging System ). And paging management system is selectable by the programmer determines whether to use the system by programming. In order

to efficiently use the physical memory, Linux The system uses both Intel CPU Memory segmentation and paging management mechanism.

in Linux 0.11 Kernel, during the address mapping, we need to distinguish 3 Address and transform the concept of species between them:

a. (Process) of the logical address; b. CPU Linear address; c. The actual physical memory address.

Logical address ( Logical Address ) Refers to the offset portion of the address associated with the generated program segment. in Intel Which means the program executing

in protected mode code segment offset address of indefinite length (assuming code segments, data segments exactly the same). Application programmers need only deal with

logical addresses, segmentation and paging mechanism for him is completely transparent, involving only by the system programmer.

Linear address ( Linear Address ) Is a logical address into a physical address of an intermediate layer between the conversion. Program code will produce a logical address,

or is the segment offset, plus the base address of the corresponding segment generates a linear address. If paging is enabled, the linear address can then be transformed to

produce a physical address. If the paging mechanism is not enabled, the linear address is the physical address directly. Intel 80386 Linear address space capacity 4G .

--26--
2.6 Linux kernel's memory usage

Physical address ( Physical Address ) Is to point out now CPU Addressing physical memory address signals on the external address bus, the result is the final address of the

address conversion. If the paging mechanism is enabled, the linear address will use the item page directory and page tables into a physical address. If the paging mechanism is not

enabled, the linear address directly become a physical address.

Virtual Memory( Virtual Memory ) Refers to the amount of memory the computer showing a much larger memory than actually owns. It allows programmers to compile and

run the system memory than it actually has a much larger program. This has led many large-scale projects can be implemented on systems with limited memory resources. A very

appropriate analogy is: you do not have a long track can make a train from Shanghai to Beijing to open. You only need a sufficiently long tracks (for example, 3 Km) to complete

this task. The approach taken was to the back of the shop to the front of the train tracks at once, as long as you are operating fast enough and can meet the requirements, will be

able to train like running on a complete orbit. This is virtual memory management tasks to be done. in Linux 0.11 Kernel, for each program (process) have divided the total capacity

of 64MB Virtual memory space. Thus the logical address range of the program 0x0000000 To 0x4000000 .

Sometimes we also called the logical address of the virtual address. Because similar to the concept of virtual memory space, the logical address is the actual physical

memory capacity independent.

Segment in memory system, logical address of a program is automatically mapping (conversion) by the segmentation mechanism to a linear address of the intermediate

layer. Each time a reference is a reference to the memory of the memory of the memory segment. When a program references a memory address, by the respective segment

base address is added to the programmer visible logical address is formed corresponding to a linear address. At this time, if the paging mechanism is not enabled, the linear

address is sent to CPU On the external address bus, a corresponding physical memory directly addressable.

If using a paging mechanism, the linear address at this time is only an intermediate result, the paging mechanism is also required to transform, and then finally mapped to

actual physical memory addresses. And segmentation mechanism is similar to paging mechanism allows us to redirect (conversion) memory reference every time to suit our

specific requirements. The most common use of paging occasions when the system memory is actually divided into many blocks messy, it can create a large, continuous image

memory space, so do not worry about the program and manage these distributed memory blocks. Paging mechanism to enhance the performance of the segmentation

mechanism. Page address translation is based on the transformation of the base section. Any protective measures paging mechanism and does not replace protection segment

transform and perform further checks only operation.

therefore, CPU The main purpose of address translation (mapping) is to solve the problem of mapping the virtual memory space to physical memory space. Meaning refers to

virtual memory space utilizing two or external memory space, so that the program can not limit the actual amount of physical memory and a method of using the memory. Usually

virtual memory space is much greater than the actual amount of physical memory.

Then the virtual memory space management is how to achieve it? Similar principles and operation of the train metaphor. First, when a program needs to exist when a

memory not used (i.e., the corresponding memory page has been marked in the memory is not in the page table entry in memory), CPU We need a way to know the situation. This

is done by 80386 The page fault abort to achieve. When a process references a page in memory address does not exist, it will trigger CPU Generating a page fault abort, and the

cause of the interruption linear address into CR2 Control register. Therefore, the process of handling the interrupt can know the exact address of the page abnormalities occur,

which can process the required page is loaded from the secondary storage space (such as a hard disk) into physical memory. If at this time all of the physical memory has been

occupied, then the aid can be part of the memory space as two swap buffer ( Swapper ) The page memory temporarily used in the buffer exchange into two, then the requested

page into memory. This is the memory management of the missing pages loading mechanism, Linux 0.11 The kernel is in the program mm / memory.c Implemented.

Intel CPU Use segments ( Segment ) To address the concept of the program. Each section defines the priority information in a memory area and accessible. And each

program can have several memory segments. A logical address (or virtual address) that is a program for addressing the specific address and para positions. in Linux 0.11 ,

Program logical addresses to linear addresses transformation process using CPU Global descriptor table GDT And local descriptor table LDT . by LDT Mapped address space

called the global address space by LDT Mapped address space is called a local address space, both of which constitute the virtual address space. Figure specific use 2-10 Fig.

--27--
2.6 Linux kernel's memory usage

Global descriptor table GDT LDT LDT Task 1


user data
The local table ldtN

State Segment tssN Data Code


segment kernel code segment
data section
code segment Task 1 user
Task 1 TSS code
Table ldt1 local state

table ldt0 partial

segment tss1 system


LDT LDT 0 user data
status section tss0
task
Kernel code
sys segment code
Data Code
segment data section
data section
code segment Task 0 user
Data Code
Task 0 TSS code
NULL

Overall situation Partial

Map 2-10 Linux System virtual address space allocation map

FIG drawn in the case where the two tasks. For Interrupt Descriptor Table idt It is stored in the kernel code segment. Because

Linux 0.11 The kernel, the kernel and the code and data segments for each task are respectively mapped to the same base address of the linear address space, and a segment

limit length of the same, so the code and data segments cores and tasks respectively overlap. In addition, Linux 0.11 The kernel does not use descriptor system.

The basic principles of memory paging management is the whole area into the main memory 4096 Byte pages of memory pages. When using the application program

memory, memory pages allocated to it as a unit.

When using this memory paging management, execution of each process (task) can be used much more than the actual memory capacity of continuous address space. for Intel

80386 System CPU It can provide up 4G Linear address space. for Linux 0.11 The kernel, the system sets a global descriptor table GDT The descriptor for the maximum number of

entries 256 ,among them 2 Entry is free, 2 Entry system, each process uses two. Thus, when the system can accommodate up to ( 256-4) / 2 + 1 = 127 Tasks, and the virtual

address range is (( 256-4) / 2) * 64MB

Approximately equal 8G . but 0.11 Kernel manually define the maximum number of tasks NR_TASKS = 64 , One for each process virtual address range 64M And the virtual address is

the starting position of each process (task number - 1) * 64MB . Therefore, virtual address space is used 64MB * 64 = 4G See Figure 2-11 Fig. 4G Coincided with CPU The same linear

address space or the physical address space, so 0.11 Kernel relatively easy to confuse the concept of three types of addresses.

Process (task) 0 Process 1 Process 2

0 64M 128M 192M 4G

- code execution - Data - parameters


area and the stack

--28--
2.7 Linux system to use the stack

Map 2-11 Linux 0.11 Linear address space using a schematic

We need to process virtual address by converting its local descriptor CPU The entire linear address space address, and then use the table of contents page PDT (A page

table) and page table PT (Two page tables) mapped to the actual physical address page. Therefore, the two translations should not be confused.

In order to use the actual physical memory, the linear address is mapped to each process a different memory page of the main memory area by two memory page table

dynamically. Therefore, the maximum available per process virtual memory space is 64MB . The logical address of each process by adding the task number * 64M , Can be

converted to a linear address. But in comments, we will process usually referred to simply as the address linear address.

For more information about memory paging management, see 10 For a description of the beginning of the chapter, or see the appendix. From Linux Kernel 0.99 Later

version, use of memory space has changed. Each process can be enjoyed the whole separate 4G The address space. Because of space constraints, this will not be described

here.

2.7 Linux The method used in the system stack

This section outlines the Linux Kernel boot from the boot to the system during normal operation of the embodiment using the stack. Description of the relationship between

this part of the kernel code is relatively close, you can skip. Come back at the beginning of the code carefully read the appropriate research.

Linux 0.11 Communist system uses four stack. One is the temporary use of the system to initialize the stack; one is for the stack (the kernel stack) kernel for its own

use only one system at a fixed location address space, but also was the task 0 Userland stack; the other is through a system call for each task, the stack used when

executing kernel, kernel mode stack we call the task, each task has its own separate kernel mode stack; the last one is tasks performed by the user mode stack, the end

located task address space (process). Hereinafter will be described respectively.

2.7.1 Initialization phase boot initialization ( bootsect.s

, setup.s)

when bootsect Code is ROM BIOS Bootloader physical memory 0x7c00 When, the stack segment is not provided and, of course, did not use the program stack. until bootsect

Be moved to 0x9000: 0 At the time, and only then the stack segment register SS Set as 0x9000 , The stack pointer

esp Register is set to 0xff00 , That the top of the stack 0x9000: 0xff00 Office, see boot / bootsect.s The first 61 , 62 Row. setup.s

The program also follows the bootsect Set in the stack segment. This is the temporary use of the system to initialize the stack.

When entering protected mode ( head.s)

From head.s Program since the system began formal operation in protected mode. At this time, the kernel stack segment is set to the data segment ( 0x10 ), The stack

pointer esp Set to point user_stack The top of the array (see head.s The first 31 Line), retained 1 Page memory ( 4K ) Is used as a stack. user_stack In the array definition sched.c of

67--72 OK, containing a total of 1024 Long word. Its location in the physical memory can be found at FIG. 2-12 Fig. At this point the stack is the kernel stack own use.

--29--
2.7 Linux system to use the stack

Other modules

other code kernel module

stack segment ss Other parts

kernel module
head sched user_stack [1k], 1 this page

* Task [] array of pointers


system module
The other main

portion of code

GDT Global Descriptor Table (2K)

Interrupt Descriptor Table idt (2k)

Code Code Other portions of

memory page table (4k X 4)


Esp stack pointer
memory page directory table (4K)
0x0000

Map 2-12 Schematic diagram of the kernel stack used when you enter the protected mode

Initialization ( main.c)
in main.c In the execution move_to_user_mode () Before the code, the system has been using the stack. In the executed

move_to_user_mode () after that, main.c The code is "switched" into tasks 0 In execution. By executing fork () System call, main.c

middle init () In the task 1 The execution and the use of task 1 It stacks. and main () In itself is " Switch " Become a task 0 After continued use of the above kernel stack as its own

task 0 The user mode stack. About tasks 0 A detailed description of the stacks can be found described later.

2.7.2 Task stack

Each task has two stacks, respectively, for performing a user mode and kernel mode programs, and are referred to as user mode and kernel mode stack stack. The main

difference between these two small stacks comprising stack task kernel mode, the amount of data stored can not exceed ( 4096-- Task data structures) bytes, approximately 3K byte.

The user mode stack task but the user can 64MB Space extends.

In the user mode runtime

Each task (except task 0 ) Has its own 64MB Address space. When a task (process) has just been created, the user mode stack pointer which is provided at the end of its

address space ( 64MB To the top), while the kernel mode stack were disposed at the end of the page where its task data structures. Applications have been using the stack when

running in user mode. Actual physical memory used by the stack CPU

Determine the paging mechanism. due to Linux Achieve a replication write ( Copy on Write ), So the process is created, if the process and its parent process does not use the stack,

the stack corresponds both share the same physical memory pages.

In kernel mode runtime

Each task has its own stack kernel mode, the task for each task data structure ( task_struct ) On the same page. This is when you create a new task, fork () Program

in the task tss Kernel-level segment of the stack field ( tss.esp0 with tss.ss0) Set, see

kernel / fork.c , 93 Row:

p-> tss.esp0 = PAGE_SIZE + (long) p; p-> tss.ss0 =


0x10;

among them p Data structure pointer is the task of the new task, tss It is a task state segment structure. Save it as a new kernel memory for application tasks

task_struct Structure data, tss Structure (segment) is task_struct In a field. Kernel stack segment value of the task tss.ss0 also been

--30--
2.7 Linux system to use the stack

Set to become 0x10 (I.e., the kernel data section), and tss.esp0 Points to save task_struct End structure of the page. See Fig. 2-13 Fig.

Top of the stack


stack Stack

Stack pointer (esp0)


A memory (4096 bytes)

Task data structure

Process pointer (current)

Map 2-13 Kernel mode stack is a schematic diagram of the process

Why allocate come from the main memory area by the memory manager of a memory for storing task data structures can also be set to the data in the kernel data

segment of it, that tss.ss0 Why can be set to 0x10 It? This range of length from the kernel code segments will be described. in head.s End of the program, are provided kernel code

and data segment descriptors. Wherein the length of the segment is set become 16MB . This length value Linux 0.11 Kernel physical memory can support the maximum length (see head.s

, 110 The beginning of the line comments). Thus, kernel code may be addressed to any location in the entire range of physical memory, of course, also includes a main memory

area. To Linux 0.98 After a long period of limited version of the kernel is modified into 1GB .

Whenever the task execution kernel needs to use its kernel stack, CPU Will use TSS Structure kernel mode it is composed of a stack arranged two values. When task

switching, old task kernel stack pointer ( esp0) It will not be saved. Correct CPU Is concerned, these two values ​are read-only. Thus whenever a task execution mode into the kernel,

the kernel state which stack is always empty.

task 0 Stack
task 0 The stack is rather special, special needs to be explained. task 0 The code and data segments of the same, from the base address are 0 Start, limited length are

also 640KB . This address range is where the basic kernel code and data reside. In the implementation of the move_to_user_mode () Thereafter, it is at the end of its core state

where the page stack task data structures, and it is in front of the user mode stack of the protected mode stack is used, i.e. sched.c of

user_stack The position of the array. task 0 Stack kernel mode initialization task is specified in the data structure in which manually set, but it is in user mode execution

stack movie_to_user_mode () When, in the simulation iret Set before the return stack. In the stack, esp is still user_stack In its original position, and ss It is set to 0x17 , I.e.

the local user mode data segment table, i.e. from memory address 0

Start and length limit 640KB Segments. Referring to FIG. 2-7 Fig.

2.7.3 Task switching between kernel mode and user mode stack Stack

The system will call the task when called into the kernel, execute kernel code. At this kernel code will use the task stack kernel mode operation. When entering kernel,

since the priority level has changed (from user mode to kernel mode), the stack segment and stack pointer and the user mode stack eflags It will be stored in the kernel mode stack

task. In execution iret Exit kernel when the user returns to the program that will restore the stack and user state eflags . This process is shown in Figure 2-14 Fig.

--31--
Directory Structure 2.8 Linux kernel source code

stack User mode stack


INT
Former SS
IRET
kernel
Original mode
ESP

Press-fitting direction
EFLAGS

CS EIP

Map 2-14 Kernel mode and user mode stack switches

2.8 Linux Kernel source code directory structure

due to Linux The kernel is a single-system kernel mode, therefore, the kernel has almost all of the programs closely linked, dependence and calls their relationship is very

close. So when reading a source code file often need to refer to other relevant documents. It is therefore necessary before you start reading the kernel source code, familiarize

yourself with the directory structure of the source code files and arrangements.

Here we first list Linux Complete kernel source code directory, including its subdirectories. Then describe the main functions of the various procedures contained in the

directory, making arrangements in the form of whole kernel source code can establish a general framework in our minds in order to start the next chapter of the source code

reader work.

When we use tar Command linux-0.11.tar.gz When unlock, the kernel is placed in the source file linux / Directory. Wherein the directory structure shown in Figure 2-15 Below:

linux ├─ boot
System boot assembler

├─ fs File system
├─ include Header files (* .h)

│ ├─ asm Associated with the CPU architecture of the part

│ ├─ linux Linux kernel dedicated section

│ └─ sys The system data structure portion

├─ init Kernel initialization procedure

├─ kernel Kernel process scheduling, signal processing, system calls and other procedures

│ ├─ blk_drv Block device driver


│ ├─ chr_drv Character device driver

│ └─ math Math coprocessor emulation handlers

├─ lib Kernel library functions

├─ mm Memory Manager
└─ tools Image generation tool kernel file

Map 2-15 Linux Kernel source directory structure

The kernel version contained in the source code directory 14 Subdirectories, including a total of 102 Code files. The following one by one the contents of these

subdirectories are described.

2.8.1 Kernel home directory linux

linux Directory is the home directory of the source code, in addition to including all the main directory 14 Other than a subdirectory also contains the only one

Makefile file. This file is compiled support tools make The parameter configuration file. make The main purpose tools is through knowledge

--32--
Directory Structure 2.8 Linux kernel source code

Which files have not been modified to automatically determine which files need to be recompiled in a system comprising a plurality of source program files. therefore, make Tools

software project management software program.

linux This directory Makefile The document also calls for all nested subdirectories contained Makefile File, so that when linux

Any files in the directory (including subdirectories) modification is outdated, make It will be recompiled. Therefore, in order to compile all the entire kernel source code files, as long

as the linux Run a directory make Software can be.

2.8.2 Boot program directory boot

boot Directory contains 3 An assembly language file, the kernel source code file first to be compiled program. This 3 The main function is to guide the completion of a

program when the computer is powered kernel startup, the kernel code is loaded into memory, and do some enter 32 System initialization before-bit protected mode of operation.

among them bootsect.s with setup.s Programs need to use as86 Software to compile, using as86 Assembly language format (similar to Microsoft), and head.s need to use GNU as To

compile, using AT & T Assembly language format. The two assembly language code list and the following brief description will be the next chapter in the code comments.

bootsect.s Disk boot program is a program block, the compiler will reside in the first sector of the disk (boot sector, 0 A track (cylinder),

0 Head first 1 Sectors). in PC Powered machine ROM BIOS After the self-test, it will be BIOS Loaded into memory 0x7C00 Department for execution.

setup.s The main program for reading the hardware configuration of the machine parameters and the kernel module system Moved to the appropriate memory location.

head.s Program will be compiled in connection system The foremost part of the module, mainly for initial setup and memory management page set up to detect the

hardware work.

2.8.3 File system directory fs

Linux 0.11 Kernel file system uses 1.0 Edition MINIX File system, which is due to Linux It is in MINIX Development of the system, using MINIX File systems

facilitate cross-compiler, and may be from MINIX Loaded Linux Partition. Although the use of

MINIX File system, but Linux And its treatment MINIX Different systems. The main difference is that MINIX The file system uses single-threaded approach, and Linux The use of

multiple threads. As a result of multi-threaded approach, Linux Multi-threaded program must be addressed to bring the race conditions, deadlocks and other problems, so Linux Than

the file system code MINIX The system is much more complex. To avoid race conditions, Linux Resource allocation system has been rigorously checked, and runs in kernel

mode, if the task is not active sleep (call sleep () ), Do not allow the kernel to switch tasks.

fs / Directory is the directory file system implementation program, contains 17 More C Language program. The main reference relationships between these procedures Figure

2-16 Each block shown in FIG behalf of a document from top to bottom is placed substantially relation by reference. Where each file name suffixes are omitted. c , The dotted box is

not part of the file system program files, lines with arrows indicate reference relationships, each thick line represents a reference relationship there.

--33--
Directory Structure 2.8 Linux kernel source code

High-level function

file_table
exec fcntl ioctl

data access

open stat

read_write

char dev pipe block dev file dev Low-level manipulation functions
namei

inode

truncate

bitmap

super
Cache Management

buffer

ll_rw_block

Map 2-16 fs References between each function in the program directory.

As can be seen from the figure, the directory in which the program is divided into four sections: a high speed buffer management, low-level file, the file data and file level

access functions, when in this catalog file of notes, into which we will four parts are described.

For the file system, we can use it as a high-speed buffer memory extension. All access to the file system data, we need to first read the high-speed buffer. The

catalog management file system program mainly used in the distribution and use of block device buffer cache buffer blocks. Program Manager is a high-speed buffer buffer.c ,

While other programs are mainly used for file system management.

in file_table.c File, currently only defines a file handle (descriptor) an array of structures. ioctl.c File references

kernel / chr_drv / tty.c The function implements a character device io control function. exec.c The main program includes a program execution function

do_execve () It is all exec () The main function function cluster. fcntl.c A program for implementing file i / o Control system function is called.

read_write.c A program for realizing the file read / write and three positioning system calls. stat.c Program is implemented in two states get file system calls. open.c The main

program file contains the implementation of the system to modify the properties and close the file created with function calls.

char_dev.c The main characters include equipment to read and write function rw_char () . pipe.c Program includes piping system calls read and write functions and create

the pipe. file_dev.c Based on the program included i File node descriptor structure and read and write functions. namei.c The main program includes the operating system functions

and file system directory name and file name of the calling function. block_dev.c Program includes read and write function block data. inode.c Program includes a file system for i Nodes

operating function. truncate.c Procedures for releasing device data file space occupied when deleting files.

bitmap.c A program for processing the file system i Bitmap node and logical data blocks. super.c Handler program includes a file system superblock. buffer.c Program is

mainly used for high-speed buffer memory for processing. Virtual box ll_rw_block The bottom block is read function device, it is not in fs Catalog, but kernel / blk_drv /

ll_rw_block.c Reading and writing block device driver functions. Placed here just let us clearly see that the file system for block devices read and write data, you need a

high-speed buffer drivers and block device ( ll_rw_block () ) To be operated, the assembly itself is not the file system dealing directly with the device driver blocks.

In a program annotation process, we will give another call hierarchical relationships between the various main functions of these files.

--34--
Directory Structure 2.8 Linux kernel source code

2.8.4 Header home directory include

A total of header files in a directory 32 A. h head File. There main directory 13 A, asm There subdirectories 4 A, linux There subdirectories 10 A, sys There subdirectories 5 A.

These header files, see the following Description of the respective functions, and the role of specific information contained in the header file annotations See chapter.

<A.out.h> a.out Header files, define a.out Executable file format and some macros.

<Const.h> Constant symbol header files, currently only defined i Node i_mode Each flag field.

<Ctype.h> Character type header files. It defines some judgment about the character type and converting macros.

<Errno.h> Error No. header files. The system comprises various error number. ( Linus From minix In the introduction).

<Fcntl.h> Document control header file. Operable control descriptor file and constants defined symbols.

<Signal.h> Heads files. Defined symbolic constant signal, the signal structure and the operation function prototype signal.

<Stdarg.h> Standard parameter header files. In the form of macro variables defined parameter list. Mainly explained - types ( va_list ) And tri

Macro ( va_start, va_arg with va_end ) For vsprintf , vprintf , vfprintf function.
<Stddef.h> Standard definition header file. Defined NULL, offsetof (TYPE, MEMBER) .

<String.h> String header file. Mainly defines the built-in functions related to operation of the string.

<Termios.h> Terminal input and output functions header file. The main terminal interface asynchronous communication define the control port.

<Time.h> Time Type header. Chief among these are defined tm Something about the structure and function prototype time.

<Unistd.h> Linux Standard header file. Symbols and constants defined type, and affirms that the various functions. As defined

__LIBRARY__ , It also includes the number of system calls and inline assembly _ syscall0 () Wait.

<Utime.h> User time header. It defines the structure and the access and modification times utime () prototype.

Architecture associated header files in subdirectories include / asm

The header file defines some of the main CPU Data structure closely related to architecture, macro functions and variables. Altogether 4 Files.

<Asm / io.h> io head File. Macro assembler embedded form definition io Port function operation.

<Asm / memory.h> Memory copy header files. contain memcpy () Embedded assembler macro function.

<Asm / segment.h> Operating segment header file. For embedded segment register defines the operation assembly function.

<Asm / system.h> System header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

Linux Special kernel header files in subdirectories include / linux

<Linux / config.h> Kernel configuration header file. Define the keyboard language and hard disk type ( HD_TYPE ) Options.

<Linux / fdreg.h> Floppy header files. Definitions of parameters comprises the floppy disk controller.

<Linux / fs.h> File system header files. Definition File Table Structure ( file, buffer_head, m_inode Wait).

<Linux / hdreg.h> Hard disk parameters headers. Accessing the hard disk port register definition information, status code, the partition table and the like.

<Linux / head.h> head Header file defines a simple structure segment descriptors, and several selectors constants.

<Linux / kernel.h> Kernel headers. It contains some common prototype custom kernel function.

<Linux / mm.h> Memory management header files. It contains the defined page size and page number of the release function prototypes.

<Linux / sched.h> Scheduler header file that defines the task structure task_struct The initial task 0 The data,

There are also several descriptors parameter set and get embedded assembly function macro statement.

<Linux / sys.h> System call header files. contain 72 System calls C Function handler to ' sys_ ' beginning.

<Linux / tty.h> tty Header file that defines the related tty_io Serial communications parameters constant.

System specific data structures subdirectory include / sys

<Sys / stat.h> File Status header file. Containing configuration file or system state stat {} And constants.

<Sys / times.h> It defines the process run time structure tms as well as times () Function prototype.

<Sys / types.h> Type header files. System defines the basic data types.

<Sys / utsname.h> System Name header files.

<Sys / wait.h> Wait for the call header. Definition of system calls wait () nuclear waitpid () And dependent constant symbol.

--35--
Directory Structure 2.8 Linux kernel source code

2.8.5 Kernel initialization program directory init

This directory contains only a file main.c . It used to perform all of the kernel initialization, and then move to create a new user-mode process, and run on the console device shell

program.

First, the program allocates the buffer memory capacity based on how much memory the machine, if it is set up to use the virtual disk, then later in the buffer

memory also left room for it. After it initializes all hardware, including the artificial creation of a task ( task 0 ), And set the interrupt enable flag. After executing the move from

kernel mode user mode, the system calls the process of creating the first function fork () Create a run for init () Process, the child process, the system console environment

settings, and to generate a child process in run shell program.

2.8.6 Kernel home directory kernel

linux / kernel Directory contains the CCP 12 And a code file Makefile File, in addition to 3 Subdirectory. All programs are stored in the processing tasks kernel / Directory,

including as fork , exit , The scheduler as well as some system calls procedures. Also includes a processing interrupt handling process exceptions and traps. Subdirectory includes a

low-level device driver, such as get_hd_block with tty_write Wait. Because of the complex relationship between these documents calling code, and therefore not listed here quote in

detail the relationship between the individual files, but can still be roughly classified as shown in Figure 2-17 Fig.

General Procedure Hardware interrupt procedure System call program

schedule.c
asm.s system_call.s Call relationship
panic.c mktime

pintk, vsprintf traps.c fork.c, sys.c, exit.c, signal.c

Map 2-17 Call hierarchy of each file

asm.s A program for a processing system hardware interrupt caused by abnormal, for the respective actual hardware exception handler is in the traps.c File, in each

interrupt processing, respectively call traps.c The corresponding C Language processing function.

exit.c The main program includes procedures for handling system calls the process to terminate. It contains process releases the session (process group) to terminate the

program and exit handlers and kill the process, terminate the process, the process hangs and other system calls.

fork.c Program shows sys_fork () The system uses two calls C Language functions: find_empty_process () with

copy_process () .
mktime.c Program comprises a kernel function of time mktime () For calculating from 1970 year 1 month 1 day 0 When the play start date seconds, as a start

seconds. only at init / main.c It was called once.

panic. Contains a core program displays an error message and stop function panic () .

printk.c Program specific information contains a kernel function display printk () .

sched.c Program including the basic functions related to scheduling ( sleep_on , wakeup , schedule Etc.) and some simple function call system. There are also several related

functions floppy operation timing.

signal.c Program included in the signal processing relating to 4 System call and a corresponding interrupt handler function for processing signals do_signal () .

sys.c The program includes a number of system calls, some of which has not been achieved.

system_call.s Program implements Linux System call ( int 0x80 ) Interface process, contains the actual process in the system calls the corresponding C Language processing

functions, processing functions are distributed throughout the Linux Kernel code.

--36--
Directory Structure 2.8 Linux kernel source code

vsprintf.c Program implements now included in the standard library functions of string formatting functions.

Block device driver subdirectory kernel / blk_drv

Typically, the user is to access the device via the file system, device driver for the file system to achieve the call interface. When using block device, due to the large data

throughput, in order to efficiently use the data on a block device, between the user process and the block device using the cache mechanism. When accessing data on a block

device, the system first in the form of data blocks on the data block read into a cache of the device, and then provided to the user. blk_drv Subdirectory contains 4 More c File and 1

Header file. head File blk.h Since the block device is dedicated to the program, and so C Files together. Approximate relationship between these files, see Fig. 2-18 Fig.

blk.h ll_rw_blk.c

hd.c floppy.c ramdisk.c

Map 2-18 blk_drv Files in the directory hierarchy.

blk.h Defined 3 More C Block device configuration program and data blocks that are common to request structure. hd.c Procedure the main data blocks of the hard disk

drive underlying function read / write, mainly do_hd__request () function; floppy.c The main program implements the read data block floppy

/ Write drive function, mainly do_fd_request () function. ll_rw_blk.c Program implements low-level block device data read / write function

ll_rw_block () , All the other programs in the kernel data read and write operations are carried out by this function block device. You will see that the function is called block devices

to access data in many places, especially in the high-speed buffer handling file fs / buffer.c in.

Character device driver subdirectories kernel / chr_drv

Program Subcategory character device containing a total of 4 More C Language program and 2 An assembler files. These documents realized the serial port

rs-232 Driving a serial terminal, keyboard and console terminal device. Map 2-19 It is roughly call the hierarchical relationships between them.

tty_io.c tty_ioctl.c

serial.c rs_io.s console.c keyboard.S

Map 2-19 Showing the relationship between the character device program

tty_io.c Program includes tty Character device read function tty_read () And write function tty_write () It provides top access interface for file systems. Also included in

the serial interrupt process called C function do_tty_interrupt () The function will be called in the interrupt type as a character read in.

console.c File mainly contains initialize console and console write function con_write () For the tty Equipment called. Also contains a display and a keyboard

interrupt initialization setup con_init () .

rs_io.s Assembler for implementing two serial interrupt handler interface. The interrupt handler from the interrupt identification register in accordance with (port 0x3fa or 0x2fa

) Acquired 4 Two interrupt types are processed separately, and in the process the interrupt type the code read characters call

do_tty_interrupt () .
serial.c Asynchronous serial communication chip for UART Initiate operation, and sets the interrupt vector two communication ports. Also

--37--
2.9 core system and the relationship between the user program

include tty For output to the serial port rs_write () function.

tty_ioctl.c Program implements tty of io Control interface functions tty_ioctl () As well as termio (s) terminal io Read and write functions structure, and will call for system sys_ioctl

() of fs / ioctl.c The called program.

keyboard.S Program achieved a major keyboard interrupt handling process keyboard_interrupt .

Coprocessor emulation and operating procedures subdirectories kernel / math

The subdirectory is currently only one C program math_emulate.c . one of them math_emulate () Function is interrupted int7 The interrupt handler to be called C function.

When the machine is not math coprocessor, and CPU But when executing the coprocessor instruction, it will trigger the interrupt. Therefore, the use of the software interrupt can be

used to simulate the function of the coprocessor. Kernel version discussed in this book does not yet contain emulation code relating coprocessor. This program simply print an

error message, and sends a program signal of a user error coprocessor

SIGFPE .

2.8.7 Kernel library functions directory lib

Kernel Library function is used for the kernel initialization process init / main.c Running in user mode process (process 0 , 1 ) Provides call support. It is exactly the same as

ordinary static library implementation. Readers can learn about the general libc The basic principles of composition libraries. in lib / There directory 12 More C Language files, except

for one by the tytso Compiled malloc.c Longer than the program, other programs are short, some only twelve lines of code that implements the interface function of some system

calls.

These documents include the main exit function _ exit () Close the file functions close (fd) , Copy the file descriptor function dup () , The file open function open () Write file

functions write () , Program execution function execve () , Memory allocation function malloc () , Wait for the child state function wait () , Create session system calls setsid () And in include

/ string.h All string manipulation functions implemented.

2.8.8 Memory manager directory mm

The catalog includes 2 Code files. Mainly used for the main memory area management program to achieve a process of logical addresses to linear addresses and linear

addresses to the main memory area mapped physical memory address by paging memory management mechanism, the process virtual memory page of the main memory to

establish a correspondence between the physical memory pages zone.

Linux The kernel handles memory paging and segmentation using two ways. The first is the 386 of 4G Virtual address space into 64

Segments, each segment 64MB . All kernel occupies a first segment of which, and the physical address of the segment with the same linear address. Then assign each task a

segment to use. Paging mechanism for mapping the specified page to the physical memory segment, detecting fork Create any duplicate copies, and perform the copy-on-write

mechanism.

page.s Including memory page file abort ( int 14 ) Handler, mainly due to lack of procedures for processing page page caused by an illegal address access and abort

caused page protection.

memory.c Program includes a function to initialize the memory mem_init () ,by page.s Memory interrupt procedure call

do_no_page () with do_wp_page () function. When you create a new process and perform the copy process operations that use memory processing functions of the file

management to allocate memory space.

2.8.9 Compile the kernel utilities directory tools

This directory build.c Program for the Linux Respective directories are separately compiled object code generated combined image file into the kernel of an operating image .

The specific features can be found in the next chapter content.

2.9 The relationship between core system and the user program

in Linux System, the kernel provides an interface for both applications. One is the system call interface (the first 5 Section for instructions), that interrupt call int 0x80 ; The

other hand, the kernel library function (at 12 Section for instructions) to exchange information with the kernel. Kernel is the basic library functions C Library libc made of. Many system

calls as a basic C Part of the language function library implementation.

The main system call is available to be used directly or system software used to implement the library functions. The average user is a program developed by calling

--38--
2.10 linux / Makefile file

Like with libc And other library functions to access core resources. By these libraries program calls application code to complete a variety of common tasks, e.g., opening and

closing access to a file or device, for scientific computing, error handling and the user identification number and access group ID And other system information.

System call is the highest level kernel interface with the outside world. In the kernel, each system call has a sequence number (in

include / linux / unistd.h Defined in the file header), and often implemented as macros. Applications should not directly use the system call, because in that case, portability

program on the bad. So now Linux Standard Library LSB ( Linux Standard Base ) And many other standards do not allow applications to directly access the system call macros. For

documentation system calls can be found in Linux The first operating system manuals online 2 section.

Library functions typically include C The language does not provide advanced functions perform user-level functions, such as input / output functions and string handling.

Some library functions just Enhancements version of the system call. For example, the standard I / O Library Functions fopen with fclose It provides the system call open

with close Similar functionality, but it is at a higher level. In this case, the system calls usually offer slightly better performance than the library functions, library functions but was

able to provide more functionality, and more error detection capability. The system provides library functions can be found in the documentation for the operating system online

Manual 3 section.

2.10 linux / Makefile file

From this section, we begin the kernel source code file comments. First Comment linux The first file encountered in the directory Makefile . The subsequent sections according

to annotate structure similar description herein.

2.10.1 Functional Description

Makefile File is equivalent to a batch file program during compilation. It is a tool program make The input data file at run time. As long as containing Makefile The

current directory, type make Command, it will be based on Makefile Setting file of source or object code files are compiled, connection or installation activities.

make Utilities can automatically determine a large program systems in those files need to be recompiled, and issue the command to compile the program files. In use make

Before, we need to write Makefile Information file that describes the relationship between the respective programs in the entire package, and give a specific control command for

each file to be updated. Generally, when the program is updated in accordance with its target file, and these objects are created by the compiler. Once you've written a suitable Makefile

File, then after you some source code files of every program in the system modified, to perform make Command will be able to carry out all the necessary work to recompile. make Program

is to use Makefile Last modified data files and code files ( last-modification time) To determine which files need to be updated for each file needs to be updated it will be based Makefile

The information issuing the appropriate commands. in Makefile File, beginning with '#' are comments lines. The beginning of the file '=' assignment statement defines some

parameters or abbreviated commands.

This one Makefile The main role is to indicate file make Programs compiled independently connected end-use of tools / Directory build Executing program code to

connect all compiled kernel and combined into a running kernel image image . Specific is boot / middle

bootsect.s , setup.s use 8086 Compile assembler respectively generate respective execution module. Re-use of all other program source code GNU Compiler gcc / gas Compiling

and connected module system . Then build These three tools are combined into a kernel image file image. Basic Compiler connected / combined structure in FIG. 2-20 Fig.

--39--
2.10 linux / Makefile file

head main kernel mm fs lib

bootsect setup system

Build Tools
Kernel image file

Image

Map 2-20 Compiling and linking the kernel / combined structure

2.10.2 Code comments

program 2-1 linux / Makefile file

1#
2 # If you want the ram-disk device, define this to be the # if you want to use the RAM disk device, then it
3 # Size in blocks. # Define the size of the block.

4#
5 RAMDISK = # -DRAMDISK = 512
67 AS86
= As86 -0 -a # 8086 assembler and linker, see after the introduction of the list. Definition of each rear strap
8 LD86 = Ld86 -0 # They are: -0 8086 to generate an object program; -a compatible with the gas generating portion and gld code.

910 AS
= Gas # GNU assembler and linker, see after the introduction of the list.
11 LD = Gld
12 LDFLAGS = -s -x -M # Options used GNU connector gld running. Meaning: -s output file are omitted
# Some symbol information; delete all the -X-local symbols; -M represents the standard output device requires

# Connecting the print image (display) (link map), it refers to a linker generated from
# Memory address mapping, which lists the programs loaded into segment position information in memory. specific

# In terms of the following information:

# • Object file and symbol information is mapped to the location in memory;

# • How common symbols are placed;

# • Connect all the files contained references to members and their symbols.

13 CC = Gcc $ (RAMDISK) # gcc is the GNU C compiler. For UNIX-like script (script) program,
# When referring to the definition identifier, required in front of and around the identifier $ sign in parentheses.

14 CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer \


15 -fcombine-regs -mstring-insns # gcc option. Before the end of the line '\' symbol indicates that the next line is a continuation line.

# Options meaning: -Wall print all warnings; -O optimize the code;


# - fstrength-reduce optimization loop; -mstring-insns is
# Linus in learning gcc gcc compiler to increase the options for gcc-1.40
# 386 CPU used in the copy operation command string structure can be removed.
16 CPP = Cpp -nostdinc -Iinclude # cpp gcc before (pre) handler. -nostdinc -Iinclude containing
# Yi is not the standard header file search files in a directory, but the use -I
# Options specified directory or search for header files in the current directory.

--40--
2.10 linux / Makefile file

1718 #

19 # ROOT_DEV specifies the default root-device when making the image.


20 # This can be either FLOPPY, / dev / xxxx or empty, in which case the
twenty one # Default of / dev / hd6 is used by 'build'.
twenty two #

twenty three ROOT_DEV = / dev / hd6 # ROOT_DEV specify the default root file system when creating a kernel image (image) files used
# In the device, which may be a floppy (FLOPPY), / dev / xxxx or simply empty, empty time
# build procedure (in tools / directory) uses the default value / dev / hd6.
2425 ARCHIVES = substituting certain kernel / kernel.o mm / mm.o fs / fs.o # kernel directory, mm directory and directory fs generated

# Code file. For ease of reference here to use them


# ARCHIVES (archive) identifier represents.
26 DRIVERS = kernel / blk_drv / blk_drv.a kernel / chr_drv / chr_drv.a # library block and character device. .a table
# This is illustrated archive file, that contains a number of executable binary code subroutine

# Ordered set of libraries, typically the GNU ar generating program. GNU ar is a binary
# Document processing program for creating, modifying and extracting files from the archive.

27 MATH = Kernel / math / math.a # Math libraries.


28 LIBS = Lib / lib.a # General libraries from the lib / directory of files compiled.
2930 .cs:
# make old-fashioned implicit suffix rules. This line indicates the following command will make use of all

# . c .s file compiled assembler. ':' Represents the following rule is a command.


31 $ (CC) $ (CFLAGS) \
32 - nostdinc -Iinclude -S -o $ *. s $ <# refers gcc CFLAGS specified using the foregoing options and
# Use only the header files include / directory, do not assemble after the properly compiled on the

# Stop (-S), resulting in assembly language with the respective files corresponding to the input C of

# Code files. By default, the assembler file generated by the original file name to remove the C .c

# And plus .s suffix. -o representation followed in the form of the output file. Of which $ *. S (or $ @ )

# Automatic target variable, $ <first prerequisite representatives here that is qualified


# * . C file.
33 .so: # It said it would all .s assembler .o files compiled into object files. Next is real
# Referring now specifically to the operation command.

34 $ (AS) -c -o $ *. O $ <# compiler will use gas assembler compiled .o object files. -c indicates that only compiled
# Or assembly, without connecting operation.

35 .co: # . Similar to the above, * c files - * .o object files.


36 $ (CC) $ (CFLAGS) \
37 - nostdinc -Iinclude -c -o $ *. o $ <# use gcc to compile C language file into an object file but not connected.
3839 all:
Image # all express goal to create top-level Makefile known. Here that is the image file.
4041 Image: boot / bootsect boot / setup tools / system tools / build # Targets (Image file) is

# 4 following elements produced semicolon, respectively boot / directory and bootsect


# setup files, tools / directory system and build files.
42 tools / build boot / bootsect boot / setup tools / system $ (ROOT_DEV)> Image
43 sync # These two lines are executed command. The first line indicates the use of build tools in the tools directory

# Program (below will explain how to generate) will bootsect, setup and system files
# To $ (ROOT_DEV) the root file system device is assembled into the kernel image file Image.

# sync synchronization command is to force the second line buffer block data immediately write disk and updates the super block.

4445 disk: Image


# This goal represents the disk to be produced by Image.

46 dd bs = 8192 if = Image of = / dev / PS0 # dd is the standard UNIX command: copy a file, according to the options

# And format conversion. bs = the number of bytes a read / write.


# If = input file represented, of = represents the output to a file.

--41--
2.10 linux / Makefile file

# Here / dev / PS0 is the first floppy disk drive (device file).
4748 tools / build: tools / build.c
# Build.c program generated by the program execution tools directory build.
49 $ (CC) $ (CFLAGS) \
50 - o tools / build tools / build.c # compiler generates the build command execution program.
5152 boot / head.o: boot / head.s
# Generating a .so head.o object file using rules given above.
5354 tools / system:
boot / head.o init / main.o \
55 $ (ARCHIVES) $ (DRIVERS) $ (MATH) $ (LIBS) # represents a file system tools directory
# Listed elements to be generated by the right semicolons.

56 $ (LD) $ (LDFLAGS) boot / head.o init / main.o \


57 $ (ARCHIVES) \
58 $ (DRIVERS) \
59 $ (MATH) \
60 $ (LIBS) \
61 - o tools / system> System.map # Generating a system command. Last> System.map representation
# gld need to connect to redirect image stored in the System.map file.
# See the explanatory notes on the use System.map file.
6263 kernel / math / math.a:
# Math co-processing functions implemented by math.a file command on the next line.

64 (Cd kernel / math; make) # Into the kernel / math / directory; run the make utility.
# The following similar meaning here from 66--82 row.
6566 kernel / blk_drv / blk_drv.a:
# Function block device file blk_drv.a
67 (Cd kernel / blk_drv; make)
6869 kernel / chr_drv / chr_drv.a:
# Function character device file chr_drv.a
70 (Cd kernel / chr_drv; make)
7172 kernel / kernel.o:
# Kernel object module kernel.o
73 (Cd kernel; make)
7475 mm / mm.o:
# Memory management module mm.o

76 (Cd mm; make)


7778 fs / fs.o:
# File system object module fs.o
79 (Cd fs; make)
8081 lib / lib.a:
# Library functions lib.a

82 (Cd lib; make)


8384 boot / setup: boot / setup.s
# Is used herein begins three lines and the connector 8086 assembly

85 $ (AS86) -o boot / setup.o boot / setup.s # Setup.s file for compiling generated setup file.
86 $ (LD86) -s -o boot / setup boot / setup.o # - s option indicates that you want to remove the symbols from the object file.

8788 boot / bootsect: boot / bootsect.s


# Ibid. Generating bootsect.o disk boot block.
89 $ (AS86) -o boot / bootsect.o boot / bootsect.s
90 $ (LD86) -s -o boot / bootsect boot / bootsect.o
9192 tmp.s: boot / bootsect.s tools / system
# From this role 92--95 four lines are added at the beginning of the program bootsect.s

# Line length information about the file system. The method is first generated contain "SYSSIZE = actual length of the file system."

# Line information tmp.s file, and then add in the subsequent bootsect.s file. The method of obtaining the length of the system is:

--42--
2.10 linux / Makefile file

# Firstly ls command to the file system displays a long list, the list to obtain the line segment with the digital file grep command byte

# Information and orientation stored in tmp.s temporary file. The cut command for cutting string, tr carriage for removing the end of the line.

# Wherein the actual length :( + 15) / 16 for obtaining length information 'section' representation. Section 1 = 16 bytes.
93 (Echo -n "SYSSIZE = ("; ls -l tools / system | grep system \
94 | Cut -c25-31 | tr '\ 012' ''; echo "+ 15) / 16")> tmp.s
95 cat boot / bootsect.s >> tmp.s
96 a
97 clean: # when executing 'make clean', it will execute the command on the line 98--103, remove all documents generated by the compiling and linking.

# 'Rm' command is to delete the file, meaning -f option is to ignore the file does not exist, and does not delete the information.

98 rm -f Image System.map tmp_make core boot / bootsect boot / setup


99 rm -f init / *. o tools / system tools / build boot / *. o
100 (Cd mm; make clean) # Enter mm / directory; the implementation of clean rule the directory Makefile file.
101 (Cd fs; make clean)
102 (Cd kernel; make clean)
103 (Cd lib; make clean)
104 a
105 backup: clean # The rule will be executed first clean the above rule, then linux / directory is compressed, generating
# backup.Z compressed files. 'Cd ..' represents retreated linux / on a (parent) directory;
# 'Tar cf - linux' tar archive that the implementation of the program for linux / directory. -cf expressed the need to create

# The new archive '| compress -' said it would execute tar program by the pipeline operator ( '|')
# Transmitted to the output compressor compress, and is stored as a compressed program file backup.Z.

106 (Cd ..; tar cf - linux | compress -> backup.Z)


107 sync # Forcing the buffer block data immediately write disk and updates the disk superblock.

108109 dep:

# The rule used to target or dependencies between files. These dependencies are created to make in order to determine whether you need to

# Reconstruction of a target object. For example, when a head after the documents have been altered, make it through dependencies generated recompiled with the

# All * .c file header files related. Specific methods are as follows:


# Sed string editing program for the Makefile (where that is their own) for processing, the output is deleted Makefile
# File '### Dependencies' all lines subsequent lines (following the start of the line from 118), and generates tmp_make
# Temporary files (that is, the role of 110 lines). Then for each C file in the init / directory (there is only one file
# main.c) gcc perform preprocessing operations, -M flag tells the preprocessor output correlation rules that describe each object,
# And compliance with these rules make syntax. For each source file, the output of preprocessor make a rule, the result
# The form of the corresponding source file target file name plus its dependencies - lists all the header files included in the source file.

# Line 111 is actually $$ i $ ($ I) mean. Where $ i is the value of the preceding sentence shell variables.
# The results are then added to the pretreated tmp_make temporary file, and then copying the temporary file into the new file Makefile.
110 sed '/ \ # \ # \ # Dependencies / q' <Makefile> tmp_make
111 (For i in init / * c;. Do echo -n "init /"; $ (CPP) -M $$ i; done) >> tmp_make
112 cp tmp_make Makefile
113 (Cd fs; make dep) # For the Makefile in the fs / directory also do the same process.
114 (Cd kernel; make dep)
115 (Cd mm; make dep)
116117 ### Dependencies:

118 init / main.o: init / main.c include / unistd.h include / sys / stat.h \
119 include / sys / types.h include / sys / times.h include / sys / utsname.h \
120 include / utime.h include / time.h include / linux / tty.h include / termios.h \
121 include / linux / sched.h include / linux / head.h include / linux / fs.h \
122 include / linux / mm.h include / signal.h include / asm / system.h include / asm / io.h \
123 include / stddef.h include / stdarg.h include / fcntl.h

--43--
2.10 linux / Makefile file

2.10.3 Other Information

Makefile Brief introduction

makefile File is make Utilities configuration file. Make The main purpose utility that can automatically determine a large-scale program contains many source files

which files need to be recompiled. makefile The use of complicated, but here according to the above

makefile File to make some brief. For more information, refer to GNU make manual.

In order to use make Program, you need to makefile File to tell make What to do work. usually, makefile File tells make How to compile and link a file.

When it clear that, makefile You can also tell make Run various commands (for example, as a cleanup operation to delete some files).

make The execution process is divided into two distinct phases. In the first phase, it reads all makefile File and contains

makefile Files, records all the variables and their values, explicit or implicit rules, and to construct a panorama all audiences of its prerequisites. During the second phase, make On

the use of the internal configuration of the target to determine which objects need to be rebuilt, and the use of appropriate rules to operate.

when make When recompiling the program, each modified C Code files must be recompiled. If a file has been modified over the head, then in order to ensure

proper, each containing the header file C Code program will be recompiled. Each compilation operations generate a source file corresponding to the target ( object file) .

Finally, if any source file is compiled, then all object files compiled either just finished or was it compiled must be connected together to create a new executable file.

simple makefile File contains a number of rules that have the following form:

aims( target) ...: prerequisites( prerequisites) ...

command( command)

...

...

Wherein 'target' object is usually the name of a program file generated; for example, an executable file or object file. The goal may be to take the activities of names, such

as' clear '(' clean ') . 'Prerequisite' is one or more file names is used to generate a target input conditions. Usually dependent on a target several files. The 'command' is make You

need to perform. A rule may have multiple commands, each command on its own line. Please note that you need to type a tab character before each command line! This is where

the unwary often overlooked.

If a prerequisite is found through directory search in another directory, this command does not change the rules; they will be implemented as scheduled. Therefore, you must

carefully set the command so that the command can make Find prerequisites directory prerequisites found. This needs to be done through the use of automatic variable. A process

according automatic variables are variables that can be automatically replaced in the particular case on the command line. Automatic variables are based on the value of the target

object and its prerequisites set before command execution. E.g, '$ ^' The value represents the rules all the prerequisites, including the name of the directory they are located; '$ <' Values

​represent a first rule prerequisite; ' $ @ ' Indicate that the target; and there are some automatic variables not mentioned here.

Sometimes, they are often prerequisites include the header file, and these header files and do not want to explain in the command. At this point automatic variables '$ <' It is

the first prerequisite. E.g:

foo.o: foo.c defs.h hack.h

-c $ CC (CFLAGS) $ <-o $ @

one of them '$ <' Will be replaced automatically foo.c While $ @ will be replaced foo.o

in order to make Can use idioms to update a target object, you can not specify a command, write a rule with no command or do not write the rules. at this time make The

program will be judged according to type (suffix program) source file which implicit rules to use.

Suffix rules for make Program defines the old-fashioned method of implicit rules. (Now the rules have not been replaced by the use of

--44--
2.10 linux / Makefile file

More generic clearer pattern matching rules). The following example is a dual suffix rules. Double suffix rule is defined by a pair of suffixes: source and destination suffix suffix.

Corresponding implicit prerequisite to obtain a replacement after the suffix by using the source file name suffix. Therefore, at this time the following '$ <' Value is *. c file name. The

positive article make The meaning of the rule is to *. c Programs compiled *. s Code.

. cs:
$ (CC) $ (CFLAGS) \
- nostdinc -Iinclude -S -o $ *. s $ <

Typically having a command belonging prerequisites rules, and for generating a target change at any preconditions ( target) file. However, the rules specify a command for

the target does not necessarily have the prerequisites. For example, the target ' clean ' Related containing deleted ( delete)

Rules command does not need to have prerequisites. In this case, a rule explains how and when to remake certain files, but these files are target-specific rules. make According

prerequisite to execute the command to create or update the target. A rule can also explain how and when to perform an operation.

One makefile File may also contain other characters in addition to the rules, but a simple makefile File only needs to contain the appropriate rules. Rules might seem

much more complex than the template shown above, but basically conforms.

makefile The last generation of file dependencies are used to make make To determine whether you need to rebuild a target object. For example, when a head after the

documents have been altered, make On the adoption of these dependencies, recompile associated with the header files for all *. c file.

as86, ld86 Brief introduction

as86 with ld86 By Bruce Evans Write Intel 8086 Assembler and linker. It is a completely 8086 The assembler, but it can be 386 Processor

preparation 32 Bit code. Linux Use it only to create 16 Bit boot sector

(Bootsector) Code and setup Binary code execution. The syntax of the compiler and GNU The syntax of the assembler is not compatible, but similar to Intel Assembly language

syntax (e.g., a reverse order of the operand, etc.).

Bruce Evans Yes minix operating system 32 Bit version of the main compilers, and he Linux Founder Linus Torvalds He is a good friend. Linus Himself from Bruce Evans I

learned a lot about UNIX Class knowledge of the operating system, minix The inadequacies of the operating system are also two good friends with each other to explore the results

obtained, which inspired Linus in Intel 386 Develop a new concept of the architecture of the operating system, Linux Operating system and the birth Bruce Evans Also he has a

close relationship.

For the source code and the compiler may be from the connector FTP server ftp.funet.fi On or from my website ( www.oldlinux.org)

On the download.

Use both programs and options are as follows:

as the use of methods and options:

as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src

The default settings (default values ​except for the following, another option is off by default or absent; if a flag is not explicitly stated, there will be no output):

- 03 32-bit output; list displayed on


the standard output;
The basic name of the name of the source file (ie, not including the extension after the "."); Options meanings:

- 0 starting from 16-bit code segment;


- 3 starting from the 32-bit code segments;

- and a turn as, ld portion compatibility options;


- b generates a binary file, with the file name can be followed;

- g in the target file is stored only global symbols;


- j jump statements are all long jump;
- l produce a list of files, can be followed by a list of file names;

--45--
2.10 linux / Makefile file

- m extended macro definitions in the list;

- N later followed module name (file name substituted into the target source file);
- o generate the target file, followed by the target file name;

- s symbol file is generated, followed by the symbol file name;

- u undefined symbol as a symbol of the input section is not specified;

- w does not display a warning message;

ld connector using the syntax and options: to generate

Minix a.out format version:


ld [-03Mims [-]] [-T textaddr] [-llib_extension] [-o outfile] infile ...

For generating the GNU-Minix a.out format version:


ld [-03Mimrs [-]] [-T textaddr] [-llib_extension] [-o outfile] infile ...

The default settings (default values ​except for the following, other or no option is off by default):

- 03 32-bit output;
outfile a.out format output;

- 0 head structure 16 generates a magic number of bits, and the use of subdirectories i86 -lx option;

- 3 generates a 32-bit header structure of the magic number, and the use of the i386 subdirectory -lx option;

- M display symbols linked on the standard output device;


- T followed text base address (strtoul a format suitable for use);
- i separate instruction and data segment (I & D) output;

- lx the list of files in the library /local/lib/subdir/libx.a Add link;


- m display module linked on the standard output device;
- o an output file name, followed by the name of the output file;

- r output is further adapted to generate relocatable;


- s remove all symbols in the object file.

System.map file
System.map Kernel symbol table file used to store information. The symbol table is a list of all symbols and their corresponding addresses. With each kernel compilation, it

will generate a new corresponding System.map file. When the kernel running error by System.map Parsing symbol table file, a variable name can be found corresponds to an

address value, or vice versa.

use System.map Symbol table file, in the kernel or the relevant procedural error, you can get the information we more easily identifiable. Sample symbol table shown

below:

c03441a0 B dmi_broken
c03441a4 B is_sony_vaio_laptop c03441c0 b
dmi_ident c0344200 b pci_bios_present
c0344204 b pirq_table

As can be seen the name dmi_broken The variable in the kernel address c03441a0 Place.

System.map Located use its software (such as the kernel logging daemon klogd) Able to find a place. At system startup, if not as a parameter in

the form of klogd Given System.map The position, klogd You will search in three places

System.map . as followed:

/boot/System.map
/System.map
/usr/src/linux/System.map

--46--
2.11 Summary

Although the kernel itself does not actually use System.map , But other procedures, such as klogd , lsof , ps As well as many other software, like

dosemu You need to have a correct System.map file. With this file, you can find these programs in accordance with a known memory address corresponding to the name of the

kernel variables to facilitate debugging the kernel.

2.11 chapter summary

This chapter provides an overview of Linux Early kernel mode of the operating system and architecture. Gives Linux 0.11 The directory structure in the form of the kernel

source code, and introduces the basic functions and hierarchy of each code file in a subdirectory in detail. Then introduced in RedHat 9 Under the build system Linux 0.11 When

the kernel, the code needs to be modified in place. Finally, from Linux Under the main kernel directory makefile File start, start the kernel source code comments.

--47--
3.1 Overview

The first 3 Chapter boot program ( boot )

3.1 Outline

This chapter describes boot / Three assembly code files in a directory, see the list 3-1 Fig. As I mentioned in the previous chapter, although these three files

are assembler, but used two syntax. bootsect.s with setup.s Using approximate Intel The assembly language syntax is required Intel 8086 Assembler and linker as86 with

ld86 ,and head.s Then use GNU Assembler format, and runs in protected mode, with GNU of as Compiled. This is a AT & T The syntax of the assembly language

program.

The main reason both compilers is due to Intel x86 Processor family is concerned, GNU The compiler supports only i386 And later out CPU . Generation to run the

program in real mode is not supported.

List 3-1 linux / boot / table of Contents

File name length (bytes) last modified time (GMT) bootsect.s 5052 bytes

Description 1991-12-05 22:47:58

head.s 5938 bytes 1991-11-18 15:05:09


setup.s 5364 bytes 1991-12-05 22:48:10

In addition to reading the code you need to know some general 8086 Assembler language other than knowledge, but also on the use of Intel 80X86 Microprocessor PC Architecture

and machine 8038632 Principles of Programming at the bit protected mode some understanding. So before you start to read the source code can probably look at the appendix

concerning PC Programming and control unit hardware interface 8038632 Programming protected mode, then the code when reading the detailed description own merits appendix

reference to specific problems.

3.2 The overall function

Here to explain the total Linux The operating system starts the main part of the implementation process. when PC After power is turned on, 80x86 Structure

CPU Automatically enters real mode, and from the address 0xFFFF0 Start the automatic execution of the program code, the address is usually ROM-BIOS In the address. PC Machine

BIOS The execution of some detection systems, and the physical address 0 At the beginning of the interrupt vector initialization. Thereafter, it will start the first sector of the device

(the disk boot sector, 512 Bytes) read into memory absolute address 0x7C00 Place, and jump to this place. Usually a floppy boot device or hard drive. Described here is very

simple, but it is enough to understand the kernel initialization process of the work.

Linux The best part is the front 8086 Written in assembly language ( boot / bootsect.s) , It will be run by BIOS Read into memory absolute address 0x7C00 (31KB) Place,

when it is executed will be moved to its own absolute address 0x90000 (576KB) At the start and after the device 2kB

Byte code ( boot / setup.s) Read into memory 0x90200 At other portions of the kernel ( system Module) were read into the address

0x10000 At the beginning, because at that time system Does not exceed the length of the module 0x80000 Byte size (i.e. 512KB ), So it will not cover the 0x90000 At the beginning

of bootsect with setup Module. Behind setup The program will system Moves to the beginning of the memory modules, so system Address code module that is equal to the actual

physical address of the kernel code to facilitate operation of and data. Map 3-1 Clearly shows Linux These programs or modules in memory location dynamically at system startup.

Wherein, each representative of a time frame bars memory

--49--
3.3 bootsect.s program

FIG image location of each program. During the system loads the message " Loading ... " . Control then passed to boot / setup.s The code, which is another real-mode assembly

language program.

bootsect.s program

setup.s program
0xA0000

system module
0x90200
0x90000
system program module head.s

Code execution position line

0x10000

0x7c00

0x0000
12345 6

Map 3-1 When the position of the boot and where the core is moved in the position memory

Some characteristics of the initiator and part identifies the host vga The type of card. If necessary, it will ask the user to select the display mode for the console. Then the

entire system from address 0x10000 Move to 0x0000 , The protected mode and jumps to the remainder of the system (in 0x0000 Office). All this time 32 Setting the start bit operating

mode is completed: IDT , GDT as well as LDT Loaded, processors and coprocessors have been confirmed, pagination work also set up; final call init / main.c middle main () program.

Source code for the above-described operation is boot / head.S In, this may be the most know-how throughout the kernel code. Note If you make a mistake in any of the foregoing

step, the computer will deadlock. Before the operating system is not yet fully operational process can not go wrong.

Why not put the system module is loaded directly into a physical address 0x0000 At the beginning and to the setup The program then move it? This is because setup The

beginning of the program code are also needed ROM BIOS Some parameters interrupt calls to get the machine (eg graphics card mode, hard disk parameter tables, etc.). when BIOS

A physical size is placed at the beginning of the memory is initialized 0x400 byte( 1Kb) The interrupt vector table, so need to use finished BIOS After the interrupt calls to this area

overwritten.

3.3 bootsect.s program

3.3.1. Functional Description

bootsect.s Disk boot block code that resides on the first sector of the disk (boot sector, 0 A track (cylinder), 0 Head first 1 Sectors). in PC Powered machine ROM BIOS After

self-test, boot sector from BIOS Loaded into memory 0x7C00 Place, then move yourself into memory 0x90000 Place. The main role of this procedure is to first setup Module (from

the setup.s Compiled) is loaded from disk to memory, followed by bootsect Back position ( 0x90200 ), Then use BIOS Interrupt 0x13 Take a currently active disk parameter table of

the reference guide plate

--50--
3.3 bootsect.s program

Number, and then displayed on the screen. " Loading system ... " String. In addition to system Modules are loaded from disk into memory 0x10000 Place to start. Then determining

the root file system device number, if not specified, it is determined based on the number of sectors per track of the disc stored in the disc guide type and kind (YES 1.44MA Offer?

) And save it to the device number root_dev ( The guide block 0x508 Address), and finally to the long jump setup Beginning of the program ( 0x90200 )carried out setup program.

3.3.2 Code comments

program 3-1 linux / boot / bootsect.s

1!
2 ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
3 ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
4 ! Versions of linux
! SYS_SIZE is the number of sections to be loaded (16 bytes Section 1). 0x3000 total of

! 0x30000 bytes = 196 kB (1024 bytes 1KB In terms of dollars, then it should be 192KB), the current version of the space is sufficient.

5!
6 SYSSIZE = 0x3000 ! Refers to the size of the compiled module connection system. See the list of the first 92 2.1. ! Here is one of

the biggest defaults.

7!
8! bootsect.s (C) 1991 Linus Torvalds
9!
10 ! Bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
11 ! Iself out of the way to address 0x90000, and jumps there.
12 !
13 ! It then loads 'setup' directly after itself (0x90200), and the system
14 ! At 0x10000, using BIOS interrupts.
15 !
16 ! NOTE! Currently system is at most 8 * 65536 bytes long. This should be no
17 ! Problem, even in the future. I want to keep it simple. This 512 kB
18 ! Kernel size should be enough, especially as this does not contain the
19 ! Buffer cache as in minix
20 !
twenty one ! The loader has been made as simple as possible, and continuos
twenty two ! Read errors will result in a unbreakable loop. Reboot by hand. It
twenty three ! Loads pretty fast by getting whole sectors at a time whenever possible.
!
! The following is a translation of the text in front of these:!

bootsect.s (C) 1991 Linus Torvalds Copyright


!
! Bootsect.s is bios- startup routines loaded 0x7c00 (31k) Department, and himself! Moved to
address 0x90000 (576k) at, and jump to there. !

! It will then use BIOS interrupt 'setup' loaded directly into their back (0x90200) (576.5k),! And loaded into the
system address 0x10000. !

! Note! The current core system is limited to a maximum length (8 * 65536) (512k) bytes, even! Future this should be no
problem. I want to keep it simple. Such a maximum core length should 512k! Sufficient, especially as there is no buffer
contained in the cache as minix. !

! Loader has been simple enough to do, so continue reading error will result in an endless loop. Only manual restart. ! Whenever possible, once

by reading all sectors, the loading process can be done quickly.

twenty four

--51--
3.3 bootsect.s program

25 ! .Globl begtext, begdata, begbss, endtext, enddata, endbss defines six global identifier;
26 .text ! Text segment;

27 begtext:
28 .data ! Data segment;

29 begdata:
30 .bss ! Uninitialized data segment (Block Started by Symbol);
31 begbss:
32 .text ! Text segment;

3334 SETUPLEN = 4
!! Nr of setup-sectors the number of sectors setup program
(setup-sectors) value;
35 BOOTSEG = 0x07c0 !! Original address of boot-sector bootsect original address (the address is a

segment, hereinafter the same);

36 INITSEG = 0x9000 !! We move boot here - out of the way to move bootsect
here - to avoid;
37 SETUPSEG = 0x9020 ! Setup starts here setup program from
here!;
38 SYSSEG = 0x1000 !.! System loaded at 0x10000 (65536) system module is loaded
into 0x10000 (64 kB) at;
39 ENDSEG = SYSSEG + SYSSIZE ! Where to stop loading stop segment
address loaded!;
4041 ! ROOT_DEV:
0x000 - same type of floppy as boot.
! Root file system floppy disk device, the same equipment and the guide;

42 ! 0x301 - first partition on first drive etc


! Root file system of a hard disk device in a first partition, and the like;

43 ROOT_DEV = 0x306 ! Specify the root file system device is the second hard disk first partition. This is old-fashioned hard disk Linux naming, meaning specific values

​are as follows!:

! Master device number = device number * 256 + minor number (i.e. dev_no = (major << 8) + minor) (major
number:! Memory 1-, 2- disk, hard 3-, 4-ttyx, 5 -tty, 6- parallel port, 7- non-named pipe) 0x300 - / dev / hd0 -
representative of the first hard disk;!! 0x301 - / dev / hd1 - first partition of a disk; ...!

! 0x304 - / dev / hd4 - the fourth partition of a disk;! 0x305 - / dev /


hd5 - representative of the second hard disk;! 0x306 - / dev / hd6 -
first partition of the two disks ;! ...

! 0x309 - / dev / hd9 - 2nd 4th partition plate;! From the linux kernel version 0.95 has been used
with the current method of the same name.
4445 entry start
! Tell the linker program, program execution begins at start label.

46 start: ! Line 47--56 role itself (the bootsect) segment from the current position 0x07c0 (31k)! Moved to 0x9000

(576k), the total of 256 words (512 bytes), then jumps to! Go moving the reference code place, that the

next statement of the program.

47 mov ax, # BOOTSEG ! The ds segment register to 0x7C0;


48 mov ds, ax
49 mov ax, # INITSEG ! Es The segment register is set to 0x9000;

50 mov es, ax
51 mov cx, # 256 ! Mobile word count value = 256;

52 sub si, si ! Source address ds: si = 0x07C0: 0x0000


53 sub di, di ! Destination addresses es: di = 0x9000: 0x0000

54 rep ! Repeat until cx = 0


55 movw ! Move a word;

--52--
3.3 bootsect.s program

56 jmpi go, INITSEG ! Indirect jump. Here INITSEG pointed to jump to the segment address. ! From the bottom, CPU

execution is moved to the code segment at 0x9000.

57 go: mov ax, cs ! The ds, es and ss are set to the segment (0x9000) located after the mobile code.

58 mov ds, ax ! Because the program has a stack operation (push, pop, call), the stack must be set.

59 mov es, ax
60 ! Put stack at 0x9ff00. ! Sp point stack pointer 0x9ff00: at (i.e. 0x9000 0xff00)
61 mov ss, ax
62 mov sp, # 0xFF00 ! Arbitrary value >> 512
! Since the code segment moved up, so to reset the position of the stack segment. ! SP 512 is

much greater than just point offset (i.e., address 0x90200)! Can. Because the setup program also

placed from the beginning address 0x90200,! Setup program at a time of about four sectors, thus

pointing to a large sp! In (0x200 + 0x200 * 4 + stack size) at.

6364 ! Load the setup-sectors directly after the bootblock.

65 ! Note that 'es' is already set up.


! Bootsect block immediately after the root setup code data loading module.

! Note es have been set up. (When moving the code segment object is pointing es address 0x9000).

6667 load_setup:

! Line 68--77 use BIOS interrupt INT 0x13 is the use of the setup module from the second disk sector! 0x90200 start

reading at the beginning, a total of four sectors read. If the read error, the reset driver, and! Retry, no escape route. INT

0x13 used as follows:! Read Sector:

! Ah = 0x02 - disk sector read into memory; al = number of sectors to be read; ch = number of tracks (cylinders) and the lower 8 bits;

cl = the start sector (bits 0-5), the track numbers! high 2 (6-7);! dh = head number;

dl = drive number (if the hard disk is set to bit 7);


! Es: bx point to the data buffer; if the error flag CF is set.
68 mov dx, # 0x0000 ! Drive 0, head 0
69 mov cx, # 0x0002 ! Sector 2, track 0
70 mov bx, # 0x0200 ! Address = 512, in INITSEG
71 mov ax, # 0x0200 + SETUPLEN ! Service 2, nr of sectors
72 int 0x13 ! Read it
73 jnc ok_load_setup ! Ok - continue
74 mov dx, # 0x0000
75 mov ax, # 0x0000 ! Reset the diskette
76 int 0x13
77 j load_setup
7879 ok_load_setup:

8081 ! Get disk drive parameters, specifically nr of sectors / track

! Take the disk drive parameters, in particular the number of sectors per track. ! Take the disk drive

parameters INT 0x13 call format and return the following information:! Ah = 0x08

dl = drive number (if the hard disk will have a set of 7).
! returned messages:

! CF is set if an error occurs, and ah = status code. ! Ah = 0, al


= 0, bl = drive type (AT / PS2)
! Ch = lower 8 bits maximum track number, cl = maximum number per track (bits 0-5) sector, the maximum track number 2 (bits 6-7) High! Dh = the maximum number of

heads, dl = drive number,


! Es: di - Floppy disk parameter table.
8283
mov dl, # 0x00

--53--
3.3 bootsect.s program

84 mov ax, # 0x0800 ! AH = 8 is get drive parameters


85 int 0x13
86 mov ch, # 0x00
87 seg cs ! Represents the next paragraph in the statement operands referred cs segment registers.

88 mov sectors, cx ! Save the number of sectors per track.

89 mov ax, # INITSEG


90 mov es, ax ! Because the disk parameters taken above the value es interrupted rid of, change back here again.

9192 ! Print some inane message


! Display some information ( 'Loading system ...' carriage return, a total of 24 characters).

9394
mov ah, # 0x03 ! Read cursor pos
95 xor bh, bh ! Read the cursor position.

96 int 0x10
9798
mov cx, # 24 ! A total of 24 characters.

99 mov bx, # 0x0007 ! Page 0, attribute 7 (normal)


100 mov bp, # msg1 ! Points to the string to be displayed.

101 mov ax, # 0x1301 ! Write string, move cursor


102 int 0x10 ! Write string and move the cursor.

103104 ! Ok, we've written the message, now

105 ! We want to load the system (at 0x10000)! Now on the system module is loaded into 0x10000 (64k) at.
106107
mov ax, # SYSSEG

108 mov es, ax ! Segment of 0x010000 ! Es = segment address of the storage system.

109 call read_it ! Read on the system disk module, es for input parameters.

110 call kill_motor ! Switch off the drive motor, so that you can know the status of the drive.

111112 ! After that we check root-device to use. If the device is which

113 ! Defined (! = 0), nothing is done and the given device is used.
114 ! Otherwise, either / dev / PS0 (2,28) or / dev / at0 (2,8), depending
115 ! On the number of sectors that the BIOS reports currently.
! Since then, we have to check what the root file system device (referred to as the root device) use. If you have specified device (! = 0)! To direct a given

device. Otherwise, it needs to be based on the number of sectors per track BIOS reporting! OK in the end use / dev / PS0 (2,28) or / dev / at0 (2,8).

! Top row two device files meanings:


! Major number is in Linux floppy 2 (see comment line 43), the minor number = type * 4 + nr, where nr is the floppy 0-3
respectively A, B, C or D;! Type is the type of floppy disk drive (2 1.2M 7 1.44M, or the like). ! Because 7 = 4 + 0 * 28, the / dev /
PS0 (2,28) refers 1.44MA drive, which device number is 0x021c! Likewise / dev / at0 (2,8) refers to a drive 1.2MA its device
number is 0x0208.
116117
seg cs
118 mov ax, root_dev ! Root device number

119 cmp ax, # 0


120 jne root_defined
121 seg cs
122 mov bx, sectors ! Save the number of sectors per track is taken above the line 88. ! If sectors = 15 then
the drive is 1.2Mb; if sectors = 18, it indicates that the 1.44Mb floppy!. Because bootable
drive, so it must be the A drive.
123 mov ax, # 0x0208 ! / Dev / ps0 - 1.2Mb
124 cmp bx, # 15 ! Determines whether the number of sectors per track = 15

125 je root_defined ! If it is equal, then the ax is to guide the device number of the drive.

126 mov ax, # 0x021c ! / Dev / PS0 - 1.44Mb

--54--
3.3 bootsect.s program

127 cmp bx, # 18


128 je root_defined
129 undef_root: ! If not the same, then an infinite loop (crash).
130 jmp undef_root
131 root_defined:
132 seg cs
133 mov root_dev, ax ! Be saved inspected the device number.

134 135 ! After that (everyting loaded), we jump to

136 ! The setup-routine loaded directly after


137 ! The bootblock:
! This, all programs are loaded, we jump to be! Bootsect loaded in
the back of the setup program to go.
138139
jmpi 0, SETUPSEG ! Jump to 0x9020: 0000 (setup.s at the beginning of the program). !!!! This

concludes this procedure. !!!!

! Here are two subroutines.


140141 ! This routine loads the system at address 0x10000, making sure

142 ! No 64kB boundaries are crossed. We try to load it as fast as


143 ! Possible, loading whole tracks whenever we can.
144 !
145 ! In: es - starting address segment (normally 0x1000)
146 !
! This subroutine modules will be loaded into the system memory address 0x10000, and determines that no cross border 64KB of memory. We tried as soon as possible! Load carried

out, whenever possible, data on the entire track every load. ! Input: es - start memory address segment value (usually 0x1000)

147 sread: .word 1 + SETUPLEN ! Sectors read of current track


! Read the number of tracks in the current sector. It has been read into the boot sector of a sector at the beginning!

Bootsect setup program and the number of sectors occupied by SETUPLEN.

148 head: . word 0 ! Current head ! The current head number.

149 track: .word 0 ! Current track! Current track number.


150 151 read_it:

! Test input segment value. Read data from the disc must be stored at the beginning of the boundary is located 64KB memory address, otherwise enter an infinite loop. ! Clear bx register, used

to indicate the start position of the current segment and storing data.

152 mov ax, es


153 test ax, # 0x0fff
154 die: jne die ! Es must be at 64kB boundary! Es value must address 64KB boundary!
155 xor bx, bx ! Bx is starting address within segment! Bx offset positions within a segment.
156 rp_read:
! Determine whether all the data has been read. Comparing whether the current segment is the system in which the terminal segment (#ENDSEG) data, if not it! Ok1_read jump to the label

read following the data read continues. Otherwise, exit the subroutine returns.

157 mov ax, es


158 cmp ax, # ENDSEG ! Have we loaded all yet?! Are all the data has been loaded?
159 jb ok1_read
160 ret
161 ok1_read:
! Calculate and validate the current track number of sectors to be read, in a register ax.

! Start offset position based on the sector number of the current track has not been read, and the byte data segment is calculated if all unread to read the sector, the

! The total number of bytes read whether it will exceed 64KB limit the length of the segment. If more than, the number of bytes up to the read (64KB - inner section

--55--
3.3 bootsect.s program

! Offset position), the anti-calculate the number of sectors to be read.

162 seg cs
163 mov ax, sectors ! Take sectors per track.
164 sub ax, sread ! Subtracting the current track has read the number of sectors.

165 mov cx, ax ! Cx = ax = current track is not the number of sectors to read.

166 shl cx, # 9 ! Cx = cx * 512 bytes.


167 add cx, bx ! Cx = cx + current offset value in paragraph (BX)!
= After the read operation, the number of bytes read into the inner section co.

168 jnc ok2_read ! If there is no more than 64KB bytes, then jump to ok2_read Branch.

169 je ok2_read
170 xor ax, ax ! If more than 64KB plus read all the unread sector on the track, the calculation

171 sub ax, bx ! At this time, up to the number of read bytes (64KB - read offset inner section), and then converted

172 shr ax, # 9 ! To require a number of sectors read.

173 ok2_read:
174 call read_track
175 mov cx, ax ! Cx = number of sectors that have been read operations.

176 add ax, sread ! Current number of sectors on the track that has been read.

177 seg cs
178 cmp ax, sectors ! If there are sectors on a track currently unread, jump to the ok3_read.
179 jne ok3_read
! On data (head No. 1) read the next track of the head face. If you have finished, you read the next track.

180 mov ax, # 1


181 sub ax, head ! Determine the current head number.

182 jne ok4_read ! If the head is 0, 1 data sector is read again the head face.
183 inc track ! Otherwise read the next track.

184 ok4_read:
185 mov head, ax ! Save the current head number.

186 xor ax, ax ! Clear the current track has read the number of sectors.

187 ok3_read:
188 mov sread, ax ! Save the current track has read the number of sectors.

189 shl cx, # 9 ! Read the last number of sectors * 512 bytes.

190 add bx, cx ! Adjustments within the current data segment starting position.

191 jnc rp_read ! If the boundary value is less than 64KB, then jump to rp_read (156 lines), the data read continues. ! Otherwise adjust the

current section, read the next piece of data for the preparation.

192 mov ax, es


193 add ax, # 0x1000 ! The segment base adjusted to point at the beginning of the next 64KB of memory.

194 mov es, ax


195 xor bx, bx ! Clear the segment data starting offset value.

196 jmp rp_read ! Jump to rp_read (156 lines), the continue reading data.

197
! Currently specified read start sector on the track and the number of sectors required to read data es: bx beginning. See the next line 67 to read BIOS disk interrupt! Int 0x13, ah =

Description 2.

! Al - need to read the number of sectors; es: bx - buffer starting position.

198 read_track:
199 push ax
200 push bx
201 push cx
202 push dx
203 mov dx, track ! Take the current track number.

204 mov cx, sread ! Take the current read sector number on the track.

205 inc cx ! Cl = start reading sectors.


206 mov ch, dl ! Ch = current track number.

207 mov dx, head ! Take the current head number.

--56--
3.3 bootsect.s program

208 mov dh, dl ! Dh = head number.


209 mov dl, # 0 ! Dl = drive number (A 0 indicates that the current drive).

210 and dx, # 0x0100 ! Head number is not greater than 1.

211 mov ah, # 2 ! Ah = 2, read disk sectors function number.

212 int 0x13


213 jc bad_rt ! If an error, then jump to bad_rt.
214 pop dx
215 pop cx
216 pop bx
217 pop ax
218 ret
! Driver performs a reset operation (interrupt function disk 0), the jump to read_track retry.
219 bad_rt: mov ax, # 0
220 mov dx, # 0
221 int 0x13
222 pop dx
223 pop cx
224 pop bx
225 pop ax
226 jmp read_track
227 228 / *

229 * This procedure turns off the floppy drive motor, so


230 * That we enter the kernel in a known state, and
231 * Do not have to worry about it later.
232 * /
! This subroutine for the motor is turned off floppy drive, so we enter the kernel after it is in a known state, there is no need to worry about it later.

233 kill_motor:
234 push dx
235 mov dx, # 0x3f2 ! Floppy drive port control card, write-only.
236 mov al, # 0 ! A drive off the FDC, disable the DMA and interrupt requests, off the motor.

237 outb ! The contents of the output to the al dx to the specified port.

238 pop dx
239 ret
240241 sectors:

242 . word 0 ! Floppy disk to store the number of sectors per track of the current boot.

243 244 msg1:

245 . byte 13,10 ! Carriage return, ASCII code wrap.

246 . ascii "Loading system ..."


247 . byte 13,10,13,10 ! Total 24 ASCII characters.
248 249 .org 508
! Represents the following statements from the address 508 (0x1FC) starts, so ROOT_DEV! 508 at

the beginning 2 bytes of the boot sector.

250 root_dev:
251 . word ROOT_DEV ! Here storage device number where the root file system (init / main.c will

use).
252 boot_flag:
253 . word 0xAA55 ! Hard disk to a valid ID.

254 255 .text

256 endtext:

--57--
3.4 setup.s program

257 .data
258 enddata:
259 .bss
260 endbss:

3.3.3 Other Information

Correct bootsect.s Illustration and description of this procedure, you can search on the Internet at large amounts of data. among them Alessandro Rubini

And by me with the translation. " Linux Kernel source code roaming "article ( http://oldlinux.org/Linux.old/docs/) Compare kernel boot process is described in detail in detail, a good

reference. Because this program is in 386 Running real mode, and therefore relatively easy to be understood. If the reading is still difficult at this time, it is recommended that you

first go over again 80x86 Compilation of relevant knowledge and hardware (can be found in Ref. [ 1] with[ 16] ), Then continue reading this book.

For the latest development Linux Kernel modifications of this procedure is small, it remained with 0.11 Version looks like.

3.4 setup.s program

3.4.1. Functional Description

setup The main role of the program is to use ROM BIOS Interrupt read machine system data, and saves the data to 0x90000 Starting position (overwritten bootsect The

place where the program), the parameters achieved and the memory location reserved table below 3 - 1 Fig. These parameters will be used by the kernel procedures, for example,

a character device driver set ttyio.c Procedures.

table 3 - 1 setup Read and program parameters reserved

Memory address Length (bytes) name description

0x90000 2 Cursor position The column number ( 0x00- Far left), line number ( 0x00- Topmost)

0x90002 2 Number of extended memory System from 1M Extended memory numbers starting with ( KB ).

0x90004 2 Display page The currently displayed page

0x90006 1 Display Mode

0x90007 1 Character number of columns

0x90008 2 ??

0x9000A 1 Display memory Display memory ( 0x00-64k, 0x01-128k, 0x02-192k, 0x03 = 256k)

0x9000B 1 Display state 0x00- color, I / O = 0x3dX ; 0x11- monochrome, I / O = 0x3bX

0x9000C 2 Parameters Carter display parameters

...

0x90080 16 Hard disk parameter table The first 1 A hard disk parameter table

0x90090 16 Hard disk parameter table The first 2 Hard disk parameter table (if not, then cleared)

0x901FC 2 No root device Where the root file system device number ( bootsec.s Set)

then setup The program will system Modules from 0x10000-0x8ffff (At that time that the kernel module system system The length does not exceed the value: 512KB ) Moved

down to the absolute address of the block of memory 0x00000 Place. Next, loading Interrupt Descriptor Table Register ( idtr) And a global descriptor table register ( gdtr) Open A20 Address

lines, reset the two interrupt control chip 8259A The hardware interrupt number reset

0x20 - 0x2f . The last set CPU Control Register CR0 (Also known as machine status word) to enter 32 Bit protected mode and jump to is located system The front section of the

module head.s The program continues to run.

In order to allow head.s in 32 Run, this program temporarily installed in the interrupt descriptor table the protected mode ( idt ) And the global descriptor

--58--
3.4 setup.s program

Table ( gdt ), And gdt Set in the current data segment descriptors and descriptor kernel code segments. In the following head.s Resets these descriptor tables necessary

kernel program.

Now, according to CPU Addressing modes in real mode and protected mode, a comparative method will be briefly described 32 The main features of the bit

protected-mode operating mechanism, in order to easily understand the procedures in this section. Gradually be described in detail in the following sections.

In real mode, the main memory address addressing a segment and an offset value is used, the segment value is stored in the segment registers (e.g. ds ), And the maximum

length of the segment is fixed 64KB . The segment offset address stored in the register for addressing any one (e.g. si ). Thus, according to the value of a segment register and an

offset register, can be calculated memory address actually points, see Fig. 3-2 (a) Fig.

In the protected mode operating mode, the segment registers are no longer stored in the address segment base address, but an index of an item in the segment descriptor

table. The base address specified by the index value of segment descriptor entry contains the addressed memory segment required, other access level values ​and the maximum

length of the segment information section. Addressable memory location specified by the entry segment descriptor segment base address value and the offset value combination,

the maximum length of the segment is also specified by the descriptor. Seen, and compared to the real mode addressing, segment register value index into a segment descriptor,

the concept of an offset value in the original or real mode. Thus, addressing a memory address in the protected mode requires a multiple than the real mode procedures, i.e.

required descriptor table. This is because access to the information needs of a memory segment in protected mode more, a 16 Bit segment registers fit so much content. Is shown

in Figure 3-2 (b) Fig.

register register
variable
64kb esi

ds si

ds
Descriptor Table

gdtr

Under (a) real mode addressing. Under (b) protected mode addressing.

Map 3-2 Comparison of the real mode and protected mode addressing mode

Thus, before entering the protected mode, you must be set up to use the descriptor table, for example, a global descriptor table gdt . Then use the command lgdt The base

address of the descriptor table informed CPU ( gdt Base address table is stored gdtr register). Then protected mode flag is set to enter the machine status word 32 Bit protected

mode of operation.

3.4.2 Code comments

program 3-2 linux / boot / setup.s

1!
2! setup.s (C) 1991 Linus Torvalds
3!
4 ! Setup.s is responsible for getting the system data from the BIOS,
5 ! And putting them into the appropriate places in system memory.
6 ! Both setup.s and system has been loaded by the bootblock.
7!

--59--
3.4 setup.s program

8 ! This code asks the bios for memory / disk / other parameters, and
9 ! Puts them in a "safe" place: 0x90000-0x901FF, ie where the
10 ! Boot-block used to be. It is then up to the protected mode
11 ! System to read them from there before the area is overwritten
12 ! For buffer-blocks.
!
! Setup.s responsible for getting data from the system BIOS, and put the appropriate place in the data system memory. ! Setup.s case has

been loaded by the system and bootsect boot block into memory. !

! The code asks bios on memory / disk / other parameters, and these parameters into a "safe" place:!
0x90000-0x901FF, also formerly bootsect block of code once in place, then covered in bumper! before the
system is read out of protected mode.
13 !
1415 ! NOTE! These had better be the same as in bootsect.s!

! Bootsect.s following parameters are the same and the best!

1617 INITSEG = 0x9000


! We move boot here -! Out of the way in which the original bootsect segment.
18 SYSSEG = 0x1000 ! System loaded at 0x10000 (65536).! System at 0x10000 (64k) at.
19 SETUPSEG = 0x9020 ! This is the current segment! Segment address this program is located.
2021 .globl begtext, begdata, begbss, endtext, enddata, endbss

twenty two .text

twenty three begtext:

twenty four .data

25 begdata:
26 .bss
27 begbss:
28 .text
2930 entry start

31 start:
3233 ! Ok, the read went well so we get current cursor position and save it for

34 ! Posterity.
! Ok, the whole disk read process is normal, the cursor position will now be saved for future use.

3536
mov ax, # INITSEG ! This is done in bootsect already, but ...! Ds will be set to #INITSEG (0x9000). This
has been bootsect program! Set too, but now is the setup program, Linus felt the
need to re-! Set it.

37 mov ds, ax
38 mov ah, # 0x03 ! Read cursor pos
! BIOS interrupt 0x10 read cursor function number of ah = 0x03 Input:! Bh =

page number

! Returns: ch = scanning start line, cl = end of the scan lines, dh = line number (0x00 is

the top), dl = column number (0x00 is left!).

39 xor bh, bh
40 int 0x10 ! Save it in known place, con_init fetches
41 mov [0], dx ! It from 0x90000.
! A few words to say at the cursor position information stored at 0x90000, console! Will take time to

initialize.

42

--60--
3.4 setup.s program

43 ! Get memory size (extended mem, kB)! Take the following three expanded memory size values ​(KB).
! Is calling interrupt 0x15, function number ah = 0x88

! Return: ax = starting from at 0x100000 (1M) extended memory size (KB). ! CF if the
error is set, ax = error code.
4445
mov ah, # 0x88
46 int 0x15
47 mov [2], ax ! 0x90002 extended memory present value at (1 word).
4849 ! Get video-card data:
! Below this card for taking the current display mode. ! Call BIOS interrupt 0x10, function returns the number ah = 0x0f:! Ah =

number of characters in the column, al = display mode, bh = the currently displayed page. ! 0x90004 (1 word) holds the current

page, 0x90006 display mode, 0x90007 number of characters in the column.

5051
mov ah, # 0x0f
52 int 0x10
53 mov [4], bx ! Bh = display page
54 mov [6], ax ! Al = video mode, ah = window width
5556 ! Check for EGA / VGA and some config parameters! Check display (EGA / VGA) and taking parameters.

! Call BIOS interrupt 0x10, additional function selection - take way messaging
number:! Ah = 0x12, bl = 0x10 return: bh = display status!!

(0x00 - color mode, I / O port = 0x3dX)!


(0x01 - monochrome mode, I / O port = 0x3bX)! Bl =

mounted display memory

! (0x00 - 64k, 0x01 - 128k, 0x02 - 192k, 0x03 = 256k) cx = Carter display parameters
(see description after the program)!.
5758
mov ah, # 0x12
59 mov bl, # 0x10
60 int 0x10
61 mov [8], ax ! 0x90008 = ??
62 mov [10], bx ! 0x9000A = display memory installed, 0x9000B = display state (color / monochrome)

63 mov [12], cx ! 0x9000C = Carter display parameters.

6465 ! Get hd0 data


! Take the first hard disk information (hard copy parameters table).

! The first address of the first one turned out to be the hard disk parameter table interrupt vector value of 0x41! The second hard disk!

Parameter table immediately after the first one table, the interrupt vector to the value of 0x46 This also points to a second hard disk! Parameter

table first site. Length of the table is 16 bytes (0x10).

! Following two BIOS parameter table copying a program related to two hard disk at a first storage 0x90080! Disk table,

stored at 0x90090 second disk table.

6667
mov ax, # 0x0000
68 mov ds, ax
69 lds ! Si, [4 * 0x41] 0x41 takes the value of the interrupt vector, i.e. ds hd0 address parameter table: si

70 mov ax, # INITSEG


71 mov es, ax
72 mov di, # 0x0080 ! Destination address of transmission: 0x9000: 0x0080 es: di
73 mov cx, # 0x10 ! Total transmission 0x10 bytes.

74 rep
75 movsb
76

--61--
3.4 setup.s program

77 ! Get hd1 data


7879
mov ax, # 0x0000
80 mov ds, ax
81 lds ! Si, [4 * 0x46] 0x46 take the value of the interrupt vector, that is the address parameter table ds hd1: si

82 mov ax, # INITSEG


83 mov es, ax
84 mov di, # 0x0090 ! Destination address of transmission: 0x9000: 0x0090 es: di
85 mov cx, # 0x10
86 rep
87 movsb
8889 ! Check that there IS a hd1 :-)! Check the system of the two hard disks, and if not the second table is cleared.

! BIOS interrupt calls using the 0x13 take the disk type function. ! Function

number ah = 0x15;

! Input: dl = drive number (0x8X a hard disk: 0x80 refers to the first hard disk, the second hard disk 0x81) Output:! Ah = type code; 00
- this is not disk, CF is set; 01 - floppy drive, no change-line support;!
02 - is a floppy (or other mobile devices), there are change-line support; 03 - is a hard disk.
9091
mov ax, # 0x01500
92 mov dl, # 0x81
93 int 0x13
94 jc no_disk1
95 cmp ah, # 3 ! Is it hard? (Type = 3?).
96 je is_disk1
97 no_disk1:
98 mov ax, # INITSEG ! 2nd hard disk does not exist, then the first two hard disks table is cleared.

99 mov es, ax
100 mov di, # 0x0090
101 mov cx, # 0x10
102 mov ax, # 0x00
103 rep
104 stosb
105 is_disk1:
106107 ! Now we want to move to protected mode ...! Now we have to enter the protected mode in a ...

108109
cli ! No interrupts allowed!! Not allowed at this interruption.
110111 ! First we move the system to it's rightful place

! First we will system module to the correct position.


! The bootsect system boot program is read into the module from the position 0x10000 (64k) begins. At that time, assume! System module does not

exceed the maximum length of 0x80000 (512k), i.e. it does not exceed the end memory address 0x90000,! Bootsect they will move to their starting place

0x90000, and the setup is loaded behind it. ! Uses the following program is then moved to the entire system modules 0x00000 position, i.e. from the

0x10000 to 0x8ffff! Memory blocks (512K), the lower end piece to move the position 0x10000 (64K) to the memory.

112
113 mov ax, # 0x0000
114 cld ! 'Direction' = 0, movs moves forward
115 do_move:
116 mov es, ax ! Destination segment es:! Di destination address (initially 0x0000: 0x0)
117 add ax, # 0x1000
118 cmp ax, # 0x9000 !'Ve 64k of code from 0x8000 segment started moving finished?

--62--
3.4 setup.s program

119 jz end_move
120 mov ds, ax ! Source segment ds:! Si source address (initially 0x1000: 0x0)
121 sub di, di
122 sub si, si
123 mov cx, # 0x8000 ! Mobile 0x8000 words (64K bytes).
124 rep
125 movsw
126 jmp do_move
127 128 ! Then we load the segment descriptors

! Since then, we loaded descriptor.


! Start here encounter operating 32-bit protected mode, requiring knowledge of Intel 32-bit protected mode of the programming,! Information on this, please

explain in detail in the appendix or after a brief review of the list. Only here for an overview. ! In protected mode before running, we need to set that you need

to use the descriptor table. It should set global! Descriptor tables and interrupt descriptor table. !

! LIDT instructions for loading an interrupt descriptor table (IDT) register, whose operand is 6 bytes, the descriptor table is 0-1 byte length value (bytes);! Is 2-5 bytes

Description the linear 32-bit descriptor table base address (the first address), see the following form! instructions 219-220 and row lines 223-224. Interrupt each entry (8

bytes) pointed out that information when the interrupt occurs! Need to call the code descriptor table, and interrupt vector is somewhat similar, but contain more information. !

! LGDT instructions for loading Global Descriptor Table (GDT) register, which is the same as the operand of the instruction format lidt. Global Descriptor! Each descriptor entry (8

bytes) of the table describes the information in the protected mode code and data segments (blocks). Including segments! Maximum length (16), the linear segment base address

(32), the privilege level of the segment, whether the segment flag in memory, as well as read and write permissions! Some other protected mode operation. See behind the

205-216 line. !

129 130 end_move:

131 mov ax, # SETUPSEG ! Right, forgot this at first. Did not work :-)
132 mov ds, ax ! Ds point to this program (setup) segment.

133 lidt idt_48 ! Load idt with 0,0


! Loading interrupt descriptor table (IDT) register, idt_48 6 is the position number of byte operation! (See

line 218). 2 bytes long before idt limit table, Table 4 bytes idt! Located base address.

134 lgdt gdt_48 ! Load gdt with whatever appropriate


! Loading Global Descriptor Table (GDT) register, gdt_48 6 is the position number of byte operation! (See line 222).

135 136 ! That was painless, now we enable A20

! The above operation is very simple, and now we turn to A20. For a description of the signal line A20 see the program list. ! On a number of ports and the order relates to, a

keyboard interface may be described with reference to the kernel / chr_drv / keyboard.S program.

137
138 call empty_8042 ! Waits for input buffer is empty.

! Only when the input buffer is empty may be a write command.


139 mov al, # 0xD1 ! Command write 0xD1 command code -! Represents the data to be written

140 out # 0x64, al ! P2 port 8042. 1 bit for the port P2 strobe line A20. ! Data to be written to
0x60 mouth.
141 call empty_8042 ! Waiting for input buffer is empty, to see whether the command is accepted.

142 mov al, # 0xDF ! A20 ON! Parameter selection through address line A20.

143 out # 0x60, al


144 call empty_8042 ! Input buffer is empty, then the A20 line has been gated.

145 146 ! Well, that went ok, I hope. Now we have to reprogram the interrupts :-(

--63--
3.4 setup.s program

147 ! We put them right after the intel-reserved hardware interrupts, at


148 ! Int 0x20-0x2F. There they will not mess up anything. Sadly IBM really
149 ! Messed this up with the original PC, and they have not been able to
150 ! Rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
151 ! Which is used for the internal hardware interrupts as well. We just
152 ! Have to reprogram the 8259's, and it is not fun.
!! I hope everything is normal. Now we have to re-program the interrupts !! We just put them in a hardware interrupt reserved intel back
in int 0x20-0x2F. !! where they do not cause conflict. Unfortunately, the mess in the original IBM PC, and will not allow rectified. bios !!
PC machines will break on the 0x08-0x0f, these interrupts are also used for internal hardware interrupts. !! So we have to re-program
the 8259 interrupt controller, which is not at all boring.

153
154 mov al, # 0x11 ! Initialization sequence
! 0x11 represents the initialization command start, is ICW1 command word, represent the edges! Edge

trigger, even multi-chip 8259, the last to be sent ICW4 command word.

155 out # 0x20, al ! Send it to 8259A-1! 8259A sent to the master chip.
! Defined below two machine code word is directly represented by the relative jump instruction, from the prolonged action. ! 0xEB directly near jump instruction opcode with a

value of relative displacement bytes. Accordingly branch range is -127 to 127. The CPU! This relative displacement value to the EIP register to form a new valid address. At

this time, an EIP points to the next instruction to be executed. ! Number of CPU clock cycles spent executing is 7-10. 0x00eb represents a jump instruction value is 0, so it

directly! Next instruction is executed. These instructions may provide a total delay time of the CPU clock cycles 14-20. In a corresponding not illustrated as86! Instruction

mnemonics, thus directly using the Linus setup.s and some machine code assembler to represent such instructions. Further,! Number of clock cycles per a NOP is three, and

therefore the delay to achieve the same effect requires 6-7 NOP instructions.

156 . word 0x00eb, 0x00eb ! Jmp $ + 2, jmp $ + 2 ! '$' Indicates the address of the current instruction,

157 out # 0xA0, al ! And to 8259A-2 ! Then sent to the 8259A from the chip.

158 . word 0x00eb, 0x00eb


159 mov al, # 0x20 ! Start of hardware int's (0x20)
160 out # 0x21, al ! Send ICW2 main chip command word, starting interrupt number to send odd addresses.

161 . word 0x00eb, 0x00eb


162 mov al, # 0x28 ! Start of hardware int's 2 (0x28)
163 out # 0xA1, al ! ICW2 command word sent from the chip, the chip interrupt number from the start.

164 . word 0x00eb, 0x00eb


165 mov al, # 0x04 ! 8259-1 is master
166 out # 0x21, al ! ICW3 command word sent to the master chip, the master chip from the chip even IR2 INT.

167 . word 0x00eb, 0x00eb ! See instructions after the code list.

168 mov al, # 0x02 ! 8259-2 is slave


169 out # 0xA1, al ! Command sent from the chip ICW3 word denotes the bond from the core chip to the main INT! IR2

pins on the chip.

170 . word 0x00eb, 0x00eb


171 mov al, # 0x01 ! 8086 mode for both
172 out # 0x21, al ! Send master command word chip ICW4. 8086 model;! EOI ordinary manner, commands to be sent

to reset. Initialization is complete, the chip is ready.

173 . word 0x00eb, 0x00eb


174 out # 0xA1, al ! Send command word from the chip ICW4, the contents above.

175 . word 0x00eb, 0x00eb


176 mov al, # 0xFF ! Mask off all interrupts for now
177 out # 0x21, al ! Shielded all the main chip interrupt request.

178 . word 0x00eb, 0x00eb


179 out # 0xA1, al ! Shielded from all chip interrupt request.

180 181 ! Well, that certainly was not fun :-(. Hopefully it works, and we do not

182 ! Need no steenking BIOS anyway (except for the initial loading :-).
183 ! The BIOS-routine wants lots of unnecessary data, and it's less

--64--
3.4 setup.s program

184 ! "Interesting" anyway. This is how REAL programmers do it.


185 !
186 ! Well, now's the time to actually move into protected mode. To make
187 ! Things as simple as possible, we do no register set-up or anything,
188 ! We let the gnu-compiled 32-bit programs do that. We just jump to
189 ! Absolute address 0x00000, in 32-bit protected mode.
!! Well, of course the above paragraph boring, hope that this will work, but we no longer need the tedious BIOS (in addition to the initial load !! ☺ .

BIOS routine requires a lot of unnecessary data, and it's not at all disappointed. That was the "real" !! programmers do.

190
! Here is set to enter the 32-bit protected mode. First load machine status word (lmsw-Load Machine Status Word), also known as! Control registers CR0, bit 0 set to 1

which causes the CPU to operate in protected mode.

191 mov ax, # 0x0001 ! Protected mode (PE) bit! Protected mode bit (PE).
192 lmsw ax ! This is it!! So load machine status word!
193 jmpi 0,8 ! Jmp offset 0 of segment 8 (cs)! Skip to paragraph 8 cs, 0 offset.
! We have moved to a system module 0x00000 place to start, so here is offset address 0. Section herein! 8 has a value in the protected mode segment selector, and

for selecting and descriptor table descriptor table entry and the privilege level required. ! Segment selector is 16 bits (2 bytes); privilege level represented by bits 0-3

0-1 requested, linux operating system uses only two: 0 (system) and 3 (user level)! ; 2 bits for selecting a global descriptor table (0) or a local descriptor table (1);! bit

3-15 is the index of the descriptor table entry, select the first several descriptors indicated. Therefore, the segment selector! 8 (0b0000,0000,0000,1000) indicating a

request privilege level 0, using the first term in the global descriptor table, the indicated! 0 is the base address of the code (see row 209), so here instruction will jump

to execute the code in the system.

194 195 ! This routine checks that the keyboard command queue is empty

196 ! No timeout is used - if this hangs there is something wrong with


197 ! The machine, and we probably could not proceed anyway.
! The following routine checks keyboard command queue is empty. Do not use this method timeout - if this crash, then the PC has a

problem, we have no way to deal with anymore!.

! Only when the input buffer is empty (Status Register Bit 2 = 0) can be a write command.
198 empty_8042:
199 . word 0x00eb, 0x00eb ! This is the two machine code jump instruction (jump to the next one), is equivalent to the operation delay time and space.

200 in al, # 0x64 ! 8042 status port! Reading AT keyboard controller status register.
201 test al, # 2 ! Is input buffer full?! Test position 2, the input buffer is full?
202 jnz empty_8042 ! Yes - loop
203 ret
204 205 gdt:! described at the beginning of the global descriptor table. A plurality of descriptor table descriptor is 8 bytes long consisting of items.

! Here are three descriptor entries. Item 1 useless (line 206), but must exist. Item 2 is a system code segment! Descriptor (lines 208-211),

item 3 is a system data descriptor (lines 213-216). Each descriptor specifically! Meaning Description see list later.

206 . word 0,0,0,0 ! Dummy! The first one descriptor, do not.


207 ! Here gdt offset table is 0x08, when loaded code segment register (segment selector), using this offset value.
208 . word 0x07FF ! 8Mb - limit = 2047 (2048 * 4096 = 8Mb)
209 . word 0x0000 ! Base address = 0
210 . word 0x9A00 ! Code read / exec
211 . word 0x00C0 ! Granularity = 4096, 386
212 ! Here gdt offset table is 0x10, when loading data segment register (e.g., ds, etc.), using the offset value.
213 . word 0x07FF ! 8Mb - limit = 2047 (2048 * 4096 = 8Mb)
214 . word 0x0000 ! Base address = 0
215 . word 0x9200 ! Data read / write
216 . word 0x00C0 ! Granularity = 4096, 386
217 218 idt_48:

--65--
3.4 setup.s program

219 . word 0 ! Idt limit = 0


220 . word 0,0 ! Idt base = 0L
221 222 gdt_48:

223 . word 0x800 ! Gdt limit = 2048, 256 GDT entries! 2k byte length of the global table, each of 8
bytes as a descriptor entry! Table so the CCP 256 may have.

224 . word 512 + gdt, 0x9 ! Gdt base = 0X9xxxx


! 4 bytes constituting the linear memory address: 0x0009 << 16 + 0x0200 + gdt i.e.
0x90200 + gdt (i.e., offset in this block, the 205 OK!).
225 226 .text

227 endtext:
228 .data
229 enddata:
230 .bss
231 endbss:

3.4.3 Other Information

In order to obtain the basic parameters of the machine, this program repeatedly calls BIOS Interrupt, and has been involved with some of the operations of the hardware

port. The following briefly describes the procedure used to BIOS Interrupt calls, and A20 Reasons address line problems were explained on the last-mentioned Intel 32 Bit protected

mode problem.

3.4.3.1 The current memory image

in setup.s After the execution, the system module system It is moved to a physical address 0x0000 At the beginning, and from 0x90000 The storage system at some basic

parameters of the kernel will be used, as shown in a schematic 3-3 Fig.

data
Temporary global descriptor table
module setup.s
(Gdt)

0x90200
system parameters The original program is

segment descriptor 0x90000 overwritten bootsect.s

Library module (lib)

Memory management module (mm)

codes setup.s code

Kernel module (Kernel)


system program

main.c program

head.s program

0x00000

Map 3-3 setup.s After completion of the program memory schematic procedure

--66--
3.4 setup.s program

In this case there are three temporary global descriptor table, the first one ( NULL ) Without the other two are the code segment and data segment descriptors. They point to

the start of the system module, i.e. the physical address 0x0000 Place. So that when setup.s The last instruction is executed ' jmp 0,8 ' (First 193 When the line), it will jump head.s At

the beginning of the program to continue execution. This instruction is' 8' Segment selector is used to specify a desired item descriptors used herein means gdt The code segment. ' 0

' Is the symbol described in item offset value specific code.

3.4.3.2 BIOS Video interrupt 0x10

Here procedures used in the above description ROM BIOS Video interrupt several sub-function calls.

A. Get display card information (other auxiliary function selection):

table 3 - 2 Obtain Display card information (function number: ah = 0x12 , bh = 0x10 )

Input / return information register Description

ah Function number = 0x12 Obtain card information


Enter information
bh Sub-function number = 0x10 .

Video Status:

0x00 - Color mode (the video hardware I / O Port base address 0x3DX );
bh
0x01 - Monochrome mode (the video hardware I / O Port base address 0x3BX ); NOTE: wherein the

port address X Value can be 0 - f .

Installed memory size:


bl
00 = 64K, 01 = 128K, 02 = 192K, 03 = 256K

Characteristics of the connector bit

information: Description of Bits

0 Characteristic line 1 ,status 2 ;

ch 1 Characteristic line 0 ,status 2 ;

2 Characteristic line 1 ,status 1 ;

3 Characteristic line 0 ,status 1 ;

4-7 Not used (as 0)

Video switch setting information:

returned messages Description of Bits

0 switch 1 shut down;

1 switch 2 shut down;

2 switch 3 shut down;

3 switch 4 shut down;

4-7 Unused. original EGA / VGA Switch

settings:
cl
0x00 MDA / HGC ;

0x01-0x03 MDA / HGC ;

0x04 CGA 40x25 ;

0x05 CGA 80x25 ;

0x06 EGA + 40x25 ;

0x07-0x09 EGA + 80x25 ;

0x0A EGA + 80x25 monochrome;

0x0B EGA + 80x25 monochrome.

--67--
3.4 setup.s program

3.4.3.3 The basic hard disk parameter table ( " INT 0x41 ")

Interrupt vector table, int 0x41 Interrupt vector location ( 4 * 0x41 = 0x0000: 0x0104 ) Not interrupt program address is stored, but the first hard disk basic parameters of

the table. for 100% Compatible BIOS , Here kept the first address array of hard disk parameter table

F000h: E401h . The second hard disk parameter table base address stored in the entry int 0x46 Interrupt vector at the position.

table 3 - 3 The basic parameters of the hard disk information table

Displacement size English Name Description

0x00 word cyl Number of cylinders

0x02 byte head Number of heads

0x03 word The write current begins to decrease cylinder (only PC XT Use, the other for 0)

0x05 word wpcom Before beginning to write pre-compensation cylinder number (multiply 4 )

0x07 byte maximum ECC The burst length (only XT Use, the other for 0 )

Control byte (the drive selection step) bits 0

Unused

Place 1 Reserved ( 0) ( shut down IRQ)

Place 2 Allow reset

0x08 byte ctl Place 3 If the number of heads greater than 8 The home 1

Place 4 Unused ( 0)

Place 5 If the number of cylinders + 1 FIG bad area at the manufacturer, then set 1

Place 6 Ban ECC Retry

Place 7 Forbidden try again.

0x09 byte Standard timeout value (only XT Use, the other for 0 )

0x0A byte Formatting timeout value (only XT Use, the other for 0 )

0x0B byte Drive timeout value detector (only XT Use, the other for 0 )

0x0C word lzone Head-landing (stop) cylinder number

0x0E byte sect The number of sectors per track

0x0F byte Reservations.

3.4.3.4 A20 Address line problem

1981 year 8 month, IBM The company first introduced the personal computer IBM PC in use CPU Yes Intel 8088 . In this microcomputer the address line only 20 root( A0 -

A19) . At the time memory RAM Only a few hundred KB Or less 1MB Time, 20 Address lines sufficient to address the memory. Its highest address can be addressed 0xffff: 0xffff , That

is 0x10ffef . For beyond 0x100000 (1MB) The default addressing address to encircle 0x0ffef . when IBM Company 1985 Was introduced AT Machine when using Intel 80286 CPU ,have

twenty four Address lines, the maximum addressable 16MB And with a 8088 Fully compatible real-mode operation mode. However, in the address value exceeds 1MB

When it does not like 8088 Achieved as address for addressing surround. But then there are already some programs that use this mechanism to work around the

address. In order to achieve full compatibility, IBM It invented a switch used to enable or disable 0x100000 Address bit. Because at the time 8042 Just idle port pin on the

keyboard controller (output port P2 Pin P21 ), So we use the pin as the address bit control AND gate. The signal to be known A20 . If it is zero, then the bit 20 And the

above address are cleared. In order to achieve compatibility.

Because when the machine is started, the default condition, A20 Address lines is prohibited, so the operating system must use the appropriate method to open it. However,

due to a variety of different compatible chip sets used to do this but it is very troublesome. Thus typically select several control methods.

Correct A20 Common methods of controlling the signal line is provided by the keyboard controller port value. here setup.s program( 138-144

Row) that the use of the typical control. For some other compatible PC can also be used for other ways to do A20 Control line.

--68--
3.4 setup.s program

Some operating systems will A20 And prohibiting the opening part of the standard in the conversion process is performed between a real mode and a protected mode of

operation. Because of the speed controller keyboard is very slow, so you can not use the keyboard controller A20 Line to operate. For this reason the introduction of a

A20 Fast door options ( Fast Gate A20) It uses I / O port 0x92 To deal with A20 A signal line, avoiding the use of slow keyboard controller operation. For free system can

only use the keyboard controller 0x92 Control port, but that port may also be compatible with other devices (such as a graphics chip) on a computer used, resulting in

system errors.

Another way is by reading 0xee Port to open A20 The signal line, the port will write ban A20 A signal line.

3.4.3.5 8259 Interrupt Controller Chip

8259A A programmable interrupt controller chip, each piece can manage 8 Interrupt sources. By cascading multiple sheet management can constitute up 64 System

interrupt vectors. in PC / AT Series compatible, the use of the two 8259A Chip, a total of management 15 Level interrupt vectors. Which is shown schematically in Figure cascaded 3-4

Fig. From which the chips INT Pin is connected to the main chip IR2 Pin on. the Lord 8259A Chip is the port address 0x20 From chip 0xA0 .

clock IRQ0 IR0 IR1


keyboard IRQ1 INT INTR
connected with the serial IR2 IR3 8259A
port 2 IRQ3 int IRQ2 1 IR4 main sheet CPU
IRQ4 serial parallel IR5 IR6 IR7
interface 2 IRQ5 floppy Data D7-D0
IRQ6
parallel port 1 IRQ7

Address 0x20-0x3f A0
CS
CAS2-0

Real-time clock IRQ8 IR0 CAS2-0


INT0AH IRQ9 Reserved IR1 INT
IRQ10 Reserved IRQ12 IR2 IR3 8259A
mouse IRQ11 PS2 hard IR4 from sheet
disk coprocessor IRQ13 IR5 IR6 IR7
IRQ14 IRQ15 reserved

Address 0xA0-0xbf A0
CS

Map 3-4 PC / AT Computer cascading style 8259 Control System

Under the control of the bus controller, the chip may be in a programmed state and an operating state. Programming status is CPU use IN or OUT Instructions 8259A Chip

initial programming state. Once the initial programming, i.e. chips into operation, this device has to respond to the interrupt request by the external apparatus at any time ( IRQ0 -

IRQ15 ). By interrupting the arbitration select the chip will select the current highest priority interrupt request as an interrupt service objects, and by CPU Pin INT Notice CPU The

arrival of external interrupt requests, CPU After the response, the data bus from the chip D7-D0 The current service object programmed interrupt number sent, CPU Thus obtaining

the corresponding interrupt vector values, and execute the interrupt service routine.

in Linux Kernel interrupt number, the hardware interrupt signal from the corresponding int 32 ( 0x20 ) Started ( int 0 - int 31 For

CPU Trap interrupt), that is the interrupt number range int32 - int 47 .

3.4.3.6 Intel CPU 32 Bit protected mode of operation

Intel CPU Generally it can operate in two modes, i.e., real address mode and protected mode. Early Intel CPU ( 8088/8086 ) Only work in real mode, you can

only run a single task at a time. for Intel 80386 More chip can also run 32 Under-bit protected mode. In protected mode can support multi-tasking; support 4G Physical

memory; support virtual memory; memory support page

--69--
3.4 setup.s program

Management and stage management; support for privilege level.

While running in protected mode mechanism is understanding Linux An important basis for the kernel, but due to limited space, a brief introduction of their works can

reference the appendix. But still recommended for beginners can be listed on the books after the book, make a careful study. To really understand setup.s The following

procedures and head.s Role of a program, at least first understand the segment selector, and descriptor 80x86 The page table addressing mechanism.

3.4.3.7 Memory management registers

Intel 80386 CPU Have 4 Register control data structure used to locate the segment memory management:

GDTR ( Global Descriptor Table Register ) Global descriptor table register;

LDTR ( Local Descriptor Table Register ) Local descriptor table register; These registers descriptor table to point GDT with LDT A detailed

description of these two tables, see the Appendix.

IDTR ( Interrupt Descriptor Table Register ) Interrupt Descriptor Table Register; interrupt vector points to this register process (handler) Table ( IDT ) Entry

point. Processing all interrupt entry address information is stored in the descriptor table entry.

TR ( Task Register ) Task register;


The handler definition points to the current task register (process) of the desired information, i.e. the data structure of the task task {} .

3.4.3.8 Control register

Intel 80386 Total control register 4 One, named CR0 , CR1 , CR2 , CR3 . These registers can only be adopted by the system program MOV Instruction

accesses. See Fig. 3-5 Fig.

31 twenty three 15 7 0

Page directory base address register Reserved


CR3
Page Directory Base Register (PDBR) Reserved

Page abnormalities linear address Page


CR2
Fault Linear Address

Reserved
CR1
Reserved

P Reserved E T E M P

G Reserved T S M P E CR0

Map 3-5 Control register structure

Control register CR0 Containing the entire system control flags that control or indicating the operating state or condition of the entire system. among them:

PE - Protected Mode open position ( Protection Enable , Bit 0 ). If this bit set, it will cause the processor to start running in protected mode.

MP - Coprocessor existence flag ( Math Present , Bit 1 ). For control WAIT Function instruction to run with the co-processing.

EM - Simulation Control ( Emulation , Bit 2 ). Indicates whether the need for emulation coprocessor.

TS - Task switching ( Task Switch , Bit 3 ). Whenever a task switch processor will set this bit and the test bit coprocessor instructions explained

before.

ET - Extension type ( Extention Type , Bit 4 ). This bit indicates the type of co-processor system contained (YES 80287

still is 80387 ).
PG - Paging operations ( Paging , Bit 31 ). This bit indicates whether the page tables using the linear address into a physical address. See 10 Chapter description of the

paged memory management.

CR2 For PG When set page process abnormal operation. CPU Linear address that caused the error will be stored in the register.

CR3 Also in PG When the flag is set to function. This register is CPU Designated page table directory of the current task running used.

--70--
3.5 head.s program

3.5 head.s program

3.5.1 Functional Description

head.s After the program is compiled, it can be connected system The beginning of the front part of the module, which is why called the head ( head)

The reason the program. From here, the kernel is completely run in protected mode. heads.s Previous assembler syntax is different, using the AT & T The assembly language

format, and requires the use GNU of gas with gld2 Compile connections. Therefore, please note the direction of the code are assigned from left to right.

This program is actually an absolute address in memory 0 At the place to start. The function of this program is relatively simple. First, each data segment register is loaded,

reset the interrupt descriptor table idt A total of 256 Item, and each entry point to a dummy only reported error interrupt routine. Then reset the global descriptor table gdt .

Subsequently physical addresses 0 versus 1M SUMMARY compared at the beginning of the detection A20 Whether the address line has really turned on (if not open, it is higher

than in access 1Mb When physical memory address CPU Actual only access ( IP MOD 1Mb ) Content at the address), if detected, they discovered not turned on, then enter an infinite

loop. The program then test PC Machine is comprising a math coprocessor chip ( 80287 , 80387 Or compatible chips), and the control register CR0 Setting the corresponding flag bit.

Then set the paging mechanism to handle memory management, page directory table on the absolute physical address 0 At the beginning (which is also the physical memory

location of the program, this program would therefore be overwritten), placed immediately behind the addressable co 16MB Memory 4 Page table, and set their entries respectively.

Finally return instruction previously placed in the stack / init / main.c Entry address of the program pops up, to run main () program.

3.5.2 Code comments

program 3-3 linux / boot / head.s

1/*
2 * Linux / boot / head.s
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * Head.s contains the 32-bit startup code.


9*
10 * NOTE !!! Startup happens at absolute address 0x00000000, which is also where
11 * The page directory will exist. The startup code will be overwritten by
12 * The page directory.
13 * / / *

* head.s 32 containing the startup code.

* Note !!! 32 boot code from the beginning of the absolute address 0x00000000, here also is where the page directory will exist,

* So here's startup code will be overwritten page directory.


*/
14 .text
15 .globl _idt, _gdt, _pg_dir, _tmp_floppy_area
16 _pg_dir: # Page directory will be stored here.
17 startup_32: # Lines 18-22 each data set segment registers.
18 movl $ 0x10,% eax # For the GNU assembler, each number you want to direct '$' start, otherwise it is an address.

2 In the current Linux operating systems, gas and gld, respectively, have been renamed as and ld.

--71--
3.5 head.s program

# Each register name must begin with '%', eax ax represents a 32-bit register.

# Note again !!! here already in the 32-bit mode of operation, so there's not a $ 0x10 0x10 to address each load
# Segment register, it is now in fact, is an offset value in a global descriptor table, or more correctly, is described in a descriptor table entry

# The selectors. For a description of selectors under setup.s See description in the row 193. Here the meaning is requesting $ 0x10

# Privilege level 0 (bits 0-1 = 0), select the global descriptor table (bit 2 = 0), the selection list item 2 (bits 3-15 = 2). It just means that

# Descriptor entry to the data table. (See specific numerical descriptor 212, 213 in front of the line setup.s)
# The following is the meaning of the code: Set ds, es, fs, gs in the selector is configured setup.s data segment (global descriptor table

# The item 2) = 0x10, and the stack is placed in the array region stack_start user_stack point, and then use this program
# New interrupt descriptor table and a global table section described later defined. The new global segment description table and the initial content are substantially setup.s

# Like, only modified into a long segment limit from 16MB 8MB. stack_start defined in kernel / sched.c, 69 rows. It is the point
# An array of pointers to the end of the long user_stack.

19 mov% ax,% ds
20 mov% ax,% es
twenty one mov% ax,% fs
twenty two mov% ax,% gs
twenty three lss _stack_start,% esp # It represents _stack_start ss: esp, set the system stack.
# stack_start defined in kernel / sched.c, 69 rows.
twenty four call setup_idt # Call to set the interrupt descriptor table subroutine.

25 call setup_gdt # Set global descriptor table calling subroutine.


26 movl $ 0x10,% eax # reload all the segment registers
27 mov% ax,% ds # after changing gdt. CS was already
28 mov% ax,% es # reloaded in 'setup_gdt'
29 mov% ax,% fs # Since modifications of the GDT, it is necessary to reload all segment registers.

30 mov% ax,% gs # The code segment register CS had been reloaded in the setup_gdt.
# Since the section of indefinite length into a segment descriptor provided from the Program 16MB 8MB setup.s program (see lines 208-216 setup.s

# And later in the program lines 235-236), so here again performed for all segment register load operation is necessary.
# Further, by using the observation bochs track, if the CS does not loaded again performed, then the executed code segment to the CS 26 rows are not visible

# Section of indefinite length or 8MB. It would appear to be reloaded CS, but in the actual test results show that CS machine has been loaded before.

31 lss _stack_start,% esp


# 32-36 lines used to test whether A20 address line has been opened. The method used is a write to any memory location 0x000000

# A value, and then look at memory address 0x100000 (1M) is whether at this value. If you have been the same, then it has been
# Compare it, that is an infinite loop, crash. A20 represents the address strobe line is not, the result can not use the kernel memory above 1M.

32 xorl% eax,% eax


33 1: incl% eax # check that A20 really IS enabled
34 movl% eax, 0x000000 # loop forever if it is not
35 cmpl% eax, 0x100000
36 je 1b # '1b' represents backward (Backward) to jump to a label (33 lines).
# If '5f' indicates the forward (Forward) 5 to jump to the label.
37 / *
38 * NOTE! 486 should set bit 16, to check for write-protect in supervisor
39 * Mode Then it would be unnecessary with the "verify_area ()" -. Calls.
40 * 486 users probably want to set the NE (# 5) bit also, so as to use
41 * Int 16 for math errors.
42 * / / *

* Note! In the following program, the 486 16-bit should be set to check for write protection in Supervisor mode,
* Since then "verify_area ()" call is not required. 486, you may also want to NE (# 5) is set to
* Error math coprocessor use int 16.
*/
# The following program (43-65) for checking whether there is a math coprocessor chip. The method is a modification of the control register CR0, in

# Performing a coprocessor instruction under the assumption that the presence of the coprocessor, if an error occurs, then it indicates absence of the coprocessor chip,

# You need to set the bit coprocessor emulator EM (bit 2) CR0 is, and there is a flag MP (bit 1) to reset the coprocessor.

--72--
3.5 head.s program

43 movl% cr0,% eax # check math chip


44 andl $ 0x80000011,% eax # Save PG, PE, ET
45 / * "Orl $ 0x10020,% eax" here for 486 might be good * /
46 orl $ 2,% eax # Set MP
47 movl% eax,% cr0
48 call check_x87
49 jmp after_page_tables # Jump to the 135 line.
5051 / *

52 * We depend on ET to be correct. This checks for 287/387.


53 * / / *

* We rely on the correctness of the ET mark to detect the presence or absence of 287/387.

*/
54 check_x87:
55 fninit
56 fstsw% ax
57 cmpb $ 0,% al
58 je 1f / * No coprocessor: have to set bits * /
59 movl% cr0,% eax # If there is a forward jump to number 1, or rewrite cr0.
60 xorl $ 6,% eax / * Reset MP, set EM * /
61 movl% eax,% cr0
62 ret
63 .align 2 # Here the meaning of ".align 2" refers to the storage boundary alignment adjustment. "2" indicates the adjustments to the address of the last 2 bits are zero,

# I.e., 4-byte aligned memory address mode.


64 1: . byte 0xDB, 0xE4 / * Fsetpm for 287, ignored by 387 * / # 287 coprocessor code.
65 ret
6667 / *

68 * Setup_idt
69 *
70 * Sets up a idt with 256 entries pointing to
71 * Ignore_int, interrupt gates. It then loads
72 * Idt. Everything that wants to install itself
73 * In the idt-table may do so themselves. Interrupts
74 * Are enabled elsewhere, when we can be relatively
75 * Sure everything is ok. This routine will be over-
76 * Written by the page tables.
77 * / / *

* Below this is to set the interrupt descriptor table subroutine setup_idt

*
* Idt interrupt descriptor table 256 provided with entries, and an interrupt point ignore_int door. Then load interruption

* Descriptor Table Register (with lidt instruction). Really practical to install the door after the break. When we think of all the other places

* Then turn interrupt normal. This subroutine will be overwritten page table.
*/
# Interrupt descriptor table entry is 8 bytes, though, but in a different format in the global table, referred to as gate descriptor
# (Gate Descriptor). 0-1,6-7 its byte offset, byte selectors 2-3, 4-5 bytes are some flags.
78 setup_idt:
79 lea ignore_int,% edx # Ignore_int effective address (offset) value register edx
80 movl $ 0x00080000,% eax # The selector 0x0008 into the upper 16 bits of eax.
81 movw% dx,% ax / * Selector = 0x0008 = cs * /
# Low shift value 16 into the lower 16 bits of eax. At this point eax contains

--73--
3.5 head.s program

# Gate descriptor identifier value lower 4 bytes.


82 movw $ 0x8E00,% dx / * Interrupt gate - dpl = 0, present * /
83 # At this time, a high gate descriptor containing edx 4-byte value.

84 lea _idt,% edi # _idt interrupt descriptor table address.


85 mov $ 256,% ecx
86 rp_sidt:
87 movl% eax, (% edi) # The dumb interrupt gate descriptor is stored in the table.

88 movl% edx, 4 (% edi)


89 addl $ 8,% edi # edi points to the next table.
90 dec% ecx
91 jne rp_sidt
92 lidt idt_descr # Loading the interrupt descriptor table register value.

93 ret
9495 / *

96 * Setup_gdt
97 *
98 * This routines sets up a new gdt and loads it.
99 * Only two entries are currently built, the same
100 * Ones that were built in init.s. The routine
101 * Is VERY complicated at two whole lines, so this
102 * Rather long comment is certainly needed :-).
103 * This routine will beoverwritten by the page tables.
104 * / / *

* Set global descriptor table entry setup_gdt

* This subroutine is provided a new global descriptor table GDT, and load. At this point only creates two entries with the former

* The same surface. The subroutine only two lines, "very" complex, so of course take so long to annotate ☺ .
* This subroutine will be overwritten page table.

*/
105 setup_gdt:
106 lgdt gdt_descr # Load Global Descriptor Table Register (content has been set, see lines 234-238).
107 ret
108109 / *

110 * I put the kernel page tables right after the page directory,
111 * Using 4 of them to span 16 Mb of physical memory. People with
112 * More than 16MB will have to expand this.
113 * /
/ * Linus kernel memory page tables placed directly after the page directory, the use of four tables addressed 16 Mb of physical memory.

* If you have more than 16 Mb of memory, we need to be expanded changed here.


*/
# Each page table is 4 Kb bytes long (a page memory), and each page table entry requires 4 bytes, a page table can store a total of
# 1024 entries. If a page table entry address 4 Kb address space, a page table can of 4 Mb of physical memory addressing.
# Format page table entry is: bits 0-11 store a number of flags before items, such as whether the memory (P 0 bit), write permission (R / W bit 1),

# Normal users or users using the super (U / S bit 2), with or without modification (if dirty) (D 6 bits) and the like; bits 12-31 are the entry

# Page frame address, physical memory is used to indicate a starting address.

114 .org 0x1000 # Starts at offset 0x1000 is a first page table (offset 0 will be stored at the beginning of the page table directory).

115 pg0:
116117 .org 0x2000

118 pg1:
119

--74--
3.5 head.s program

120 .org 0x3000


121 pg2:
122123 .org 0x4000

124 pg3:
125 126 .org 0x5000
# Defined below memory block starting at offset 0x5000.
127 / *
128 * Tmp_floppy_area is used by the floppy-driver when DMA can not
129 * Reach to a buffer-block. It needs to be aligned, so that it is not
130 * On a 64kB border.
131 * /
/ * When the DMA (direct memory access) can not access the buffer block, memory block following tmp_floppy_area

* Available on the floppy disk driver. Its address needs to adjust the alignment, so as not to cross the border 64kB.

*/
132 _tmp_floppy_area:
133 . fill 1024,1,0 # 1024 Total retention, each 1 byte, the value 0 is filled.
134
# Below these stack operation (pushl) used to call /init/main.c program and return preparation.
# The first three values ​should be 0 stack are envp, argv argc pointer and value, the main () is not used.
# Push operation line 139 is an analog of the first return address stack operation invoked main.c program, if
# When main.c program really quit, it will return to the label L6 continue execution at here, that is an endless loop.
# 140 rows main.c address onto the stack, so that, in the set page process (setup_paging) after the end of
# Performing 'ret' main.c program will address popped off the stack when the return instruction, and to execute the program went main.c.

135 after_page_tables:
136 pushl $ 0 # These are the parameters to main :-)
137 pushl $ 0 # These are the parameters (refer to init / main.c) calls the main program.

138 pushl $ 0 # Wherein the '$' symbol indicates that this is an immediate operand.

139 pushl $ L6 # return address for main, if it decides to.


140 pushl $ _main # '_Main' is the internal representation of the compiler of the main.
141 jmp setup_paging # Go to line 198.
142 L6:
143 jmp L6 # main should never return here, but
144 # just in case, we know what happens.
145 146 / * This is the default interrupt "handler" :-) * /

/ * The following is the default interrupt "vector handle" ☺ * /

147 int_msg:
148 . asciz "Unknown interrupt \ n \ r" # Definition string "Unknown interrupt (carriage return)."
149 .align 2 # 4-byte aligned memory address mode.
150 ignore_int:
151 pushl% eax
152 pushl% ecx
153 pushl% edx
154 push% ds # Please note here! ! ds, es, fs, gs, although other 16-bit registers, but the stack
# In the stack 32 it will still form, i.e., take 4 bytes of stack space.
155 push% es
156 push% fs
157 movl $ 0x10,% eax # Segment selector is set (make ds, es, fs gdt point data segment table).
158 mov% ax,% ds
159 mov% ax,% es
160 mov% ax,% fs
161 pushl $ int_msg # The call printk function parameters pointer (address) stack.

--75--
3.5 head.s program

162 call _printk # The function of /kernel/printk.c.


# '_Printk' printk after compilation module internal representation.
163 popl% eax
164 pop% fs
165 pop% es
166 pop% ds
167 popl% edx
168 popl% ecx
169 popl% eax
170 iret # Returning (pushed onto the stack when the CPU interrupt call flag register (32) also eject value).
171 172
173 / *

174 * Setup_paging
175 *
176 * This routine sets up paging by setting the page bit
177 * In cr0. The page tables are set up, identity-mapping
178 * The first 16MB. The pager assumes that no illegal
179 * Addresses are produced (ie> 4Mb on a 4Mb machine).
180 *
181 * NOTE! Although all physical memory should be identity
182 * Mapped by this routine, only the kernel page functions
183 * Use the> 1Mb addresses directly. All "normal" functions
184 * Use just the lower 1Mb, or the local data space, which
185 * Will be mapped to some other place - mm keeps track of
186 * That.
187 *
188 * For those with more memory than 16 Mb - tough luck I've.
189 * Not got it, why should you :-) The source is here. Change
190 * It (Seriously -.. It should not be too difficult Mostly
191 * Change some constants etc. I left it at 16Mb, as my machine
192 * Even can not be extended past that (ok, but it was cheap :-)
193 * I've tried to show which constants to change by having
194 * Some kind of marker at them (search for "16Mb"), but I
195 * Will not guarantee that's all :-()
196 * / / *

* This subroutine cr0 by setting a flag in the control register (PG 31 bits) to start the paging processing functions on the memory,

* And set the contents of each page table entries to map the identity prior to 16 MB of physical memory. Pager assumes no illegal

* Address mapping (i.e., the memory address is greater than 4Mb provided on the machine only 4Mb).

* note! Despite all the physical address should be the identity map of the routine, but only the kernel page management functions can

* Directly> 1Mb of address. All "normal" function uses the address space just below 1Mb, or using local data
* Space, address space will be mapped to some other place to go - mm (memory management program) will manage these things.

* For those guys have more than 16Mb of memory - so lucky, I have not, why do you have ☺ . In the code
* Here, modify it now. (In fact, this is not too difficult. Usually only modify some constants. I set it
* To 16Mb, because my machine again how expansion can not even exceed this limit (of course, my machine is very cheap ☺ ).
* I have to give the place needs to be changed by setting certain flag (search for "16Mb"), but I can not guarantee for these
* Change on the line).
*/
# In the physical memory address 0x0 storage at the beginning of a page directory table and four page table. Page directory table is common to all processes in the system, and

# Here four page table is part of the kernel only. For the new process, the system will apply the page stored in its main memory page table area.

# 1 memory page length is 4096 bytes.


197 .align 2 # 4-byte memory address boundary-aligned manner.

--76--
3.5 head.s program

198 setup_paging: # First five memory (a page table directory + 4) Clear


199 movl $ 1024 * 5,% ecx / * 5 pages - pg_dir + 4 page tables * /
200 xorl% eax,% eax
201 xorl% edi,% edi / * Pg_dir is at 0x000 * /
# 0x000 from the start page directory address.

202 cld; rep; stosl


# The following four settings page table of contents entries, because we (the kernel) There are four page table so just set four.

# As the structure and the structure of the page table entry page directory entry, a 4 bytes. See the description in the row 113 above.

# "$ Pg0 + 7" represents: 0x00001007, Item 1 of the table of contents.


# The address of a page table resides = 0x00001007 & 0xfffff000 = 0x1000;
# Attribute flag on a page table = 0x00001007 & 0x00000fff = 0x07, indicates the presence of the page, the user can read and write.

203 movl $ pg0 + 7, _pg_dir / * Set present bit / user r / w * /


204 movl $ pg1 + 7, _pg_dir + 4 / * --------- "" --------- * /
205 movl $ pg2 + 7, _pg_dir + 8 / * --------- "" --------- * /
206 movl $ pg3 + 7, _pg_dir + 12 / * --------- "" --------- * /
# The following six lines filled out in all four page table entries, a total of: 4 (page tables) * 1024 (item / page table) = 4096 (0 - 0xfff),
# I.e., physical memory can be mapped 4096 * 4Kb = 16Mb.

# Each content is: the physical memory page address + sign (here was 7) the current item is mapped.
# The method used is the last item fill by reverse order from the last page of the table. Last entry in a page table page table
# Position 1023 * 4 = 4092. Therefore, the position of the last page of the last item is $ pg3 + 4092.
207 movl $ pg3 + 4092,% edi # Edi last item on the last page.
208 movl $ 0xfff007,% eax / * 16Mb - 4096 + 7 (r / w user, p) * /
# Finally, an address corresponding to the physical memory pages are 0xfff000,

# Plus attribute flags 7, that is 0xfff007.


209 std # Direction bit, edi decrement value (4 bytes).
210 1: stosl / * Fill pages backwards - more efficient :-) * /
211 subl $ 0x1000,% eax # Each fill a physical address value minus 0x1000.
212 jge 1b # If less than 0 then the whole Tianxie good.
# Set the page directory base register value cr3, and pointing to the page directory table.

213 xorl% eax,% eax / * Pg_dir is at 0x0000 * / # page directory table at 0x0000.
214 movl% eax,% cr3 / * Cr3 - page directory start * /
# The startup process using paging (PG cr0 the flag, 31 bits)
215 movl% cr0,% eax
216 orl $ 0x80000000,% eax # Add PG flag.
217 movl% eax,% cr0 / * Set paging (PG) bit * /
218 ret / * This also flushes prefetch-queue * /
# After changing the paging process flag transfer instruction requires a refresh instruction prefetch queue, here is the return instruction ret.

# Another function of the return instruction is the address of the main program pop the stack, and the program starts running /init/main.c.

# This program this really over.


219 220 .align 2
# 4-byte memory address boundary-aligned manner.

221 .word 0
222 idt_descr: # The next two lines is 6-byte instruction operand lidt: length, base address.
223 . word 256 * 8-1 # idt contains 256 entries
224 . long _idt
225 .align 2
226 .word 0
227 gdt_descr: # The next two lines is 6-byte instruction operand lgdt: length, base address.
228 . word 256 * 8-1 # so does gdt (not that that's any # Not note.
229 . long _gdt # magic number, but it works for me: ^)
230231
. align 3 # 8-byte memory address boundary-aligned manner.

232 _idt: . fill 256,8,0 # idt is uninitialized # 256 items, each 8-byte, fill zero.

--77--
3.5 head.s program

233
# Global table. The first four entries are empty (no), code segment, the data segment descriptors, descriptor system, wherein
# Linux system descriptor no use for it. Back with space for 252 for placing the created task
# Local descriptors (the LDT) and the corresponding task state segment TSS descriptor.

# (0-nul, 1-cs, 2-ds, 3-sys, 4-TSS0, 5-LDT0, 6-TSS1, 7-LDT1, 8-TSS2 etc ...)
234 _gdt: . quad 0x0000000000000000 / * NULL descriptor * /
235 . quad 0x00c09a0000000fff / * 16Mb * / # 0x08, the maximum length of the kernel code segment 16M.

236 . quad 0x00c0920000000fff / * 16Mb * / # 0x10, the maximum length of the kernel data section 16M.

237 . quad 0x0000000000000000 / * TEMPORARY - do not use * /


238 . fill 252,8,0 / * Space for LDT's and TSS's etc * /

3.5.3 Other Information

3.5.3.1 After the end of program execution memory image

head.s After the implementation of the program, it has officially completed the setup memory page directory and page tables, and re-set the actual use of the kernel

interrupt descriptor table idt And a global descriptor table gdt . It also opened up for the floppy driver 1KB Byte buffer. at this time system

See detail image module in memory 3-6 Fig.

lib module code module code

fs mm kernel module code

module code main.c program

code Global Descriptor Table

gdt (2k) interrupt descriptor

table idt (2k)

system module
head.s floppy part of the code

buffer (1k) memory page table


0x5000
head.s Code pg3 (4k) of memory page table 0x4000
0x3000
pg2 (4k) of memory page table
0x0000
pg1 (4k) of memory page table
0x1000
0x2000
pg0 (4k) of memory page

directory table (4K)

Map 3-6 system Schematic image module in memory

3.5.3.2 Intel 32 Bit protected operating mechanism

The key to understanding this process is to really understand Intel 386 32 Bit protected mode operation mechanism, but also continue to read the rest of the following

procedures are necessary. In order to 8086 CPU compatible, 80x86 Protected mode is more complex to be treated. when CPU When operating in protected mode, it is the real mode

segment address as the protected mode descriptor pointers, this period is stored in the register offset value is a descriptor in the descriptor table. And the base address of the

current descriptor table is stored in the descriptor table register, a global descriptor table register as gdtr , Interrupt Descriptor Table Register door idtr , Loading these registers need

to use a dedicated instruction tables lgdt or lidt .

CPU When real mode operating mode, segment registers used to place a memory segment address (such as 0x9000 ), But this time in the segment be addressed 64KB Memory.

But when protected mode operating mode, when an address value is placed in the segment register in the memory is not specified, but rather a descriptor entry in a descriptor

table offset with respect to one of the base address of the descriptor table . at this 8 The length of the 'side' and the segment base address of the segment, and other features

described bit byte segment descriptor contains the linear address. Thus at this time the addressed memory location is coupled with the current code segment base pointer is

performed eip Value. Of course, this time addressed actual physical memory address, the need

--78--
3.5 head.s program

To page through the memory management mechanism in order to get treatment after transformation. in short, 32 Memory addressing in need Guaige Wan-bit protected mode, after

the descriptor table descriptor and memory page management is determined.

The use of different aspect, the descriptor table is divided into three types: the Global Descriptor Table ( GDT ), Interrupt Descriptor Table ( IDT ) And Local Descriptor Table

( LDT ). when CPU Running in protected mode, a time GDT with IDT Only one each, respectively, by the register GDTR

with IDTR Specify their table base. Local table can have 0-8191 One, which is the base address of the current LDTR Contents of the register specify, using

GDT In a descriptor load, i.e. LDT Also by the GDT Descriptor specified. But at a time it is also only one of which is considered active.

Generally for each task (process) using a LDT . At runtime, the program can use GDT

The current task descriptors and LDT Descriptor.


Interrupt Descriptor Table IDT Structure and GDT Similarly, in Linux It is located right in the kernel GDT Behind the table. Containing a total of 256 item

8 Byte descriptor. Each descriptor entry but the format and GDT Different, wherein the offset value is stored by a corresponding interrupt process ( 0-1 , 6-7

Bytes), which segment selector value ( 2-3 Byte) and flag ( 4-5 byte).
Map 3-7 Yes Linux In the schematic kernel memory descriptor table is used. Figure each task GDT Descriptor occupies two entries. GDT Table LDT0 Descriptor

entry is the first task (process) the local descriptor table descriptor, TSS0 The first task is a task state segment ( TSS ) Descriptor. Each LDT It contains three

descriptors, without first, second task code segment descriptor, the third task data and stack segment descriptor. when DS Segment register is a first task of

the data segment selector, DS: ESI The data in a data segment refers to the task.

DS: segment length limit

segments
data item

DS: 0 DS: ESI


register

DS segment register Data & stack code segment

descriptor task descriptors Local Descriptor Table LDT0

(NULL)

Descriptor Descriptor TSSn


LDT2 LDTn Descriptor
segment descriptor (NULL)
segment register ESI descriptor kernel code
kernel data segment
system descriptor (unused)
descriptor descriptor TSS0
TSS2 TSS1 LDT0 descriptor
Descriptor Descriptor LDT1

Global descriptor table


descriptor GDT 256

LDTR register

GDTR register CS

00000000

Map 3-7 Linux Kernel symbol table schematic description.

--79--
3.6 Summary

3.6 chapter summary

In the boot loader bootsect.s will setup.s Code and system Module is loaded into memory, and are themselves and setup.s Code into physical memory 0x90000 with 0x90200

After, the implementation of the right to put the setup program. among them system The header contains a module head.s Code.

setup The main role of the program is to use ROM BIOS The interrupt routine to get some basic parameters of the machine, and save 0x90000

Memory block beginning, the program for later use. Same time system Move down to the physical address of the module 0x00000 At the beginning, so, system

middle head.s Code in the 0x00000 At the beginning of the. Then load the base address of the descriptor table descriptor table register, is performed 32

Running in protected mode ready. Next, the interrupt control hardware reset, and finally by setting the machine control register CR0

And jump to system Module head.s The code at the beginning of the CPU enter 32 Run-bit protected mode.

Head.s The main role of the code is to initialize the preliminary interrupt descriptor table 256 Item gate descriptor, checks A20 Whether the address line has been opened,

if the test system contains a math coprocessor. Then initialize memory page table of contents, prepare work for the paged memory management. Jump to last system Initialization

program module init.c Continue execution.

The main content is described in detail in the next chapter init / main.c Function and role of the program.

--80--
4.1 Overview

The first 4 Chapter initialization procedure ( init)

4.1 Outline

In the source code of the kernel init / Only one directory main.c file. After performing system boot / Directory head.s Program will be executed after the right to main.c . The

program is not long, but it includes all the work of the kernel initialization. Therefore, when the program needs to read the code with reference to a number of other initialization

part of the program. If we can fully understand all the procedures invoked here, then after reading this chapter you should Linux Kernel have a general understanding.

From the beginning of this chapter, we will be in contact with a large number of C Program code, so the reader has some of the best C Knowledge of the language. The best

one reference book or Brian W. Kernighan with Dennis M. Ritchie Edited " C Programming Language ", the fifth chapter of the book to understand about pointers and arrays, can be

said to understand C The key language.

In comments C When the language program, in order to be distinguished from any original program notes, we use the '//' as the start comment statements. Translation

original comments about the use of its mark as a comment. For the header files included in the program (*. h ), Meaning a schematic for explanation purposes only, specific details

will be given in the comment annotation contents corresponding header sections.

4.2 main.c program

4.2.1. Functional Description

main.c Firstly, the previous program setup.s Root file system device number of system parameters and program achieved some memory global variables. These variables

indicate the memory capacity of the main memory starting address of the memory, the system has a high-speed buffer memory and an end address. If you define a virtual disk ( RAMDISK

), The main memory will be reduced appropriately. The entire memory image is shown in Figure 4-1 Fig.

Kernel virtual disk cache The primary bank

Map 4-1 Memory system schematic functional division.

FIG, also part of the cache memory and is deducted ROM BIOS Occupied part. Local disk buffer cache for temporarily storing data blocks and other devices to 1K ( 1024 )

Byte of a data block unit. The main memory area of ​memory by the memory management module mm

Manage distribution through the paging mechanism to 4K A byte memory page units. Kernel can access the data cache in freedom, but need mm You can use to

allocate memory pages.

Then, the kernel hardware initialization all aspects. It comprises a trap-door, block, character and equipment tty Including artificial settings

--81--
4.2 main.c program

The first task ( task 0 ). After all initialization is complete after setting the interrupt enable flag to enable interrupts, main () Switch to the task 0 Run. In reading these initialization

routine, it is best to follow the procedures to be invoked in-depth look into it, if it could not stand up, temporarily put off, continue to look at the next initialization call. After some

research where there is no understanding to continue the reading.

After the completion of the initialization entire kernel, the kernel will perform handover to the right of the user mode (task 0 ), That CPU From 0 Switch to the privileged

class first 3 Privilege level. at this time main.c The main program on the work of the task 0 in. The system then processes the first call to create a function fork () Create a run for init

() The child process. The whole system initialization process shown in Figure 4-2 Fig.

system initialization Process 1

Functional division and allocation cycle to load the root file system Process 2

of portions of physical memory

Setting the standard IO terminal directed to the rc

Each part of the initialization


Create a process 2 Execute shell
system, including initialization task 0

2 cycle wait for the process to exit drop out


Move to perform the task 0

Process n

Create a process 1 (init) Create a child process Setting the standard IO terminal

Idle execution pause () Wait for the process to exit the Execute shell

Exit input terminal


Task 0 (process 0)

Map 4-2 Kernel initialization process flow schematic

The program first to use the system to determine how to allocate physical memory, then calls kernel initialization function of each part separately for memory management,

interrupt handling, block and character devices, process management as well as hard and floppy disk hardware initialization process. After completion of these operations, the

various parts of the system having been in the running state. Since then the program themselves "manual" to the task 0 (process 0 ) Running, and use fork ()

Calls for the first time create a process 1 ( init process). in init The process proceeds with the application environment initialization and execution shell Login procedure. The original

process 0 Scheduling will be performed when the system is idle, then the task 0 Execution only pause () System call, and it will call the dispatch function.

in init Process, if the terminal environment is established, it will then generate a child process (process 2 ), Used to run shell program/ bin / sh . If the child process exits, the

parent process into an infinite loop, continues to generate child processes, and perform once again in this child process shell program

/ Bin / sh , While the parent process continues to wait.

Since the process of creating a new process is fully replicated by way of the parent process code and data segments are implemented, so for the first time fork ()

Creating a new process init When, in order to ensure that the new process does not process the user mode stack 0 The extra information required process 0 Do not use the

user-mode stack before creating the first new process, that required task 0 Do not call the function. Thus, in main.c The main program moves to the task 0 After the execution, the

task 0 The code fork () It can not be called a functional form. The method is implemented using a program gcc Built-in function to perform this form of system calls. See the following

procedures - twenty three Row.

By declare an inline (inline) function, the code can make gcc integrated function to the calling code. This will increase the speed of code execution, because eliminating the

overhead of a function call. In addition, if any of the actual argument is a constant, then the value is known at compile time these may not need to make all the code inline functions

are included and make the code has also been simplified.

--82--
4.2 main.c program

In addition, the task 0 middle pause () Also you need to use the function inline form definition. If the dispatcher the first implementation of the newly created process

init Then pause () The use of function calls will not have any problems. However, the kernel scheduler execution of the parent process (process 0 ) And the child process

init The order is random, creating a init There may be the first scheduling process 0 carried out. therefore pause () We must also use macros to achieve.

for Linux , All tasks are run in user mode, including many system applications, such as shell Procedures, network subsystem programs. Kernel source code lib / Library files

in a directory that is dedicated to providing support functions for the newly created process here.

4.2.2 Code comments

program 4-1 linux / init / main.c

1/*
2 * Linux / init / main.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #define __LIBRARY__ // definition of the variable is defined to include inline assembly code in unistd.h information.

8 #include <unistd.h> default directory // * .h header files that include /, then the code would not explicitly specify the location.
// if not the UNIX standard header file, you need to specify the directory where, and enclosed in double quotes. // Standard symbolic constants and

the type of file. Symbols and constants defined type, and affirms that the various functions. // If the definition of __LIBRARY__, it also contains the

system call number and inline assembly code syscall0 () and so on.

9 #include <time.h> // Time Type header. The most important definition of the function prototype tm structure and some of the relevant time.

1011 / *

12 * We need this inline - forking from kernel space will result


13 * In NO COPY ON WRITE (!!!), until an execve is executed. This
14 * Is no problem, but for the stack. This is handled by not letting
15 * Main () use the stack at all after fork (). Thus, no function
16 * Calls - which means inline code for fork too, as otherwise we
17 * Would use the stack upon exit from 'fork ()'.
18 *
19 * Actually only pause and fork are needed inline, so that there
20 * Will not be any messing with the stack from main (), but we define
twenty one * Some others too.

twenty two * /

/*
* We need following these embedded statements - created from the kernel space process (forking) will result in replication (COPY ON WRITE) when not write !!!

* Until the implementation of a execve call. This may cause problems for the stack. The method of treatment is to keep the main after () call fork () use

* Any stack. And therefore can not have function calls - meaning fork also use the embedded code, otherwise we are in () exit from the fork

* When you should use the stack.

* Actually only need to pause and fork to use inline to ensure that the main () does not mess up the stack, but we also
* It defines a number of other functions.

*/
// This program will be moved to the user mode (switching to the task 0) after the implementation of fork (), thus avoiding duplication problems in kernel space to write.

// After performing moveto_user_mode (), this program as a task 0 is running. The task is all sub 0 // creates the parent of the process. When creating the first

sub-process, task 0 stack will be copied. It is therefore desirable not to have any main.c run operations on the stack when the task at 0 // environment, so as not to

mess up the stack, so it will not mess up the stack all child processes.

--83--
4.2 main.c program

twenty three static inline _syscall0 (Int, fork )


// This is unistd.h in embedded macro code. Calling Linux in embedded assembly in the form of a system call interrupt 0x80. This interrupt is all // system call

entry. Article statement is actually int fork () system call to create a process. // syscall0 name of the last parameter 0 means no, 1 means a parameter. See include

/ unistd.h, 133 rows.

twenty four static inline _syscall0 (Int, pause ) // int pause () system call: Pause the process of execution until // receive
a signal.
25 static inline _syscall1 (Int, setup, void *, BIOS) // int setup (void * BIOS) system call, only for
// linux initialization (only to be called in this program).
26 static inline _syscall0 (Int, sync ) // int sync () system call: update the file system.
2728 #include <linux / tty.h>
// tty header file, which defines tty_io, aspects of the serial communication parameters constant.

29 #include <linux / sched.h> // scheduler header file, which defines the task_struct task structure, a first initial tasks
// The data. There are some in the form of a macro definition of the relevant descriptor parameters set and get the // embedded

assembly function procedures.

30 #include <linux / head.h> // head header file defines a simple structure segment descriptors, and several selectors constants.

31 #include <asm / system.h> // system header files. In the form of macro defines a number // description of the setting or modifier /

door interrupted embedded assembler subroutine.

32 #include <asm / io.h> // io header files. Macro assembler embedding function defined in the form io of port operation.

3334 #include <stddef.h>


// define the standard header files. Definition of NULL, offsetof (TYPE, MEMBER).

35 #include <stdarg.h> // standard parameter header. In the form of macro variables defined parameter list. Mainly explained - a
// type (va_list) and three macros (va_start, va_arg and va_end), vsprintf, // vprintf, vfprintf.

36 #include <unistd.h>
37 #include <fcntl.h> // control file header. Operable control descriptor file and constants defined symbols.
38 #include <sys / types.h> // type of header files. System defines the basic data types.

3940 #include <linux / fs.h>


// file system header files. Table structure definition file (file, buffer_head, m_inode, etc.).
4142 static char printbuf [1024];
// a static array of strings used to display the kernel cache information.

4344 extern int vsprintf ();


// send the formatted output to a string (in the kernel / vsprintf.c, 92 lines).
45 extern void init (Void); // function prototype, initialization (168 lines).
46 extern void blk_dev_init (Void); // block device initialization subprogram (kernel / blk_drv / ll_rw_blk.c, 157 lines)
47 extern void chr_dev_init (Void); // initialize character device (kernel / chr_drv / tty_io.c, 347 lines)
48 extern void hd_init (Void); // hard disk initialization program (kernel / blk_drv / hd.c, 343 lines)
49 extern void floppy_init (Void); // floppy drive initialization program (kernel / blk_drv / floppy.c, 457 lines)
50 extern void mem_init (Long start, long end ); // initialize memory management (mm / memory.c, 399 lines)

51 extern long rd_init (Long mem_start, int length); // virtual disk initialization (kernel / blk_drv / ramdisk.c, 52)
52 extern long kernel_mktime (Struct tm * tm ); // computing system boot time (seconds).
53 extern long startup_time ; // kernel boot time (boot time) (seconds).
5455 / *

56 * This is set up by the setup-routine at boot-time


57 * /
/*
* Setup.s by the following data are provided in the boot time (see Chapter 3, Table 3.2).
*/
58 #define EXT_MEM_K (* (Unsigned short *) 0x90002) // 1M later extended memory size (KB).
59 #define DRIVE_INFO (* (Struct drive_info *) 0x90080) // hard disk parameter table base.
60 #define ORIG_ROOT_DEV (* (Unsigned short *) 0x901FC) // where the root file system device number.
6162 / *

--84--
4.2 main.c program

63 * Yeah, yeah, it's ugly, but I can not find how to do this correctly
64 * And this seems to work. I anybody has more info on the real-time
65 * Clock I'd be interested. Most of this was trial and error, and some
66 * Bios-listing reading. Urghh.
67 * /
/*
* Yes ah, yes ah, following this program very bad, but I do not know how to implement correctly, and if it can run. If there is
* For more information about real-time clock, then I'm interested. These are temptations out, and read some bios program, Oh!
*/
6869 #define CMOS_READ (Addr) ({\
// This macro reads the CMOS real-time clock information.

70 outb_p (0x80 | addr, 0x70); \ // 0x70 is a write port number, 0x80 | addr is the CMOS memory address to be read.

71 inb_p (0x71); \ // 0x71 is read port number.


72 })
73
// define the macro. Converting binary values ​into BCD code.

74 #define BCD_TO_BIN (Val) ((val) = ((val) & 15) + ((val) >> 4) * 10)
75
// This subroutine takes CMOS clock and sets the boot time startup_time (seconds). See behind the CMOS memory list.

76 static void time_init (Void)


77 {
78 struct tm time ; // time tm structure defined in the include / time.h in.
79
// CMOS access speed is very slow. In order to reduce the time error, after reading all the values ​in the following cycle, if the second case in CMOS // value change,

then re-read all values. Thus the core can be controlled with CMOS timing error in 1 second.

80 do {
81 time .tm_sec = CMOS_READ (0); // current time value in seconds (both BCD code value).

82 time .tm_min = CMOS_READ (2); // current minute value.

83 time .tm_hour = CMOS_READ (4); // current hour value.


84 time .tm_mday = CMOS_READ (7); // today's date in January.
85 time .tm_mon = CMOS_READ (8); // current month (1-12).
86 time .tm_year = CMOS_READ (9); // current year.
87 } While ( time .tm_sec! = CMOS_READ (0));
88 BCD_TO_BIN ( time .tm_sec); // converted into binary values.

89 BCD_TO_BIN ( time .tm_min);


90 BCD_TO_BIN ( time .tm_hour);
91 BCD_TO_BIN ( time .tm_mday);
92 BCD_TO_BIN ( time .tm_mon);
93 BCD_TO_BIN ( time .tm_year);
94 time .tm_mon--; // tm_mon month is in the range of 0-11.
// call the kernel / mktime.c in function to calculate the number of seconds to play the day after the boot from January 1970 when 1 0, // as boot time.

95 startup_time = kernel_mktime (& time );


96 }
9798 static long memory_end = 0;
// machine having a physical memory (in bytes).
99 static long buffer_memory_end = 0; // buffer cache end address.
100 static long main_memory_start = 0; // main memory (for paging) starting position.
101102 struct drive_info {Char dummy [32];} drive_info ; // hard disk parameter table for storing information.

103104 void main (Void)


/ * This really IS void, no error here. * /
105 { / * The startup routine assumes (well, ...) this * /

--85--
4.2 main.c program

/ * This is indeed void, and right. The startup procedure (head.s) is so assumed in * / // see head.s few lines
of code line program 136 begins.
106 / *
107 * Interrupts are still disabled. Do necessary setups, then
108 * Enable them
109 * /
/*
* At this point the interrupt is still prohibited, done after the necessary settings to turn it on.

*/
// the following code to save:
// Number ROOT_DEV root device; cache end address buffer_memory_end; // number of machines memory
memory_end; main memory starting address main_memory_start;
110 ROOT_DEV = ORIG_ROOT_DEV ; // ROOT_DEV defined in fs / super.c, 29 lines.
111 drive_info = DRIVE_INFO ; // copy the hard disk parameter table at 0x90080.

112 memory_end = (1 << 20) + ( EXT_MEM_K << 10); // Size = 1Mb memory bytes + extended memory (k) * 1024 bytes.

113 memory_end & = 0xfffff000; // Ignore less than 4Kb (1 pages) amount of memory.

114 if ( memory_end > 16 * 1024 * 1024) // If the memory than 16Mb, 16Mb press count.
115 memory_end = 16 * 1024 * 1024;
116 if ( memory_end > 12 * 1024 * 1024) // If memory> 12Mb, the end of the buffer is set = 4Mb

117 buffer_memory_end * 1024 * 4 = 1024;


118 else if ( memory_end > 6 * 1024 * 1024) // else if memory> 6Mb, then set the buffer end = 2Mb
119 buffer_memory_end = 2 * 1024 * 1024;
120 else
121 buffer_memory_end * 1024 * 1024 = 1; // end or is set buffer = 1Mb
122 main_memory_start = buffer_memory_end ; // = the starting position of the buffer in main memory end; // if defined virtual disk memory, virtual disk is

initialized. At this time, main memory will be reduced. See kernel / blk_drv / ramdisk.c.

123 #ifdef RAMDISK


124 main_memory_start + = rd_init ( main_memory_start , RAMDISK * 1024);
125 #endif
// The following is the kernel initializes all aspects. When reading the best to follow the calling program go in depth look, see // if it does not go on, then put

off, continue to look at an initial call - this is the voice of experience ☺ .

126 mem_init ( main_memory_start , memory_end );


127 trap_init (); // trap door (hardware interrupt vector) is initialized. (Kernel / traps.c, 181)
128 blk_dev_init (); // block device initialization. (Kernel / blk_drv / ll_rw_blk.c, 157)
129 chr_dev_init (); // character device initialization. (Kernel / chr_drv / tty_io.c, 347)
130 tty_init (); // tty initialization. (Kernel / chr_drv / tty_io.c, 105)
131 time_init (); // Set the boot time startup_time (see line 76).
132 sched_init (); // initialize scheduler (tr loaded task 0, ldtr) (kernel / sched.c, 385)
133 buffer_init ( buffer_memory_end ); // initialize buffer management, construction and other memory list. (Fs / buffer.c, 348)

134 hd_init (); // initialize hard disk. (Kernel / blk_drv / hd.c, 343)
135 floppy_init (); // initialize the floppy drive. (Kernel / blk_drv / floppy.c, 457)
136 sti (); // initialize all the work is done, enable interrupts.
// The following process parameters set by the stack, using the interrupt return instruction 0 start task execution.

137 move_to_user_mode (); // user mode execution to the next. (Include / asm / system.h, line 1)
138 if (! fork ()) { / * We count on this going ok * /
139 init (); // execute in the new child process (task 1).
140 }
// The following code starts to run as a task to zero.

141 / *
142 * NOTE !! For any other task 'pause ()' would mean we have to get a
143 * Signal to awaken, but task0 is the sole exception (see 'schedule ()')
144 * As task 0 gets activated at every idle moment (when no other tasks
145 * Can run). For task0 'pause ()' just means we go check if some other

--86--
4.2 main.c program

146 * Task can run, and if not we return here.


147 * /
/ * WARNING !! For any other task, 'pause ()' will mean that we will have to wait to receive a return signal
* Ready to run back to the state, but the task 0 (task0) is the only exception (see 'schedule ()'), because the task 0
* Any free time will be activated (when no other tasks at runtime), so for the task 0'pause () 'only means
* We return to see if there are other tasks can be run, if not, then we'll come back here, we have been circulating execute 'pause ()'.
*/
// pause () system call (kernel / sched.c, 144) will be converted to an interrupt task 0 wait state, and then perform scheduling functions. // but switching to the task

scheduling function will find the system 0 as long as no other tasks can be run without depending on the status of the task // 0.

148 for (;;) pause ();


149 }
150 151 static int printf (Const char * fmt, ...)

// generates and outputs the formatted information to the standard output device stdout (1), where on the screen display means. Parameter '* fmt' // specified

output format employed, see various standard C language books. The routine is just one example of how to use vsprintf. // This program uses vsprintf () printbuf

formatted string in a buffer, and () // output the contents of the buffer to the standard equipment write (1 - stdout). vsprintf () function to achieve see kernel /

vsprintf.c.

152 {
153 va_list args;
154 int i;
155
156 va_start (Args, fmt);
157 write (1, printbuf , I = vsprintf ( printbuf , Fmt, args));
158 va_end (Args);
159 return i;
160 }
161 162 static char * argv_rc [] = { "/ bin / sh ", NULL };
// string array parameter when calling the program.

163 static char * envp_rc [] = { " HOME = / ", NULL }; // calling environment string array for executing a program.

164 165 static char * argv [] = { "- / bin / sh ", NULL };


// Ibid.
166 static char * envp [] = { " HOME = / usr / root ", NULL };
165 // above line argv [0] character "-" sign is a shell program passed to sh. , Sh // program will be executed by identifying the flag as a login shell.
Their implementation and enforcement at the shell prompt sh not the same.
167
// in main () to initialize the system have been made, including memory management, hardware devices and drivers. init () function runs (Task 1) in the

sub-process task 0 // 1st created. It first of the first program (shell) will be executed // initialize the environment, and then load the program and execute it.

168 void init (Void)


169 {
170 int pid, i;
171
// This is a system call. For reading the hard disk partition table information parameters include a virtual disk and loaded (if present) and the mounting // root file system device. The

macro function is defined on the line 25, the corresponding function is sys_setup (), the kernel / blk_drv / hd.c, 71 rows.

172 setup ((void *) & drive_info );


// Open the device below "/ dev / tty0" read-write access mode, which corresponds to the terminal console.

// Since this is the first operation to open the file, the file handle number (file descriptor) generated must be 0. The handle is a UNIX-like operating systems // default

console standard input handle stdin. Here it is opened to read and write in order to replicate // generate standard output (write) handles stdout and stderr output handle

stderr.

173 (Void) open ( "/ dev / tty0 ", O_RDWR , 0);


174 (Void) dup (0); // copy handle, handle number to produce 1 - stdout standard output device.

--87--
4.2 main.c program

175 (Void) dup (0); // copy handle, the handle is generated No. 2 - stderr standard error output device.

// The following buffers and the number of blocks the print total number of bytes, 1024 bytes per block and the number of bytes of free memory area of ​main memory.

176 printf ( "% d buffers =% d bytes buffer space \ n \ r ", NR_BUFFERS ,


177 NR_BUFFERS * BLOCK_SIZE );
178 printf ( ' Free mem:% d bytes \ n \ r ", memory_end - main_memory_start );
// The following fork () is used to create a child process (Task 2). For the child process is created, fork () returns a value of 0, // process for the original (parent) process

number pid of the child process is returned. So 180-184 sentence is the content of the child process execution. The child closes a handle // 0 (stdin), read-only open the / etc

/ rc file using the execve () function to process itself to replace / bin / sh // program (i.e., shell programs), and then execute / bin / sh program. Brought environment variables

and parameters are given by argv_rc and envp_rc // array. About execve () See fs / exec.c program, 182 line.

// function _exit () error code when the exit 1-- unlicensed operation; 2 - file or directory does not exist.

179 if (! (pid = fork ())) {


180 close (0);
181 if ( open ( "/ etc / rc ", O_RDONLY , 0))
182 _exit (1); // If you open the file fails, the exit (lib / _exit.c, 10).
183 execve ( "/ bin / sh ", argv_rc , envp_rc ); // replace / bin / sh and program execution.

184 _exit (2); // if execve () fails to exit.


185 }
// The following is the parent process (1) executed statement. wait () waits for the child process to stop or terminate, the return value should be the process ID of the child process (pid). // This

is the role of three child processes to wait for the end of the parent process. & I is located in a position to return status information. If wait () // return value is not equal to the number of child

processes, continue to wait.

186 if (pid> 0)
187 while (pid! = wait (& I))
188 / * Nothing * /; / * Air circulation * /

// If you perform here, on the implementation of the newly created child process has been stopped or terminated. The following loop first and then create a child process, // if error,

the "Create initialization program a child process failed" message and continue. For the child process created by the close of the previous // have also left handle (stdin, stdout,

stderr), to create a new session and set process group number, and then open // / dev / tty0 as stdin again, and copied to stdout and stderr. Execution Systems interpreter / bin / sh

again. But this time the implementation of environmental parameters and an array of the chosen alternative // ​set (see above lines 165-167). Then the parent process to run again

wait () to wait. // if the child has stopped the execution, on the standard output error message "child process pid to stop the run, return code is i", and then go on ... // continue to

retry to form a "big" death cycle.

189 while (1) {


190 if ((pid = fork ()) <0) {
191 printf ( ' Fork failed in init \ r \ n ");
192 continue;
193 }
194 if (! pid) { // new child process.
195 close (0); close (1); close (2);
196 setsid (); // Create a new session period, see later description.

197 (Void) open ( "/ dev / tty0 ", O_RDWR , 0);


198 (Void) dup (0);
199 (Void) dup (0);
200 _exit ( execve ( "/ bin / sh ", argv , envp ));
201 }
202 while (1)
203 if (pid == wait (& I))
204 break;
205 printf ( "\ n \ rchild% d died with code% 04x \ n \ r ", pid, i);
206 sync (); // synchronous operation, flush the buffer.

207 }
208 _exit (0); / * NOTE! _Exit, not exit () * / / * Note! Is _exit (), not the exit () * /
// _exit () and exit () are used to terminate a normal function. But _exit () system call directly is a sys_exit, and exit () // is often a function common function library. It

will first perform some cleanup operations, such as call termination handler executes each, close the

--88--
4.2 main.c program

// standard IO and so on, and then call sys_exit.


209 }
210

4.2.3 Other Information

4.2.3.1 CMOS information

PC Machine CMOS ( complementary metal oxide semiconductor Complementary metal oxide semiconductor) memory is actually powered by a battery 64 or 128 byte RAM Memory

block is part of the system clock of the chip. Some machines have bigger memory capacity.

That 64 Byte CMOS Originally IBM PC-XT Format for saving on the machine clock and date information, is stored in BCD code. Because this information only to 14 Bytes, the

remaining bytes are used to store the number of system configuration data.

CMOS The address space is in addition to the basic address space. Thus does not include executable code. It requires the use of the port

70h, 71h use IN with OUT Instructions to access. In order to read the specified byte offset position, first need to use OUT To port 70h Transmitting specified byte offset value, then IN

Instruction from 71h Port reads the specified byte information.

This program (lines 70 ) Address of the byte to be read or on a 80h Value is not necessary. Since that time CMOS Memory capacity has not been exceeded 128

Bytes, or 80h The operation is of no effect. The reason why there is such an operation because it was Linus Lack of hand CMOS Aspects of the information, CMOS Clock

and date are offset out his experiments gradually, perhaps he or offset in the experiment on 80h Just made all the right result (and also modify other places), so he

will have a code that this step unnecessary operations. But from 1.0 After release, the operation can be removed (see 1.0 Version of the kernel

drivers / block / hd.c The first 42 Row from the Code). table 4-1 Yes CMOS A profile memory information.

table 4-1 CMOS 64 Jane byte information table

Address offset value Description Address offset value Description

0x00 The current second value (real time clock) 0x11 Retention

0x01 Alarm second value 0x12 Type of hard drive

0x02 Current minutes (real time clock) 0x13 Retention

0x03 Alarm value min 0x14 Equipment bytes

0x04 Current hour value (real time clock) 0x15 Base memory (low byte)

0x05 Alarm value h 0x16 Base memory (high byte)

0x06 The current day of the week (real time clock) 0x17 Extended Memory (low byte)

0x07 Today's date (real time clock) of the month 0x18 Extended memory (high byte)

0x08 The current month (real time clock) 0x19-0x2d Retention

0x09 Current year (real time clock) 0x2e Checksum (low byte)

0x0a RTC Status Register A 0x2f Checksum (high byte)

0x0b RTC Status Register B 0x30 1Mb More extended memory (low byte)

0x0c RTC Status Register C 0x31 1Mb More extended memory (high byte)

0x0d RTC Status Register D 0x32 In which the value of the current century

0x0e POST Diagnostic status byte 0x33 Information signs

0x0f Stop status byte 0x34-0x3f Retention

0x10 Disk drive type

4.2.3.2 transfer fork () Creating a new process

fork It is a system call function. The system calls duplicate the existing process, and create an original process (referred to as the parent process) is almost exactly the

same as a new entry, and execute the same code in the process table, but the new process (referred to herein as the child) It has its own data space and environmental

parameters.

--89--
4.2 main.c program

In the parent process, call fork () Returns the child process identification number PID While in the child fork () Will be returned 0 Value, so, although at this time or in the

same execute a program, but has begun to diverge, each perform their own part of the code. in case fork () Call fails, it will return less than 0 Value. Such as schematic 4-3 Fig.

pid = 0
New process

pid! = 0
The original process pid = fork () The original process

Map 4-3 transfer fork () Creating a new process

init That program is fork () Return value of a call to distinguish and execute different code segments. The code of the above 179 with 194 Row and the child process is to

determine the sub-execution start process of code block (use execve () System calls other programs are executed here sh ), The

186 with 202 Line is a block of code executed by the parent process.

4.2.3.3 About SESSION ( session) the concept of

In the first 2 Chapter we said, the program is an executable file, and the process ( process ) Is an instance of the program execution. In the kernel, each process uses

a different positive integer greater than zero is identified, called the process ID number pid (Porcess ID) . And through a process fork () Call creates one or more child

processes that can form a process group. For example, in the following shell

On the command line, type a command pipeline,

[Plinux root] # cat main.c | grep for | more

Each of these commands: cat , grep with more We all belong to a group process.

Process group is a collection of one or more processes. The process is similar, each process has a unique set of process group ID gid ( Group ID ). Process Group gid It is a

positive integer. Each process has a process called group leader, the head of the process is its process ID pid Equal to the process group gid Process. A process by calling setpgid () To

participate in the process of an existing group or create a new process group. The concept of group process has many uses, but the most common is that we send forward the

implementation of the program on the terminal station termination signal (usually by Ctrl-C Key combination), and to terminate all processes throughout the process group. For

example, if we sent a signal to the pipeline termination command, the command three simultaneously terminated.

The session period ( Session , Otherwise known as a session) is a collection of one or more process group. Normally, all programs executed after the user logs belong to a

session period, while their login shell It is the first session of process ( Session leader ). When we Log ( logout Time), we all belong to this session of the process will be terminated.

One of the main purposes of which is the concept of a session. setsid ()

Function is used to create a new session period. Typically, this function is called by the environment initialization procedure, see next section describes. Figure relationship

between processes, process groups and sessions of 4-4 Fig.

--90--
4.3 Environmental initialization

group process

group process process process

Process
Process

Processes
Processes
SESSION

Process Group

Map 4-4 The relationship between processes, process groups and sessions of

4.3 Environmental initialization

After kernel system initialization is complete, the system also need to perform further initialization work environment based on the specific configuration, in order to really

have some work environments have a common system. In the previous section 183 Rows and 200 Row, init () Function directly started the command interpreter ( shell program)/ bin /

sh , But is not the case in actual systems available. In order to deal with and many people have logged onto the system at the same time the ability to use the system, the system is

usually in here or a similar location, program execution environment initialization system init.c And this program will be based on system / etc / Directory configuration settings file,

create a child process for each terminal device in the system supported a terminal and run the initial setup program in the child process agetty (Collectively, getty program), getty The

program will be displayed on the terminal user login prompt information. " login: . "When a user types a user name later, getty Replace to perform login program. login Program verified

by the user to enter a password after the final call shell Program, and enter shell Interactive working interface. The implementation of the relationship between them Figure 4-5 Fig.

process 1 init

fork ()

agetty

exec ()

login

exec ()

shell

Map 4-5 Environmental program initialization

Although these procedures ( init, getty, login, shell ) Does not belong to the core areas, but this effect several programs have some basic understanding of why the kernel

will promote understanding provided so versatile.

init The main task of the process is based on / etc / rc Set information file, in which the execution command, then according to / etc / inittab Information in the file, login is

allowed for each terminal device using fork () Create a child process, and transported in each sub-process in the newly created

--91--
4.4 Summary

Row agetty 3 ( getty )program. and init Process is called wait () , Wait for the child to enter the end state. Every time it's the end of a child process exits, it will be based on wait () return pid

No. know which child process corresponding to the terminal end, so it will then create a new child process to the corresponding terminal equipment, and re-execute the child

process agetty program. In this way, each of the terminal devices are always allowed to have a corresponding process for its pending.

Under normal operation, init determine agetty We are working with to allow users to log in and receive orphan processes. Isolated processes are those processes whose

fathers process has been completed; in Linux All processes must belong to a single process tree trees, so isolated process must be charged. When the system is closed, init Responsible

for killing all other processes, unmounting all filesystems and stopping the processor work, and it is configured to do any work.

getty The main task of the program is to set the terminal type, attributes, procedures and line speed. It opens and initializes a tty Port, display a message, and waits for the

user to type a user name. The program can only be executed by the superuser. In general, if / etc / issue Text file exists, getty Which will first display the text information, and then

displays the login prompt (for example: plinux login: ), Read the user's login name, type, and execution login program.

login Program is mainly used to require the user to enter a password to log. The user name entered by the user, it is from the password file passwd Acquired the

corresponding user entries, and then call getpass () To show "Password:" Message, read the user types the password, and then use the encryption algorithm type the password is

encrypted, and the password file in the user entry pw_passwd Compare field. If the user types the password several times are invalid, login The program will error code 1 Exit

execution, represents the logon process fails. At this point the parent process (process init )of wait () It will return the exit process pid And therefore creates a child process again

according to the information recorded and perform again for the terminal device in the sub-process agetty Procedure, the process is repeated.

If the user types the password is correct, login It will put the current working directory ( Currend Work Directory ) To modify the password file specified in the user's initial

working directory. And the access to the user terminal equipment modified to read / write and write groups, group setting process

ID . Then initialize the environment variable information using the information obtained, for example, home directory ( HOME = ),in use shell program( SHELL = ), username( USER = with

LOGNAME = ) And default path sequence program execution system ( PATH = ). Then the display / etc / motd file( message-of-the-day Text information) in, and check whether the user

and displays information messages. At last login Program to change the logged in user ID And execute the password file that the user specified in item shell Programs such as bash or

csh Wait.

If the password file / etc / passwd In the user does not specify which items shell Program, the system will use the default / bin / sh program. If the password file does not

specify the user's home directory for the user, then the system will use the default root directory /. related login

Some description of the process execution options and special access restrictions, see Linux System online manual pages ( man 8 login ).

shell Program is a complex command-line interpreter, the program is executed when the user logs in when the system interact. It is the place where users interact with the

computer operation. It gets the information entered by the user, and then execute the command. To the user at the terminal can be shell Interact directly input, you can also use shell

Script file to shell Interpreter input.

During the logon process login Begin execution shell When brought parameter argv [0] The first character is '-' Indicates that the shell Log in as a shell It is executed. At this

point the shell Program will be based on the character, and the login process to perform some appropriate action. log in shell It will be the first from / etc / profile And file. profile File

(if present) reads and executes the command. If you enter shell When set up ENV

Environment variables, or log in shell of. profile File set up this variable, shell The next step will be to read and execute commands from the file named variable. Therefore, the

user should command each time you log on to be executed. profile File, and put each run shell Command must be executed on ENV Variable specified file. Set up ENV Methods

environment variable is the following statement in your home directory. profile File.

4.4 chapter summary

for 0.11 Edition kernel code analysis apparent from the above, the root file system is a MINIX File system, and wherein the document comprises long / etc / rc , / bin

/ sh , / dev / * As well as some of the directory / etc / , / dev / , / bin / , / home / , / home / root / Can form a

3 agetty - alternative Linux getty.

--92--
4.4 Summary

The most simple root file system, so Linux Up and running.

From here, to read the following chapters can be main.c Program as a main line, do not need to read in order of chapters. If readers do not understand the mechanisms of

memory paging management, it is recommended to first read the first 10 Chapter contents of memory management.

In order to smoothly understand the following chapters, the author strongly hope that readers this time to review again 32 Mechanism-bit protected mode operation,

carefully read these descriptions provided in the appendix or reference Intel 80x86 About the books, the operating mechanism protected mode completely clear, then continue

reading.

If you successfully read here by order of the chapters, so you Linux System kernel initialization process should already have a general understanding. But you may also

ask the question: "After generating a series of processes, time-sharing system is how to run these processes or how to schedule these processes to run it, ie 'wheel' is how it turn

up??" . The answer is simple: the kernel is through the implementation of sched.c

Program scheduling function schedule () with system_call.s The timing clock interrupt process _ timer_interrupt To operate. Each core set 10 Ms issue a clock interrupt, and interrupt

the process by calling do_timer () Function checks all processes of the current state of implementation of the process to determine the next step.

For the process during execution due to a lack of resources and want to temporarily use a temporary need wait for a while, it will pass in a system call

sleep_on () Class function indirectly call schedule () Function, CPU The right to use voluntarily handed over to another process to use. As the system will run next process which is

entirely schedule () And priority decisions based on the current status of all processes. For the process has been runnable state, when the clock interrupt process determine the time

slice it running has been used up, it will in do_timer () Performing a switching operation process, the process CPU Use rights will be unwillingly deprived give another process to use.

Scheduling Functions schedule () And the clock interrupt process that is one of the themes of the next chapter.

--93--
5.1 Overview

The first 5 Chapter kernel code ( kernel)

5.1 Outline

linux / kernel / Directory includes a total of 10 More C And language files 2 An assembly language file and a kernel Compiled files in the configuration file management Makefile

. See the list 5-1 Fig. Wherein three subdirectories code comments will be carried out in subsequent sections. This chapter 13 Code file comments. First we have the general

overall introduction to the basic functions of all programs in order to start this 12 Files and functions implemented cross call between them have a general understanding of the

code one by one and then annotate detail.

List 5-1 linux / kernel / table of Contents

file name size Last Modified Time (GMT) Description

blk_drv / 1991-12-08 14:09:29

chr_drv / 1991-12-08 18:36:09

math / 1991-12-08 14:09:58

Makefile 3309 bytes 1991-12-02 03:21:37 m

asm.s 2335 bytes 1991-11-18 00:30:28 m

exit.c 4175 bytes 1991-12-07 15:47:55 m

fork.c 3693 bytes 1991-11-25 15:11:09 m

mktime.c 1461 bytes 1991-10-02 14:16:29 m

panic.c 448 bytes 1991-10-17 14:22:02 m

printk.c 734 bytes 1991-10-02 14:16:29 m

sched.c 8242 bytes 1991-12-04 19:55:28 m

signal.c 2651 bytes 1991-12-07 15:47:55 m

sys.c 3706 bytes 1991-11-25 19:31:13 m

system_call.s 5265 bytes 1991-12-04 13:56:34 m

traps.c 4951 bytes 1991-10-30 20:20:40 m


vsprintf.c 4800 bytes 1991-10-02 14:16:29 m

5.2 Overall Functional Description

Code files in that directory from the functions can be divided into three categories, one is hardware (abnormal) interrupt handler files, one is the system call service handler

file, the other is the process of scheduling and other common functions file, see Figure 1.5 . We are now the basis of this classification, a more detailed explanation from the function

to achieve.

--95--
5.2 Overall Functional Description

5.2.1. Class hardware interrupt processing program

Including two code files: asm.s with traps.c file. asm.s Assembly language used to implement most of the hardware interrupt processing caused by abnormal. and traps.c

Program is to achieve a asm.s Interrupt processing call c function. Several other hardware interrupt handler file system_call.s with mm / page.s Implemented.

Before the user program (process) control to the interrupt handler, CPU The first will be at least 12 Stack information byte is pressed into the interrupt handler. This situation

is a long call (subroutine call inter-segment) Compare alike. CPU Will return code segment selector and the offset value of the address onto the stack. Another comparison between

the segment calls is much like the place 80386 The information on the stack is pressed into the object code, rather than the interrupt stack code. Thus, when an interrupt occurs, the

kernel-mode stack and the object code. In addition, CPU It is always the flag register EFLAGS The contents of the stack. If the priority level changes, such as changing from

user-level to system-level kernel,

CPU Will be the original stack segment and stack pointer value pushed onto the stack code in the interrupt routine. For the contents of the stack having priority change is shown in

Figure 5-1 Fig.

Former SS Former SS

Original ESP Original ESP


Press-fitting direction
EFLAGS EFLAGS

CS CS

EIP EIP error

code

(A) without error code (B) with error code

Map 5-1 The contents of the stack when the interrupt occurs

asm.s Mainly related to the code file Intel Reserved Interrupt int0 - int16 The deal, the rest reserved interrupts int17-int31 by Intel The company reserved for future

expansion of use. Each corresponding to the interrupt controller chip IRQ dispatched int32-int47 of 16 A processing program treats in various hardware (e.g., a clock, a keyboard, a

floppy disk, a math co-processor, a hard disk, etc.) initialization procedure. Linux System call interrupts int128 (0x80)

The process will be in kernel / system_call.s Given. DETAILED DESCRIPTION see definition of each interrupt one after the other information in the code comments.

As some of the abnormalities caused by interrupted, CPU Internally generate an error code onto the stack (abort int 8 with int10 - int 14 ), See Figure 5-1 (b) Shown, while

other interrupts, but not with the error code (e.g., zero error and a boundary check error, etc.), and therefore,

asm.s The program will deal with all interrupts and processed separately according to whether they carry the error code. But the process flow remains the same.

For processing of a hardware interrupt caused by abnormal Figure 5-2 Fig.

--96--
5.2 Overall Functional Description

All registers onto the stack.

Error codes -> Drawing

Interrupt return address -> Drawing

Register is set to all segments of the

kernel code segment selector value Note 1: The kernel code selector is

0x08; Note 2: 0 No error on the use of

codes; Note 3: C function calls are


Call the relevant C handler
implemented in traps.c. Error code

onto the stack and the interrupt return

Pop stack error code and then interrupt address is used as the parameter C

stack return address function.

All pop stack register

Interrupt return

Map 5-2 Hardware interrupt abnormal (fault, trap) caused by the treatment process

5.2.2. System call processing procedures

Linux The application calls the kernel function is interrupted by a call int 0x80 Conducted, register eax Put the call in number. Therefore, the interrupt is called, the system

call. Implement system calls related documents including system_call.s , fork.c , signal.c , sys.c with exit.c

file.
system_call.s Role of a program similar to the hardware interrupt processing asm.s The role of the program, in addition to the clock interrupt and hard disk, floppy disk

interrupt processing. and fork.c with signal.c One function is similar traps.c The role of the program, the system provides interrupt call C

Handler. fork.c Program provides two C Handler: find_empty_process () with copy_process () . signal.c The program also provides a processing function related to

process signals do_signal () , Is called the system call interrupt processing. It also includes 4 System calls sys_xxx () function.

sys.c with exit.c Program implements a number of other sys_xxx () System call function. These ones sys_xxx () Handler functions are required to call the appropriate system

call, and some are using assembly language, such as sys_execve () ; While others with C Language (for example,

signal.c middle 4 System call function).

We can be understood in terms of simple naming convention of these functions: usually ' do_ ' The beginning of the interrupt processing call C Function, either the

system call processing functions common to either a system call exclusive; and to ' sys_ ' System call functions that begin with is a dedicated system call handler specified.

E.g, do_signal () Function basically is a function of all system calls to be executed, and do_hd () , do_execve () It is a dedicated system calls C Handler.

5.2.3 Other generic class program

These programs include schedule.c , mktime.c , panic.c , printk.c with vsprintf.c .

schedule.c Program includes kernel calls the most frequent schedule () , sleep_on () with wakeup () Function, the kernel is the core of the scheduler, for performing the

process execution state of the handover or change process. mktime.c Program includes only a kernel function of time mktime () ,only at init / main.c It was called once. panic.c Contains

a panic () Function to display an error message when an error occurs and the kernel is running down. printk.c with vsprintf.c Kernel program information display support, to achieve

a core dedicated display function

--97--
5.3 Makefile file

printk () String formatting and output functions vsprintf () .

5.3 Makefile file

5.3.1. Features

Compile linux / kernel / Under the program make Configuration file, not including the three subdirectories. The format of the file with the composition of the first chapter list

1.2 Basically the same, while reading can refer to the list 1.2 The relevant comments.

5.3.2. File Comments

program 5-1 linux / kernel / Makefile

1#
2 # Makefile for the FREAX-kernel.
3#
4 # Note! Dependencies are done automagically by 'make dep', which also
5 # Removes any old dependencies. DO NOT put your own dependencies here
6 # Unless it's something special (ie not a .c file).
7#
# FREAX kernel Makefile file.
#
# note! Dependency is performed by the 'make dep' automatically, which will automatically remove the original dependency information. Do not put your own

# Dependency information on here, unless it is (that is not a message .c file) special file.
# (Linux first name FREAX, the name was later changed to Linux ftp.funet.fi administrator)
89 AR
= Gar # GNU binary file processing program for creating, modifying and extracting files from the archive.
10 AS = Gas # GNU assembler.
11 LD = Gld # The GNU linker.
12 LDFLAGS = -s -x # connection program all the parameters, -s omitted all symbols output file information. -x Delete all local symbols.

13 CC = Gcc # GNU C language compiler.


14 CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
15 - finline-functions -mstring-insns -nostdinc -I ../ include
# C compiler options. -Wall display all warnings; -O optimization option, to optimize code size and execution time;
# - fstrength-reduce execution code optimization cycle, excluding iteration variable; -fomit-frame-pointer will be omitted to save unnecessary

# The frame pointers; -fcombine-regs merge register, reduce the use of register class; -finline-functions all Jane
# Single short code embedded function calls the program; -mstring-insns Linus own filling optimization options, will no longer use;
# - nostdinc -I ../ include not using the default path contains the file, and use this specified directory (../include).
16 CPP = Gcc -E -nostdinc -I ../ include
# C pre-processing options. -E C only run pre-treatment, pre-treatment and the results for all of the specified program is output to the standard output C

# The apparatus or a specified output file; -nostdinc -I ../ include op.


17
# The following rule indicates that make use of the following command will compile all .c files generated .s Assembler. The rule of command

# Refers gcc CFLAGS using the specified options compiled C code is compiled without stops (-S), thereby generating
# C each corresponding to the input file assembler code file. Assembler default file name is generated by the original file name C
# Remove .c and .s suffix plus. -o represented followed by the name of the output file. Of which $ *. S (or $ @ ) is automatic target variable,

# $ <Represents the first prerequisite here that is qualified * .c files.


18 .cs:
19 $ (CC) $ (CFLAGS) \
20 - S -o $ *. S $ <
# The following rule means that all .s assembler .o files compiled into object files. Line 22 is a command to achieve the specific operation.

--98--
5.3 Makefile file

twenty one .so:

twenty two $ (AS) -c -o $ *. O $ <


twenty three .co: # . Similar to the above, * c files - * .o object files. Not connect.
twenty four $ (CC) $ (CFLAGS) \
25 - c -o $ *. o $ <
2627 OBJS = sched.o system_call.o traps.o asm.o fork.o \
# Define the target file variable OBJS.
28 panic.o printk.o vsprintf.o sys.o exit.o \
29 signal.o mktime.o
3031 kernel.o: $ (OBJS)
# Use the following prerequisites have after OBJS command to connect to the target kernel.o

32 $ (LD) -r -o kernel.o $ (OBJS)


33 sync
34
# The following rules for the cleanup. When performing 'make clean', it will execute commands on the line 36--40 remove all compiled
# Connection file generated. 'Rm' command is to delete the file, meaning -f option is to ignore the file does not exist, and does not delete the information.

35 clean:
36 rm -f core * .o * .a tmp_make keyboard.s
37 for i in * .c; do rm -f `basename $$ i .c`.s; done
38 (Cd chr_drv; make clean) # Enter chr_drv / directory; the implementation of clean rule in the Makefile directory.
39 (Cd blk_drv; make clean)
40 (Cd math; make clean)
41
# Here was the objective or rules for checking dependencies between files. Methods as below:

# Sed string editing program for the Makefile (where that is their own) for processing, the output is deleted Makefile
# File all lines subsequent lines '### Dependencies' (below line 51 from the beginning), and generates tmp_make
# Temporary files (action line 43). Gcc then performs a preprocessing operation on each file in the C kernel / directory.
# - M flag tells the preprocessor output description of the rules relating to each target file, and make compliance with these rules syntax.

# For each source file, the output of preprocessor make a rule, the result is a certain form of the corresponding source file
# File name plus its dependencies - lists all the header files included in the source file. The pretreatment results are added to the temporary

# Tmp_make file, and then copy the temporary file into a new file Makefile.
42 dep:
43 sed '/ \ # \ # \ # Dependencies / q' <Makefile> tmp_make
44 (For i in * .c; do echo -n `echo $$ i | sed '.. S, \ c, \ s,'` ""; \
45 $ (CPP) -M $$ i; done) >> tmp_make
46 cp tmp_make Makefile
47 (Cd chr_drv; make dep) # For the Makefile in chr_drv / directory also do the same process.
48 (Cd blk_drv; make dep)
4950 ### Dependencies:

51 exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \


52 . . /include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
53 . . /include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
54 . . /include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
55 . . /include/asm/segment.h
56 fork.s fork.o: fork.c ../include/errno.h ../include/linux/sched.h \
57 . . /include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
58 . . /include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
59 . . /include/asm/segment.h ../include/asm/system.h
60 mktime.s mktime.o: mktime.c ../include/time.h
61 panic.s panic.o: panic.c ../include/linux/kernel.h ../include/linux/sched.h \
62 . . /include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
63 . . /include/linux/mm.h ../include/signal.h

--99--
5.4 asm.s program

64 printk.s printk.o: printk.c ../include/stdarg.h ../include/stddef.h \


65 . . /include/linux/kernel.h
66 sched.s sched.o: sched.c ../include/linux/sched.h ../include/linux/head.h \
67 . . /include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
68 . . /include/signal.h ../include/linux/kernel.h ../include/linux/sys.h \
69 . . /include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h \
70 . . /include/asm/segment.h
71 signal.s signal.o: signal.c ../include/linux/sched.h ../include/linux/head.h \
72 . . /include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
73 . . /include/signal.h ../include/linux/kernel.h ../include/asm/segment.h
74 sys.s sys.o: sys.c ../include/errno.h ../include/linux/sched.h \
75 . . /include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
76 . . /include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
77 . . /include/termios.h ../include/linux/kernel.h ../include/asm/segment.h \
78 . . /include/sys/times.h ../include/sys/utsname.h
79 traps.s traps.o: traps.c ../include/string.h ../include/linux/head.h \
80 . . /include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
81 . . /include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
82 . . /include/asm/system.h ../include/asm/segment.h ../include/asm/io.h
83 vsprintf.s vsprintf.o: vsprintf.c ../include/stdarg.h ../include/string.h

5.4 asm.s program

5.4.1 Functional Description

asm.s Assembly program includes most CPU The underlying code is detected fault exception processing, including a math coprocessor ( FPU ) Exception handling. The

program and kernel / traps.c The program has a close relationship. The main approach of the program is to call in the corresponding interrupt handler C Function that displays the

error location and error number, and then quit interrupting.

When reading this code with reference to FIG. 5-3 The stack would be helpful to change a schematic view, FIG Each row represents 4 Bytes. Before starting the program,

the stack pointer esp It refers to a column in the interrupt return address (Figure esp0 Office). When that will be called C function

do_divide_error () Or other C After the function address stack, the pointer position is esp1 At this time through the exchange instruction, the address of the function is placed eax Register,

and the original eax The value is saved on the stack. After some registers onto the stack, the stack pointer position esp2 Place. When the official call do_divide_error () Previously,

the program will begin at esp0 The value of the stack pointer onto the stack, put esp3 At, and pop the stack before an interrupt return pointer register by adding 8 I went back to esp2

Place.

- 100 -
5.4 asm.s program

Ss esp Ss esp

original original original original

original eflags original eflags

cs eip C cs eip
interrupt return address
function address esp0 error_code (eax) C esp0
(EAX) esp1 function addresses esp1

ebx (EBX)

ecx ecx

edx edx

edi esi edi esi

44 ebp 44 ebp

ds ds

es fs es fs

error_code esp2 error_code esp2

esp0 esp3 esp0 esp3

(A) there is no error interrupt call number is love (B) interrupting the wrong number calls pushed onto the stack

Map 5-3 Error schematic process stack change

Formal call do_divide_error () Before the error code and esp0 The reason is to stack as calls C function

do_divide_error () Parameters. in traps.c In the function prototype is:

void do_divide_error (long esp, long error_code) .

Therefore, in this C Function you can print out the error number and position error. The remaining error exception process program processing procedure described herein

is substantially similar.

5.4.2 Code comments

program 5-2 linux / kernel / asm.s

1/*
2 * Linux / kernel / asm.s
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * Asm.s contains the low-level code for most hardware faults.


9 * Page_exception is handled by the mm, so that is not here. This
10 * File also handles (hopefully) fpu-exceptions due to TS-bit, as

--101--
5.4 asm.s program

11 * The fpu must be properly saved / resored. This has not been tested.
12 * / / *

* asm.s program including most hardware failures (or error) for a bottom-level code. Page exceptions are generated by the memory management program

* mm treatment, it is not here. This program also handles (hope so) fpu due TS- position caused by abnormal,
* Because fpu must correctly save / restore process, which has not been tested.
*/
13
# This code files mainly related to Intel reserved interrupts int0 - int16 treatment of (int17-int31 reserved for future use).
# Here are some statements global function name, its prototype described in traps.c.
14 .globl _divide_error, _debug, _nmi, _int3, _overflow, _bounds, _invalid_op
15 .globl _double_fault, _coprocessor_segment_overrun
16 .globl _invalid_TSS, _segment_not_present, _stack_segment
17 .globl _general_protection, _coprocessor_error, _irq13, _reserved
18
# int0 - (code following meanings see Fig. 5.3 (a)).
# The following error is zero (divide_error) processing code. Label '_divide_error' is actually a C-language function
# Number divide_error () after the name of the compiled module generated corresponding. '_Do_divide_error' function in traps.c.
19 _divide_error:
20 pushl $ _do_divide_error # First, the address of the function that will be called the stack. This program error number is zero.

twenty one no_error_code: # Here is the deal with no error number at the entrance, see line 55 below and the like.

twenty two xchgl% eax, (% esp) # _do_divide_error address eax, eax be exchanged stack.
twenty three pushl% ebx
twenty four pushl% ecx
25 pushl% edx
26 pushl% edi
27 pushl% esi
28 pushl% ebp
29 push% ds # ! ! After the 16-bit segment register stack have 4 bytes.
30 push% es
31 push% fs
32 pushl $ 0 # "Error code" # The error code on the stack.

33 lea 44 (% esp),% edx # Take the original call return address stack pointer location, and pushed onto the stack.

34 pushl% edx
35 movl $ 0x10,% edx # Kernel code data segment selector.
36 mov% dx,% ds
37 mov% dx,% es
38 mov% dx,% fs # '*' Sign indicates the downward Call operand is absolutely nothing to do with the program pointer PC.

39 call *% eax # Call C functions do_divide_error ().


40 addl $ 8,% esp # Let the stack pointer points to re-register at fs stack.
41 pop% fs
42 pop% es
43 pop% ds
44 popl% ebp
45 popl% esi
46 popl% edi
47 popl% edx
48 popl% ecx
49 popl% ebx
50 popl% eax # The original content of the pop eax.
51 iret
52
# int1 - debug debug interrupt entry point. The process above.

--102--
5.4 asm.s program

53 _debug:
54 pushl $ _do_int3 # _do_debug C function pointer stack. Or less the same.
55 jmp no_error_code
56
# int2 - unshielded interrupt calls the entry point.
57 _nmi:
58 pushl $ _do_nmi
59 jmp no_error_code
60
# int3 - with _debug.
61 _int3:
62 pushl $ _do_int3
63 jmp no_error_code
64
# int4 - overflow error interrupt entry point.
65 _overflow:
66 pushl $ _do_overflow
67 jmp no_error_code
68
# int5 - boundary checking error interrupt entry point.
69 _bounds:
70 pushl $ _do_bounds
71 jmp no_error_code
72
# int6 - invalid entry point operation command error interrupts.

73 _invalid_op:
74 pushl $ _do_invalid_op
75 jmp no_error_code
76
# int9 - coprocessor segment exceeds the error interrupt entry point.

77 _coprocessor_segment_overrun:
78 pushl $ _do_coprocessor_segment_overrun
79 jmp no_error_code
80
# int15 - Reserved.
81 _reserved:
82 pushl $ _do_reserved
83 jmp no_error_code
84
# int45 - (= 0x20 + 13) math coprocessor (Coprocessor) issued an interrupt.
# When the coprocessor executing an operator IRQ13 interrupt signal is issued to inform the CPU operation is completed.

85 _irq13:
86 pushl% eax
87 xorb% al,% al # 80387 when performing calculations, CPU execution wait for the completion of its operation.

88 outb% al, $ 0xF0 # By writing 0xF0 port, the interrupt will eliminate BUSY signal a continuation of the CPU, and re

# 80387 processor activation request extension pin PEREQ. The main purpose is to ensure that

# Before proceeding with any instruction 80387, and respond to this interrupt.

89 movb $ 0x20,% al
90 outb% al, $ 0x20 # Control chip sends the EOI (End Of Interrupt) signal 8259 to the main interrupt.

91 jmp 1f # These two jumps from the delay effect.


92 1: jmp 1f
93 1: outb% al, $ 0xA0 # Again from 8259 interrupt controller chip sends EOI (End Of Interrupt) signal.
94 popl% eax

--103--
5.4 asm.s program

95 jmp _coprocessor_error # _coprocessor_error original of this document has now been put
# (Kernel / system_call.s, 131)
96
# The following interrupt when you call the wrong number will be pushed onto the stack after interrupt return address, and therefore also need to return the error number pops up.

# int8 - double error conditions. (The following code meanings see FIG. 5.3 (b)).
97 _double_fault:
98 pushl $ _do_double_fault # C function onto the stack address.

99 error_code:
100 xchgl% eax, 4 (% esp) # error code <->% eax, eax original value is saved on the stack.
101 xchgl% ebx, (% esp) # & Function <->% ebx, ebx original value is saved on the stack.
102 pushl% ecx
103 pushl% edx
104 pushl% edi
105 pushl% esi
106 pushl% ebp
107 push% ds
108 push% es
109 push% fs
110 pushl% eax # Error code # Error number stack.

111 lea 44 (% esp),% eax # Offset # The program returns the value of the stack pointer location address stack.

112 pushl% eax


113 movl $ 0x10,% eax # Set the kernel data segment selector.

114 mov% ax,% ds


115 mov% ax,% es
116 mov% ax,% fs
117 call *% ebx # Call the appropriate C function, its parameters have been pushed onto the stack.

118 addl $ 8,% esp # Position of the stack pointer points to re-stack placed fs content.

119 pop% fs
120 pop% es
121 pop% ds
122 popl% ebp
123 popl% esi
124 popl% edi
125 popl% edx
126 popl% ecx
127 popl% ebx
128 popl% eax
129 iret
130
# int10 - Invalid Task State Segment (TSS).
131 _invalid_TSS:
132 pushl $ _do_invalid_TSS
133 jmp error_code
134
# int11 - segment does not exist.
135 _segment_not_present:
136 pushl $ _do_segment_not_present
137 jmp error_code
138
# int12 - stack segment error.
139 _stack_segment:
140 pushl $ _do_stack_segment
141 jmp error_code

--104--
5.4 asm.s program

142
# int13 - General Protection error.
143 _general_protection:
144 pushl $ _do_general_protection
145 jmp error_code
146
# int7 - device does not exist (_device_not_available) in (kernel / system_call.s, 148)
# int14 - page fault (_page_fault) in (mm / page.s, 14)
# int16 - Coprocessor Error (_coprocessor_error) in (kernel / system_call.s, 131)
# Clock interrupt int 0x20 (_timer_interrupt) in (kernel / system_call.s, 176)
# System call int 0x80 (_system_call) in (kernel / system_call.s, 80)

5.4.3 Other Information

5.4.3.1 Intel Reserved defined interrupt vector

Here are Intel Reserved Description interrupt vector specific meaning, see Table 5-1 Fig.

table 5-1 Intel reserved Meaning interrupt number

Interrupt number name Types of signal Explanation

0 Devide error malfunction SIGFPE Generated when the operation of division by zero.

1 Debug Trap When SIGTRAP when performing the step debugging program, the flag register

failures This interrupt is generated when eflags the T flag.

2 nmi hardware Produced by non-maskable interrupt NMI.

3 Breakpoint trap SIGTRAP int3 generated by the breakpoint instruction with the same debug process.

4 Overflow trap SIGSEGV eflags overflow flag OF cause.

5 Bounds check malfunction When outside the effective address causes SIGSEGV addressing.

6 Invalid Opcode malfunction SIGILL An invalid opcode instruction execution CPU.

7 Device not available malfunction SIGSEGV device does not exist, it means coprocessor. In both cases will occur in the

Interrupt: (a) CPU encounters a turn and instruction set, and when the EM. In this

case, the instruction that caused the processing program should simulate exception.

(B) MP and TS are set when the state, CPU encounters a turn back or WAIT

instruction. In this case, the processing program to be updated when necessary, the

status of the coprocessor.

8 Double fault Aborted SIGSEGV double fault error.

9 Coprocessor segment Aborted SIGFPE Coprocessor segment exceeded.

overrun

10 Invalid TSS malfunction SIGSEGV TSS found invalid the CPU switches.

11 Segment not present malfunction SIGBUS Description segment identifier is not under.

12 Stack segment malfunction SIGBUS Address does not exist or stack segment beyond the stack segment.

13 General protection malfunction SIGSEGV caused by the operation does not meet the 80386 protection mechanism (privilege level) of.

14 Page fault malfunction SIGSEGV page is not in memory.

15 Reserved 16

Coprocessor error malfunction SIGFPE Error signals issued due to the coprocessor issue.

--105--
5.5 traps.c program

5.5 traps.c program

5.5.1 Functional Description

traps.c Procedures will include some level code to handle exceptions fault (hardware break) asm.s In the corresponding call C function. Debugging information for

displaying error and error location numbers. one of them die () General function for displaying detailed error information in the interrupt processing, the code of the last initialization

function trap_init () In front init / main.c Are called for a hardware interrupt vector exception handling (the trap door) is initialized and set to allow the interrupt request incoming

signal. In reading the procedures necessary to reference asm.s program.

5.5.2 Code comments

program 5-3 linux / kernel / traps.c

1/*
2 * Linux / kernel / traps.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * 'Traps.c' handles hardware traps and faults after we have saved some
9 * State in 'asm.s'. Currently mostly a debugging-aid, will be extended
10 * To mainly kill the offending process (probably by giving it a signal,
11 * But possibly by killing it outright if necessary).
12 * /
/*
* After saving the program in some state asm.s, the present program handles hardware faults and traps. Mainly for debugging purposes,

* After the expansion process was used to kill the damaged (mostly by sending a signal, but also directly kill if necessary).
*/
13 #include <string.h> // string header file. Mainly defines the built-in functions related to operation of the string.

1415 #include <linux / head.h>


// head header file defines a simple structure segment descriptors, and several selectors constants.

16 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

17 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

18 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

19 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

20 #include <asm / io.h> // input / output header file. Defined hardware port I / O macro assembler statements.

twenty one

// The following statement defines three embedded assembler macro statement function. See the list of embedded compilation of basic grammar or appendix. // Get a byte at address

addr of the segment seg.

// parentheses, with a combination of statements (statement braces) may be used as the expression, where the last value of its output is __res.

twenty two #define get_seg_byte (Seg, addr) ({\


twenty three register char __res; \
twenty four __asm ​__ ( " push %% fs; mov %% ax, %% fs; movb %% fs:% 2, %% al; pop %% fs "\

25 : "= a "(__ res): "" (seg), " m "(* ( addr))); \


26 __res;})
27
// segment seg take a long word at address addr (4 bytes).
28 #define get_seg_long (Seg, addr) ({\

--106--
5.5 traps.c program

29 register unsigned long __res; \


30 __asm ​__ ( " push %% fs; mov %% ax, %% fs; movl %% fs:% 2, %% eax; pop %% fs "\
31 : "= a "(__ res): "" (seg), " m "(* ( addr))); \
32 __res;})
33
// takes a value fs segment register (selectors).

34 #define _fs () ({\


35 register unsigned short __res; \
36 __asm ​__ ( " mov %% fs, %% ax ":" = a "(__ res) :); \
37 __res;})
38
// The following defines the function prototype.

39 int do_exit (Long code); // exit program processing. (Kernel / exit.c, 102)
4041 void page_exception (Void);
// pages abnormal. Actually page_fault (mm / page.s, 14)
42
// The following defines the interrupt handler prototype code (kernel / asm.s or system_call.s) in.
43 void divide_error (Void); // int0 (kernel / asm.s, 19).
44 void debug (Void); // int1 (kernel / asm.s, 53).
45 void nmi (Void); // int2 (kernel / asm.s, 57).
46 void int3 (Void); // int3 (kernel / asm.s, 61).
47 void overflow (Void); // int4 (kernel / asm.s, 65).
48 void bounds (Void); // int5 (kernel / asm.s, 69).
49 void invalid_op (Void); // int6 (kernel / asm.s, 73).
50 void device_not_available (Void); // int7 (kernel / system_call.s, 148).
51 void double_fault (Void); // int8 (kernel / asm.s, 97).
52 void coprocessor_segment_overrun (Void); // int9 (kernel / asm.s, 77).
53 void invalid_TSS (Void); // int10 (kernel / asm.s, 131).
54 void segment_not_present (Void); // int11 (kernel / asm.s, 135).
55 void stack_segment (Void); // int12 (kernel / asm.s, 139).
56 void general_protection (Void); // int13 (kernel / asm.s, 143).
57 void page_fault (Void); // int14 (mm / page.s, 14).
58 void coprocessor_error (Void); // int16 (kernel / system_call.s, 131).
59 void reserved (Void); // int15 (kernel / asm.s, 81).
60 void parallel_interrupt (Void); // int39 (kernel / system_call.s, 280).
61 void irq13 (Void); // int45 coprocessor interrupt processing (kernel / asm.s, 85).
62
// This subroutine is used to print the name of the error interrupt, the length of the error number, EIP calling program, EFLAGS, ESP, fs segment register values, // segment base

address, segment, process ID pid, task number, 10 words section script. If the stack in the user data segment, // print the contents of the stack 16 further bytes.

63 static void die (Char * str , Long esp_ptr, long nr)


64 {
65 long * esp = (long *) esp_ptr;
66 int i;
6768
printk ( "% s:% 04x \ n \ r ", str , Nr & 0xffff);
69 printk ( ' EIP: \ t% 04x:% p \ nEFLAGS: \ t% p \ nESP: \ t% 04x:% p \ n ",
70 esp [1], esp [0], esp [2], esp [4], esp [3]);
71 printk ( ' fs:% 04x \ n ", _fs ());
72 printk ( ' base:% p, limit:% p \ n ", get_base ( current -> ldt [1]), get_limit (0x17));
73 if (esp [4] == 0x17) {
74 printk ( ' Stack: ");
75 for (i = 0; i <4; i ++)

--107--
5.5 traps.c program

76 printk ( "% p ", get_seg_long (0x17, i + (long *) esp [3]));


77 printk ( "\ n ");
78 }
79 str (I);
80 printk ( ' Pid:% d, process nr:% d \ n \ r ", current -> pid, 0xffff & i);
81 for (i = 0; i <10; i ++)
82 printk ( "% 02x ", 0xff & get_seg_byte (Esp [1], (i + (char *) esp [0])));
83 printk ( "\ n \ r ");
84 do_exit (11); / * Play segment exception * /
85 }
86
These // The following function is to do_ the beginning of the name of the corresponding interrupt handler calls the C function.

87 void do_double_fault (Long esp, long error_code)


88 {
89 die ( ' double fault ", esp, error_code);
90 }
9192 void do_general_protection (Long esp, long error_code)

93 {
94 die ( ' general protection ", esp, error_code);
95 }
9697 void do_divide_error (Long esp, long error_code)

98 {
99 die ( ' divide error ", esp, error_code);
100 }
101102 void do_int3 (Long * esp, long error_code,

103 long fs, long es, long ds,


104 long ebp, long esi, long edi,
105 long edx, long ecx, long ebx, long eax)
106 {
107 int tr;
108109
__asm ​__ ( " str %% ax ":" = a "( tr): "" (0)); // access task register value tr.
110 printk ( ' eax \ t \ tebx \ t \ tecx \ t \ tedx \ n \ r% 8x \ t% 8x \ t% 8x \ t% 8x \ n \ r ",
111 eax, ebx, ecx, edx);
112 printk ( ' esi \ t \ tedi \ t \ tebp \ t \ tesp \ n \ r% 8x \ t% 8x \ t% 8x \ t% 8x \ n \ r ",
113 esi, edi, ebp, (long) esp);
114 printk ( "\ n \ rds \ tes \ tfs \ ttr \ n \ r% 4x \ t% 4x \ t% 4x \ t% 4x \ n \ r ",
115 ds, es, fs, tr);
116 printk ( ' EIP:% 8x CS:% 4x EFLAGS:% 8x \ n \ r ", esp [0], esp [1], esp [2]);
117 }
118 119 void do_nmi (Long esp, long error_code)

120 {
121 die ( ' nmi ", esp, error_code);
122 }
123 124 void do_debug (Long esp, long error_code)

125 {
126 die ( ' debug ", esp, error_code);
127 }

--108--
5.5 traps.c program

128 129 void do_overflow (Long esp, long error_code)

130 {
131 die ( ' overflow ", esp, error_code);
132 }
133 134 void do_bounds (Long esp, long error_code)

135 {
136 die ( ' bounds ", esp, error_code);
137 }
138139 void do_invalid_op (Long esp, long error_code)

140 {
141 die ( ' invalid operand ", esp, error_code);
142 }
143 144 void do_device_not_available (Long esp, long error_code)

145 {
146 die ( ' device not available ", esp, error_code);
147 }
148 149 void do_coprocessor_segment_overrun (Long esp, long error_code)

150 {
151 die ( ' coprocessor segment overrun ", esp, error_code);
152 }
153 154 void do_invalid_TSS (Long esp, long error_code)

155 {
156 die ( ' invalid TSS ", esp, error_code);
157 }
158 159 void do_segment_not_present (Long esp, long error_code)

160 {
161 die ( ' segment not present ", esp, error_code);
162 }
163 164 void do_stack_segment (Long esp, long error_code)

165 {
166 die ( ' stack segment ", esp, error_code);
167 }
168 169 void do_coprocessor_error (Long esp, long error_code)

170 {
171 if ( last_task_used_math ! = current )
172 return;
173 die ( ' coprocessor error ", esp, error_code);
174 }
175 176 void do_reserved (Long esp, long error_code)

177 {
178 die ( ' reserved (15,17-47) error ", esp, error_code);
179 }
180

--109--
5.5 traps.c program

// Here is an exception (trap) interrupt program initialization routine. Set their interrupt call gate (interrupt vector). The main difference // set_trap_gate () and

set_system_gate () is that the former is set to the privilege level 0, which is 3. So // breakpoint trap interrupt int3, overflow interrupt overflow and boundary error

interrupt bounds can be generated by any program. // These two functions are embedded assembler macro (include / asm / system.h, line 36, line 39).

181 void trap_init (Void)


182 {
183 int i;
184
185 set_trap_gate (0, & divide_error ); // set operation error interrupt vector value addition. Or less identical.
186 set_trap_gate (1,& debug );
187 set_trap_gate (2,& nmi );
188 set_system_gate (3 & int3 ); / * Int3-5 can be called from all * /
189 set_system_gate (4 & overflow );
190 set_system_gate (5 & bounds );
191 set_trap_gate (6 & invalid_op );
192 set_trap_gate (7 & device_not_available );
193 set_trap_gate (8,& double_fault );
194 set_trap_gate (9,& coprocessor_segment_overrun );
195 set_trap_gate (10 & invalid_TSS );
196 set_trap_gate (11 & segment_not_present );
197 set_trap_gate (12 & stack_segment );
198 set_trap_gate (13 & general_protection );
199 set_trap_gate (14 & page_fault );
200 set_trap_gate (15 & reserved );
201 set_trap_gate (16 & coprocessor_error );
// will int17-48 first trap door are set to reserved, after every hardware will be re-set their own trap door during initialization.
202 for (i = 17; i <48; i ++)
203 set_trap_gate (I, & reserved );
204 set_trap_gate (45 & irq13 ); // set coprocessor trap door.
205 outb_p ( inb_p (0x21) & 0xfb, 0x21); // allow IRQ2 master chip 8259A interrupt request.
206 outb ( inb_p (0xA1) & 0xdf, 0xA1); // Allow the 8259A chip IRQ13 interrupt request.
207 set_trap_gate (39 & parallel_interrupt ); // set parallel port trapdoor.
208 }
209

5.5.3 Other Information

5.5.3.1 The basic format of the embedded assembler

This section is the first contact to the source program in the kernel C Language embedded assembly code. Since we usually C Preparation process language program

generally will not use the embedded assembler, so here it is necessary to conduct a brief description of its basic format, a detailed description can be found in GNU gcc Manual [ 5] The

first 4 Chapter content ( Extensions to the C Language Family ), Or see reference [ 20]

( Using Inline Assembly with gcc ).

The basic format with input and output parameters for the embedded assembly:

asm ( " Assembly statement "

: Output register

: Input Register

: A register will be modified );

--110--
5.5 traps.c program

Wherein, "compilation of statements" is where you write the assembler instruction; "output register" this indicates when executing the embedded assembly, which registers

for storing the output data. Here, these registers respectively correspond to a C Language expression or a memory address; "input register" represents an input value at the start of

assembly code execution, the register number specified here should be stored, and they correspond to the one C Variable or constant values. Here we use examples to illustrate

the use of the embedded assembler statement.

Here we present the previous code first twenty two Lines starting with a piece of code as an example to explain in detail, in order to see this code we have been

rearranged and numbers.

01 #define get_seg_byte (Seg, addr) \

02 ({\
03 register char __res; \

04 __asm ​__ ( "push %% fs; \


05 mov %% ax, %% fs; \
06 movb %% fs:% 2, %% al; \
07 pop %% fs "\
08 : "= A" (__res) \
09 : "" (Seg), "m" (* (addr))); \

10 __res;})

This 10 It defines a line of code embedded assembly language macro function. Usually compiled the most convenient way is to put them in the statement within a macro.

Combination with parentheses, statements (statement braces) may be used as the expression, wherein the last variable __ res (First 10

Row) is the output value of the expression.

Because the macro statement is necessary to define on one line, hence the use of the backslash '\' connect these statements in a row. This macro definition will be replaced

to the location where the macro name is referenced in the program. The first 1 Line defines the name of the macro, that macro function name get_seg_byte (seg, addr) . The first 3 Line

defines a variable register __ res . The first 4 __ on line asm__ It represents the beginning of the embedded assembler statements. From 4 To row 7 Row 4 article AT & T Compilation of

statements format.

The first 8 Output register row that is, the meaning of the phrase after the end of the run code eax Value represents a register in a __ res

Variables, as an output value of this function, "= a " middle" a " Loading code is called, "=" indicates that this is the output register. The first 9 The bank said in this code starts running

seg Put eax Register, "" indicates the output of the same positions above the same register. and(*( addr))

It represents a memory address offset value. In order to use the address value in the above assembler statements embedded assembler output and input registers predetermined

uniform sequentially numbered sequentially from top to bottom from left to right sequence from the output register "% 0 " Start, were recorded as% 0 ,% 1 , …%9 . Thus, the output of the

register number is% 0 (There is only one output register), the first part of the input register ( "" ( seg)) The number is% 1 Then part number is% 2 . The above first 6 % On line 2 Which

represents the (* ( addr)) The memory offset.

Now let's study 4-7 Role of the code on the line. The first sentence fs The contents of the stack segment register; the second sentence eax The value assigned to segment fs

Segment register; is the third sentence fs: (* (addr)) Bytes into the designated al Register. When executing the compiled statements, output register eax Value will be placed __ res As

the macro function (block structure expression) return value. Very simple, is not it?

Through the above analysis, we know the name of the macro seg On behalf of a specified memory segment value, while addr It indicates a memory address offset amount.

Until now, we should be clear that the function of this program, right! The macro function is a function to take a byte from the memory address specified segment and an offset value.

In one example look.

01 asm ( "cld \ n \ t"

02 "Rep \ n \ t"

03 "Stol"

--111--
5.5 traps.c program

04 : / * No output register * /

05 : "C" (count-1), "a" (fill_value), "D" (dest)

06 : "% Ecx", "% edi");

1-3 This is usually three lines of assembler statements for clear direction, repeats the stored value. The first 4 This line illustrates the embedded assembler

output register is not used. The first 5 Meaning the line is: will count-1 The value is loaded into ecx Register (loaded code " c " ), fill_value Loaded into eax in, dest Put edi in.

Why should gcc Compiler to do such a load register values, and not let ourselves do it? because gcc As it can be some register allocation optimization. E.g fill_value Value

may have been eax in. If you are in a loop in it, gcc They may remain in operation throughout the cycle eax , So that you can use less of each cycle in a

movl Statements.

The last line of action is to tell gcc The values ​of these registers has changed. Very strange, right? However, in gcc Know what you do to get these registers after, this is

indeed capable of gcc Optimizing operational help. table 5-2 It is something you might use the register to load the code and specific meaning.

table 5-2 Common Storage Loaded Code Description

Code Explanation Code Description

a Use register eax m Use memory address

b Use register ebx o And using the memory address offset value may be added

c Use register ecx I Constant use 0-31

d Use register edx J Constant use 0-63

S use esi K Constant use 0-255

D use edi L Constant use 0-65535

Dynamic allocation byte addressable register ( eax


q M Constant use 0-3
, ebx , ecx or edx )

r Dynamically allocated register using any N use 1 Byte constants ( 0-255 )

GM can use a valid address ( eax , ebx , ecx , edx Or


g O Constant use 0-31
memory variable)

A use eax versus edx joint( 64 Bit)

The following examples are not to let yourself which variables specify which registers, but let gcc Choose for you.

01 asm ( "leal (% 1,% 1, 4),% 0"

02 : "= R" (y)

03 : "0" (x));

The first sentence of assembly statement leal (r1, r2,4), r3 Statement indicates r1 + r2 * 4 r3 . This example can be very quickly x Multiply 5 . among them

"0%", "% 1" Refers to gcc Automatically register allocation. Here"% 1" Represents the input value x To put in the register, "% 0 " It represents the output value register. Before the

output of the register number is equal to the code must be added. If the input code register is 0 Or is empty, then use the same corresponding output register. So, if gcc will r Appointed

as eax , Then the compilation is the meaning of the statement above:

"Leal (eax, eax, 4), eax"

--112--
5.6 system_call.s program

Note: While executing code, if you do not want the statement to be compiled gcc Optimization and move where you need to asm Add symbol behind

volatile Key words:

asm volatile (......);


Or a more detailed explanation as follows:

__asm__ __volatile__ (......);

In the following example with a long, if you can understand, it shows that embed assembly code for you, basically no problem. This code is from include / string.h

File removal is strncmp () Implementation of string comparison functions. It should be noted that each line in the "\ n \ t " For gcc Attractive preprocessor output list is

provided, meaning C The same language.

//// string 1 is compared with the first count characters of the string 2. // Parameters: cs - string 1, ct - 2, count

the string - the number of characters to compare.

//% 0 - eax (__ res) returns the value,% 1 - edi (cs) string pointer 1,% 2 - esi (ct) string pointer 2,% 3 - ecx (count). // Returns: 1 if the
string> string 2, 1 is returned; string string 2 = 1, 0 is returned; string 1 <string 2, -1 is returned. extern inline int strncmp (Const char * cs, const
char * ct, int count ) {

register int __res; // __res is register variables.


__asm ​__ ( "cld \ n" // clear direction bit.

"1: \ tdecl% 3 \ n \ t" // count--.


"Js 2f \ n \ t" // If count <0, the reference numeral 2 to jump forward.

"Lodsb \ n \ t" // get a string of characters ds 2: [esi] al, and esi ++.
"Scasb \ n \ t" // character string and comparing al es 1 is: [edi], and edi ++.
"Jne 3f \ n \ t" // If not equal, then jump forward to numeral 3.
"Testb %% al, %% al \ n \ t" // The characters are NULL characters?

"Jne 1b \ n" // not, then jump back to number 1, the comparison continues.

"2: \ txorl %% eax, %% eax \ n \ t" // is NULL character, eax cleared (return value).
"Jmp 4f \ n" 4 // jump to the label forward end.
"3: \ tmovl $ 1, %% eax \ n \ t" // eax in the set.
"Jl 4f \ n \ t" // If the previous comparison character string 2 <2 character string, returns an end.

"Negl %% eax \ n" // otherwise eax = -eax, returns a negative value, end.

"4:"
: "= A" (__res): "D" (cs), "S" (ct), "c" ( count ): "Si", "di", "cx");
return __res; // returns the result of the comparison.

5.6 system_call.s program

5.6.1 Functional Description

This program is mainly for system calls ( system_call) Interrupt int 0x80 Inlet process and a signal detection process (from the code section 80

Start line), while the two systems are given underlying interface functions, respectively, sys_execve with sys_fork . Also lists the similar process coprocessor error ( int 16) The

device does not exist ( int7) The clock interrupt ( int32) , Hard disk interrupt ( int46) , Floppy disk interrupt ( int38) The interrupt handler.

For the soft interrupt ( system_call , coprocessor_error , device_not_available) , The process is basically first calls the corresponding C Handler function to prepare some of the

parameters onto the stack, then call C Treatment of the corresponding functional function, and then the process returns

--113--
5.6 system_call.s program

FIG detected signal level to the current task, a minimum value of the reset signal and the signal processing bitmap. System calls C

Language processing functions are distributed throughout linux Kernel code, the include / linux / sys.h System array of function pointers header file to match.

For hardware interrupt request signal IRQ Sent to interrupt its processing to the interrupt controller chip is the first 8259A Send end hardware interrupt control word

instruction EOI And then call the appropriate C Function handler. For the clock interrupt also signals a bitmap of the current task detection processing.

For system calls ( int 0x80) Interrupt the process, you can see it as a " interface " program. The actual processing of each system call function basically by calling the

appropriate C Functions performed. The so-called "Bottom half" function.

This program when you enter, first check eax The function number is valid (within a given range), then save the registers will be used. Linux The default kernel ds,

es Data segment for the kernel, and fs Segments for user data. Followed by a jump address table ( sys_call_table ) Call the appropriate system call C function. in C After the

function returns, save ( push ) Call returns a value.

Next, view the status of implementation of the program of this calling process. If for the above C Function of the operating state or otherwise into the process execution state

from the other state, it has been used up or due to the time slice ( counter == 0 ), The calling process scheduling function schedule ()

( jmp _schedule ). Since the implementation of " jmp _schedule " Previously the return address ret_from_sys_call Stack, so the implementation of End schedule () After eventually

return to ret_from_sys_call Continues to perform.

From ret_from_sys_call The label at the beginning of the code to perform some post-processing system calls. The main judge whether the current process is the initial

process 0 It will exit the system calls, interrupts return. According to another code segment or stack and used to determine whether the present call is a system call process

ordinary process, if not then the kernel process (e.g., an initial process 1 ) Or other. Content is also immediately popped off the stack exit system call interrupt. End code is used to

process a call signal calling process system. If the signal process structure bitmap indicates that the process has received the signal, the signal processing function is called do_signal

() .

Finally, the program restore register contents saved, quit the interrupt processing and returns to the calling program. If the signal will be the first time " return " Corresponding

to the signal processing function to perform, and then returns to the calling system_call program of.

Figure entire process system call processing procedures 5-4 Fig.

--114--
5.6 system_call.s program

System interrupt call (eax = call number) ebx,

ecx, edx placed in call parameters

Call number out of range? Y

register stack
eax = -1

ds, es point kernel code segment fs is in the

local data segment (user data)

Call the corresponding handler C

Not Ready
Job status?

Calling schedule () Y
Time slice = 0?

Y
The initial task?

Y
user program?

N
User stack?

The minimum signal level semaphore process view

taken process, calls do_signal ()

Pop the register stack of super

Interrupt return

Map 5-4 The system interrupt call processing flow

5.6.2 Code comments

program 5-4 linux / kernel / system_call.s

1/*
2 * Linux / kernel / system_call.s
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * System_call.s contains the system-call low-level handling routines.


9 * This also contains the timer-interrupt handler, as some of the code is
10 * The same. The hd- and flopppy-interrupts are also here.
11 *
12 * NOTE: This code handles signal-recognition, which happens every time

--115--
5.6 system_call.s program

13 * After a timer-interrupt and after each system call. Ordinary interrupts


14 * Do not handle signal-recognition, as that would clutter them up totally
15 * Unnecessarily.
16 *
17 * Stack layout in 'ret_from_system_call':
18 *
19 * 0 (% esp) -% eax
20 * 4 (% esp) -% ebx
twenty one * 8 (% esp) -% ecx
twenty two * C (% esp) -% edx
twenty three * 10 (% esp) -% fs
twenty four * 14 (% esp) -% es
25 * 18 (% esp) -% ds
26 * 1C (% esp) -% eip
27 * 20 (% esp) -% cs
28 * 24 (% esp) -% eflags
29 * 28 (% esp) -% oldesp
30 * 2C (% esp) -% oldss
31 * / / *

* system_call.s file containing the system call (system-call) the underlying processing routine. As some of the code is relatively similar, so

* It also includes a clock interrupt processing (timer-interrupt) handler. Hard disk and floppy disk interrupt handler is here.

*
* Note: The code processing signal (Signal) to identify, are identified after each clock interrupts and system calls. general

* Interrupt signal does not deal with signal recognition, because the system would cause confusion.

*
* The contents of the stack when the call returns ( 'ret_from_system_call') from the system line 19-30 see above.

*/
3233 SIG_CHLD
17 = # Defined SIG_CHLD signal (child process to stop or end).
3435 EAX
= 0x00 # Stack offset position of each register.
36 EBX = 0x04
37 ECX = 0x08
38 EDX = 0x0C
39 FS = 0x10
40 ES = 0x14
41 DS = 0x18
42 EIP = 0x1C
43 CS = 0x20
44 EFLAGS = 0x24
45 OLDESP = 0x28 # When a privilege level change.

46 OLDSS = 0x2C
47
# These are the offset values ​task structure (the task_struct) variables, see include / linux / sched.h, 77 line begins.
48 state =0 # these are offsets into the task-struct. # process status code
49 counter = 4 # Task running time count (decrement) (ticks), run time slice.
50 priority = 8 // Run priority number. Task starts running counter = priority, the greater the longer run.
51 signal = 12 // bitmap is a signal, each bit represents a signal, the signal value of the bit offset value = +1.

52 sigaction = 16 # MUST be 16 (= len of sigaction) // sigaction structure length must be 16 bytes. // structure array attributes performs signal offset

value, and the operation information corresponding to the signal flag to be performed.

53 blocked = (33 * 16) // Offset of the blocking signal by the bitmap.

54

--116--
5.6 system_call.s program

# The following definitions sigaction structure offsets, see include / signal.h, line 48 starts.
55 # Offsets within sigaction
56 sa_handler = 0 // handles a signal processing process (descriptor).

57 sa_mask = 4 // semaphore mask


58 sa_flags = 8 // set of signals.
59 sa_restorer = 12 // restore function pointer, see kernel / signal.c.
6061 nr_system_calls = 72
# The total number of system version 0.11 Linux kernel calls.

6263 / *

64 * Ok, I get parallel printer interrupts while using the floppy for some
65 * Strange reason. Urgel. Now I just ignore them.
66 * / / *

* Well, when you use the floppy drive I get a parallel printer interrupt, very strange. Oh, whatever it is now.
*/
# Defining the entry point.

67 .globl _system_call, _sys_fork, _timer_interrupt, _sys_execve


68 .globl _hd_interrupt, _floppy_interrupt, _parallel_interrupt
69 .globl _device_not_available, _coprocessor_error
70
# System call number wrong.
71 .align 2 # Memory 4 byte alignment.
72 bad_sys_call:
73 movl $ -1,% eax # eax mid-1, exits the interrupt.
74 iret
# Re-execute the scheduler entry. Schedule in the scheduler (kernel / sched.c, 104).
75 .align 2
76 reschedule:
77 pushl $ ret_from_sys_call # The ret_from_sys_call address stack (101 lines).
78 jmp _schedule
# # # # int 0x80 --linux system calls the entry point (to call interrupt int 0x80, eax is call number).
79 .align 2
80 _system_call:
81 cmpl $ nr_system_calls-1,% eax # If the call number is out of range, then it is set to -1 and exit in eax.
82 ja bad_sys_call
83 push% ds # Save the original segment register values.

84 push% es
85 push% fs
86 pushl% edx # Corresponding C language function call parameters ebx, ecx, edx placed in the system call.

87 pushl% ecx # push% ebx,% ecx,% edx as parameters


88 pushl% ebx # to the system call
89 movl $ 0x10,% edx # set up ds, es to kernel space
90 mov% dx,% ds # ds, es to the kernel data segment (global descriptor table data segment descriptors).

91 mov% dx,% es
92 movl $ 0x17,% edx # fs points to local data space
93 mov% dx,% fs # fs is in the local data segment (local descriptor table descriptor data).
# Sentence following meanings operands are: call address = _sys_call_table +% eax * 4. See instructions after the list.
# Corresponding to the C program sys_call_table include / linux / sys.h in which is defined a 72 comprises
# Address array system call table C handler.
94 call _sys_call_table (,% eax, 4)
95 pushl% eax # The system call returns the value of the stack.

96 movl _current,% eax # Take the current task (process) data structure address eax.

--117--
5.6 system_call.s program

# Below 97-100 row view the current running status of the task. If not in the ready state (state is not equal to 0) went to perform scheduling program.

# If the task in the ready state, but its time slice has run out (counter = 0), but also to perform the scheduler.
97 cmpl $ 0, state (% eax) # State
98 jne reschedule
99 cmpl $ 0, counter (% eax) # Counter
100 je reschedule
# The following code performs after returning from a system call C functions, the amount of the signal recognition process.

101 ret_from_sys_call:
# First, determine whether the current task is the initial task task0, is if you do not have to process it semaphore aspects of direct return.
# _task on line 103 corresponding to the task program C [] array, corresponds to a reference direct reference task task [0].

102 movl _current,% eax # task [0] can not have signals
103 cmpl _task,% eax
104 je 3f # Forward (Forward) 3 jump to label.
# By checking the original call selector program code to determine whether the calling program is the kernel task (e.g., task 1). If it is directly
# Exit interrupt. Otherwise, for the average amount of signal processing process need be. Comparison operators choose here the average user to select whether the code segments

# Fu 0x000f (RPL = 3, the local table, the first segment (code segments)). If not, the program exits the interrupt jump.
105 cmpw $ 0x0f, CS (% esp) # was old code segment supervisor?
106 jne 3f
# If the original stack segment selector is not 0x17 (i.e., the original user is not in the stack data segment) is dropped out.

107 cmpw $ 0x17, OLDSS (% esp) # was stack segment = 0x17?


108 jne 3f
# The following code fragment (109-120) was the first use of the current task takes the signal bitmap structure (32, signals each representative of one kind),

# Signal is then blocked task structure (masking) code, the signal blocking allowed bits, to obtain the minimum value of the signal value, then

# Bitmap original signal corresponding to the signal bit is reset (set to 0), the last one of the signal value as a parameter called do_signal ().

# do_signal () in (kernel / signal.c, 82), which is pushed onto the stack 13 including the parameter information.

109 movl signal (% eax),% ebx # FIG signal bit taken ebx, each one representative of one kind of signal, a total of 32 signals.

110 movl blocked (% eax),% ecx # Take obstruction (masking) signal bitmap ecx.
111 notl% ecx # Each negated.

112 andl% ebx,% ecx # Obtain permission bitmap signal.

113 bsfl% ecx,% ecx # From the low (0 bit) to start scanning the bitmap to see whether there was 1,

# If so, the reserved bit ecx offset value (i.e., the first of several 0-31).
114 je 3f # If no signal then jumps forward to exit.
115 btrl% ecx,% ebx # The reset signal (the original signal containing a bitmap EBX).

116 movl% ebx, signal (% eax) # Resave signal bitmap information current-> signal.
117 incl% ecx # The signal is adjusted to 1 starting from the number (1-32).

118 pushl% ecx # Signal values ​onto the stack as one of the parameters of the call do_signal.

119 call _do_signal # C function call signal processing program (kernel / signal.c, 82)
120 popl% eax # Pop-up signal value.

121 3: popl% eax


122 popl% ebx
123 popl% ecx
124 popl% edx
125 pop% fs
126 pop% es
127 pop% ds
128 iret
129
# # # # int16 - The following code error signal is issued by the coprocessor processing. Branch to the C function math_error ()
# (Kernel / math / math_emulate.c, 82), after the return to the jump ret_from_sys_call continues execution.
130 .align 2
131 _coprocessor_error:
132 push% ds
133 push% es

--118--
5.6 system_call.s program

134 push% fs
135 pushl% edx
136 pushl% ecx
137 pushl% ebx
138 pushl% eax
139 movl $ 0x10,% eax # ds, es is set to point to the kernel data segment.

140 mov% ax,% ds


141 mov% ax,% es
142 movl $ 0x17,% eax # fs is set to point to the local data segment (data segment program error).

143 mov% ax,% fs


144 pushl $ ret_from_sys_call # The following call returns the address of the stack.

145 jmp _math_error # C function performed math_error () (kernel / math / math_emulate.c, 37)
146
# # # # int7 - device does not exist or coprocessor is not present (Coprocessor not available).
# If the control register CR0 EM flag is set, then when the CPU executes a command ESC Escape will trigger the interrupt, so that
# This may be an opportunity for the interrupt handler analog ESC Escape command (line 169).

# CR0 of TS flag is set when the CPU executes a task switch. TS may be used to determine when the contents of the coprocessor (context)
# The task being performed and the CPU does not match up. When the CPU is running an escaped discovery TS instruction set, it will lead to the interruption.

# At this point you should restore the coprocessor to perform a new task state (165 lines). See (kernel / sched.c, 77) in FIG.
# The interrupt will be transferred to the final execution continues at label ret_from_sys_call (detect and process signals).

147 .align 2
148 _device_not_available:
149 push% ds
150 push% es
151 push% fs
152 pushl% edx
153 pushl% ecx
154 pushl% ebx
155 pushl% eax
156 movl $ 0x10,% eax # ds, es is set to point to the kernel data segment.

157 mov% ax,% ds


158 mov% ax,% es
159 movl $ 0x17,% eax # fs is set to point to the local data segment (data segment program error).

160 mov% ax,% fs


161 pushl $ ret_from_sys_call # The return address is stacked below the jump or call.

162 clts # clear TS so that we can use math


163 movl% cr0,% eax
164 testl $ 0x4,% eax # EM (math emulation bit)
# If it is not caused by EM is interrupted, the new recovery task coprocessor state,

165 je _math_state_restore # C function performed math_state_restore () (kernel / sched.c, 77).


166 pushl% ebp
167 pushl% esi
168 pushl% edi
169 call _math_emulate # Call C functions math_emulate (kernel / math / math_emulate.c, 18).
170 popl% edi
171 popl% esi
172 popl% ebp
173 ret # ret here will jump to ret_from_sys_call (101 lines).
174
# # # # int32 - (int 0x20) clock interrupt handler. Interrupt frequency is set to 100Hz (include / linux / sched.h, 5),
# Timing chip is initialized in 8253/8254 (kernel / sched.c, 406) at. Thus here jiffies plus 1 every 10 milliseconds.
# This code will jiffies is incremented by one, sent commands to the end of 8259 interrupt controller, and then with the current privilege level as a parameter called

# C function do_timer (long CPL). When the call returns turn to detect and process signals.

--119--
5.6 system_call.s program

175 .align 2
176 _timer_interrupt:
177 push% ds # save ds, es and put kernel data space
178 push% es # into them.% fs is used by _system_call
179 push% fs
180 pushl% edx # we save% eax,% ecx,% edx as gcc does not
181 pushl% ecx # save those across function calls.% ebx
182 pushl% ebx # is saved as we use that in ret_sys_call
183 pushl% eax
184 movl $ 0x10,% eax # ds, es is set to point to the kernel data segment.

185 mov% ax,% ds


186 mov% ax,% es
187 movl $ 0x17,% eax # fs is set to point to the local data segment (data segment program error).

188 mov% ax,% fs


189 incl _jiffies
# Since no automatic initialization EOI interrupt control chip, so there need to send instructions to the hardware interrupt ends.

190 movb $ 0x20,% al # EOI to interrupt controller # 1


191 outb% al, $ 0x20 # Operation Command Word OCW2 feed port 0x20.

# 3 do_timer parameter selector is removed from the current privilege level (0 or 3) pushed onto the stack, as below.
192 movl CS (% esp),% eax
193 andl $ 3,% eax # % Eax is CPL (0 or 3, 0 = supervisor)
194 pushl% eax
# do_timer (CPL) to perform task switching, timing, etc., in kernel / shched.c, 305-line implementation.
195 call _do_timer # 'Do_timer (long CPL)' does everything from
196 addl $ 4,% esp # task switching to accounting ...
197 jmp ret_from_sys_call
198
# # # # This is sys_execve () system call. Take interrupt call program code to call the C function pointer as an argument do_execve ().
# do_execve () in the (fs / exec.c, 182).
199 .align 2
200 _sys_execve:
201 lea EIP (% esp),% eax
202 pushl% eax
203 call _do_execve
204 addl $ 4,% esp # EIP pushed onto the stack when the pressure dropped calls.

205 ret
206
# # # # sys_fork () call for creating a child process is system_call function 2. Prototype in include / linux / sys.h in.
# First call C functions find_empty_process (), to obtain a process ID pid. If the mission returns negative then the current array
# Full. Then call copy_process () replication process.
207 .align 2
208 _sys_fork:
209 call _find_empty_process # Call find_empty_process () (kernel / fork.c, 135).
210 testl% eax,% eax
211 js 1f
212 push% gs
213 pushl% esi
214 pushl% edi
215 pushl% ebp
216 pushl% eax
217 call _copy_process # Call C functions copy_process () (kernel / fork.c, 68).
218 addl $ 20,% esp # Discard all here to push content.
219 1: ret

--120--
5.6 system_call.s program

220
# # # # int 46 - (int 0x2E) hard interrupt handler, in response to a hardware interrupt request IRQ14.
# When the operation is complete or the hard disk will issue this error interrupt signal. (See kernel / blk_drv / hd.c).

# 8259A interrupt controller from the first to the end of the chip transmission hardware interrupt instruction (EOI), then the function takes a pointer variable do_hd placed in edx

# Register juxtaposed do_hd is NULL, then the function determines whether the pointer is NULL edx. If it is empty, then assign points to edx

# unexpected_hd_interrupt (), to display an error message. EOI command is then sent to the master chip 8259A, and the call edx
# Function pointer: read_intr (), write_intr () or unexpected_hd_interrupt ().
221 _hd_interrupt:
222 pushl% eax
223 pushl% ecx
224 pushl% edx
225 push% ds
226 push% es
227 push% fs
228 movl $ 0x10,% eax # ds, es set kernel data segment.
229 mov% ax,% ds
230 mov% ax,% es
231 movl $ 0x17,% eax # fs is set to a local data segment of the calling program.

232 mov% ax,% fs


# Since no automatic initialization EOI interrupt control chip, so there need to send instructions to the hardware interrupt ends.

233 movb $ 0x20,% al


234 outb% al, $ 0xA0 # EOI to interrupt controller # 1 # Sent from the 8259A.

235 jmp 1f # give port chance to breathe


236 1: jmp 1f # Delay effect.
237 1: xorl% edx,% edx
238 xchgl _do_hd,% edx # do_hd defined as a function pointer, will be assigned read_intr () or
# write_intr () function addresses. (Kernel / blk_drv / hd.c)
# Into the register edx do_hd after the pointer variable is set to NULL.
239 testl% edx,% edx # Test whether the function pointer Null.
240 jne 1f # If empty, the pointer points to a C function unexpected_hd_interrupt ().
241 movl $ _unexpected_hd_interrupt,% edx # (Kernel / blk_drv / hdc, 237).
242 1: outb% al, $ 0x20 # 8259A interrupt controller to send EOI command master (End hardware interrupt).

243 call *% edx # "Interesting" way of handling intr.


244 pop% fs # The sentence calling do_hd point C function.
245 pop% es
246 pop% ds
247 popl% edx
248 popl% ecx
249 popl% eax
250 iret
251
# # # # int38 - (int 0x26) floppy disk drive interrupt handler, in response to a hardware interrupt request IRQ6.
# Its processing and handling the hard face essentially the same. (Kernel / blk_drv / floppy.c).
# First 8259A interrupt controller to send EOI command master chip, then the function takes a pointer variable do_floppy placed in eax

# Register juxtaposed do_floppy is NULL, then the function determines whether the pointer is NULL eax. Such as empty, then assign points to eax

# unexpected_floppy_interrupt (), to display an error message. Then call the function eax points: rw_interrupt,
# seek_interrupt, recal_interrupt, reset_interrupt or unexpected_floppy_interrupt.
252 _floppy_interrupt:
253 pushl% eax
254 pushl% ecx
255 pushl% edx
256 push% ds
257 push% es

--121--
5.6 system_call.s program

258 push% fs
259 movl $ 0x10,% eax # ds, es set kernel data segment.
260 mov% ax,% ds
261 mov% ax,% es
262 movl $ 0x17,% eax # fs is set to a local data segment of the calling program.

263 mov% ax,% fs


264 movb $ 0x20,% al # 8259A interrupt controller to send EOI command master (End hardware interrupt).

265 outb% al, $ 0x20 # EOI to interrupt controller # 1


266 xorl% eax,% eax
267 xchgl _do_floppy,% eax # do_floppy is a function pointer, will be assigned the function of actual processing C program,

# Into the eax register after the pointer variable do_floppy blank.
268 testl% eax,% eax # Whether the test function pointer = NULL?

269 jne 1f # If empty, the pointer points to a C function unexpected_floppy_interrupt ().


270 movl $ _unexpected_floppy_interrupt,% eax
271 1: call *% eax # "Interesting" way of handling intr.
272 pop% fs # Do_floppy sentence calls the function pointed.
273 pop% es
274 pop% ds
275 popl% edx
276 popl% ecx
277 popl% eax
278 iret
279
# # # # int 39 - (int 0x27) parallel port interrupt handler corresponding to a hardware interrupt request signal IRQ7.
# This version of the kernel has not been achieved. Here just send EOI command.

280 _parallel_interrupt:
281 pushl% eax
282 movb $ 0x20,% al
283 outb% al, $ 0x20
284 popl% eax
285 iret

5.6.3. Other Information

5.6.3.1 GNU Assembly language 32 Bit addressing mode

Uses AT & T The assembly language syntax. 32 Regular-bit addressing format is as follows:

AT & T: immed32 (basepointer, indexpointer, indexscale) Intel:

[basepointer + indexpointer * indexscal + immed32]

The calculated position addressing format is: immed32 + basepointer + indexpointer * indexscale

In the application, you do not need to write all of these fields, but immed32 with basepointer Among the must have a presence. Here are some examples.

o For a specified C Addressing linguistic variables:

AT & T: _booga Intel: [_booga]


Note: underscore before the variable was static (global) from the assembly program C variable( booga) Methods.

o Contents of the register address location pointed to:

AT & T: (% eax) Intel: [eax]


o The content of the register as a base address of a variable:

--122--
5.7 mktime.c program

AT & T: _variable (% eax) Intel: [eax + _variable]


o Addressing an array of integer values ​(the ratio is 4 ):

AT & T: _array (,% eax, 4) Intel: [eax * 4 + _array]

o Use direct byte offset:


for C Language: * ( p + 1) among them p It is a pointer to a character char * AT & T: then AT & T format:

1 (% eax) among them eax Is p Value. Intel: [eax + 1]

o in a 8 Recording a byte addressable array of characters specified. among them eax The record number is specified, ebx Are specified character offset address in the

record:

AT & T: _array (% ebx,% eax, 8) Intel: [ebx + eax * 8 + _array]

5.7 mktime.c program

5.7.1 Functional Description

This is only a function of the program mktime () , Only the kernel. Calculated from 1970 year 1 month 1 day 0 When the number of seconds to play after the date of the boot,

as boot time.

5.7.2 Code comments

program 5-5 linux / kernel / mktime.c program

1/*
2 * Linux / kernel / mktime.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <time.h>
// time header file that defines the data structure of the standard time tm some processing time and function prototypes.

89 / *

10 * This is not the library routine, it is only used in the kernel.


11 * As such, we do not care about years <1970 etc, but assume everything
12 * Is ok. Similarly, TZ etc is happily ignored. We just do everything
13 * As easily as possible. Let's find something public for the library
14 * Routines (although I think minix times is public).
15 * /
16 / *
17 . * PS I hate whoever though up the year 1970 - could not they have gotten
18 * A leap-year instead? I also hate Gregorius, pope or no. I'm grumpy.
19 * /
/*
* This is not a library function, it is only used by the kernel. Therefore, we do not care about less than the year 1970 and so on, but assumed everything was normal.

* Similarly, the time zone TZ first while ignoring the problem. We are just as simple as possible to deal with the problem. Best to find some public libraries

* (Although I think it's a function of time minix it is public).


* Also, I hate the people that set the start of 1970 - they do not choose to start from a leap year? I hate the Gregorian calendar,
* Pope, bishops, I do not care. I'm a grumpy person.
*/
20 #define MINUTE 60 // 1 minute seconds.

--123--
5.7 mktime.c program

twenty one #define HOUR (60 * MINUTE ) // 1 hour in seconds.


twenty two #define DAY (twenty four* HOUR ) // 1 day in seconds.
twenty three #define YEAR (365 * DAY ) // the number of seconds a year.

2425 / * Interestingly, we assume leap-years * /

/ * It is interesting to take into account the leap year * /

// following an annual limit, it defines the number of seconds the array at the beginning of each month.

26 static int month [12] = {


27 0
28 DAY * (31),
29 DAY * (31 + 29),
30 DAY * (31 + 29 + 31),
31 DAY * (31 + 29 + 31 + 30),

32 DAY * (31 + 29 + 31 + 30 + 31),

33 DAY * (31 + 29 + 31 + 30 + 31 + 30),

34 DAY * (31 + 29 + 31 + 30 + 31 + 30 + 31),

35 DAY * (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31),

36 DAY * (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30),

37 DAY * (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31),

38 DAY * (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30)

39 };
40
// This function computing power on the day after the number of seconds to play from 1 January 1970 at 0:00, as the start time.

41 long kernel_mktime (Struct tm * tm )


42 {
43 long res;
44 int year;
4546
year = tm -> tm_year - 70; // 70 years from now the number (2 representation) of years elapsed, // so there

will be 2000 problem.

47 / * Magic offsets (y + 1) needed to get leapyears right. * /


/ * In order to obtain the correct number of leap years, where the need for such a magical bias value (y + 1) * /

48 res = YEAR * Year + DAY * ((Year + 1) / 4); // number of seconds elapsed time in the multi-+ 1 day each leap year

49 res + = month [ tm -> tm_mon]; // the number of seconds of time, plus the number of seconds in a year when the month.

50 / * And (y + 2) here. If it was not a leap-year, we have to adjust * /


/ * And (y + 2). If (y + 2) is not a leap year, then we have to be adjusted (by subtracting the number of seconds the time of day). * /

51 if ( tm -> tm_mon> 1 && ((year + 2)% 4))


52 res - = DAY ;
53 res + = DAY * ( tm -> tm_mday-1); // the number of seconds plus the time the number of days in the past month.

54 res + = HOUR * tm -> tm_hour; // the number of seconds plus the time of day in the past several hours.

55 res + = MINUTE * tm -> tm_min; // the number of seconds plus time within a few minutes past the hour.

56 res + = tm -> tm_sec; // plus the number of seconds elapsed within 1 minute.

57 return res; // That is equal to the number of seconds elapsed time since 1970.

58 }
59

5.7.3 Other Information

5.7.3.1 Calculation time leap year

Basic calculation leap year is: if y Can be 4 Divisible and can not be 100 Divisible, or can be 400 Divisible, then y It is a leap

year.

--124--
5.8 sched.c program

5.8 sched.c program

5.8.1 Functional Description

sched.c It is the kernel function of task scheduling procedures, including the basic functions related to scheduling ( sleep_on , wakeup ,

schedule Etc.) and some simple system calls (such as getpid () ). Other Linus In order to facilitate programming, taking into account the timing of the floppy disk drive requires a

program, it will also operate several functions into a floppy disk here.

Code these basic functions, though not long, but some abstract and difficult to understand. Fortunately, There are many textbooks this explanation was very clear, so

you can refer to other books discussion of these functions. The target is focuses on textbooks, books or theory, there is nothing to talk about the ☺ . Here only the scheduling

function schedule () Some clarification.

schedule () The function first of all tasks (processes) to detect any task a wake-up signal has been. The specific method is for each task in the task

array, check alarm timer value alarm . If the task of alarm Time has expired ( alarm <jiffies),

Signal is provided at its bitmap SIGALRM Signal, then clear alarm value. jiffies Is the number of ticks of the system begin to run from the boot ( 10ms /

Tick). in sched.h Defined. If the external signal is blocked there are other signals to remove signals bit map process, and the task in interruptible sleep state ( TASK_INTERRUPTIBL

), Then set the task to the ready state ( TASK_RUNNING ).

Followed by a core processing part of the scheduling function. This code is based on the time slice and priority of the process scheduling mechanism to select the task to

be performed next. It first checks the task loop array all tasks, task ready state according to each value of the remaining implementation time counter Select the maximum value of a

task, and using switch_to () To the task switching function. The ready state if the value of all the tasks are equal to zero, represents a time slice at the moment all the tasks have

been run to completion, so the priority value based on the task priority Run time slice value reset each task counter And then re-execute cycle check all task execution time slice

value.

The other two worth mentioning that the function is automatically enter sleep function sleep_on () And wake-up function wake_up () These two functions, although very short,

but better than schedule () Function difficult to understand. Here it is explained by way of illustration. general speaking, sleep_on () The main function is the function when a process

(or task) the requested resource is busy or not in memory temporarily switched out, waiting in the queue waiting for some time. It continues to run when switched back again. Way

into the queue is the use of the function tmp Contact pointer as each is waiting for the task.

Party function involves the task of the three pointer operations: * p , tmp with current * p Waiting queue head pointer, such as the file system memory

i Node i_wait Pointer, the buffer memory operation buffer_wait Pointer or the like; tmp It is a temporary pointer; current It is the current task pointer. For those changes in the pointer

memory, we can use FIG. 5-5 Schematic description. An elongated figure represents a sequence of bytes of memory.

When entering the function

tmp *P current

Original task waiting Current task

When calling schedule ()

tmp *P current

Original task waiting Current task

Map 5-5 sleep_on () A function pointer changes FIG.

When first entered the function, the queue head pointer * p It has been directed (descriptor process) waiting in the task waiting in the queue structure. Of course, at the

beginning of the implementation of the system, no waiting on the queue of waiting tasks. So the image above the original waiting task at the beginning does not exist at this time

--125--
5.8 sched.c program

* P direction NULL . By pointer operations, before calling the scheduler, the queue head pointer to the current task structure, and the function of temporary pointer tmp Pointing to
the original waiting tasks. When so by the action of the temporary pointer, in several processes waiting for the same resources and multiple calls to this function, the program
implicitly construct a waiting queue. D 5-6 We can more easily understand sleep_on () Formation waiting queue function. It is shown when inserted into the third task of the head of
the queue situation.

Tmp pointer Tmp pointer Tmp (NULL)


Function block

Queue head pointer


buffer_wait The current Task 2 to wait Waiting for Task 1
task current task2 task1
Task structure
task

Map 5-6 sleep_on () Implicit function of the task queue.

After insertion waiting queue, sleep_on () Function will be called schedule () Function to execute another process. When the process is awakened and re-execute executes

subsequent statements, than it is to early to enter the queue waiting for a wake-up process.

Wake manipulation functions wake_up () Waiting for the available resources of designated tasks set to the ready state. This function is a generic wakeup function. In some

cases, for example, reading data blocks on the disk, either due to waiting tasks in the queue may be to wake up, and therefore also need to be awakened pointer structure blanking

task. Thus, in the subsequent process goes to sleep but was awakened re-executed sleep_on () When, in the process you do not need to wake up.

There is also a function interruptible_sleep_on () Its structure and sleep_on () Of essentially similar, but prior to the current task scheduling is set to become an interruptible

wait state, and also need to queue on after this task is awakened if there are subsequent waiting tasks, and if so, schedule them to run. In the kernel 0.12 Start, these two functions

are combined, only the status of the task as a parameter to distinguish between the two cases.

When reading the code of this document, preferably while the reference file comprising include / kernel / sched.h Comments in the file, in order to more clearly understand

the mechanism of the kernel scheduler.

5.8.2 Code comments

program 5-6 linux / kernel / sched.c

1/*
2 * Linux / kernel / sched.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * 'Sched.c' is the main kernel file. It contains scheduling primitives


9 * (Sleep_on, wakeup, schedule etc) as well as a number of simple system
10 * Call functions (type getpid (), which just extracts a field from
11 * Current-task
12 * /
/*
* 'Sched.c' main kernel file. Including the basic functions related to scheduling (sleep_on, wakeup, schedule, etc.) and

--126--
5.8 sched.c program

* Some simple system calls (such as getpid (), get a field only from the current job).
*/
13 #include <linux / sched.h> // scheduler header file. It defines the task structure task_struct, a first initial tasks
// The data. There are some in the form of a macro definition of the relevant descriptor parameters set and get the // embedded

assembly function procedures.

14 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

15 #include <linux / sys.h> // header file system calls. System containing 72 C function call handler to 'sys_' beginning.

16 #include <linux / fdreg.h> // floppy header. Definitions of parameters comprises the floppy disk controller.

17 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

18 #include <asm / io.h> // io header files. Defined hardware port I / O macro assembler statements.

19 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

2021 #include <signal.h>


// signal header files. Signal defined symbolic constant, the sigaction structure, operation, function prototype.

2223 #define _S (Nr) (1 << ((nr) -1)) // nr signal takes a binary value of bits in the signal corresponding to the bitmap. Signal number 1-32.

// bitmap signal values ​such as 5 = 1 << (5-1) = 16 = 00010000b.


twenty four #define _BLOCKABLE (~ ( _S ( SIGKILL ) | _S ( SIGSTOP ))) // except SIGKILL SIGSTOP signal and the other is
// can be blocked (... 10111111111011111111b).
25
// display task number nr process ID, process status and the number of free kernel stack bytes (approximately).

26 void show_task (Int nr, struct task_struct * P)


27 {
28 int i, j = 4096-sizeof (struct task_struct );
2930
printk ( "% d: pid =% d, state =% d, ", nr, p-> pid, p-> state );
31 i = 0;
32 while (i <j &&! ((char *) (p + 1)) [i]) // after detection of the data structure of the task specified number of bytes equal to 0.

33 i ++;
34 printk ( "% d (of% d) chars free in kernel stack \ n \ r ", i, j);
35 }
36
// display all tasks task number, process ID, process status and the number of free kernel stack bytes (approximately).

37 void show_stat (Void)


38 {
39 int i;
4041
for (i = 0; i < NR_TASKS ; I ++) // NR_TASKS system can accommodate the largest process (task) number (64),

42 if ( task [I]) // definition include / kernel / sched.h line 4.


43 show_task (I, task [I]);
44 }
4546 #define LATCH (1193180 / HZ )
// definition of ticks per time slice ☺ .
4748 extern void mem_use (Void);
// [??] is not defined anywhere and reference the function.

4950 extern int timer_interrupt (Void); // clock interrupt handler (kernel / system_call.s, 176).

51 extern int system_call (Void); // system call interrupt handler (kernel / system_call.s, 80).
5253 union task_union {
// define the tasks of the Joint (structural members and task stack array of characters program members).

54 struct task_struct task ; // because the data structure and its kernel mode stack memory a task on the same page

55 char stack [ PAGE_SIZE ]; // in it from the stack segment register ss can be obtained for the data segment selector.

56 };
// each task (process) is running in kernel mode has its own kernel mode stack. Here the definition of the task structure kernel mode stack.

--127--
5.8 sched.c program

5758 static union task_union init_task = { INIT_TASK }; Data (in sched.h) // define the initial task.

5960 long volatile jiffies = 0;


// begin to run from the boot time value of ticks (10ms / tick).
// previous qualifier volatile, English interpretation is volatile, unstable meaning. This is not the required gcc // variables to optimize treatment, and do not move

position, because maybe other program to modify its value.

61 long startup_time = 0; // boot time. 0:: 0: 0 Number of seconds from the start time of 1970.

62 struct task_struct * current = ( init_task . task ); // this task pointers (initialized to initial tasks).
63 struct task_struct * last_task_used_math = NULL ; // pointer used coprocessor task.
6465 struct task_struct * task [ NR_TASKS ] = {& ( init_task . task )}; // define an array of task pointers.

6667 long user_stack [ PAGE_SIZE >> 2]; // Define the user stack, 4K. Pointer refers to the last item.

68
// This structure is used to set the stack ss: esp (data segment selector, pointer), see head.S, the first 23 rows.

69 struct {
70 long * a;
71 short b;
72 } Stack_start = {& user_stack [ PAGE_SIZE >> 2], 0x10};
73 / *
74 * 'Math_state_restore ()' saves the current math information in the
75 * Old math state array, and gets the new ones from the current task
76 * /
/*
* Saves the current contents of the old coprocessor coprocessor status array, and the current task coprocessor

* SUMMARY loaded into the coprocessor.

*/
// when the task is scheduled after exchanged, the function to save the original state of the coprocessor task (context) and resume the execution state of the coprocessor scheduling

incoming // new current task.

77 void math_state_restore ()
78 {
79 if ( last_task_used_math == current ) // If the task is not (on a task is the current task change is returned).
80 return; // Here the meaning of "on a mission" is the task just swapped out.

81 __asm ​__ ( " fwait "); // before sending the first command to send a coprocessor instruction WAIT.

82 if ( last_task_used_math ) { // If the task uses a co-processor, save its state.


83 __asm ​__ ( " fnsave% 0 "::" m "( last_task_used_math -> tss.i387));
84 }
85 last_task_used_math = current ; // Now, last_task_used_math points to the current task, // use be swapped

out to prepare for the current task.

86 if ( current -> used_math) { // If the current task coprocessor used, then restore its status.

87 __asm ​__ ( " frstor% 0 "::" m "( current -> tss.i387));


88 } Else { // Otherwise explanation is the first time,
89 __asm ​__ ( " fninit ": :); // initialization command is then sent on to the coprocessor,

90 current -> used_math = 1; // set up and use a coprocessor flag.


91 }
92 }
9394 / *

95 * 'Schedule ()' is the scheduler function. This is GOOD CODE! There


96 * Probably will not be any reason to change this, as it should work well
97 * In all circumstances (ie gives IO-bound processes good response etc).
98 * The one thing you might take a look at is the signal-handler code here.
99 *

--128--
5.8 sched.c program

100 * NOTE !! Task 0 is the 'idle' task, which gets called when no other
101 * Tasks can run. It can not be killed, and it can not sleep. The 'state'
102 * Information in task [0] is never used.
103 * /
/*
* 'Schedule ()' function is scheduled. This is a very good code! There is no reason to modify it, as it can be in all
* Work environment (such as being able to respond well to treatment boundaries, IO-). Only one thing is worth noting that the signal here
* Handling code.

* note! ! 0 task is idle ( 'idle') mission, only when no other tasks can run call it. It can not be killed
* Dead, I can not sleep. 0 task status information in a 'state' is never used.
*/
104 void schedule (Void)
105 {
106 int i, next, c;
107 struct task_struct ** p; // pointer to a structure pointer tasks.

108109 / * Check alarm, wake up any interruptible tasks that have got a signal * /

/ * Detection alarm (the alarm timer value process), wake-up interrupt tasks have been any signal * /

110
// array of tasks from the last task starts detection alarm.
111 for (p = & LAST_TASK ; P> & FIRST_TASK ; --P)
112 if (* p) {
// If the task by setting the timing value Alarm, and has expired (alarm <jiffies), then in the bitmap is set SIGALRM signal, ie // SIGALARM signal transmission tasks.

Then clear alarm. The default action of this signal is to terminate the process. // jiffies is the number of ticks from system boot since the beginning of (10ms / tick).

Sched.h definition line 139.

113 if ((* p) -> alarm && (* p) -> alarm < jiffies ) {


114 (* P) ​-> signal | = (1 << ( SIGALRM -1));
115 (* P) ​-> alarm = 0;
116 }
// If the signal in the bitmap signals are blocked except there are other signals, and the task can be interrupted in the state, the set ready state task. Wherein // '- ( _BLOCKABLE

& (* P) ​-> blocked) 'for ignoring signals is blocked, but can not be blocked SIGKILL and SIGSTOP.

117 if (((* p) -> signal & ~ ( _BLOCKABLE & (* P) ​-> blocked)) &&
118 (* P) ​-> state == TASK_INTERRUPTIBLE )
119 (* P) ​-> state = TASK_RUNNING ; // set ready (executable) state.
120 }
121 122 / * This is the scheduler proper: * /

/ * Here is the main part of the scheduler * /

123
124 while (1) {
125 c = -1;
126 next = 0;
127 i = NR_TASKS ;
128 p = & task [ NR_TASKS ];
// This code also starts a loop processing task from the last task of the array, the groove array and skip-free task. // comparing each ready state task counter

(decrement task of running time tick count) value, which value is large, the running time is not long, next to // point to which the task number.

129 while (--i) {


130 if (* -! p)
131 continue;
132 if ((* p) -> state == TASK_RUNNING && (* p) -> counter> c)
133 c = (* p) -> counter, next = i;
134 }

--129--
5.8 sched.c program

// If the comparison result obtained with a counter value greater than 0, the loop is exited 124 line starting, switching tasks (line 141).

135 if (c) break;


// Otherwise, according to the priority value of each task, the updated counter value of each task, and then return to 125-line re-compare. // counter value calculated for

the counter = counter / 2 + priority. Here the calculation does not consider the status of the process.

136 for (p = & LAST_TASK ; P> & FIRST_TASK ; --P)


137 if (* p)
138 (* P) ​-> counter = ((* p) -> counter >> 1) +
139 (* P) ​-> priority;
140 }
// switch to the next task number for the task of running. In the next row 126 are initialized to zero. Therefore, if the system does not have any other tasks // run, the next is

always 0. Therefore, the scheduling function to perform the task 0 when the system is idle. The Task execution 0 // pause () system calls only, and will call this function.

141 switch_to (Next); // switch to the next task number for the task, and run it.
142 }
143
//// pause () system call. Convert the current status of the task to be interrupted wait state, and re-scheduling. // The system call will cause the process to sleep until a

signal is received. This signal is used to terminate the process or the process calls // capture a signal function. Only when a signal is captured, the capture and signal

processing function returns, PAUSE () will return. // At this pause () Returns the value should be -1, and errno is set to EINTR. There is also not fully realized (until

version 0.95).

144 int sys_pause (Void)


145 {
146 current -> state = TASK_INTERRUPTIBLE ;
147 schedule ();
148 return 0;
149 }
150
// set the current task uninterruptible wait state, sleep and let the head of the queue pointer points to the current task. // will return only when explicitly

awakened. This function provides the synchronization mechanism between the process and the interrupt handler. // function arguments * p placed queue head

pointer is waiting tasks.

151 void sleep_on (Struct task_struct ** p)


152 {
153 struct task_struct * Tmp;
154
// If the pointer is invalid, then exit. (Object pointer may be NULL, but the pointer itself is not 0).
155 if (! p)
156 return;
157 if ( current == & ( init_task . task )) // If the current task is the task 0, then crash (impossible!).
158 panic ( ' task [0] trying to sleep ");
159 tmp = * p; // Let tmp point has been waiting for the task (if any) on the queue.
160 * P = current ; // will wait for sleep queue pointer points to the current head of the task.

161 current -> state = TASK_UNINTERRUPTIBLE ; // set the current task uninterruptible wait state.
162 schedule (); // reschedule.
// Only when the task waiting to be awakened, the scheduler just returned here, it means that the process has been explicitly awakened. // Now that everyone is waiting for the same

resources, so when resources are available, it is necessary to wake up all waiting for the resource process. // call the function nesting, nesting will wake up all waiting for the resource

process.

163 if (tmp) // If there are tasks waiting in the front, it can also be set to a ready state (wake up).

164 tmp-> state = 0;


165 }
166
// The current task is set to interruptible wait state, and placed * p specified wait queue.

167 void interruptible_sleep_on (Struct task_struct ** p)


168 {
169 struct task_struct * Tmp;

--130--
5.8 sched.c program

170
171 if (! p)
172 return;
173 if ( current == & ( init_task . task ))
174 panic ( ' task [0] trying to sleep ");
175 tmp = * p;
176 * P = current ;
177 repeat: current -> state = TASK_INTERRUPTIBLE ;
178 schedule ();
// If there are tasks waiting in the waiting queue, and the queue head pointer is pointing to the current task when the task is not, then the waiting task is set to the ready state //

run and re-executes the scheduler. * P when the pointer points to the current task is not, indicates the current task is put into the // queue, another new task is inserted into the

waiting queue, therefore, should also all other tasks waiting to be set Operating status.

179 if (* p && * p! = current ) {


180 (** p). state = 0;
181 goto repeat;
182 }
// The following code is an error, it should be * p = tmp, let the rest wait queue head pointer to the task, otherwise insert // wait before the current mandate of the task queue were

erased. Of course, also need to delete the statement on the 192 line.

183 * P = NULL ;
184 if (tmp)
185 tmp-> state = 0;
186 }
187
// wake specified task * p.
188 void wake_up (Struct task_struct ** p)
189 {
190 if (p && * p) {
191 (** p). state = 0; // set ready (operable) state.
192 * P = NULL ;
193 }
194 }
195 196 /
*
197 * OK, here are some floppy things that should not be in the kernel
198 * Proper. They are here because the floppy needs a timer, and this
199 * Was the easiest way of doing it.
200 * /
/*
* Well, from here is some information about subroutine floppy disk, this should not be placed in the main part of the kernel. Put them here
* Because the floppy needs a clock, and on here is the most convenient way.
*/
// code for this process is a timing floppy lines 201-262. Before reading this code, please look at the instructions later in the chapter about the block
device driver diskette // (floppy.c). A floppy disk or to read a block device driver code in the run. // time unit wherein: 1 tick = 1/100 sec.

// the following storage array pointer to start the process to wait for the floppy motor to normal speed. 0-3 floppy array index corresponding AD.

201 static struct task_struct * wait_motor [4] = { NULL , NULL , NULL , NULL };
// The following granduncle were stored ticks each floppy motor needed to start. Default program start time is 50 ticks (0.5 seconds).

202 static int mon_timer [4] = {0,0,0,0};


// array The following were the records of the floppy drive before the motor stops the need to maintain the time. The program is set to 10000 ticks (100 seconds).

203 static int moff_timer [4] = {0,0,0,0};


// current number corresponding to the floppy disk controller output register. Each of the register are defined as

follows: Bits 7-4 @: DA control the startup drive motor. 1-- Start; 0 - off.

--131--
5.8 sched.c program

// Bit 3: 1 - allows DMA and interrupt requests; 0 - Disabling DMA and interrupt requests. // Bit 2: 1 -
boot diskette controller; 0 - reset the floppy disk controller. // bits 1-0: 00--11 for selecting a control
floppy AD.
204 unsigned char current_DOR = 0x0C; // set the initial value here is: allow DMA and interrupt requests, started FDC.

205
// specify the floppy drive to start the waiting time required for the normal operation state. //

nr - Floppy number (0-3), the return value is the number of ticks.

206 int ticks_to_floppy_on (Unsigned int nr)


207 {
208 extern unsigned char selected ; // Select the floppy mark (kernel / blk_drv / floppy.c, 122).
209 unsigned char mask = 0x10 << nr; // start Madabite bit digital output corresponding to the selected floppy register.
210 High // mask 4 bits are each floppy flag to start the motor.

211 if (nr> 3)
212 panic ( ' floppy_on: nr> 3 "); // The system has up to four floppy drive.

// first pre-set specified time (100 seconds) floppy nr need to go through before stalling. Then take the current value of the register DOR // mask in a temporary

variable, and specifies the floppy motor start flag is set.

213 moff_timer [Nr] = 10000; / * 100 s = very big :-) * / // Stop duration.
214 cli (); / * Use floppy_off to turn it off * /
215 mask | = current_DOR ;
// If no floppy drive is selected, the other first reset select bit floppy, then set selection bits specify the floppy drive.

216 if (! selected ) {
217 mask & = 0xFC;
218 mask | = nr;
219 }
// if the current value of the motor with the requirements of the different digital output register, the output ports to the new FDC digital value (mask), and if the requirements of the motor to start //

not yet started, the set value of the corresponding timer is started floppy (HZ / 2 = 0.5 seconds, or 50 ticks). // if already started, and then set the timing to start the two ticks, satisfy the following

do_floppy_timer () after decreasing in the first determination requirements. // the timing required to perform this code. Thereafter the digital output register updating the current variable

current_DOR.

220 if (mask! = current_DOR ) {


221 outb (Mask, FD_DOR );
222 if ((mask ^ current_DOR ) & 0xf0)
223 mon_timer [Nr] = HZ /2;
224 else if ( mon_timer [Nr] <2)
225 mon_timer [Nr] = 2;
226 current_DOR = Mask;
227 }
228 sti ();
229 return mon_timer [NR]; // return the last value required for motor start-up time.

230 }
231
// waits for a specified period of time required to start the motor floppy drive, and then return.

// Set the floppy specified motor starting speed normally required to delay and wait for sleep. In the timer interrupt process will determine the delay value has been declining // set

here. When the delay expires, it will wake up the waiting process here.

232 void floppy_on (Unsigned int nr)


233 {
234 cli (); // disable interrupts.

235 while ( ticks_to_floppy_on (Nr)) // If the motor actuation timing has not arrived yet, the current process has been set

236 sleep_on (Nr + wait_motor ); // is not interrupted sleep and wait for the motor to run into the queue.
237 sti (); // open the interruption.

238 }
239
// set the floppy motor is stopped to close the corresponding timer (3 seconds).

// Without the use of the function explicitly close the specified floppy motor, the motor will be shut down after the open 100 seconds.

--132--
5.8 sched.c program

240 void floppy_off (Unsigned int nr)


241 {
242 moff_timer [Nr] = 3 * HZ ;
243 }
244
// diskette timer processing routine. Update motor start timing value and the motor is stopped off timer value. The clock timer interrupt subroutine will // process is called, so

the system through a tick (10ms) will be called every time the motor is turned on at any time to update or stop timer //'s value. If one of the timing to stop the motor, the motor

will start the digital output register bit is reset.

245 void do_floppy_timer (Void)


246 {
247 int i;
248 unsigned char mask = 0x10;
249
250 for (i = 0; i <4; i ++, mask << = 1) {
251 if (! (mask & current_DOR )) // If the motor is not specified DOR is skipped.
252 continue;
253 if ( mon_timer [I]) {
254 if (! - mon_timer [I])
255 wake_up (I + wait_motor ); // If the motor to start the timer wakes up the process.
256 } Else if (! moff_timer [I]) { // If the timing to stop the motor is

257 current_DOR & = ~ Mask; // reset respective motor start bit, and

258 outb ( current_DOR , FD_DOR ); // update the digital output registers.

259 } Else
260 moff_timer [I] -; // motor stall countdown timer.

261 }
262 }
263 264 #define TIME_REQUESTS 64
// can have up to 64 timer list (64 tasks).
265
// timer list structure and timer arrays.
266 static struct timer_list {
267 long jiffies ; // timer ticks.
268 void (* fn) (); // timer handler.
269 struct timer_list * Next; // next timer.
270 } timer_list [ TIME_REQUESTS ], * next_timer = NULL ;
271
// add a timer. Input parameter values ​for the designated timing (ticks) and the appropriate handler pointer. // floppy disk driver

(floppy.c) performed by using the function to activate or deactivate the delay operation of the motor. // jiffies - ticks in terms of 10

ms; * fn () - function to the execution timing of the time.

272 void add_timer (Long jiffies , Void (* fn) (void))


273 {
274 struct timer_list * P;
275
// If the timer handler pointer is NULL, then exits.
276 if (! fn)
277 return;
278 cli ();
// If the timer value <= 0, then immediately invokes its handler. And the timer is not added to the list.

279 if ( jiffies <= 0)


280 (Fn) ();
281 else {
// timer from the array, looking for a free entry.
282 for (p = timer_list ; P < timer_list + TIME_REQUESTS ; P ++)

--133--
5.8 sched.c program

283 if (! p-> fn)


284 break;
// If the timer has run out of the array, the system crashes ☺ .
285 if (p> = timer_list + TIME_REQUESTS )
286 panic ( ' No more time requests free ");
// fill in the appropriate information to the timer data structure. And links list head

287 p-> fn = fn;


288 p-> jiffies = jiffies ;
289 p-> next = next_timer ;
290 next_timer = P;
// list item by timing values ​in ascending order. Ticks need to subtract the top surface at the time of ordering, so long as the timer when dealing // Check the list head timing

of the first term has expired can be. [[?? This program does not seem thoughtful. If the newly inserted timer values ​// <original header when a timer value, the timer value

should all subsequent new is subtracted a first timing value. ]]

291 while (p-> next && p-> next-> jiffies <P-> jiffies ) {
292 p-> jiffies - = p-> next-> jiffies ;
293 fn = p-> fn;
294 p-> fn = p-> next-> fn;
295 p-> next-> fn = fn;
296 jiffies = P-> jiffies ;
297 p-> jiffies = P-> next-> jiffies ;
298 p-> next-> jiffies = jiffies ;
299 p = p-> next;
300 }
301 }
302 sti ();
303 }
304
//// clock interrupt handler function C, _timer_interrupt in kernel / system_call.s in (row 176) is called. // parameter cpl is the current privilege level 0 or
3,0 represents the kernel code execution.
// for a due process execution time slice is used up, the task switching. And perform a timed update work.
305 void do_timer (Long cpl)
306 {
307 extern int beepcount ; // speaker sound time ticks (kernel / chr_drv / console.c, 697)
308 extern void sysbeepstop (Void); // close the speaker (kernel / chr_drv / console.c, 691)
309
// If the count number to the utterance, sound is turned off. (0x61 port to send commands, reset bit 0 and 1. Bit 0 counter operation control // 2

8253, control speaker 1 bit).

310 if ( beepcount )
311 if (! - beepcount )
312 sysbeepstop ();
313
// If the current privilege level (cpl) to 0 (the highest representation is the core program of work), then the kernel run-time stime increments; // [Linus kernel

program referred to as super user (supervisor) program, see system_call .s, English comments] on line 193 // If cpl> 0, it means that the user program is usually

at work, increase utime.

314 if (cpl)
315 current -> utime ++;
316 else
317 current -> stime ++;
318
// If a user timer is present, then the value of the list of the first timer is decremented by one. If equal to 0, // call the corresponding processing program and the processing

program pointer is set to null. Then remove the timer.

319 if ( next_timer ) { // next_timer a timer list head pointer (see line 270).
320 next_timer -> jiffies -;

--134--
5.8 sched.c program

321 while ( next_timer && next_timer -> jiffies <= 0) {


322 void (* fn) (void); // here inserted a function pointer defined! ! !
323
324 fn = next_timer -> fn;
325 next_timer -> fn = NULL ;
326 next_timer = next_timer -> next;
327 (Fn) (); // call handler.
328 }
329 }
// if the current floppy disk controller FDC digital output register motor starting bit set, the timer program diskette (line 245) is executed.

330 if ( current_DOR & 0xf0)


331 do_floppy_timer ();
332 if ((- current -> counter)> 0) return; // run time if the process is not finished, then exit.
333 current -> counter = 0;
334 if (! cpl) return; // for kernel mode program counter value is not dependent scheduling.

335 schedule ();


336 }
337
// call the function system - alarm timer set time value (in seconds).

// If the parameter seconds> 0, then set the new value and return to the original timing time value. Otherwise it returns 0.

338 int sys_alarm (Long seconds)


339 {
340 int old = current -> alarm ;
341
342 if (old)
343 old = (old - jiffies ) / HZ ;
344 current -> alarm = (Seconds> 0)? ( jiffies + HZ * Seconds): 0;
345 return (old);
346 }
347
// get the current process pid.
348 int sys_getpid (Void)
349 {
350 return current -> pid;
351 }
352
// get the parent process ID ppid.

353 int sys_getppid (Void)


354 {
355 return current -> father;
356 }
357
// get user number uid.
358 int sys_getuid (Void)
359 {
360 return current -> uid;
361 }
362
// get euid.
363 int sys_geteuid (Void)
364 {
365 return current -> euid;
366 }

--135--
5.8 sched.c program

367
// get the group number gid.

368 int sys_getgid (Void)


369 {
370 return current -> gid;
371 }
372
// get egid.
373 int sys_getegid (Void)
374 {
375 return current -> egid;
376 }
377
// system call functionality - reduce the use of priority on the CPU (someone will use it? ☺ ). // increment greater than

zero should be limited, otherwise, can increase the priority! !

378 int sys_nice (Long increment)


379 {
380 if ( current -> priority-increment> 0)
381 current -> priority - = increment;
382 return 0;
383 }
384
// initialization routine scheduling program.

385 void sched_init (Void)


386 {
387 int i;
388 struct desc_struct * P; // pointer descriptor table structure.
389
390 if (sizeof (struct sigaction )! = 16) // sigaction signal state is located about the structure.
391 panic ( ' Struct sigaction MUST be 16 bytes ");
// set the initial task (task 0) task state and local descriptor table descriptor data (include / asm / system.h, 65).
392 set_tss_desc ( gdt + FIRST_TSS_ENTRY , & ( init_task . task .tss));
393 set_ldt_desc ( gdt + FIRST_LDT_ENTRY , & ( init_task . task .ldt));
// clear task descriptor table entry and the array (note that i = 1 starts, the initial task descriptors still).

394 p = gdt +2+ FIRST_TSS_ENTRY ;


395 for (i = 1; i < NR_TASKS ; I ++) {
396 task [I] = NULL ;
397 p-> a = p-> b = 0;
398 p ++;
399 p-> a = p-> b = 0;
400 p ++;
401 }
402 / * Clear NT, so that we will not have troubles with that later on * /
/ * Clear the flag register bit NT, so there would be trouble later * /
Recursive // ​NT flag is used to control the program call (Nested Task). When NT is set, then the current task switching can cause interrupt
task execution // iret instruction. NT noted back_link field TSS is valid.
403 __asm ​__ ( " pushfl; andl $ 0xffffbfff, (% esp); popfl "); // Reset the NT flag.
404 ltr (0); 0 // The task of TSS is loaded into the task register tr.

405 lldt (0); // local descriptor table loaded into the local descriptor table register.

// Note! ! GDT is loaded in the corresponding descriptor LDT selector to ldtr. Only clear to load this time, after loading new tasks // LDT, TSS is based on

CPU automatically loaded in the LDT entry.

// The following code is used to initialize the timer 8253.

--136--
5.8 sched.c program

406 outb_p (0x36,0x43); / * Binary, mode 3, LSB / MSB, ch 0 * /


407 outb_p ( LATCH & 0xff, 0x40); / * LSB * / // timer value of the low byte.

408 outb ( LATCH >> 8, 0x40); / * MSB * / // timer value of the high byte.

// set the clock interrupt handler handler (setting the clock interrupt gate).

409 set_intr_gate (0x20, & timer_interrupt );


// modify masks the interrupt controller, the interrupt enable clock.

410 outb ( inb_p (0x21) & ~ 0x01,0x21); // set the


system call interrupt gate.
411 set_system_gate (0x80, & system_call );
412 }
413

5.8.3 Other Information

5.8.3.1 Floppy Disk Controller Programming

For access to programming 4 Ports, respectively corresponding to one or more registers. for 1.2M There are a number of floppy disk controller port.

table 5-3 Floppy disk controller port

I / O port Reading and writing of Register Name

0x3f2 Only Digital output register (Digital Control Register)

0x3f4 Write FDC Main Status Register

0x3f5 Only Read / Write FDC Data register

0x3f7 Read-only Digital input register

0x3f7 just write Disk control register (transmission rate control)

Digital output port (port number control) is a 8 Bit register which controls the drive motor is turned on, the drive selection, start / reset FDC As well as enable / disable DMA

And interrupt request.

FDC The status register is a main 8 Bit register is used to reflect the floppy disk controller FDC And a floppy disk drive FDD The basic state. Typically, CPU to FDC Before

sending a command or from FDC Before obtaining the operation result, the master must read the status register bits, to discriminate the current FDC Data register is ready and

determines the direction of data transfer.

FDC A plurality of registers corresponding to the data port (write only type parameter register and the command register, read-only result register), but any one time, only

one appears in the data port register 0x3f5 . When accessing the write-only register, the main state control DIO Direction bit must be 0 ( CPU FDC ), And vice versa when the read

access type register. When reading the results only in FDC After reading the results considered busy, usually resulting data Up 7 Bytes.

The floppy disk controller can accept a total of 15 Command. Each command through three stages: the command phase, implementation phase and the results stage.

Command stage CPU to FDC Send command byte and parameter bytes. The first byte of each command byte is always the command (command code). Thereafter followed 0--8 Byte

parameters.

The implementation phase is FDC Perform the operation specified command. In the implementation phase CPU That without intervention, usually through FDC It issues an

interrupt request to know the end of the command execution. in case CPU dispatched FDC Command is transmitted data, FDC You can interrupt or DMA Conducted. Interrupt each

transfer 1 byte. DMA Way in DMA Controller Management, FDC Transmitting data to and from memory until all of the data transferred. at this time DMA Controller will signal the

transfer byte count termination FDC Finally, the FDC Issues an interrupt request signal inform CPU The implementation phase is completed.

The result is a stage CPU Read FDC Data register return value, to thereby obtain FDC The results of the command execution. Return result data length 0--7 byte. For data

command does not return results, should the FDC Interrupt Status command transmission detecting operation state is obtained.

--137--
5.9 signal.c program

5.9 signal.c program

5.9.1 Functional Description

signal.c All procedures involving the kernel functions relating to signal processing. in UNIX System, the signal is a "software interrupt" mechanism. There are many more

complex procedures will be used to signal. Signaling mechanism provides a method for processing asynchronous events. For example, a user at the terminal keyboard type ctrl-C Key

combination to terminate execution of a program. This operation will produce a SIGINT ( SIGnal INTerrupt ) Signal, and is sent to the process currently executing in the foreground;

when a process is provided when an alarm clock expires, the system will send a process to SIGALRM Signal; hardware when an exception occurs, the system will send the

appropriate signal to the process being performed. In addition, a process can send a signal to another process. For example, kill () Function to send the child process to terminate the

execution of the same set of signals.

The signal processing mechanism at an early UNIX Systems already have, but those early UNIX Signal processing kernel method is not so reliable. Signal may be lost,

but also in dealing with critical area code signal process is sometimes difficult to close a specified later

POSIX It provides a reliable method for processing a signal. To maintain compatibility, or this program provides two methods of processing signals.

Usually an unsigned long integer ( 32 Bit position) represents the various signals. So up to represent 32 Different signals. Excerpts Linux Kernel, defined twenty two Different

signals. among them 20 Kinds of signals are POSIX.1 All signals specified in the standard, additional 2 Species are Linux Dedicated signal: SIGUNUSED (Undefined) and SIGSTKFLT

(Stack error), the former means the system can not currently support all other signal types. This twenty two Specific names and definitions of types of signals may signal a list of

the reference program, see also

include / signal.h head File.

For the process, when a signal is received, it may be composed of three different process or operation mode.

1. Ignore the signal. Most signals can be ignored process. But there are two signals can not afford to ignore: SIGKILL with SIGSTOP . Can not

The reason being ignored is to provide a method for determining the super-user to terminate or stop any processes specified. Further, if the signal is ignored certain

hardware exception is generated (e.g., 0 In addition), the act or state of the process may become the unknowable.

2. Capture the signal. To do this, we must first tell the kernel to call our custom signal when the specified signal generation

Handler. In this handler, we can do anything, of course, can not do anything, play the same role in ignoring the signal. An example of a custom signal

processing function to capture the signal is: if we some temporary files created during program execution, then we can define a function to capture SIGTERM (Terminate

execution) signal and do some work to clean up temporary files in the function. SIGTERM Signal is kill The default command signal sent.

3. Default action. Each kernel signals to provide a default action. Usually these default action is to terminate the process of execution. Ginseng

Description Signal list see after the program.

This procedure gives a blocking signal is provided and the process of obtaining the code (mask) system calls sys_ssetmask () with sys_sgetmask () The signal processing

system calls sys_singal () (I.e., conventional signal processing functions signal () ), System operations modify the process when it receives a specific signal taken calls sys_sigaction

() ( Both reliable signal processing function sigaction ()) And interrupt functions in the system call handler for processing signals do_signal () . For the operation of the signal

transmission signal as a function send_sig () And notifies the parent process functions tell_father () It was included in another program ( exit.c )in. Name prefix program sig They are

signal signal For short.

signal () with sigaction () More similar function, signal changes are the original handler ( handler, Or handler called). but signal ()

It is the way the core operation of the conventional signal processing, in some special time may result in loss of signal.

in include / signal.h The first header 55 Row, signal () Function prototype is declared as follows:

void (* signal (int signr, void (* handler) (int))) (int);

This one signal () Function with two parameters. Need to capture a specified signal signr ; Another new signal processing function pointer (new signal handler) void (*

handler) (int) . New signal handler is a function having no return value and a pointer to an integer parameter, the integer parameter when a specified signal generating passed to

the kernel handler. signal () Function returns the original signal processing

--138--
5.9 signal.c program

Handle, the handle returned is also a non-return value and having a function pointer integer parameter. And it is performed after once invoked, the signal handler will be reset to

the default handler to handle the new value SIG_DFL .

in include / signal.h File (first 45 Since the line), the default handler SIG_DFL And ignored handler SIG_IGN It is defined as:

# define SIG_DFL ((Void (*) (int)) 0)


# define SIG_IGN ((Void (*) (int)) 1)

Respectively represent no return value of function pointers, and signal () The same requirements as a function of the second parameter. Pointer values ​are 0 with 1 . Logically, these

two pointer value is a function of the actual value of the address of the program impossible. Thus, in signal () The function can be two special pointer value to determine whether to

use the default or ignore the signal handler to signal processing (of course SIGTERM with SIGSTOP Can not be ignored). See the list below for the first program 94-98 Processing

lines.

When a program is executed, the system will be provided in a manner to process all signals SIG_DFL or SIG_IGN . In addition, when the program

fork () When a child process, the child process will inherit the parent process of signal processing (signal mask). Thus the parent of the set signal processing mode and equally

effective child process.

In order to continuously capture a specified signal, signal () Examples of commonly used manner following functions.

void sig_handler (int signr) // signal handler.


{
signal (SIGINT, sig_handler); // to process the next signal generation and re-set your own handler.
. . .
}

main () {

signal (SIGINT, sig_handler); // main program set up your own signal handler.
. . .
}

signal () Function unreliable because when the signal has occurred into the signal processing functions in their own setting, but once again before re-set your own

handler, it is possible this time there is another signal generator. But this time the system has been set to default values ​handler. Therefore, it may cause loss of signal.

sigaction () Function uses sigaction Data structure to hold the information specified signal, which is a reliable mechanism for signal processing core, which allows us to

easily view or modify the specified signal handler. This function is signal () A superset of the function. This function

include / signal.h Header (first 66 Line) in declared as:

int sigaction (int sig, struct sigaction * act, struct sigaction * oldact);

Where the parameter sig We need to view or modify the signal that the signal handler, the latter two parameters are sigaction Pointer to a structure. When parameter act Pointer

not NULL When you can act Modify the behavior of the information specified signal structure. when oldact Is not empty, the kernel will return the original signal information is

provided in the structure. sigaction See the structure shown below:

48 struct sigaction {
49 void (* sa_handler) (int); // signal handler.
50 sigset_t sa_mask; // mask signal, a signal can block the specified set.
51 int sa_flags; // signal option flags.
52 void (* sa_restorer) (void); // signal recovery function pointer (internal system).
53 };

--139--
5.9 signal.c program

When the modification of a signal processing method, if the handler sa_handler Not the default handler SIG_DFL Or ignore handler SIG_IGN , Then sa_handler Handler

can be invoked before, sa_mask Field specifies a set of signals to process the signal mask bitmap needs to be added to. If the signal handler returns, the system will return to

the process of the original signal mask bitmap. So that when a signal handler is called, we can block some signals specify. When the signal handler is invoked, the new bitmap

mask signal automatically the transmitted signal to include a current blocking continues to send the signal. During the process so we can ensure a specified signal blocking

without them lost with a signal until the process is completed. In addition, but on many occasions during a blocking signal is usually kept only one of its examples, that when

unblocking blocked for more of the same signal will once again call the signal handler. After we changed a signal handler, unless changed again, or else has been using the

handler. This is the traditional signal () Function is not the same.

signal () Function will revert to its default handler after the end of a signal handler.

sigaction Structure sa_flags Other options for specifying processing of the signals, the definition of these options, see

include / signal.h File (first 36-39 Line) instructions.

sigaction The last field in the structure and sys_signal () Function parameters restorer It is a function pointer. When compiled by the linker Libc Library provides for

user-mode stack to clean up after the signal handler, and restores the system call is stored in eax The return value, see details below.

do_signal () Function is a kernel system calls ( int 0x80) The interrupt handler to signal preprocessor. When each call to process the system call, if the process signal has

been received, then the function will be the handler (i.e., corresponding to the signal processing function) signal into the user program stack. In this way, the current system will be

executed after the call returns immediately signal the end of the handle of the program, and then continue to execute the user program, see Figure 5-7 Fig.

User program interrupt handler

System call int 0x80 C function calls the


corresponding function processing program.
Next Statement

Preprocessing the signal


recognition. Call do_signal ()
function. The signal
processing program into the
Signal processing program
user stack handler.

IRET kernel system call

Map 5-7 Called the signal handler.

in do_signal () Before the function parameters of the signal processing program into the user stack, will extend down the first user program stack pointer longs Longword

(see procedure below 106 Line), and then the insertion of the relevant parameters wherein, referring to FIG. 5-8 Fig. due to

do_signal () Function from 104 The line of code begins more difficult to understand, here we will be described in detail.

When the user invokes the system call just enter the kernel, the kernel mode stack of the process will be made CPU FIG Autopush 5-8 Contents shown in, namely: user

program SS with ESP And the next instruction in the user program execution point position CS with EIP . Call functions processed the specified system and is ready to call do_signal

() When (ie, system_call.s program 118 After the line), the contents of kernel mode stack see 5-9 As shown in the left. therefore do_signal () Parameter is the content of the stack in

the kernel mode.

--140--
5.9 signal.c program

stack User mode stack

Former SS

kernel
Original mode
ESP

Press-fitting direction
EFLAGS

CS EIP
long

After modifying the actual esp

L106 modify the value of the original ESP here

Map 5-8 do_signal () Modifications to the user function stack

User mode stack


stack

Original ss

kernel
Original mode
esp

eflags
old_eip eflags
User program edx ecx eax (call
cs eip

iret before esp program executed code, return value)

ds [blocked] signal

es fs edx signr sa_restorer


About to execute code

ecx ebx
Press-fitting direction

eax

signal
The signal processing
signr

Before calling do_signal point

After pointing call do_signal

Map 5-9 do_signal () Function modifies the specific user mode stack of the process

The default handler two signals processed ( SIG_IGN with SIG_DFL After), if the user-defined signal processing (signal handler sa_handler ), From 104 Line

from do_signal () Begin to handle user-defined into the user mode stack. It returns the first kernel mode Central user program execution stack pointer points eip Save

as old_eip , Then eip Alternatively to point to a custom handle

sa_handler , I.e. so that the kernel mode FIG stack eip direction sa_handler . Next, by storing kernel mode "original esp "minus longs Value, the user-mode stack extends

downwardly 7 or 8 Long word space. Finally, the copy number of the register contents on the kernel stack into this space, see on the right in FIG.

Total to the user mode stack placed 7 To 8 Values, we are now well placed to explain why the meaning of these values ​these values.

old_eip That is, the return address of the original user program is in the kernel stack eip Before being replaced to a signal handler address retained.

eflags , edx with ecx The original value before the user program in system call, basically calling parameters of the system call, after the system call returns still need to restore these

register values ​of the user program. eax The return value is stored in the system call. If the signal processing also allows the receipt itself is also stored on the stack has blocked

the process code blocked . The next one is the signal signr value.

--141--
5.9 signal.c program

The last one is a pointer to a function of signal activity recovery sa_restorer . This recovery function is not set by the user, as defined in the user signal () It provides a signal

only when the function value signr And a signal handler handler .

Here is SIGINT A simple example of a signal provided from the signal handler definition of the default, press Ctrl-C Key combination will produce SIGINT signal.

# include <signal.h>
# include <stdio.h>
# include <unistd.h>

void handler (int sig) // signal handler.


{
printf ( "The signal is% d \ n", sig); (void) signal
(SIGINT, SIG_DFL); // restore the default handler SIGINT signal. (Actually the kernel
} // restores to the default value, but not necessarily the case for other systems)

int main () {

(Void) signal (SIGINT, handler); // Set the user defined SIGINT signal handler.
while (1) {
printf ( "Signal test \ n."); sleep (1);
// wait one second.
}}

Wherein the signal processing function handler () Will signal SIGINT It is called to perform the event. The first function outputs a message, will then SIGINT Set to the

default signal processing signal handler. Therefore, in the second press Ctrl-C Key combination, SIG_DFL The program will end run.

Then sa_restorer This function is coming from? In fact, it is provided by the library functions in Libc Function library has its function, is defined as follows:

. globl ____sig_restore
. globl ____masksig_restore
# If not blocked, use the restorer function ____sig_restore:

addl $ 4,% esp # Discard signal value signr

popl% eax # Recovery system call return value.

popl% ecx # User program to restore the original register values.

popl% edx popfl


# When the flag register restore user program.
ret
# If blocked, use the following retorer function, blocked for ssetmask use. ____masksig_restore:

addl $ 4,% esp # Discard signal value signr

call ____ssetmask # Old blocking mask set signal


addl $ 4,% esp # Blocked value is discarded.

popl% eax
popl% ecx
popl% edx popfl
ret

--142--
5.9 signal.c program

The main role of this function is to signal processing procedure after the recovery after the return value and the user program execution system call number register

contents, and clear signal value as a signal processing program parameters signr . When the compiler user-defined signal processing procedure, the compiler will function into the

user program. This function is responsible for cleaning up the signal handler after the implementation of the recovery program user register values ​and the system call returns a

value, it does not seem to run through the signal handler, but returned directly from the system call.

Finally, explain the process execution. in do_signel () After the execution, system_call.s Will put kernel mode processes eip All of the following values ​popped off the stack. In

the implementation of the iret After instruction, CPU It will be the kernel mode stack cs: eip , eflags as well as ss: esp Pop, back to the user mode to execute the program. due to eip Directing

signal has been replaced with a handle, and therefore, will perform at the moment that is a user-defined signal processing procedure immediately. In the signal processing program

executed, by ret instruction, CPU We will hand over control to sa_restorer He points to restore the program to execute. and sa_restorer User mode program to do some clean-up

stack, i.e. skip signal value on the stack signr And the return value of the system call eax And register ecx , edx And a flag register eflags . After a full recovery and system calls each

register CPU status. Finally, sa_restorer of ret Instruction pops the original user program eip (Ie on the stack old_eip ), Returned to the execution of the user program.

5.9.2 Code comments

program 5-7 linux / kernel / signal.c

1/*
2 * Linux / kernel / signal.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

8 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

9 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

1011 #include <signal.h>


// signal header files. Defined symbolic constant signal, the signal structure and the operation function prototype signal.

1213 volatile void do_exit (Int error_code); // previous qualifier volatile ask the compiler not to optimize them.

14
// get the current task bitmap mask signal (mask).
15 int sys_sgetmask ()
16 {
17 return current -> blocked;
18 }
19
// Set new mask bit signal in FIG. SIGKILL can not be shielded. The return value is the original signal mask bitmap.

20 int sys_ssetmask (Int newmask)


twenty one {

twenty two int old = current -> blocked;


2324
current -> blocked = newmask & ~ (1 << ( SIGKILL -1));
25 return old;
26 }
27
// copy the data to the fs sigaction data segment to place. .
28 static inline void save_old (Char * from, char * to)
29 {
30 int i;

--143--
5.9 signal.c program

3132
verify_area (To, sizeof (struct sigaction )); // memory to verify the adequacy of the.
33 for (i = 0; i <sizeof (struct sigaction ); I ++) {
34 put_fs_byte (* From, to); // copy to fs segment. Typically user data segment.

35 from ++; // put_fs_byte (in include / asm / segment.h in).


36 to ++;
37 }
38 }
39
// copy the data from the sigaction from the data segment to the position fs to place.

40 static inline void get_new (Char * from, char * to)


41 {
42 int i;
4344
for (i = 0; i <sizeof (struct sigaction ); I ++)
45 * (To ++) = get_fs_byte (From ++);
46 }
47
// signal () system call. Similar to the sigaction (). Install the new signal handler (handler signal) for the specified signal. // signal handler function may be specified by the user, it

may be SIG_DFL (default handler) or SIG_IGN (ignored). // Parameter signum - specified signal; handler - specified handle; restorer - recovery function pointer, the function

provided by the Libc // library. For recovering the original values ​of several registers and the system returns // called when the value of the system call returns, the system as if no

call signal processing program executed directly returned to the user after the program as a signal processing program. // function returns a handle to the original signal.

48 int sys_signal (Int signum, long handler, long restorer)


49 {
50 struct sigaction tmp;
5152
if (signum <1 || signum> 32 || signum == SIGKILL ) // signal value to be in the range of (1-32),
53 return -1; // and shall not be SIGKILL.
54 tmp.sa_handler = (void (*) (int)) handler; // specified signal handler.
55 tmp.sa_mask = 0; // mask signal during execution.
56 tmp.sa_flags = SA_ONESHOT | SA_NOMASK ; // use the handle only once after return to their defaults, // and

allow the signal received at his handler in.

57 tmp.sa_restorer = (void (*) (void)) restorer; // save the resume processing function pointer.
58 handler = (long) current -> sigaction [Signum-1] .sa_handler;
59 current -> sigaction [Signum-1] = tmp;
60 return handler;
61 }
62
// sigaction () system call. Change the course of the operation upon receipt of a signal. signum is in addition to any // SIGKILL signal. [If the new operation (action)

is not empty] new operation is installed. If oldaction pointer is not null, then the operation of the original to be retained // oldaction. Returns 0 on success, -1

otherwise.

63 int sys_sigaction (Int signum, const struct sigaction * Action,


64 struct sigaction * Oldaction)
65 {
66 struct sigaction tmp;
67
// the value of the signal to be in the range of (1-32), and SIGKILL signal handler can not be changed.

68 if (signum <1 || signum> 32 || signum == SIGKILL )


69 return -1;
// Set new operation (operation) in the structure sigaction signal.
70 tmp = current -> sigaction [Signum-1];

--144--
5.9 signal.c program

71 get_new ((Char *) action,


72 (Char *) (signum-1 + current -> sigaction ));
// If oldaction pointer is not empty, then save the pointer to the original position oldaction referred to.
73 if (oldaction)
74 save_old ((Char *) & tmp, (char *) oldaction);
// If the enable signal is received in the own signal handler, so that the mask is 0, otherwise set mask signal present.

75 if ( current -> sigaction [Signum-1] .sa_flags & SA_NOMASK )


76 current -> sigaction [Signum-1] .sa_mask = 0;
77 else
78 current -> sigaction [Signum-1] .sa_mask | = (1 << (signum-1));
79 return 0;
80 }
81
// system call interrupt handler real signal handler (in kernel / system_call.s, 119 lines). This code // main function is to signal handler stack
into the user program, the signal handler program executed immediately after the end of the // and returns the system call, and then
continue the user program.
82 void do_signal (Long signr, long eax, long ebx, long ecx, long edx,
83 long fs, long es, long ds,
84 long eip, long cs, long eflags,
85 unsigned long * esp, long ss)
86 {
87 unsigned long sa_handler;
88 long old_eip = eip;
89 struct sigaction * Sa = current -> sigaction + Signr - 1; // current-> sigaction [signu-1].
90 int longs;
91 unsigned long * tmp_esp;
9293
sa_handler = (unsigned long) sa-> sa_handler;
// If the signal handler is SIG_IGN (ignored) Returns; if the handle is SIG_DFL (default process), then if the signal is // SIGCHLD is returned, otherwise terminate

the process of execution

94 if (sa_handler == 1)
95 return;
96 if (! sa_handler) {
97 if (signr == SIGCHLD )
98 return;
99 else
100 do_exit (1 << (signr-1)); // Why bitmap to signal parameters? No reason!? ☺
// this should be do_exit (1 << (signr)).
101 }
// If the signal handler is used only once, then the handle blank (which has been stored in the signal handler sa_handler pointer).

102 if (sa-> sa_flags & SA_ONESHOT )


103 sa-> sa_handler = NULL ;
// The following code is inserted into the signal handler stack user, will also sa_restorer, signr, mask process (if not set // SA_NOMASK), eax, ecx, edx invoked as system

parameters and call the original procedure returns a pointer and flag register value onto the stack //. Therefore, in this system call interrupt (0x80) will be executed first user's

signal handler program when the user returns to the program, and then continue // execution of the user program.

// user code pointer points to the system calls the signal handler eip.
104 * (& Eip) = sa_handler;
// If the signal handler to allow their own signal is received, it is also necessary to process the blocking code on the stack. // Note that the results

longs here should choose (7 * 4) :( 8 * 4) because the stack is 4 bytes operation.

105 longs = (sa-> sa_flags & SA_NOMASK ?) 7: 8;


// original caller user stack pointer extended downwardly 7 (or 8) characters long (for storage parameter signal handler calls, etc.),

--145--
5.9 signal.c program

// and check the memory usage (for example, if the memory is allocated new super-sector pages, etc.).

106 * (& Esp) - = longs;


107 verify_area (Esp, longs * 4);
// user from the stack to the storage sa_restorer, signal signr, blocked mask (if SA_NOMASK set), // eax, ecx, edx, eflags user program
source code and pointers.
108 tmp_esp = esp;
109 put_fs_long ((Long) sa-> sa_restorer, tmp_esp ++);
110 put_fs_long (Signr, tmp_esp ++);
111 if (! (sa-> sa_flags & SA_NOMASK ))
112 put_fs_long ( current -> blocked, tmp_esp ++);
113 put_fs_long (Eax, tmp_esp ++);
114 put_fs_long (Ecx, tmp_esp ++);
115 put_fs_long (Edx, tmp_esp ++);
116 put_fs_long (Eflags, tmp_esp ++);
117 put_fs_long (Old_eip, tmp_esp ++);
118 current -> blocked | = sa-> sa_mask; // process blocking code (mask) add the code bits sa_mask.
119 }
120

5.9.3 Other Information

5.9.3.1 Process Signal Description

Process signal is a simple message for the communication between processes, usually a reference value in the following table, and does not carry any other information.

For example, when a child process terminates or ends, it will have a numbered 17 of SIGCHILD A signal is sent to the parent process to notify the parent about the current status

of the child process.

A handle on how to process the received signal, there are two approaches: First, do not deal with the process of the program, at which point the signal will be processed

by the corresponding default signal handler system; second approach is to use their own process The signal processing program for processing a signal.

table 5-4 Process signal

Grade name Explanation The default action

(Hangup) When you no longer generates the core control signal terminal, or when you close Xterm Or

off modem . Since the terminal does not control daemon, which are commonly used SIGUP The need (Abort) Off control terminal or process.
1 SIGHUP
to issue a signal to reread its configuration file.

(Interrupt) From a terminal keyboard. The driver will usually terminal and ^ C
2 SIGINT (Abort) Terminate the program.
Binding.

3 SIGQUIT (Quit) From a terminal keyboard. The driver will usually end with ^ \ binding. ( Dump) And generating program is terminated
dump core file.

(Illegal Instruction) Program error or to perform an illegal operation instruction. (Dump) And generating program is terminated
4 SIGILL
dump core file.

5 SIGTRAP (Breakpoint / Trace Trap) Debugging, trace breakpoints.

(Dump) And generating program is terminated


6 SIGABRT (Abort) Gives up, abnormal termination.
dump core file.

(Dump) And generating program is terminated


6 SIGIOT (IO Trap) with SIGABRT
dump core file.

7 SIGUNUSED (Unused) did not use.

8 SIGFPE (Floating Point Exception) Floating-point exception. (Dump) And generating program is terminated

--146--
5.10 exit.c program

dump core file.

(Kill) Program is terminated. This signal can not be caught or ignored. Want to immediately

9 SIGKILL terminate a process, it sends a signal 9 . Note that the program will not have any opportunity to do (Abort) Program is terminated.

cleanup work.

10 SIGUSR1 (User defined Signal 1) User-defined signal. (Abort) The process is terminated.

(Segmentation Violation) When the program is invalid memory references will produce this signal. (Dump) And generating program is terminated
11 SIGSEGV
For example: No mapping memory addressed; unlicensed memory addressing. dump core file.

12 SIGUSR2 (User defined Signal 2) Reserved for user program IPC Or other purposes. ( Abort) The process is terminated.

(Pipe) When the program writes to a pipe socket or the absence of the signal generated by the
13 SIGPIPE (Abort) The process is terminated.
reader.

(Alarm) The signal will be called in the user alarm A delay system call set number of seconds after.
14 SIGALRM (Abort) The process is terminated.
This signal is used to determine the system call timeout.

(Terminate) Kindly claim for a program termination. it is kill The default signal. versus SIGKILL Different,

15 SIGTERM the signal can be captured, so that we can do cleanup work before decommissioning. (Abort) The process is terminated.

16 SIGSTKFLT (Stack fault on coprocessor) Coprocessor stack error. (Abort) The process is terminated.

(Child) Parent issue. Stop or terminate child process. You can change its meaning for other (Ignore) Child process to stop or end.
17 SIGCHLD
purposes.

(Continue) The resulting signal is SIGSTOP Stopped process to resume operation. It can be (Continue) The implementation of the
18 SIGCONT
captured. recovery process.

19 SIGSTOP (Stop) Stop the process of running. This signal can not be caught or ignored. (Stop) To stop the process running.

(Terminal Stop) Stop key sequence to the terminal. This signal can be captured or ignored.
20 SIGTSTP (Stop) To stop the process running.

(TTY Input on Background) Background process attempts to read data from a terminal no longer be

twenty one SIGTTIN controlled, at which point the process will be stopped until you receive (Stop) To stop the process running.

SIGCONT signal. This signal can be captured or ignored.

(TTY Output on Background) Background process attempting to output data to a terminal no longer

twenty two SIGTTOU be controlled, at which point the process will be stopped until you receive (Stop) To stop the process running.

SIGCONT signal. The signal may be captured or ignored.

5.10 exit.c program

5.10.1 Functional Description

The program describes the process (task) termination and deal with matters exit. The main course included the release of the session (process group) to terminate the

program and exit handlers and kill the process, terminate the process, the process hangs and other system calls. Also includes the process of signal transmission function

send_sig () And notifies the parent process child process termination function tell_father () .

Function to release process release () The main data structure according to the specified task (task descriptors) pointer, delete the specified task process pointer in the

array, the release of the relevant kernel memory pages and immediately let rescheduled to run the task.

Process group termination function kill_session () Hang up the process by sending a signal to the current process a session with the same number of processes. System

calls sys_kill () Used to send any signal to the specified process. According to the parameters pid (Process ID number) of different values,

--147--
5.10 exit.c program

The system call sends a signal to a different process or process group. Notes program already lists the various handling different situations.

Program exit handler do_exit () In the system call interrupt handler is invoked. It will first release of code and data segments occupied by the current process of memory

pages, and then send a signal to the child process termination SIGCHLD . Then close all open files in the current process, the release of the terminal equipment, the coprocessor, the

process if the current process is the process group leader, need to terminate all the processes. Then the current process is set to rigid state, set an exit code, and sends the parent

process child process termination signal. Finally, let the kernel rescheduled to run the task.

System calls waitpid () To suspend the current process until pid Specified child process exits (terminate) signal or receive to terminate the process, or the need to call a

signal handler (signal handler). in case pid Within the meaning of the child process has long been out (become a so-called zombie processes), then this call will return immediately.

All the resources used by the child process will be released. The specific operation function must also be different according to their processing parameters. See related

comments in the code.

5.10.2 Code comments

program 5-8 linux / kernel / exit.c

1/*
2 * Linux / kernel / exit.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <errno.h>
// error number header files. The system comprises various error number. (Linus from the introduction of minix)

8 #include <signal.h> // signal header files. Defined symbolic constant signal, the signal structure and the operation function prototype signal.

9 #include <sys / wait.h> // wait for the call header. The system defined call wait () and waitpid () and constants related symbols.

1011 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

12 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

13 #include <linux / tty.h> // tty header file, which defines tty_io, aspects of the serial communication parameters constant.

14 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

1516 int sys_pause (Void);


// set the system to process calls sleep. (Kernel / sched.c, 144 lines)
17 int sys_close (Int fd); // close the specified file system calls. (Fs / open.c, 192 lines)
18
//// release a specified task slot occupied by the process and task data structure occupied by memory.

// Parameter p is a pointer to a data structure of the task. This function is called sys_kill () and sys_waitpid () in the later. // pointer array scanning task list task [] to find

the specified task. If found, the first task of emptying the trough, then release the task // data structure occupied by the memory page, and finally performs scheduling

function and exit immediately on return. If the specified task corresponding entry is not found in the task array // table, the kernel panic ☺ .

19 void release (Struct task_struct * P)


20 {
twenty one int i;
2223
if (! p) // If the process data structure pointer is NULL, nothing to do, quit.
twenty four return;
25 for (i = 1; i < NR_TASKS ; I ++) // array scanning task, to find the specified task.

26 if ( task [I] == p) {
27 task [I] = NULL ; // blank entry and release of the tasks related to memory pages.

28 free_page ((Long) p);


29 schedule (); // reschedule (not seem necessary).
30 return;

--148--
5.10 exit.c program

31 }
32 panic ( ' trying to release non-existent task "); // If there is a specified task crashes.
33 }
34
//// send a signal (sig) to the specified task (* p), rights for priv. //
Parameters: sig - signal value; //
p -- Specified pointer tasks;

// priv - flag forces to send signals. I.e., no need to consider the process of user attributes or levels but can transmit signals as claimed. // This function first determines

the correctness of the parameters, and then determining condition is satisfied. If the condition is sent to the specified process signal sig // and exit, otherwise unlicensed error number.

35 static inline int send_sig (Long sig, struct task_struct * P, int priv)
36 {
// If the signal is not correct or is empty task pointer error exit.

37 if (! p || sig <1 || sig> 32)


38 return - EINVAL ;
// If the forced transmission valid user identifier (EUID) flag is set, or the current process is the process specified EUID (i.e., own), // current process or
superuser, add the signal process bitmap otherwise error exit. Wherein the suser // () is defined as (current-> euid == 0), is used to determine whether a super
user.
39 if (priv || ( current -> euid == p-> euid) || suser ())
40 p-> signal | = (1 << (sig-1));
41 else
42 return - EPERM ;
43 return 0;
44 }
45
//// terminate the session (session).

// process the concept of a session refer to the instructions in Chapter 4 about the process and group sessions.

46 static void kill_session (Void)


47 {
48 struct task_struct ** p = NR_TASKS + task ; // pointer * p first point to the very end of the task array.

49
// scan task pointer array, for all tasks (Tasks other than 0), if the session number which is equal to // the session number of the current session process on the signal it sends

to hang up process SIGHUP.

50 while (--p> & FIRST_TASK ) {


51 if (* p && (* p) -> session == current -> session)
52 (* P) ​-> signal | = 1 << ( SIGHUP -1); // process the transmission signal to hang up.

53 }
54 }
5556 / *

57 * XXX need to check permissions needed to send signals to process


58 * Groups, etc. etc. kill () permissions semantics are tricky!
59 * /
/*
* In order to send a signal to the process group, etc., XXX need to check the license. kill () licensing mechanism is very clever!

*/
//// system call kill () can be used to send any signal to any process or process group, and not just kill the process ☺ . // parameter pid is
the process number; sig is the signal to send. // If the value of pid> 0, the signal is sent to process ID is pid process. // If all processes
pid = 0, then the process of signal will be sent to the current process group. // If pid = -1, then signal sig will be sent to all processes
except the first process. // If all processes pid <-1, the signal sig -pid sent to the process group. // If the signal sig is 0, no signal is sent,
but still error checking. If successful, 0 is returned.

--149--
5.10 exit.c program

// This function scan task array table, and sends a signal sig to the process satisfies the condition specified based on the value of the pid. If pid equals 0, // it indicates that the current

process is the process group leader, and therefore need to force sends a signal sig to all processes within the group.

60 int sys_kill (Int pid, int sig)


61 {
62 struct task_struct ** p = NR_TASKS + task ;
63 int err, retval = 0;
6465
if (! pid) while (--p> & FIRST_TASK ) {
66 if (* p && (* p) -> pgrp == current -> pid)
67 if (err = send_sig (Sig, * p, 1)) // forced to send signals.

68 retval = err;
69 } Else if (pid> 0) while (--p> & FIRST_TASK ) {
70 if (* p && (* p) -> pid == pid)
71 if (err = send_sig (Sig, * p, 0))
72 retval = err;
73 } Else if (pid == -1) while (--p> & FIRST_TASK )
74 if (err = send_sig (Sig, * p, 0))
75 retval = err;
76 else while (--p> & FIRST_TASK )
77 if (* p && (* p) -> pgrp == -pid)
78 if (err = send_sig (Sig, * p, 0))
79 retval = err;
80 return retval;
81 }
82
//// notifies the parent process - to send a signal SIGCHLD process pid: By default, a child process to stop or terminate. // If the parent is not found, the release of their own. But

according to POSIX.1 requirements, if the parent has first terminated, then the child should be the initial process // accommodating.

83 static void tell_father (Int pid)


84 {
85 int i;
8687
if (pid)
// array scanning process table looking for the specified process pid, and sends the child process to stop or terminate signal SIGCHLD.

88 for (i = 0; i < NR_TASKS ; I ++) {


89 if (! task [I])
90 continue;
91 if ( task [I] -> pid = pid)!
92 continue;
93 task [I] -> signal | = (1 << ( SIGCHLD -1));
94 return;
95 }
96 / * If we do not find any fathers, we just release ourselves * /
97 / * This is not really OK. Must change it to make father 1 * /
/ * If the parent is not found, the process on their own release. This is not good, it must be changed to serve as its parent process by the process 1. * /

98 printk ( ' BAD BAD - no father found \ n \ r ");


99 release ( current ); // If the parent is not found, the release of their own.

100 }
101
//// program exits handler. Sys_exit system call is invoked in line 137 at the next () method.
102 int do_exit (Long code) // code is error code.
103 {
104 int i;

- 150 -
5.10 exit.c program

105
// release the current process code and data segments share memory pages (free_page_tables () in mm / memory.c, 105 lines).

106 free_page_tables ( get_base ( current -> ldt [1]), get_limit (0x0F));


107 free_page_tables ( get_base ( current -> ldt [2]), get_limit (0x17));
// If the current Cheng Youzi into the process, the child process will be father set to 1 (parent process change process 1 - init). // if the child process is already dead (ZOMBIE) state,

transmits a termination signal to the child process SIGCHLD process.

108 for (i = 0; i < NR_TASKS ; I ++)


109 if ( task [I] && task [I] -> father == current -> pid) {
110 task [I] -> father = 1;
111 if ( task [I] -> state == TASK_ZOMBIE )
112 / * Assumption task [1] is always init * / / * It is assumed task [1] certainly is the process init * /
113 (Void) send_sig ( SIGCHLD , task [1], 1);
114 }
// close all open files with the current process.
115 for (i = 0; i < NR_OPEN ; I ++)
116 if ( current -> filp [i])
117 sys_close (I);
// current process working directory pwd, the root of the root and the i-node synchronous operation, and were left blank (release).

118 iput ( current -> pwd);


119 current -> pwd = NULL ;
120 iput ( current -> root);
121 current -> root = NULL ;
122 iput ( current -> executable);
123 current -> executable = NULL ;
// If the current process is a session leader (leader) process and it has a controlling terminal, the terminal is released.

124 if ( current -> leader && current -> tty> = 0)


125 tty_table [ current -> tty] .pgrp = 0;
// If the current process last used coprocessor, will last_task_used_math blank.
126 if ( last_task_used_math == current )
127 last_task_used_math = NULL ;
// If the current process is the leader process, all relevant processes of the session is terminated.

128 if ( current -> leader)


129 kill_session ();
// set the current process is dead state, indicating that the current process has freed resources. And save and exit code read by the parent process.

130 current -> state = TASK_ZOMBIE ;


131 current -> exit_code = code;
// notifies the parent process, but also to send a signal SIGCHLD namely the parent - child process to stop or terminate.

132 tell_father ( current -> father);


133 schedule (); // reschedule process runs to let the parent handle the aftermath of other zombie processes.

134 return (-1); / * Just to suppress warnings * /


135 }
136
//// system call exit (). Terminate the process.
137 int sys_exit (Int error_code)
138 {
139 return do_exit ((Error_code & 0xff) << 8);
140 }
141
//// system call waitpid (). Suspends the current process until pid specified child process exits (termination) or received signal // terminate the process, or the need to call a signal

handler (signal handler). If the child process pid already referred // exit (become a so-called zombie processes), then this call will return immediately. All the resources used by the

child process will be released. // If pid> 0, wait for the process represents a number equal to the child process pid. // If pid = 0, represents the waiting process group number is

equal to the current process group number of any child processes.

--151--
5.10 exit.c program

// If the pid <-1, represents the waiting process group pid number is equal to the absolute value of any child process. // [if pid = -1,

represents waiting for any child process. ]

// if options = WUNTRACED, said that if the child process is stopped, it immediately returns (without tracking). // if options = WNOHANG,

said that if no child process exits or terminates immediately returned. // If the return status pointer stat_addr is not empty, then it will save

the state information there.

142 int sys_waitpid ( pid_t pid, unsigned long * stat_addr, int options)
143 {
144 int flag, code;
145 struct task_struct ** p;
146
147 verify_area (Stat_addr, 4);
148 repeat:
149 flag = 0;
// start a scan task from the end of an array of all tasks, to skip empty items, this process as well as sub-items of non-current process of process items.

150 for (p = & LAST_TASK ; P> & FIRST_TASK ; --P) {


151 if (! * p || * p == current ) // skip this process and an empty entry item.

152 continue;
153 if ((* p) -> father =! current -> pid) // if the child is not the current process is skipped.
154 continue;
// At this scanning process to select a sub p is certainly the current process.

// If the number of child processes to wait pid> 0, but is not equal to the scanning sub-process p pid, the current process which is described further sub-process, the process skips // so, then

the next scanning process.

155 if (pid> 0) {
156 if ((* p) -> pid = pid!)
157 continue;
// Otherwise, if the specified pid = 0 wait for the process, said it is waiting for the process group number is equal to the current process group number of any child processes. If this time is

scanned // set number of process p process group number of the current process ranging skipped.

158 } Else if (! Pid) {


159 if ((* p) -> pgrp =! current -> pgrp)
160 continue;
// Otherwise, if the specified pid <-1, it said it is waiting for the process group number is equal to the absolute value of any child process pid. If at this time the process of being scanned // p

group number and the absolute value of pid ranging skipped.

161 } Else if (pid! = -1) {


162 if ((* p) -> pgrp = -pid!)
163 continue;
164 }
// If the first three judge pid is not met, then the current process is waiting for any child process, that is the case pid = -1. // child process selected at that
time to process what waits p. Next to deal with the state of the child process p located.
165 switch ((* p) -> state ) {
When p // child process is stopped, if this time WUNTRACED flag is not set, it indicates that the program need not return immediately, so continue to // scan other

processes. If WUNTRACED set, put status information into the 0x7f * stat_addr, and immediately return the child // number pid. Here the return state indicates that the

WIFSTOPPED 0x7f () macro is true. See include / sys / wait.h, 14 rows.

166 case TASK_STOPPED :


167 if (! (options & WUNTRACED ))
168 continue;
169 put_fs_long (0x7f, stat_addr);
170 return (* p) -> pid;
P // if the child process is dead state, it is first in the user mode and kernel mode operation time were integrated into the current process (the parent process) // then removed and pid of the

child process exit code, and releases the sub process. Finally, return to the child process exit code and pid.

171 case TASK_ZOMBIE :


172 current -> cutime + = (* p) -> utime ;
173 current -> cstime + = (* p) -> stime ;
174 flag = (* p) -> pid; // temporarily save the child process pid.

--152--
5.11 fork.c program

175 code = (* p) -> exit_code; // exit code to take the child process.

176 release (* P); // release the child process.

177 put_fs_long (Code, stat_addr); // set status information for the exit code value.

178 return flag; // exited pid of the child process.


// if the child process p state is neither stopped nor dead, then set flag = 1. // find representation through a child process to meet the requirements, but it is in

running state or sleep state.

179 default:
180 flag = 1;
181 continue;
182 }
183 }
// After the task facing an array of scanning is finished, if the flag is set, indicating a child process in line with the requirements and no waiting in exit // or dead state. If at this time you have

been set WNOHANG option (indicating that if there are no children in the withdrawal or termination state returns immediately), // immediately return 0 and exit. Otherwise, the current

process is set to be interrupt-pending and re-execute the schedule.

184 if (flag) {
185 if (options & WNOHANG ) // if options = WNOHANG, then immediately returned.

186 return 0;
187 current -> state = TASK_INTERRUPTIBLE ; // set the current process interrupt-waiting state.
188 schedule (); // reschedule.
// When they began the implementation of this process, if this process does not signal other than SIGCHLD is received, the process is repeated. Otherwise, // returns an error code and

exit.

189 if (! ( current -> signal & = ~ (1 << ( SIGCHLD -1))))


190 goto repeat;
191 else
192 return - EINTR ; // exit and return an error code.

193 }
// If the child process to meet the requirements is not found, an error code is returned.

194 return - ECHILD ;


195 }
196
197
198

5.11 fork.c program

5.11.1 Functional Description

fork () System call is used to create a child process. Linux All processes are processes 0 (task 0 ) The child process. The program is sys_fork ()

(in kernel / system_call.s Defined) the secondary processing function set of system calls, gives sys_fork () Two system calls used

C Language functions: find_empty_process () with copy_process () . Also includes verification process memory area and memory allocation functions

verify_area () .
copy_process () And the process used to create the copy of the code and data segments and the environment. In the process of copying process, the main process involved

in setting data structure information. The system first application for a new process for the memory area in the main memory to store the data structure information of its mandate,

and copy all the contents of the current process task data structure as a template for a new process task data structure.

Then copy the data structure of the task to be modified. The current process is set to the parent of the new process, the clear signal bitmaps and reset each new process

statistics. Then set the task state segment based on the current process ( TSS ) The value of each register. Since the new process returns the value creating process should be 0 ,

You need to set tss.eax = 0 . New process kernel mode stack pointer tss.esp0 The new process is set to top the task data structure where memory pages, and stack segment tss.ss0

Is provided to the kernel data segment selector. tss.ldt It is set as a local descriptor table GDT

--153--
5.11 fork.c program

The index value. If the current process uses a co-processor, the state also need to preserve the integrity coprocessor to a new process tss.i387

Structure.

After setting up a new task system code and data segment base address, limit long and copy the current process page table memory paging management. If the parent has

a file is opened, the corresponding increase in the number of open files 1 . Followed by GDT Set new tasks TSS with LDT Descriptor entries, wherein the group address information

point to the new progress of the task structure tss with ldt . Then the final set to run a new task state and returns a new process ID.

Map 5-10 The memory validation function verify_area () Adjust the starting position of the memory and verify scope FIG. Because the memory write verification function write_verify

() You need to be memory page basis ( 4096 Byte) operation, so the call write_verify () We are required before the starting position is adjusted to verify a page start position, while

the range of authentication adjusted accordingly.

nr * 64M (nr is task number) (Nr + 1) * 64M

Code data

Memory page Original starting position addr

The length of the original size


The new starting position start

The new length size

Map 5-10 Verify and adjust the memory range starting position

5.11.2 Code comments

program 5-9 linux / kernel / fork.c

1/*
2 * Linux / kernel / fork.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * 'Fork.c' contains the help-routines for the 'fork' system call


9 * (See also system_call.s), and some misc functions ( 'verify_area').
10 * Fork is rather simple, once you get the hang of it, but the memory
11 * Management can be a bitch See 'mm / mm.c':. 'Copy_page_tables ()'
12 * /
/*
* Auxiliary subroutines (see system_call.s) 'fork.c' system call is contained in the 'fork', as well as other functions
* ( 'Verify_area'). Once you get a fork, you will find that it is very simple, but the memory management is somewhat difficult.
* See 'mm / mm.c' in 'copy_page_tables ()'.
*/
13 #include <errno.h> // error number header files. The system comprises various error number. (Linus imported from the minix).

1415 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

--154--
5.11 fork.c program

// Some parameters related descriptors set and get embedded assembly function macro statement.

16 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

17 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

18 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

1920 extern void write_verify (Unsigned long address);

2122 long last_pid = 0;


// latest process ID, whose value is generated by get_empty_process ().

twenty three

//// process space area before writing validation functions.

// detection operation before the write operation to the current process address from addr to addr + size This is a space in units of pages perform. // Since the detection

page judgment is to operate as a unit, so the program first need to find out where addr start address start page, // then start the process of adding a data segment base to

make this start into CPU 4G linear address space . The last cycle // Call write_verify () before the specified size of memory write verification. If the page is read-only, shared

inspection and copying pages // operations (copy-on-write) is executed.

twenty four void verify_area (Void * addr, int size)


25 {
26 unsigned long start;
2728
start = (unsigned long) addr;
// start address of the starting location of the left edge of the adjustment for the page, while adjusting the size of the authentication area accordingly. // the sentence start & 0xfff

addr for obtaining a specified start position (i.e., start) where the offset value in the page, // plus the size range of the original verify an offset value that is to be extended to the

page where addr range start position value. Is also required to verify the start position start boundary value is adjusted to page 30 // row. See "Memory Validation adjustment

range" in front of FIG.

29 size + = start & 0xfff;


30 start & = 0xfffff000;
// start plus the following process data segment in the linear address space starting base address, into the linear address space locations throughout the system. For // 0.11 kernel code

segment and data segment which is a linear address space base address and limit are the same length.

31 start + = get_base ( current -> ldt [2]);


32 while (size> 0) {
33 size - = 4096;
// write verification page. If the page is not writable, the copy page. (Mm / memory.c, 261 lines)

34 write_verify (Start);
35 start + = 4096;
36 }
37 }
38
// set new tasks of code and data segment base address, limit long and copy the page table. // nr for a

new job number; p is a pointer to a data structure of a new task.

39 int copy_mem (Int nr, struct task_struct * P)


40 {
41 unsigned long old_data_base, new_data_base, data_limit;
42 unsigned long old_code_base, new_code_base, code_limit;
43
// get current process described in the local segment descriptor table entry identifier of indefinite length (number of bytes).

44 code_limit = get_limit (0x0f); // get the local descriptor table entry code segment middle of indefinite length.

45 data_limit = get_limit (0x17); // get the local descriptor table descriptor data items middle indefinite length. // get the base address of the current

process code and data segments in the linear address space.

46 old_code_base = get_base ( current -> ldt [1]); // take the original code base.
47 old_data_base = get_base ( current -> ldt [2]); // get the original data segment base.
48 if (old_data_base! = old_code_base) // version 0.11 does not support the case of code and data segments discrete.

49 panic ( ' We do not support separate I & D ");


50 if (data_limit <code_limit) // If the data length <the code length is not right.

--155--
5.11 fork.c program

51 panic ( ' Bad data_limit ");


// Create a new process in a linear address space of the base address is equal to 64MB * its task number.

52 new_data_base = new_code_base = nr * 0x4000000; // base address = new task number * 64Mb (size of the job).
53 p-> start_code = new_code_base; // the new process described in the local base

address of the segment descriptor in the descriptor table.

54 set_base (P-> ldt [1], new_code_base); // set the code segment base address field.
55 set_base (P-> ldt [2], new_data_base); // set the base address of a data segment descriptor field. // Set the new process page directory entries and page table entries. That is

the new process of linear memory address corresponding to the page to the actual physical address of the memory page.

56 if ( copy_page_tables (Old_data_base, new_data_base, data_limit)) {// copy the code and data segments.
57 free_page_tables (New_data_base, data_limit); // if an error occurs releasing application memory.
58 return - ENOMEM ;
59 }
60 return 0;
61 }
6263 / *

64 * Ok, this is the main fork-routine. It copies the system process


65 * Information (task [nr]) and sets up the necessary registers. It
66 * Also copies the data segment in it's entirety.
67 * /
/*
* OK, the following are the main fork subroutine. It replication system processes information (task [n]) and sets the necessary registers.

* It also copy the entire data segment.

*/
// copy process.
// where nr parameter is an array of task item number to call find_empty_process () allocation. none is pushed onto the return address stack when calling //

sys_call_table system_call.s in.

68 int copy_process (Int nr, long ebp, long edi, long esi, long gs, long none,
69 long ebx, long ecx, long edx,
70 long fs, long es, long ds,
71 long eip, long cs, long eflags, long esp, long ss)
72 {
73 struct task_struct * P;
74 int i;
75 struct file * F;
7677
p = (struct task_struct *) get_free_page (); // data structure for a new job to allocate memory.
78 if (! p) // If the memory allocation error, an error code is returned and exit.

79 return - EAGAIN ;
80 task [Nr] = p; // pointer to put the new task structure task array. // where nr is task number, returned by the
previous find_empty_process ().
81 * P = * current ; / * NOTE! This does not copy the supervisor stack * /
/ * Note! This will not copy the super-user stack * / (just copy the contents of the current process).

82 p-> state = TASK_UNINTERRUPTIBLE ; // The status of the new process must first be set uninterruptible wait state.

83 p-> pid = last_pid ; // new process ID. From the previous call find_empty_process () to get.

84 p-> father = current -> pid; // Set the parent process ID.

85 p-> counter = p-> priority;


86 p-> signal = 0; // bitmap set to 0 signal.

87 p-> alarm = 0; // alarm timer value (number of ticks).

88 p-> leader = 0; / * Process leadership does not inherit * /


Leadership / * process are not inherited * /
89 p-> utime = P-> stime = 0; // Initialize the user mode and kernel mode time period.

90 p-> cutime = p-> cstime = 0; // Initialize the child user mode and kernel mode time.

--156--
5.11 fork.c program

91 p-> start_time = jiffies ; // current time ticks.


// Set the following data required task state segment TSS (see listing described later).

92 p-> tss.back_link = 0;
// Because it is assigned to the task structure p a new memory, so in this case esp0 just points to the top of the page. ss0: esp0 // stack for a program executed in kernel

mode.

93 p-> tss.esp0 = PAGE_SIZE + (Long) p; // kernel mode stack pointer.


94 p-> tss.ss0 = 0x10; // stack segment selector (the same kernel data section).

95 p-> tss.eip = eip; // instruction code pointer.

96 p-> tss.eflags = eflags; // flag register.


97 p-> tss.eax = 0; // This is when the fork () returns, the new process will return 0 of reason.

98 p-> tss.ecx = ecx;


99 p-> tss.edx = edx;
100 p-> tss.ebx = ebx;
101 p-> tss.esp = esp; // complete copy of the new process stack contents of the parent process. Thus requiring task0

102 p-> tss.ebp = ebp; // Stack relatively "clean."


103 p-> tss.esi = esi;
104 p-> tss.edi = edi;
105 p-> tss.es = es & 0xffff; // 16-bit segment register is valid.
106 p-> tss.cs = cs & 0xffff;
107 p-> tss.ss = ss & 0xffff;
108 p-> tss.ds = ds & 0xffff;
109 p-> tss.fs = fs & 0xffff;
110 p-> tss.gs = gs & 0xffff;
111 p-> tss.ldt = _LDT (Nr); // Set the new task selector local descriptor table (LDT descriptor in the GDT).
112 p-> tss.trace_bitmap = 0x80000000; (16-bit high active).
// If the current task using a coprocessor, you save its context. Clts assembler instruction to clear the registers CR0 control tasks have been exchanged in // (TS) flag.

Whenever a task switch occurs, CPU will set this flag. This flag is used to manage the math coprocessor: // If this flag is set, then each ESC command will be captured.

If the coprocessor Present also set, then it will capture // WAIT instruction. Therefore, if a task switch occurs after ESC instruction begins execution, the contents of the

coprocessor // may need to be saved before the implementation of the new ESC instruction. An error handler will be saved coprocessor and reset the TS flag. //

command is used to save all state fnsave coprocessor operand to a destination designated memory area (tss.i387).

113 if ( last_task_used_math == current )


114 __asm ​__ ( " clts; fnsave% 0 "::" m "( p-> tss.i387));
// set new tasks of code and data segment base address, limit long and copy the page table. If an error occurs (return value is not 0), the array // reset task corresponding entry for the new task

allocation and release of memory pages.

115 if ( copy_mem (Nr, p)) { // returns non-zero indicates an error.

116 task [Nr] = NULL ;


117 free_page ((Long) p);
118 return - EAGAIN ;
119 }
// If the parent has a file is opened, it will open the corresponding file number is incremented by one.

120 for (i = 0; i < NR_OPEN ; I ++)


121 if (f = p-> filp [i])
122 f-> f_count ++;
Pwd // The current process (parent process) is, root and executable citations are incremented.

123 if ( current -> pwd)


124 current -> pwd-> i_count ++;
125 if ( current -> root)
126 current -> root-> i_count ++;
127 if ( current -> executable)
128 current -> executable-> i_count ++;
// Set new task in the GDT and LDT TSS descriptor entry, data taken from the task structure. // a task switch, the task

register tr automatically loaded by the CPU.

--157--
5.11 fork.c program

129 set_tss_desc ( gdt + (Nr << 1) + FIRST_TSS_ENTRY , & (P-> tss));


130 set_ldt_desc ( gdt + (Nr << 1) + FIRST_LDT_ENTRY , & (P-> ldt));
131 p-> state = TASK_RUNNING ; / * Do this last, just in case * /
/ * Then the final set new tasks to be running, just in case * /
132 return last_pid ; // returns the new process ID (with the task number is different).

133 }
134
// Get the number of non-repetition of the process last_pid for the new process, and return to the task number (array index) in the task array.

135 int find_empty_process (Void)


136 {
137 int i;
138139
repeat:
// If last_pid incremented beyond its positive number indicates a range, then started again from 1 pid number.

140 if ((++ last_pid ) <0) last_pid = 1;


// search in the task array that has just set up pid number used by any task. If it is then regain a pid number.
141 for (i = 0; i < NR_TASKS ; I ++)
142 if ( task [I] && task [I] -> pid == last_pid ) Goto repeat;
// looking for a free entry for the new task in the task array, and returns the number of items. last_pid is a global variable, do not return.

143 for (i = 1; i < NR_TASKS ; I ++) // task 0 excluded.


144 if (! task [I])
145 return i;
// If the task array 64 items have been fully occupied, the source code is returned.

146 return - EAGAIN ;


147 }
148

5.11.3 Other Information

5.11.3.1 Task State Segment ( TSS )information

The following chart 5-11 It is a task state segment TSS ( Task State Segment )Content. Its description, see the Appendix.

31 twenty three 15 7 0

I / O Map base address ( MAP BASE) 0,000,000,000,000,000 64

0,000,000,000,000,000 Local Descriptor Table ( LDT) Selector 60

0,000,000,000,000,000 GS 5C

0,000,000,000,000,000 FS 58

0,000,000,000,000,000 DS 54

0,000,000,000,000,000 SS 50

0,000,000,000,000,000 CS 4C

0,000,000,000,000,000 ES 48

EDI 44

ESI 40

EBP 3C

ESP 38

EBX 34

EDX 30

--158--
5.11 fork.c program

ECX 2C

EAX 28

EFLAGS twenty four

Instruction pointer ( EIP) 20

Page directory base address register CR3 ( PDBR ) 1C

0,000,000,000,000,000 SS2 18

ESP2 14

0,000,000,000,000,000 SS1 10

ESP1 0C

0,000,000,000,000,000 SS0 08

ESP0 04

0,000,000,000,000,000 Previous mission TSS Descriptor 00

Map 5-11 Task State Segment TSS The information.

CPU All information management tasks need to be stored in a special type of segment, the task state segment ( task state segment - TSS) . Figure executed shows 80386

Task TSS format.

TSS The field can be divided into two categories:

1. CPU Updated when switching tasks during dynamic set of information. These fields are:

o General purpose registers ( EAX , ECX , EDX , EBX , ESP , EBP , ESI , EDI );
o Segment register ( ES, CS, SS, DS, FS, GS );

o Flag register ( EFLAGS );


o Instruction pointer ( EIP ); Before a mission TSS Selectors (updated only when

returned).

2. CPU Read but static information set does not change. These fields are:

o Task LDT Selector;


o Task containing page directory base address register ( PDBR );

o Privilege level 0-2 The stack pointer;

o When the task switching leads CPU Generate a debug ( debug) abnormal T- Bit (bit debug trace);

o I / O Bit bitmap base address (which is the maximum length TSS The maximum length, in TSS Descriptor described).

TSS can be stored anywhere in the linear space. Similar to other types of segments, task state segment is defined by a descriptor. Currently executing

task TSS By the task register ( TR ) To direct. instruction LTR with STR And to modify the read selector (visible part of the task register) of the task register.

I / O Each bit in the bitmap 1 Bit corresponds 1 More I / O port. For example, port 41 The bit is I / O FIG bit base address + 5 , Bit offset 1 Place. In protected mode, when

the encounter 1 More I / O Instruction ( IN, INS, OUT, OUTS) , CPU First, it will check the current privilege level is less than the flag register IOPL If this condition is satisfied, on the

implementation of the I / O operating. If not, then CPU Will check

TSS middle I / O Bit bitmap. If the corresponding bit is set, the general protection exception is generated, otherwise it will perform the I / O operating.

in Linux 0.11 In the figure SS0: ESP0 Task stack pointer for storing run-time kernel mode. SS1: ESP1 with SS2: ESP2

Respectively correspond to the privileged class run 1 with 2 When using the stack pointer, the two privilege levels in Linux Not used. And the task operating in the user mode stack

pointer is held in the SS: ESP Register. From the above found, the task enters the kernel mode whenever executed, the kernel mode stack pointer initial position unchanged, both

at the location of the top of the page structure of the task data.

--159--
5.12 sys.c program

5.12 sys.c program

5.12.1 Functional Description

sys.c The main program contains many features of the system call to implement a function. Wherein, if the return value - ENOSYS , Then this edition

Linux This function is not implemented, the current reference may code to understand their implementation. All system calls the function description, see the header file include /

linux / sys.h .

The program contains a lot about the process ID Process group ID ,user ID ,user group ID The actual user ID Effective user ID And session ID ( session ) Function

operation and the like. These first below ID Explained below.

A user has a user ID ( uid ) And user groups ID ( gid ). Both ID Yes passwd File in the user settings ID , Commonly referred to as the actual user ID ( ruid

) And real group ID ( rgid ). In each file i Node information are stored in the host user ID

And group ID They pointed out the file owner and user group. Mainly for permissions when accessing files or performing discriminating operation. In addition, the task data

structure of a process, in order to achieve different functions and save 3 Kinds of users ID And group ID . Table 5-5 Fig.

table 5-5 Associated with the process of the user ID And group ID

category user ID group ID

Process uid - user ID . Indicating that the user owns the process. gid - group ID . Users specify the group that owns the process.

Effective euid - Effective user ID . Indicates that the right to access the file. egid - Effective group ID . Indicates that the right to access the file.

suid - Saved by the user ID . When the user performs settings file sgid - Save group ID . When the group execute files ID Mark ( set-group-ID )

conserved ID Mark ( set-user-ID ) When set, suid Save the executable file uid . When set, sgid Save the executable file

otherwise suid Equal process euid . gid . otherwise sgid Equal process egid .

Process uid with gid Respectively, it is the process owner user ID And group ID , That is the actual user ID ( ruid ) And real group ID ( rgid ). Power users can use set_uid () with set_gid

() Modify them. Effective user ID And effective group ID Judge for permission to access the file at the time of the process.

Saved by the user ID ( suid ) And save group ID ( sgid ) Process for setting up access set-user-ID or set-group-ID File marker. When executing a program,

process euid Usually the actual user ID , egid Usually the real group ID . Therefore, the process can only be effective user access process, effective user defined set

of files or allow access to other files. However, if a file set-user-ID

When a valid user flag is set, then the process ID It will be provided to the user of the host file ID So the process can access a restricted set this flag file,

and the user's host file ID It is saved in suid in. Similarly, file set-group-ID Flag has a similar effect and make the same deal.

For example, if the host application is a super user, but it is provided set-user-ID Mark, then when the program is running a process, then the effective user of the

process ID ( euid ) Will be provided to the superuser ID ( 0 ). So this process will have a super-user privileges. A practical example is the Linux systematic passwd command.

The command is to set up a set-user-Id The program, thus allowing users to change their passwords. Because the program needs to write a new password for the user / etc /

passwd File, and the file is only the super user has write permissions, passwd We need to use the program set-user-ID Mark.

In addition, the process also has its own identity attributes of the process ID ( pid ), The process belongs to the group process group ID ( pgrp or pgid Session) and belongs

session ID ( session ). This 3 More ID It is used to indicate the relationship between a process and the process of the user ID And group ID Nothing to do.

5.12.2 Code comments

program 5-10 linux / kernel / sys.c program

1/*

--160--
5.12 sys.c program

2 * Linux / kernel / sys.c


3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <errno.h>
// error number header files. The system comprises various error number. (Linus imported from the minix).

89 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

10 #include <linux / tty.h> // tty header file, which defines tty_io, aspects of the serial communication parameters constant.

11 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

12 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

13 #include <sys / times.h> // define the structure of the process of running time tms and times () function prototype.

14 #include <sys / utsname.h> // header file system name structure.


15
// returns the date and time.

16 int sys_ftime ()
17 {
18 return - ENOSYS ;
19 }
20
//
twenty one int sys_break ()

twenty two {

twenty three return - ENOSYS ;


twenty four }

25
// current process for the sub-process debugging (degugging).
26 int sys_ptrace ()
27 {
28 return - ENOSYS ;
29 }
30
// change and print terminal line settings.

31 int sys_stty ()
32 {
33 return - ENOSYS ;
34 }
35
// get information on the terminal line settings.

36 int sys_gtty ()
37 {
38 return - ENOSYS ;
39 }
40
// modify the file name.

41 int sys_rename ()
42 {
43 return - ENOSYS ;
44 }
45
//
46 int sys_prof ()

--161--
5.12 sys.c program

47 {
48 return - ENOSYS ;
49 }
50
// set the actual current task and / or effective group ID (gid). If the task is not super-user privileges, // you can only swap its real group ID and effective group

ID. If the task with super user privileges can be set effective and practical // the group ID. Reserved gid (saved gid) is provided with an effective gid same value.

51 int sys_setregid (Int rgid, int egid)


52 {
53 if (rgid> 0) {
54 if (( current -> gid == rgid) ||
55 suser ())
56 current -> gid = rgid;
57 else
58 return (- EPERM );
59 }
60 if (egid> 0) {
61 if (( current -> gid == egid) ||
62 ( current -> egid == egid) ||
63 ( current -> sgid == egid) ||
64 suser ())
65 current -> egid = egid;
66 else
67 return (- EPERM );
68 }
69 return 0;
70 }
71
// set the process group number (gid). If the task is not superuser privileges, it can use setgid () which is effective gid // (effective gid) arranged
so as to retain its gid (saved gid) or a real gid (real gid). // If the task has superuser privileges, then the actual gid, and retain effective gid gid
are set to the parameters specified gid.
72 int sys_setgid (Int gid)
73 {
74 return ( sys_setregid (Gid, gid));
75 }
76
// turn on or turn off process accounting functions.

77 int sys_acct ()
78 {
79 return - ENOSYS ;
80 }
81
// any physical memory mapped into the process's virtual address space.

82 int sys_phys ()
83 {
84 return - ENOSYS ;
85 }
8687 int sys_lock ()

88 {
89 return - ENOSYS ;
90 }
91

--162--
5.12 sys.c program

92 int sys_mpx ()
93 {
94 return - ENOSYS ;
95 }
9697 int sys_ulimit ()

98 {
99 return - ENOSYS ;
100 }
101
// Returns the time value (in seconds) from January 1, 1970 00:00:00 GMT start timing. If tloc is not null, // the time value is also stored there.

102 int sys_time (Long * tloc)


103 {
104 int i;
105106
i = CURRENT_TIME ;
107 if (tloc) {
108 verify_area (Tloc, 4); // verify if enough memory (four bytes).
109 put_fs_long (I, (unsigned long *) tloc); // user data segment is also placed at tloc.

110 }
111 return i;
112 }
113 114 /
*
115 * Unprivileged users may change the real user id to the effective uid
116 * Or vice versa.
117 * /
/*
* Non-privileged users can see the actual user identifier (real uid) to change the effective user identifier (effective uid), and vice versa.
*/
// set the actual task and / or the effective user ID (uid). If the task is not super-user privileges, you can only swap its // real user ID and effective user
ID. If the task with super user privileges can be set effective and real user ID. // Reserved uid (saved uid) is provided with the same effective uid
value.
118 int sys_setreuid (Int ruid, int euid)
119 {
120 int old_ruid = current -> uid;
121
122 if (ruid> 0) {
123 if (( current -> euid == ruid) ||
124 (Old_ruid == ruid) ||
125 suser ())
126 current -> uid = ruid;
127 else
128 return (- EPERM );
129 }
130 if (euid> 0) {
131 if ((old_ruid == euid) ||
132 ( current -> euid == euid) ||
133 suser ())
134 current -> euid = euid;
135 else {
136 current -> uid = old_ruid;

--163--
5.12 sys.c program

137 return (- EPERM );


138 }
139 }
140 return 0;
141 }
142
// set the task user number (uid). If the task is not superuser privileges, it can use the setuid () which is effective uid // (effective uid) is
arranged which retains uid (saved uid) or a real uid (real uid). // If the task has superuser privileges, then the actual uid, uid and effective
uid are set to retain the parameters specified by uid.
143 int sys_setuid (Int uid)
144 {
145 return ( sys_setreuid (Uid, uid));
146 }
147
// set the system time and date. Tptr parameter is from January 1, 1970 00:00:00 GMT start time value (in seconds) timing. // calling process must have

superuser privileges.

148 int sys_stime (Long * tptr)


149 {
150 if (! suser ()) // If it is not super user returns the error (license).
151 return - EPERM ;
152 startup_time = get_fs_long ((Unsigned long *) tptr) - jiffies / HZ ;
153 return 0;
154 }
155
// Get the current mission time. tms structure comprises a user time, system time, the child process user time, the child process system time.

156 int sys_times (Struct tms * Tbuf)


157 {
158 if (tbuf) {
159 verify_area (Tbuf, sizeof * tbuf);
160 put_fs_long ( current -> utime , (Unsigned long *) & tbuf-> tms_utime);
161 put_fs_long ( current -> stime , (Unsigned long *) & tbuf-> tms_stime);
162 put_fs_long ( current -> cutime, (unsigned long *) & tbuf-> tms_cutime);
163 put_fs_long ( current -> cstime, (unsigned long *) & tbuf-> tms_cstime);
164 }
165 return jiffies ;
166 }
167
// When the parameter values ​end_data_seg reasonable, and the system does have enough memory, and the process does not exceed its maximum value at the end of the data segment size

// This function sets the data segment end_data_seg specified. The end of the code must be greater than and less than the end of the stack // 16KB. The return value is the new end of the

data section (if the return value is different from the required value, it indicates that there is an error has occurred). // This function does not directly call the user, and packaged by the libc

library function, and the return value is not the same.

168 int sys_brk (Unsigned long end_data_seg)


169 {
170 if (end_data_seg> = current -> end_code && // If the parameter> end code, and
171 end_data_seg < current -> start_stack - 16384) // less than the stack -16KB,
172 current -> brk = End_data_seg; // end new data segment value is set.

173 return current -> brk ; // Returns the current value of the data segment ending process.

174 }
175 176 /
*
177 * This needs some heave checking ...
178 * I just have not get the stomach for it. I also do not fully
179 * Understand sessions / pgrp etc. Let somebody who does explain it.

--164--
5.12 sys.c program

180 * /
/*
* The following code requires some rigorous inspection ...

* I just have no appetite to do that. I do not fully understand sessions / pgrp and so on. Understand them or let people do it.
*/
// set the process group ID is pgid.
// If the parameter pid = 0, then the current process ID. If pgid is 0, the parameter pid specified process group ID as // pgid. If the function is used to move a process from

one process group to another group process, the two processes must belong to the same group // session (session). In this case, the parameter specifies pgid prior to

addition of the process group ID, the group ID of the session at this time must be the same // (line 193) is added to the process.

181 int sys_setpgid (Int pid, int pgid)


182 {
183 int i;
184
185 if (! pid) // If the parameter pid = 0, then the current process ID.

186 pid = current -> pid;


187 if (! pgid) // If pgid is 0, then the current process pid as pgid.
188 pgid = current -> pid; // [POSIX ?? described herein and the discrepancy]

189 for (i = 0; i < NR_TASKS ; I ++) // array scanning task, the task of finding a specified number of processes.

190 if ( task [I] && task [I] -> pid == pid) {


191 if ( task [I] -> leader) // If the task is already a leader, an error is returned.
192 return - EPERM ;
193 if ( task [I] -> session =! current -> session) // If the task of the session ID
194 return - EPERM ; // Unlike the current process, an error is returned.

195 task [I] -> pgrp = pgid; // set pgrp the task.
196 return 0;
197 }
198 return - ESRCH ;
199 }
200
// Returns the group number of the current process. And getpgid (0) equivalents.

201 int sys_getpgrp (Void)


202 {
203 return current -> pgrp;
204 }
205
// create a session (session) (that is, set its leader = 1), and set up its session of its group number = = its process ID number. // setsid -
SET Session ID.
206 int sys_setsid (Void)
207 {
208 if ( current -> leader &&! suser ()) // If the current process is a session leader and not have superuser

209 return - EPERM ; // returns the error.


210 current -> leader = 1; // Set the current process for the new session leader.

211 current -> session = current -> pgrp = current -> pid; // set this process session = pid.
212 current -> tty = -1; // indicates that the current process does not have control terminal.

213 return current -> pgrp; // Return the session ID.

214 }
215
// Get system information. Which utsname structure contains five fields, namely: the name of the version of the operating system, the network node name, // current release level,

hardware version level and type name.

216 int sys_uname (Struct utsname * Name)


217 {
218 static struct utsname thisname = {// here gives information structure, this coding will certainly change.

--165--
5.13 vsprintf.c program

219 "Linux .0", "nodename", "release", "version", "machine"


220 };
221 int i;
222
223 if return (name!) - ERROR ; // If the information storage buffer pointer is null then an error is returned.

224 verify_area (Name, sizeof * name); // verify whether the size of the buffer overrun (beyond the allocated memory, etc.).

225 for (i = 0; i <sizeof * name; i ++) // the copy information byte by byte utsname in the user buffer.
226 put_fs_byte (((Char *) & thisname) [i], i + (char *) name);
227 return 0;
228 }
229
// Set the current process to create the file attributes mask to mask & 0777. And return to the original mask.

230 int sys_umask (Int mask)


231 {
232 int old = current -> umask ;
233
234 current -> umask = Mask & 0777;
235 return (old);
236 }
237

5.13 vsprintf.c program

5.13.1 Functional Description

mainly includes vsprintf () Function for generating an output formatting parameters. Because the function is C The standard library function, did not address the basic core

operating principle, it can be skipped. Description Use this function directly after reading the code.

5.13.2 Code comments

program 5-11 linux / kernel / vsprintf.c

1/*
2 * Linux / kernel / vsprintf.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / * Vsprintf.c - Lars Wirzenius & Linus Torvalds * /.

8/*
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
10 * /
// Lars Wirzenius is Linus's friend, with an office at the University of Helsinki had. In the summer of 1991 to develop Linux //, Linus was not very familiar
with the C language, it will not function using a variable argument list function. So Lars Wirzenius // for him to write this code for the kernel to display
information. He later (1998) acknowledged a bug in the code until // 1994 before anyone discovered and corrected. The bug is in use * as an output
field width, forget the star // increment the pointer to skip a number. In this code, the bug still persists (line 130). His profile is http://liw.iki.fi/liw/

1112 #include <stdarg.h>


// standard parameter header. In the form of macro variables defined parameter list. Mainly it described
- a type // (the va_list) and three macros (va_start, va_arg and va_end), for // vsprintf, vprintf, vfprintf
function.

--166--
5.13 vsprintf.c program

13 #include <string.h> // string header file. Mainly defines the built-in functions related to operation of the string.

1415 / * We use this so that we can do without the ctype library * /

/ * We use the following definitions, so we can not use the ctype library * /
16 #define is_digit (C) ((C)> = '' && (c) <= ' 9') // determine whether the character numeric characters.

17
// This function converts the character string into digital integer. Input numeric string pointer is a pointer, the result value is returned. Further forward pointer.

18 static int skip_atoi (Const char ** s)


19 {
20 int i = 0;
2122
while ( is_digit (** s))
twenty three i = i * 10 + * ((* s) ++) - '';
twenty four return i;
25 }
26
Here various symbols // constants defined conversion type.

27 #define ZEROPAD 1 / * Pad with zero * / / * Zero padding * /

28 #define SIGN 2 / * Unsigned / signed long * / / * Unsigned / signed long * /


29 #define PLUS 4 / * Show plus * / / * Display plus * /

30 #define SPACE 8 / * Space if plus * / / * The case of Canada, the space set * /

31 #define LEFT 16 / * Left justified * / / * Left adjustment * /

32 #define SPECIAL 32 / * 0x * / / * 0x * /
33 #define SMALL 64 / * Use 'abcdef' instead of 'ABCDEF' * / / * Lowercase * /
34
// In addition to the operation. Input: n = dividend, base divisor; Results: n = List, the function returns the remainder. // information, see Section 4.5.3

related to embedded assembly.

35 #define do_div (N, base) ({\


36 int __res; \
37 __asm ​__ ( " divl% 4 ":" = a "( n), "= d "(__ res): "" (n), " 1" ( 0), " r "( base)); \
38 __res;})
39
// Convert integer to a hexadecimal string specified.

// Input: num- integer; base- band; size- string length; precision- digital length (precision); type- type option. // Output: str string pointer.

40 static char * number (Char * str , Int num, int base, int size, int precision
41 , int type)
42 {
43 char c, sign, tmp [36];
44 const char * digits = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
45 int i;
46
// If the type type noted with lowercase letters, then the definition of lowercase letters set. // If the type pointed out the need to

adjust the left (on the left margin), then fill in the zero flag type of shield.

// If the binary radix less than 2 or greater than 36, then exit the process, i.e. the present process can program the number of radix between 2-32.

47 if (type & SMALL ) Digits = " 0123456789abcdefghijklmnopqrstuvwxyz ";


48 if (type & LEFT ) Type & = ~ ZEROPAD;
49 if (base <2 || base> 36)
50 return 0;
// If the type pointed out to fill zero, then set the character variable c = '0' (ie ''), or c is equal to the space character. // If the type indicated is a signed value and num is less

than 0, the counter variable sign = minus sign, and the absolute value of num. // Otherwise, if the type is pointed out that the plus sign, then set sign = plus sign, or the sign =

blank spaces if the type of sign, and 0 otherwise.

51 c = (type & ZEROPAD ?) '': '';

--167--
5.13 vsprintf.c program

52 if (type & SIGN && num <0) {


53 sign = '-';
54 num = -num;
55 } Else
56 sign = (type & PLUS ) '+':? ((Type & SPACE ?) '': 0);
// If signed, the width value minus 1. If the conversion is a special type indicates, the hexadecimal two further reduced width (for 0x), // octal width minus 1

(for octal conversion results before putting a zero).

57 if (sign) size--;
58 if (type & SPECIAL )
59 if (base == 16) size - = 2;
60 else if (base == 8) size--;
// num If the value is 0, the temporary string = '0'; otherwise the given base num convert the value to a character form.

61 i = 0;
62 if (num == 0)
63 tmp [i ++] = '';
64 else while (num! = 0)
65 tmp [i ++] = digits [ do_div (Num, base)];
// if the number is greater than the accuracy of the numerical value of the character, the extended precision value into

a digital numerical value. // size width value minus the stored value for the number of characters.

66 if (i> precision) precision = i;


67 size - = precision;

// here really began to form the desired conversion results, and temporarily placed in the string str. // If the type is not zero fill

(ZEROPAD) and left-Snap (left justified) flag, the first in str // put the number of spaces to fill the remaining width values ​noted. For

with the sign bit is stored in the symbol.

68 if (! (type & ( ZEROPAD + LEFT )))


69 while (size -> 0)
70 * str ++ = '';
71 if (sign)
72 * str ++ = sign;
// If the type is pointed out that the special conversion, the conversion result for octal head one place a '0'; and for the storage of hex '0x'.

73 if (type & SPECIAL )


74 if (base == 8)
75 * str ++ = '';
76 else if (base == 16) {
77 * str ++ = '';
78 * str ++ = digits [33]; // 'X' or 'x'
79 }
// if there is no type of adjustment of the left (left-truing) flag, c store the character ( '0' or space) in the remaining width, see line 51.

80 if (! (type & LEFT ))


81 while (size -> 0)
82 * str ++ = c;
At this time, there i // num is the number of digital values. If the number is less than the number of precision value, then placed in str (precision value -i) a '0'.

83 while (i <precision--)
84 * str ++ = '';
// The value for a good turn-numeric characters to fill in str. A total of i.

85 while (i -> 0)
86 * str ++ = tmp [i];
// If the width value is still greater than zero, it means the type of sign has left Snap flag logo. Then placed in the remaining space width.

87 while (size -> 0)


88 * str ++ = '';
89 return str ; // Returns converted string.
90 }

--168--
5.13 vsprintf.c program

91
// This function is to send output to the format string.
@ In order to use the output format in the kernel, Linus kernel implements the C standard. Wherein // is the format string fmt parameter;

args value of the number is changed; buf is the buffer output string. // Please tell us about the format conversion characters refer to the list

of code.

92 int vsprintf (Char * buf , Const char * fmt, va_list args)


93 {
94 int len;
95 int i;
96 char * str ; // string conversion process for storing.
97 char * s;
98 int * ip;
99100
int flags; / * Flags to number () * /
101 / * Number () function uses the mark * /
102 int field_width; / * Width of output field * /
/ * Output field width * /
103 int precision; . / * Min # of digits for integers; max
104 number of chars for from string * /
/ * Number of integer number min;.. Max number of characters in the string * /

105 int qualifier; / * 'H', 'l', or 'L' for integer fields * /


106 / * 'H', 'l', or 'L' for integer field * /
// pointer to the first character buf, then scan format string indicating the format conversion for each perform corresponding processing.

107 for ( str = buf ; * Fmt; ++ fmt) {


// string format conversion are indicated '%', the fmt where the scan format from the string '%', find the start of the string format conversion. // format is not indicative of a general

character are sequentially stored in str.

108 if (* fmt! = '%') {


109 * str ++ = * fmt;
110 continue;
111 }
112
// obtain the following format indication flag field strings, constants and sign flags into a variable.

113 / * Process flags * /


114 flags = 0;
115 repeat:
116 + + Fmt; / * This also skips first '%' * /
117 switch (* fmt) {
118 case '-': flags | = LEFT ; Goto repeat; // Left Snap adjustment.

119 case '+': flags | = PLUS ; Goto repeat; // put a plus sign.

120 case '': flags | = SPACE ; Goto repeat; // put spaces.


121 case '#': flags | = SPECIAL ; Goto repeat; // special conversion.
122 case '': flags | = ZEROPAD ; Goto repeat; // to fill zero (i.e., '0').
123 }
124
// get the current parameter field width field value into field_width variable. If the field width is the width whichever numerical value directly. // If the width of the field is a character '*' indicates

a parameter specified width. Therefore take calls to va_arg width value. // At this time, if the width value is less than 0, a negative number indicates that the flag field with the '-' sign

(left-truing), and therefore need the insertion of the flag in the flag variable and // the value is taken as the width of the field their absolute values.

125 / * Get field width * /


126 field_width = -1;
127 if ( is_digit (* Fmt))
128 field_width = skip_atoi (& Fmt);
129 else if (* fmt == '*') {

--169--
5.13 vsprintf.c program

130 / * It's the next argument * / // Here's a bug, should be inserted ++ fmt;

131 field_width = va_arg (Args, int);


132 if (field_width <0) {
133 field_width = -field_width;
134 flags | = LEFT ;
135 }
136 }
137
// The following code, take the format string domain conversion accuracy, precision and placed in a variable. Precision field start flag is '.'. // process which is similar to the width of a

range above. If the numerical accuracy of the domain directly to whichever precision value. If the accuracy is // domain character '*' indicates a parameter specifies the precision.

Therefore take calls to va_arg precision value. At this time, if the width value is less than 0, // the value is taken for the accuracy of the absolute value of the field.

138 / * Get the precision * /


139 precision = -1;
140 if (* fmt == '.') {
141 + + Fmt;
142 if ( is_digit (* Fmt))
143 precision = skip_atoi (& Fmt);
144 else if (* fmt == '*') {
145 / * It's the next argument * /
146 precision = va_arg (Args, int);
147 }
148 if (precision <0)
149 precision = 0;
150 }
151
// The following code modifier analysis length, and stores it qualifer variables. (H, l, L meaning the description refer to the list).
152 / * Get the conversion qualifier * /
153 qualifier = -1;
154 if (* fmt == ' h '|| * fmt == ' l '|| * fmt == ' L ') {
155 qualifier = * fmt;
156 + + Fmt;
157 }
158
// The following analysis of the conversion indicator.

159 switch (* fmt) {


// If the conversion indicator is 'c', it indicates that the corresponding character parameters should be. If the flag field indicates that this time instead of left flush against the front of the @ field

width field value -1 into a space character, then placed in character parameters. If the field width is also greater than 0, then the left flush against the added width value -1 // parameter space

character character.

160 case ' c ':


161 if (! (flags & LEFT ))
162 while (--field_width> 0)
163 * str ++ = '';
164 * str ++ = (unsigned char) va_arg (Args, int);
165 while (--field_width> 0)
166 * str ++ = '';
167 break;
168
// If the conversion indicator is 's', it indicates that the corresponding argument is a string. First, take the length of the parameter string, if it exceeds the threshold accuracy, the extended

precision // = string length domain. If the flag field indicates that this time instead of left flush against the front of the field into the (width value - the length of the string) // space characters. Then

placed parameter string. If the field width is also greater than 0, then the left flush against the added // (width value - string length) after the parameter string of space characters.

169 case ' s':

--170--
5.13 vsprintf.c program

170 s = va_arg (Args, char *);


171 len = strlen (S);
172 if (precision <0)
173 precision = len;
174 else if (len> precision)
175 len = precision;
176
177 if (! (flags & LEFT ))
178 while (len <field_width--)
179 * str ++ = '';
180 for (i = 0; i <len; ++ i)
181 * str ++ = * s ++;
182 while (len <field_width--)
183 * str ++ = '';
184 break;
185
// If the format conversion operator is 'o', indicates the need to convert a parameter corresponding to a string of octets. Call the number () function handles.

186 case ' o ':


187 str = number ( str , va_arg (Args, unsigned long), 8,
188 field_width, precision, flags);
189 break;
190
// If the format conversion operator is 'p', a pointer indicates the type of the corresponding parameter. At this time, if the parameter is not set the width of the domain, // the default width of 8,

and the need to add zero. Then call the number () function for processing.

191 case ' p ':


192 if (field_width == -1) {
193 field_width = 8;
194 flags | = ZEROPAD ;
195 }
196 str = number ( str ,
197 (Unsigned long) va_arg (Args, void *), 16,
198 field_width, precision, flags);
199 break;
200
// If the format conversion indication is 'x' or 'X', it indicates that the corresponding parameters need to be printed in hexadecimal number. 'X' represents lowercase letters.

201 case ' x ':


202 flags | = SMALL ;
203 case ' X ':
204 str = number ( str , va_arg (Args, unsigned long), 16,
205 field_width, precision, flags);
206 break;
207
// If the format conversion character is 'd', 'i' or 'u', indicates that the corresponding parameter is an integer, 'd', 'i' symbol representing an integer, and therefore need to add // signed flag. 'U'

representative of an unsigned integer.

208 case ' d ':


209 case ' i ':
210 flags | = SIGN ;
211 case ' u ':
212 str = number ( str , va_arg (Args, unsigned long), 10,
213 field_width, precision, flags);
214 break;
215

--171--
5.13 vsprintf.c program

// If the format conversion indicator is 'n', it indicates the number of characters stored so far should be converted and output to the corresponding parameter designated by the pointer

position.

// first using the va_arg () obtains the argument pointer, and then the number of characters that has been converted into a good position of the cursor.

216 case ' n ':


217 ip = va_arg (Args, int *);
218 * Ip = ( str - buf );
219 break;
220
// If not format conversion character '%', wrong format string indicates directly a '%' written to the output stream. // If there is a character at the position of the character format

conversion, it is also written directly to the output character string, and returns to 107 to continue processing rows // format string. Otherwise, it said that it has to deal with at the end of

the format string, the loop exits.

221 default:
222 if (* fmt! = '%')
223 * str ++ = '%';
224 if (* fmt)
225 * str ++ = * fmt;
226 else
227 - - fmt;
228 break;
229 }
230 }
231 * str = '\ 0 '; // Finally add the converted null string at the end.
232 return str - buf ; // returns the converted character string length value.

233 }
234

5.13.3 Other Information

5.13.3.1 vsprintf () The format string

int vsprintf (Char * buf , Const char * fmt, va_list args)

vsprintf () Function is printf () One family of functions. These functions generate formatted output: accept the format string determining an output format fmt , Format number

changes parameters of the format string, generating formatted output.

printf Directly output to the standard output handle stdout . cprintf The output to the console. fprintf The output to a file handle.

printf Prozone ' v ' Character (for example, vfprintf) It represents the parameter is from va_arg Array va_list args Accept. printf Preceded by a ' s' It indicates the character to output to null

End of the string buf (In this case the user should ensure buf There is enough space to store the string). The method of using the format string described in detail below.

1. Format string

printf Series format string functions for controlling the function mode conversion, formatting, and outputs the parameters. For each format, you must have the

corresponding parameters, too many parameters are ignored. Format string contained two components, one is to be copied directly to the output of a simple character; the other is

the corresponding parameters for the format conversion instruction character string.

2. String Format Indicator

Format string indicating the following form:

% [Flags] [width] [prec.] [| H | l | L] [type]

A conversion indicating for each string are required to start a percent sign (%). among them

[Flags] A selectable marker is a sequence of characters;

--172--
5.13 vsprintf.c program

[Width] The width of the indicator is selectable;

[.Prec] Accuracy is optional ( precision) indicator;

[H | l | L] Input length modifier is optional;

[Type] Is a conversion type character (or called conversion indicator).

flags Alignment control output, numerical symbols, decimal point, the zero tail, binary, octal, hexadecimal, or the like, see above list

27-33 Comment line. Flag characters and their meanings are as follows:

# It represents the corresponding parameter needs to be converted to a "special form." For octal ( o) , The first character string to be converted

It is a zero. For hexadecimal ( x or X) , The need to convert the string ' 0x ' or' 0X ' beginning. for e, E, f, F, g as well as G Even if no decimal places, the conversion results will

always have a decimal point. for g or G After dragging the zero will not be deleted.

0 Conversion results should be attached to zero. for d, i, o, u, x, X, e, E, f, g with G , The conversion result will fill in the blanks with zeros to the left instead of

With a space. If both appear 0 And - flag, 0 Flag will be ignored. For conversion value, if the accuracy is given field, 0 Flag is also ignored.

- Results converted into the appropriate field boundary will be left adjustment (left). (The default is to make the right adjustments - right). n Conversion Example

In addition, the conversion results will fill a space on the right.

'' It should leave a space before a positive number indicates a signed conversion results produced.

+ It represents the total need to place a symbol before a symbol conversion result (+ or -). For default, only negative numbers

negative.

width Specifies the width of the output string, which specifies the minimum width value of the field. If the result is converted smaller than the specified width, at its left (or

right, if the left-adjustment flag is given) needed to fill a space or zero (the flags Flag determines) the number and the like. In addition to using a numerical width fields than can be

used '*' to indicate the width of the field is given by an integer parameter. When the conversion value is larger than the width width When the specified width, in any case small-width

values ​are not the results are truncated. Field width will be expanded to include the full results.

precision Is a minimum number of digital output. for d, I, o, u, x with X Conversion, precision value indicates the minimum number of digits appear. for e, E, f with F This value

indicates the number appear after the decimal digits. for g or G , Indicates the maximum number of significant digits. for

s or S Conversion, the accuracy of the output value of the maximum number of characters described in the character string.

Length indicator described modified form of the output type Integer conversion. Described below in 'The Integer' represents d, i, o, u, x or

X Conversion.

hh Integer conversion described later corresponds to a signed or unsigned char character parameters.

h Integer conversion described later corresponds to a signed or unsigned short integer parameters.

l Integer conversion described later corresponding to a long or unsigned long integer parameters.

ll Integer conversion described later corresponding to a long integer or unsigned long integer parameters.

L Explanation e, E, f, F, g or G Conversion results corresponding to parameters of a long double.

type Is a parameter type input and output formats accepted. Converting the meaning of each indicator is as follows:

d, I Integer parameter is converted to a signed integer. If there is accuracy ( precision) , Then given a minimum need for output

Number of digits. If the digital value is converted to a fewer number, it will add zero to its left. The default precision value is 1 .

o, u, x, X Unsigned integer will be converted to an unsigned octal ( o) , Unsigned decimal ( u) Or unsigned hexadecimal ( x or

X) Output representation. x He pledged to use lowercase letters ( abcdef ) To represent hexadecimal number, X Uppercase letters ( ABCDEF ) Represent a hexadecimal number. If there

precision field, it indicates a minimum number of digits required output. If the digital value is converted to a fewer number, it will add zero to its left. The default precision value is 1 .

e, E Both have been rounded for converting characters converts the argument to [-] d.ddde + dd form. Numbers after the decimal point one

--173--
5.14 printk.c program

Number equal precision. Without a precision field, it takes the default value 6 . If the accuracy is 0 , No decimals appear. E Uppercase letters E

To represent the exponent. Exponent part always 2 Digit number. If the value is 0 , Then the index is 00 .

f, F Both have been rounded for converting characters converts the argument to [-] ddd.ddd form. Number of digits after the decimal point, etc.

In accuracy. Without a precision field, it takes the default value 6 . If the accuracy is 0 , No decimals appear. If there is a decimal point, so at least there will be back 1 Digits.

g, G These two parameters will be converted to a conversion character f or e The format (if it is G , It is F or E format). Precision value specifies the number of integers. If the

accuracy is not a domain, it defaults 6 . If the precision is 0 Then as 1 To be treated. If the index is less than the conversion

--4 Greater than or equal to the precision, is used e format. After dragging the fractional part of zero will be deleted. Only when there is at least one decimal place decimal point will
appear.

c Parameter will be converted into an unsigned character and outputs the conversion result.

s It requires input pointer to a string, and the string to be null end. If the field with a precision, output only the fine

Of the number of characters required, and no need to string null end.

p Output pointer in hexadecimal form.

n Save for the number of characters so far from the converter output to the position indicated by the pointer corresponding to the input. Right into the parameters

Line conversion.

% A% sign output, conversion is not performed. At this time, i.e. throughout the transition indication to %%.

5.13.4 The difference between the current version of

Because the file is also part of the library functions, so from 1.2 Version of the kernel to start the direct use of the library. That is to delete the file.

5.14 printk.c program

5.14.1 Functional Description

printk () Kernel is used in the print (display) function, and function C Standard function library print () the same. The reason to re-write such a function is in the

kernel can not be dedicated to user mode fs Segment register, you must first save it. printk () Function first use svprintf () Parameters for formatting, then save the fs Calling

the case a segment register tty_write () Print information display.

5.14.2 Code comments

program 5-12 linux / kernel / printk.c

1/*
2 * Linux / kernel / printk.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * When in kernel-mode, we can not use printf, as fs is liable to


9 * Point to 'interesting' things. Make a printf with fs-saving, and
10 * All is well.
11 * /
/*
* When in kernel mode, we can not use printf, since register fs to point somewhere else not interested.
* Prepare yourself and save a printf fs prior to use, everything will be solved.

*/

--174--
5.15 panic.c program

12 #include <stdarg.h> // standard parameter header. In the form of macro variables defined parameter list. Mainly it described
- a type // (the va_list) and three macros (va_start, va_arg and va_end), for // vsprintf, vprintf, vfprintf
function.
13 #include <stddef.h> // define the standard header files. Definition of NULL, offsetof (TYPE, MEMBER).

1415 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

1617 static char buf [1024];

18
// The following function vsprintf () in line 92 begins linux / kernel / vsprintf.c in.
19 extern int vsprintf (Char * buf , Const char * fmt, va_list args);
20
// display function used by the kernel.

twenty one int printk (Const char * fmt, ...)


twenty two {

twenty three va_list args; // va_list pointer is actually a character type.


twenty four int i;
2526
va_start (Args, fmt); // function parameters to start treatment. In (include / stdarg.h, 13)

27 i = vsprintf ( buf , Fmt, args); // Use the output format string fmt args parameter list to buf. // returns the output value i

is equal to the length of the string.

28 va_end (Args); // parameter handling function ends.

29 __asm ​__ ( " push %% fs \ n \ t " // save fs.


30 "Push %% ds \ n \ t"
31 "Pop %% fs \ n \ t" // make fs = ds.
32 "Pushl% 0 \ n \ t" // The length of the string onto the stack (the stack is three parameter).

33 "Pushl $ _buf \ n \ t" // buf will address onto the stack.


34 "Pushl $ 0 \ n \ t" 0 // the value onto the stack. It is the channel number channel.

35 "Call _tty_write \ n \ t" // Call tty_write function. (Kernel / chr_drv / tty_io.c, 290).
36 "Addl $ 8, %% esp \ n \ t" // skipped (dropped) onto the stack two parameters (buf, channel).

37 "Popl% 0 \ n \ t" // pop string length value, as a return value.


38 "Pop %% fs" // restore the original fs register.

39 :: " r "( i): " ax "," cx "," dx "); // Inform the compiler, register ax, cx, dx value may have changed.
40 return i; // Returns string length.
41 }
42

5.15 panic.c program

5.15.1 Functional Description

When the kernel error, call the function panic () Error message is displayed and the system into an infinite loop. In many parts of the kernel, and if there was going

seriously wrong call to the function. In many cases, call panic () Function is a straightforward approach. You do well to follow the UNIX "As concise as possible" principle.

panic It is "panic panic" means. in Douglas Adams Novel " Hitch hikers Guide to the Galaxy "(" Galaxy hiker's Guide "), the book's most

famous sentence is" Do not Panic! " . This is a series of novels linux A hacker books read most often.

--175--
5.16 Summary

5.15.2 Code comments

program 5-13 linux / kernel / panic.c

1/*
2 * Linux / kernel / panic.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * This function is used through-out the kernel (includeinh mm and fs)


9 * To indicate a major problem.
10 * /
/*
* This function is used throughout the kernel (included in the header file * .h, the memory manager and the file system fs in mm),

* Pointed out that the main problem for error.

*/
11 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

12 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

1314 void sys_sync (Void);


/ * It's really int * / / * Actually, the integer int (fs / buffer.c, 44) * /
15
// This function is used to display important error message that appears in the kernel, and run the file system synchronization function, then enter an infinite loop - crash. // If the current process

is the task 0, it also shows that the task switching error, and has not run a file system synchronization function.

16 volatile void panic (Const char * s)


17 {
18 printk ( ' Kernel panic:% s \ n \ r ", s);
19 if ( current == task [0])
20 printk ( ' In swapper task - not syncing \ n \ r ");
twenty one else
twenty two sys_sync ();
twenty three for (;;);
twenty four }

25

5.16 chapter summary

linux / kernel Directory 12 Code files are given kernel to achieve the most important mechanisms, including system calls, process scheduling, replication, and terminate the

process of handling four-part process.

--176--
6.1 Overview

The first 6 Chapter block device drivers ( block driver)

6.1 Outline

This chapter describes the block device driver in the kernel. in Linux 0.11 Kernel primary support two kinds of hard and floppy drive block device. Because block devices

with major file system and cache, and therefore a good idea to take a quick look a chapter file system. Source code files involved see list 6-1 Fig.

List 6-1 linux / kernel / blk_drv table of Contents

file name size Last Modified Time (GMT) Description

Makefile 1951 bytes 1991-12-05 19:59:42 make profiles

blk.h 3464 bytes 1991-12-05 19:58:01 block device special file header

floppy.c 11429 bytes 1991-12-07 00:00:38 floppy driver

hd.c 7807 bytes 1991-12-05 19:58:17 hard disk drivers

ll_rw_blk.c 3539 bytes 1991-12-04 13:41:42 block device interface program ramdisk.c

2740 bytes 1991-12-06 03:08:06 Virtual disk driver

Chapter function program code can be divided into two categories, one of each corresponding block device driver, such procedures are:

1. Hard disk drivers hd.c ;

2. Floppy driver floppy.c ;


3. Virtual memory disk driver ramdisk.c ;

Another class of only one program, the kernel is the other programs access block device interface program ll_rw_blk.c . Device special file header block blk.h

And is a three block devices ll_rw_blk.c Interactive program provides a unified set of device requests the same way and start the program.

6.2 The overall function

Read and write operations to the hard and floppy disk block device data is performed by the interrupt handler. The amount of data per read and write to a logical block ( 1024

Bytes), and the device controller is based on a block sector ( 512 Bytes). In the process, the use of write request entries waiting queue buffer by sequentially operating a plurality of

write logic block.

When the program needs to read a logical block on the hard disk, it will apply to the buffer management program, and the process of the program goes to sleep waiting

state. Buffer management program first to find out whether this had previously been read data in the buffer. If the buffer already have, directly to the corresponding buffer header

pointer returns to the program and wakes up the program processes. If the requested data block does not exist in the buffer, the buffer management program can call in this chapter

lower block read and write functions ll_rw_block () Issuing a read operation request block to the corresponding block device drivers. This function will create a request structure for this

item, and inserted into the request queue. In order to provide efficiency of disk read and write, the head moving distance is reduced, when the interrupt request key using an elevator

algorithm moves.

--177--
6.2 overall function

When the request queue is empty entry device when the corresponding block indicates that the block device is not busy at the moment. So the data kernel will immediately

issue a read command to the controller of the block device. When the controller block of the device after the specified data is read into the buffer block, it will send an interrupt

request signal and the read command invokes the appropriate handler, processing continues operation or a read sector process ends this request entry. For example, the closing

operation of the respective blocks and sets the device buffer block flag data has been updated, and finally waiting for the wake-up process of the data block.

6.2.1. Device block request entries and request queue

According to the above description, we know that low-level read and write functions ll_rw_block () It is to establish contact with various items block device by requesting and

issuing read and write requests. For each piece of equipment, the use of a core block device table blk_dev [] To manage. Each piece of equipment occupies a block in the device

table. Building block device table entry for each block device (taken from the back blk.h ):

struct blk_dev_struct {
void (* request_fn) (void); // function pointer entry operation request.

struct request * Current_request; // pointer to the current item request.

};
extern struct blk_dev_struct blk_dev [ NR_BLK_DEV ]; // block device table (array) (NR_BLK_DEV = 7).

Wherein the first field is a function pointer, the corresponding entry for the operation request block device. For example, a hard disk driver, which is

do_hd_request () And for a floppy disk device, it is do_floppy_request () . The second field is a pointer to the current request configuration item, for indicating the request entry

device of the present block currently being processed, are set to the initialization NULL .

Block device table in the kernel initialization, init / main.c It is set when the program calls for each device initialization function. To facilitate the expansion,

Linus The table block device built in a major number of the array index. in Linux 0.11 , The master device has a number 7 Species, see Table 6-1 Fig. Wherein the master device

number 1 , 2 with 3 Corresponding block device: virtual disk, floppy disk and a hard disk. In block device array other items are set to default NULL .

table 6-1 Linux 0.11 Kernel major number

Main equipment type Explanation Function operation request entry

0 no no. NULL

1 Block / character ram, Memory devices (virtual disk, etc.). do_rd_request ()

2 Piece fd, Floppy device. do_fd_request ()

3 Piece hd, Hard disk device. do_hd_request ()

4 character ttyx device. NULL

5 character tty device. NULL

6 character lp The printer device. NULL

When the kernel issues a block write or other operation request device, ll_rw_block () I.e., the device will function in accordance with the operation command number of the

parameters specified in the block header and data buffering, by the corresponding function operation request entry do_XX_request () Establishing a requested item block device,

using an elevator algorithm into the request queue entries. Request queue entry consists of an array of items requested item, total 32 Item, the data structure of each requested

item as follows:

struct request {
int dev; // used device number (if it is -1, indicating that idle).
int cmd; // command (READ or WRITE).
int errors; // number of errors generated during operation.

unsigned long sector ; // start sector. (1 sector = 2)


unsigned long nr_sectors; // read / write the number of sectors.

--178--
6.2 overall function

char * buffer; // data buffer.


struct task_struct * Waiting; // wait for local operations performed tasks completed.

struct buffer_head * Bh; // buffer header pointer (include / linux / fs.h, 68).
struct request * Next; // points to the next request entry.

};
extern struct request request [ NR_REQUEST ]; // request queue array (NR_REQUEST = 32).

Current Request necklace table pointer array entry request of the device each block device request queue together constitute the apparatus. And between items by using

item field next Forming a linked list pointer. Thus block and associated equipment item request queue structure shown below. Main reason for using an array plus requested item

list structure is designed to meet two purposes: First, by using the array configuration may be requested item when searching an idle cycle operation request block, the program is

very simple and can be compiled; the second is to meet the elevator algorithm insert item operation request, and therefore need the list structure. Map 6-1 In this hard disk device

is shown having 4 A requested item, a floppy disk device having 1 Request items, and virtual disk read and write requests currently no equipment items.

For a current block device idle, when ll_rw_block () A function for the establishment of a requested item, make the device current request pointer entries current_request Directly

to the requested item just created, and call the corresponding device requests entries immediately begin operation function block device read and write operations. When a piece

of equipment has several requests entry list consisting of presence, ll_rw_block () Will use an elevator algorithm, the head movement distance according to the principle of the

minimum, the new request list item into the appropriate position.

In addition, to meet the priority read operation, when a request for the establishment of a new array of items and item search request, the search range of free entry to

establish a write request limit before the entire array of items 2/3 The range, while the remaining 1/3 Requested item devoted to the establishment of a read request items to use.

Block device table entry Request entry array (32)

do_rd_request The current request item


Virtual memory disk

current_request
The remaining requested item

Idle requested item


hard disk do_hd_request

current_request

floppy disk do_fd_request

current_request

Map 6-1 Device table entry request entry

6.2.2. Block device operation

With the hard disk in the system (kernel) IO In operation, it is necessary to consider the interactions between the three objects. They are the system, controller and drive

(e.g., hard or floppy disk drive), see FIG. 6-2 Fig. The system may send a command directly to the controller or the controller waits for an interrupt request; receiving the command

controller will control the operation of the drive, the read / write data, or perform other operations. So here we can interrupt signal issued by the controller seen as a

synchronization signal between these three, experienced steps are:

First, the system controller at the end of the specified command execution caused the interrupt process should call C Function, and then transmits the read block to the

device controller, write, reset or other operation command;

--179--
6.3 Makefile file

When completion of the specified control command will be issued an interrupt request signal, initiating system block device performs interrupt processing, and call the

specified C Function of read / write commands or other processing after the end of the command.

System (CPU) command Device Controller driver


data transmission

Interrupt Request

Map 6-2 The system, controller and driver block device

For the write operation, the system needs after issuing a write command (using hd_out () ) Administering to wait for the controller allows to write data in response to the

controller, i.e. the data need to query the controller to wait for service request flag status register DRQ Position. once DRQ Is set, the system can transmit data buffer controller to the

one sector, also the use of hd_out () function.

When all the controller data write drivers (the error), it will produce an interrupt request signal to the interrupt processing executed in foregoing preset C function( write_intr () ).

This function will check whether there is data to be written. If so, then the system controller transmitted a data sector buffer, and then waits for the interrupt controller again initiated

after the drive data writing has been so repeatedly executed. At this time, if all the data has been written to the drive, the C Processing function is executed after the end of this

write disk: Wake related processes waiting for the requested item about the data, wake up processes waiting for a request item, release the current request item and delete the

item request and the associated buffer release the lock from the list . Then call the function to request entry operation to the next read / write disk request item (if there are any).

For read the disk operating system after transmitting the start position includes a sector to be read, the number of the sector information and other commands to the

controller, the controller waits for an interrupt signal. When the controller in accordance with the requirements of the read command, a sector of the designated data to the buffer

from their drive will issue an interrupt request. Thus performs the foregoing operation is preset to read the disk C function( read_intr () ). This function first data buffer controller of

one sector into the buffer system, the buffer system to adjust the current position of the writing, and then decreasing the number of sectors required to read. If there are data to be

read (the result of diminishing the value is not 0 Under), continue to wait controller sends an interrupt signal. If all the requirements of the sector at this time have already read the

buffer system, the implementation of the above write disk operation like the end of the processing.

For virtual disk device, read and write operations because it does not involve the synchronization between the external apparatus, thus there is no such interrupt

processing. Entry of the current request read and write operations in the virtual device entirely do_rd_request () Implemented.

6.3 Makefile file

6.3.1. Functional Description

That makefile File for managing the program to compile all from this category.

6.3.2. Code comments

program 6-1 linux / kernel / blk_drv / Makefile

1#
2 # Makefile for the FREAX-kernel block device drivers.
3#

--180--
6.3 Makefile file

4 # Note! Dependencies are done automagically by 'make dep', which also


5 # Removes any old dependencies. DO NOT put your own dependencies here
6 # Unless it's something special (ie not a .c file).
7#
# FREAX kernel block device driver to the Makefile
# note! Dependency is performed by the 'make dep' automatically, which will automatically remove the original dependency information. Do not put your own

# Dependency information on here, unless it is (that is not a message .c file) special file.
# (Linux first name FREAX, the name was later changed to Linux ftp.funet.fi administrator).
89 AR
= Gar # GNU binary file processing program for creating, modifying and extracting files from the archive.
10 AS = Gas # GNU assembler.
11 LD = Gld # The GNU linker.
12 LDFLAGS = -s -x # connection program all the parameters, -s omitted all symbols output file information. -x Delete all local symbols.

13 CC = Gcc # GNU C language compiler.


# The next line is the C compiler options. -Wall display all warnings; -O optimization option, to optimize code size and execution time;
# - fstrength-reduce execution code optimization cycle, excluding iteration variable; -fomit-frame-pointer will be omitted to save unnecessary

# The frame pointers; -fcombine-regs merge register, reduce the use of register class; -finline-functions all Jane
# Single short code embedded function calls the program; -mstring-insns Linus own filling optimization options, will no longer use;
# - nostdinc -I ../ include not using the default path contains the file, and use the specified directory (../../include).
14 CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
15 - finline-functions -mstring-insns -nostdinc -I ../../ include
# C pre-processing options. -E C only run pre-treatment, pre-treatment and the results for all of the specified program is output to the standard output C

# The apparatus or a specified output file; -nostdinc -I ../../ include op.


16 CPP = Gcc -E -nostdinc -I ../../ include
17
# The following rule indicates that make use of the following command will compile all .c files generated .s Assembler. The rule of command

# Refers gcc CFLAGS using the specified options compiled C code is compiled without stops (-S), thereby generating
# C each corresponding to the input file assembler code file. Assembler default file name is generated by the original file name C
# Remove .c and .s suffix plus. -o represented followed by the name of the output file. Of which $ *. S (or $ @ ) is automatic target variable,

# $ <Represents the first prerequisite here that is qualified * .c files.


18 .cs:
19 $ (CC) $ (CFLAGS) \
20 - S -o $ *. S $ <
# The following rule means that all .s assembler .o files compiled into object files. Line 22 is a command to achieve the specific operation.

twenty one .so:

twenty two $ (AS) -c -o $ *. O $ <


twenty three .co: # . Similar to the above, * c files - * .o object files. Not connect.
twenty four $ (CC) $ (CFLAGS) \
25 - c -o $ *. o $ <
2627 OBJS = ll_rw_blk.o floppy.o hd.o ramdisk.o
# Define the target file variable OBJS.
28
# Use the following command to connect to the target file in the library with blk_drv.a prerequisite OBJS.

29 blk_drv.a: $ (OBJS)
30 $ (AR) rcs blk_drv.a $ (OBJS)
31 sync
32
# The following rules for the cleanup. When performing 'make clean', it will execute commands on the line 34--35 remove all compiled
# Connection file generated. 'Rm' command is to delete the file, meaning -f option is to ignore the file does not exist, and does not delete the information.

33 clean:
34 rm -f core * .o * .a tmp_make
35 for i in * .c; do rm -f `basename $$ i .c`.s; done
36

--181--
6.4 blk.h file

# Here was the objective or rules for checking dependencies between files. Methods as below:

# Sed string editing program for the Makefile (i.e. are files), and outputs for deletion Makefile
# File '### Dependencies' all rows behind rows (44 rows from the beginning of the next), and generates tmp_make
# Temporary files (action line 38). Gcc preprocessing operation is then performed for each file in the C kernel / blk_drv / directory.
# - M flag tells the preprocessor output description of the rules relating to each target file, and make compliance with these rules syntax.

# For each source file, the output of preprocessor make a rule, the result is a certain form of the corresponding source file
# File name plus its dependencies - lists all the header files included in the source file. The pretreatment results are added to the temporary

# Tmp_make file, and then copy the temporary file into a new file Makefile.
37 dep:
38 sed '/ \ # \ # \ # Dependencies / q' <Makefile> tmp_make
39 (For i in * .c; do echo -n `echo $$ i | sed '.. S, \ c, \ s,'` ""; \
40 $ (CPP) -M $$ i; done) >> tmp_make
41 cp tmp_make Makefile
4243 ### Dependencies:

44 floppy.s floppy.o: floppy.c ../../include/linux/sched.h ../../include/linux/head.h \


45 . . /../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
46 . . /../include/signal.h ../../include/linux/kernel.h \
47 . . /../include/linux/fdreg.h ../../include/asm/system.h \
48 . . /../include/asm/io.h ../../include/asm/segment.h blk.h
49 hd.s hd.o: hd.c ../../include/linux/config.h ../../include/linux/sched.h \
50 . . /../include/linux/head.h ../../include/linux/fs.h \
51 . . /../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \
52 . . /../include/linux/kernel.h ../../include/linux/hdreg.h \
53 . . /../include/asm/system.h ../../include/asm/io.h \
54 . . /../include/asm/segment.h blk.h
55 ll_rw_blk.s ll_rw_blk.o: ll_rw_blk.c ../../include/errno.h ../../include/linux/sched.h \
56 . . /../include/linux/head.h ../../include/linux/fs.h \
57 . . /../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \
58 . . /../include/linux/kernel.h ../../include/asm/system.h blk.h

6.4 blk.h file

6.4.1. Functional Description

This is the first file on the hard-block device parameters, as only a block device, the device code block in the same place. Wherein the primary data structure is defined in

terms of the request queue request , Macro statement defines the elevator with the search algorithm, the kernel is currently supporting virtual disk, hard and floppy disk three kinds

of block devices according to their respective major number of the corresponding constant value.

6.4.2 Code comments

program 6-2 linux / kernel / blk_drv / blk.h

1 #ifndef _BLK_H 2 #define _BLK_H


3 4 #define NR_BLK_DEV

7 // the number of device blocks.

5/*
6 * NR_REQUEST is the number of entries in the request-queue.

--182--
6.4 blk.h file

7 * NOTE that writes may use only the low 2/3 of these: reads
8 * Take precedence.
9*
10 * 32 seems to be a reasonable number: enough to get some benefit
11 * From the elevator-mechanism, but not so much as to lock a lot of
12 * Buffers when they are in the queue. 64 seems to be too many (easily
13 * Long pauses in reading when heavy writing / syncing is going on)
14 * /
/*
* NR_REQUEST defined below is the number of entries included in the request queue.

* Note that read operations only use these low-end items 2/3; read priority.
*
* 32 seems to be a reasonable figure: enough to benefit from the elevator algorithm,
* But when the buffer is in the queue and locked without appearing to be a big number. 64 spotted

* Go too (when a large number of write / synchronization run can easily lead to long pause).
*/
15 #define NR_REQUEST 32
1617 / *

18 * Ok, this is an expanded form so that we can use the same


19 * Request for paging requests when that is implemented. In
20 * Paging, 'bh' is NULL, and 'waiting' is used to wait for
twenty one * Read / write completion.

twenty two * /

/*
* The OK, the following structure is an extended form of the request, and therefore When implemented, we can request the tab

* Using the same request structure. In the tab process, 'bh' is NULL, and the 'waiting' for waiting for the read / write is completed.

*/
// The following is the structure of a request queue entries. Wherein if dev = -1, it indicates that the item was not used.

twenty three struct request {

twenty four int dev; / * -1 if no request * / // device number to use.


25 int cmd; / * READ or WRITE * / // command (READ or WRITE).
26 int errors; // number of errors generated during operation.

27 unsigned long sector ; // start sector. (1 sector = 2)


28 unsigned long nr_sectors; // read / write the number of sectors.

29 char * buffer; // data buffer.


30 struct task_struct * Waiting; // wait for local operations performed tasks completed.

31 struct buffer_head * Bh; // buffer header pointer (include / linux / fs.h, 68).
32 struct request * Next; // points to the next request entry.

33 };
3435 / *

36 * This is used in the elevator algorithm: Note that


37 * Reads always go before writes This is natural:. Reads
38 * Are much more time-critical than writes.
39 * /
/*
* The following definitions are used in elevator algorithm: Note that read operations are always carried out before the write operation.

* This is natural: read the time demands much more stringent than the write operation.

*/
40 #define IN_ORDER (S1, s2) \
41 ((S1) -> cmd <(s2) -> cmd || (s1) -> cmd == (s2) -> cmd && \
42 ((S1) -> dev <(s2) -> dev || ((s1) -> dev == (s2) -> dev && \

--183--
6.4 blk.h file

43 (S1) -> sector <(S2) -> sector )))


44
// block device configuration.

45 struct blk_dev_struct {
46 void (* request_fn) (void); // pointer to function requested operation.

47 struct request * Current_request; // request information structure.


48 };
4950 extern struct blk_dev_struct blk_dev [ NR_BLK_DEV ]; // block device table (array), each occupied by a block device.

51 extern struct request request [ NR_REQUEST ]; // request queue array.


52 extern struct task_struct * wait_for_request ; // wait queue head pointer task structure idle request.

53
// when the block device drivers (e.g. hd.c) To include this header must be defined and the corresponding driver device major number. Such // below -87 row line 61 can be

given the correct macro is defined as comprising the driver files.

54 #ifdef MAJOR_NR // major number.


5556 / *

57 * Add entries as needed. Currently the only block devices


58 * Supported are hard-disks and floppies.
59 * /
/*
* When the need to add an entry. Block device currently only supports hard drives and floppy disks (as well as virtual disk).

*/
6061 #if ( MAJOR_NR == 1) // RAM disc 1 is a major number. The reasoning may be defined herein memory block is also a major number.

62 / * Ram disk * / / * RAM disk (virtual memory disk) * /

63 #define DEVICE_NAME "Ramdisk" // device name ramdisk.


64 #define DEVICE_REQUEST do_rd_request // function device requests do_rd_request ().
65 #define DEVICE_NR (Device) ((device) & 7) // device number (0--7).
66 #define DEVICE_ON (Device) // turn on the device. Virtual disk without having to open and close.

67 #define DEVICE_OFF (Device) // Turn off the device.

6869 #elif ( MAJOR_NR == 2)


// floppy major number is 2.
70 / * Floppy * /
71 #define DEVICE_NAME "Floppy" // device name floppy.
72 #define DEVICE_INTR do_floppy // device interrupt handler do_floppy ().
73 #define DEVICE_REQUEST do_fd_request // function device requests do_fd_request ().
74 #define DEVICE_NR (Device) ((device) & 3) // device number (0--3).
75 #define DEVICE_ON (Device) floppy_on ( DEVICE_NR (Device)) // turn on the device function floppyon ().
76 #define DEVICE_OFF (Device) floppy_off ( DEVICE_NR (Device)) // Close device functions floppyoff ().
7778 #elif ( MAJOR_NR == 3)
// hard disk major number is 3.

79 / * Harddisk * /
80 #define DEVICE_NAME "Harddisk" // hard disk name harddisk.
81 #define DEVICE_INTR do_hd // device interrupt handler do_hd ().
82 #define DEVICE_REQUEST do_hd_request // function device requests do_hd_request ().
83 #define DEVICE_NR (Device) ( MINOR (Device) / 5) // device number (0--1). Each hard disk can have four partitions.
84 #define DEVICE_ON (Device) // has been hard at work, without opening and closing.

85 #define DEVICE_OFF (Device)


8687 #elif

88 / * Unknown blk device * / / * Unknown block device * /


89 #error " unknown blk device "

--184--
6.4 blk.h file

9091 #endif

9293 #define CURRENT ( blk_dev [ MAJOR_NR ] .Current_request) // CURRENT number is designated the master device requests the current configuration.

94 #define CURRENT_DEV DEVICE_NR ( CURRENT -> dev) // CURRENT_DEV CURRENT is the device number.

95
// The following two macro is defined as stated function pointer.

96 #ifdef DEVICE_INTR 97 void (* DEVICE_INTR ) (Void) = NULL


;
98 #endif
99 static void ( DEVICE_REQUEST ) (Void);
100
// release the lock of the buffer (block).

101 extern inline void unlock_buffer (Struct buffer_head * Bh)


102 {
103 if (! bh-> b_lock) // If the specified buffer bh has not been locked, a warning message is displayed.

104 printk ( DEVICE_NAME ": Free buffer being unlocked \ n");


105 bh-> b_lock = 0; // otherwise the buffer is unlocked.

106 wake_up (& Bh-> b_wait); // wake wait for the process of the buffer.

107 }
108
// end request processing.

// first designated block off the device and check whether the read buffer valid. If the buffer is valid data // update flag set, and unlocks the buffer parameter values. If the update flag

parameter value is 0, indicating that the requested item of operation has failed, so // display the relevant block device IO error message. Finally, the process of waiting for the wake-up

request item and wait for the items appear idle processes a request, release // and delete this request entry from the request list.

109 extern inline void end_request (Int uptodate)


110 {
111 DEVICE_OFF ( CURRENT -> dev); // Turn off the device.

112 if ( CURRENT -> bh) { // CURRENT specified number of the current master device request structure.

113 CURRENT -> bh-> b_uptodate = uptodate; // set update flag.


114 unlock_buffer ( CURRENT -> bh); // unlock the buffer.
115 }
116 if (! uptodate) { If the flag is 0 // update equipment an error message is displayed.

117 printk ( DEVICE_NAME "I / O error \ n \ r");


118 printk ( ' dev% 04x, block% d \ n \ r ", CURRENT -> dev,
119 CURRENT -> bh-> b_blocknr);
120 }
121 wake_up (& CURRENT -> waiting); // Wait for the process of the wake-up request item.

122 wake_up (& wait_for_request ); // wake-up process waits for requests.

123 CURRENT -> dev = -1; // release the requested item.

124 CURRENT = CURRENT -> next; // delete the item request from the request list, and

125 } // pointer to the current request is a request entry key.

126
// define macros initialization request.

127 #define INIT_REQUEST \


128 repeat: \
129 if (! CURRENT ) \ // if the current request-structured pointer is null is returned.

130 return; \ // represents a request for entry of this equipment is currently no longer need to be addressed.

131 if ( MAJOR ( CURRENT -> dev) =! MAJOR_NR ) \ // If the current major number of the device is not crash.
132 panic ( DEVICE_NAME ": Request list destroyed"); \
133 if ( CURRENT -> bh) {\
134 if (! CURRENT -> bh-> b_lock) \ // If the buffer is not locked during the operation request crash.

--185--
6.5 hd.c program

135 panic ( DEVICE_NAME ": Block not locked"); \


136 }
137 138 #endif

139140 #endif

141

6.5 hd.c program

6.5.1 Functional Description

hd.c The driver program is a hard disk controller, hard drive controller to provide read and write block and the hard disk device initialization process. All program functions

can be divided according to different functions 5 class:

Function information data structures for disk drives and hard disk initialization, such as sys_setup () with hd_init () ; Send commands to the hard disk controller

function hd_out () ; Hard processing the current function of the requested item do_hd_request () ; Hard disk interrupt handling process called C Functions such as read_intr

() , write_intr () , bad_rw_intr () with recal_intr () .

do_hd_request () Function will also be read_intr () with write_intr () Was invoked; hard disk controller operation assistance functions, such as controler_ready

() , drive_busy () , win_result () , hd_out () with

reset_controler () Wait.

sys_setup () Function use boot / setup.s Program information provided by the system parameters contained in the hard disk drive is set. Then read the hard disk partition

table and try to copy the virtual root file system image file on the boot disk to the virtual disk memory, if successful mount the virtual disk root file system, otherwise it continues to

perform common root file system load operation.

hd_init () Function for setting the HDD controller interrupt descriptor kernel initialization, the hard disk controller and an interrupt mask is reset to allow the hard disk

controller sends an interrupt request signal.

hd_out () A hard disk controller transmits the operation command function. This function takes a call during the interruption C Function pointer parameter, before sending

commands to the controller, it first uses this parameter preset the interrupt process will function pointer calls ( do_hd ), Then it sequentially according to a predetermined manner to

the hard disk controller 0x1f0 to 0x1f7 Sending a command parameter block. In addition to controller diagnostics ( WIN_DIAGNOSE ) And the establishment of drive parameters ( WIN_SPECIFY

Later) other than the two commands, the hard disk controller receiving any other command and execute the command, are to CPU Interrupt request signal, causing the system to

perform a hard disk interrupt processing (in system_call.s , 221 Row).

do_hd_request () The requested item is a hard disk operation functions. Which procedure is as follows:

First determines whether the current request entries exist, if the current request pointer entry is null, then the current block is a hard disk device has no pending request

entries, thus immediately exit the program. This is the macro INIT_REQUEST Statement executed. Otherwise, continue processing the current request items.

The disk device number and the start sector number requested items specified in the current request is reasonable to verify; information calculation request entries

provided by the current track of the disk number, cylinder number and head number request data; if the flag is reset ( reset ) Has been set, you can also set the hard

drive to re-correction mark ( recalibrate ), And the hard reset operation, the controller sends back "established drive parameters" command ( WIN_SPECIFY ). This

command does not cause the hard disk interrupt; if recalibration flag is set, then it is hard to send commands to the controller recalibrate ( WIN_RESTORE ), And pre-set

before sending the order triggered interrupts need to be performed C function( recal_intr () ), And exit. recal_intr () The main function of the role is: When the controller

performs end and led to interrupt the command to re (continue) to perform this function. If the current request entry specifies a write operation, the first set of hard disk

controller calls C Function write_intr () , Sent to the controller

--186--
6.5 hd.c program

Send command parameter block write operation, and cycle controller queries the status register to determine whether the service request flag ( DRQ ) Whether the set. If

the flag is set, then the controller is "yes" to receive data, then the request is then put within the meaning of the data buffer controller writing data in the buffer. If the

query timeout after circulating the flag is still not set, then the operation fails. So call bad_rw_intr () Function, according to the current number of processing error

occurring requested item is not continuing to determine the current request needs to be set or reset flag item to continue processing the current request re-entry. If the

current entry is a read operation request, the call set hard disk controller C Function read_intr () And sends the operation command to read the disk controller.

write_intr () It is configured as an interrupt process called when the current request is a write operation item C function. After the controller completes a write command

immediately to disk CPU Send an interrupt request signal, then wrote immediately after the operation is complete will call the function in the controller.

This function first calls win_result () Function, the controller reads the status register to determine whether an error occurred. If an error occurs during the write operation,

the call bad_rw_intr () , According to the number of times an error processing the current request item occurs to determine whether to continue the current request to give up items

still need to reset flag is set to continue processing the current request re-entry. If all of the data if no error occurs, according to the total number of sectors required to write the

current item specified in the request, the request is determined to have the requirement to write disk. If there is data to write disk, then a copy of the data sector to the controller

buffer. When all the data has been written disc, then the processing end of the current issues requested items: Wait for the wake-up process is completed the requested item,

request wake-up process waiting for free entry (if any), set the current request referred to in subparagraph buffer data has been updated logo, release the current request item

(block device removes the entry from the list). Finally, we continue to call do_hd_request () Function to continue processing other requests entry of a hard disk device.

read_intr () The requested item is currently being provided to interrupt the read operation during a call C function. The controller in the specified sector after the data is read

into the buffer from the hard drive of their own, it will send an interrupt request signal immediately. The primary role of the function is to copy data from the controller to the item

specified in the current request buffer.

versus write_intr () Way to start the same process, which also function first calls win_result () Function, the controller reads the status register to determine whether an error

occurred. If an error occurs during read the disk, and then executed write_intr () Same process. If no errors occurred, the data from the buffer is copied to a sector of the requested

item in the specified buffer. Then the total number of sectors to be read specified in the current item request, determines whether all the data has been read. If there are data to be

read, then exit to wait for a break soon. When all the data has been obtained, the processing end of the current issues requested items: wake-up process is currently waiting for the

completion of the requested item, the process waits for an idle request wake-up items (if any), set the current request referred to in subparagraph buffer data flag has been updated

releases the current request item (block device removes the entry from the list). Finally, we continue to call do_hd_request () Function to continue processing other requests entry of a

hard disk device.

In order to see more clearly the process hard disk read and write operations, we can put these functions, the interrupt execution timing relationship between the process

controller and a hard disk with three FIG. 6-3 He represented.

--187--
6.5 hd.c program

The write operation Read the disk operation

execute program Hard disk controller execute program Hard disk controller

time

Processing the request item

Interrupt processing

The controller processes

Read Status

command write

Write data transfer

Read data transfer

Map 6-3 Read / write disk data timing relationships

As it can be seen from the above analysis, the most important application of the present 4 Functions are hd_out () , do_hd_request () , read_intr () with

write_intr () . Understand this 4 The role of a function also understand the operation of the hard disk driver ☺ .

6.5.2 Code comments

program 6-3 linux / kernel / blk_drv / hd.c

1/*
2 * Linux / kernel / hd.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * This is the low-level hd interrupt support. It traverses the


9 * Request-list, using interrupts to jump between functions. As
10 * All the functions are called within interrupts, we may not
11 * Sleep. Special care is recommended.
12 *
13 * Modified by Drew Eckhardt to check nr of hd's from the CMOS.
14 * /
/*
* This program is the underlying hard disk interrupt aid program. The main scanning for the request list, the interrupt jump between functions.

* Since all functions are interrupted in the call, these functions can not sleep. Please pay special attention.
* Modified by Drew Eckhardt, the number of hard disk information detection using CMOS.

*/
15

--188--
6.5 hd.c program

16 #include <linux / config.h> // kernel configuration file header. Define the keyboard language and hard disk type (HD_TYPE) option.

17 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

18 #include <linux / fs.h> // file system header files. Table structure definition file (file, buffer_head, m_inode, etc.).
19 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

20 #include <linux / hdreg.h> // header drive parameters. Accessing the hard disk port register definition information, status code, the partition table and the like.

twenty one #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

twenty two #include <asm / io.h> // io header files. Defined hardware port I / O macro assembler statements.

twenty three #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

twenty four

// The following must be defined before the constant major number blk.h file because the file blk.h to use the constant.

25 #define MAJOR_NR 3 // hard disk major number is 3.

26 #include " blk.h " // file header block device. Definition request data structure, the data structure of a block device like functions and macros.

2728 #define CMOS_READ (Addr) ({\ // read CMOS parameter macro function.

29 outb_p (0x80 | addr, 0x70); \


30 inb_p (0x71); \
31 })
3233 / * Max read / write errors / sector * /

34 #define MAX_ERRORS 7 When // allow read / write a sector of the maximum number of errors.

35 #define MAX_HD 2 // maximum number of supported hard disk system.

3637 static void recal_intr (Void); // hard disk interrupt program when re-calibration function reset operation will call (287 lines).

3839 static int recalibrate = 1; // recalibration flag. Move the head to cylinder 0.

40 static int reset = 1; // reset flag. When a write error occurs This flag is set to reset the controller and the hard disk.

4142 / *

43 * This struct defines the HD's and their types.


44 * /
/ * The following structure defines the type and disk parameters * /

// each field are the number of heads, number of sectors per track, the number of cylinders, the pre-write precompensation cylinder number, the head landing zone cylinder number, the control

byte. // please explain their meanings see the list of programs.

45 struct hd_i_struct {
46 int head , Sect, cyl, wpcom, lzone, ctl;
47 };

// If already defined in HD_TYPE include / linux / config.h header file, which can take as parameters defined // hd_info [] data. Otherwise, the
first default values ​are set to 0, it will be set in the setup () function.
48 #ifdef HD_TYPE
49 struct hd_i_struct hd_info [] = {HD_TYPE};
50 #define NR_HD ((Sizeof ( hd_info )) / (Sizeof (struct hd_i_struct ))) // count the number of hard disks.

51 #else
52 struct hd_i_struct hd_info [] = {{0,0,0,0,0,0}, {0,0,0,0,0,0}};
53 static int NR_HD = 0;
54 #endif
55
// define hard disk partition structure. Give a physical start sector number of each partition, partitioning the total number of sectors. Wherein //

item (e.g. hd [0], and HD [5], etc.) at a multiple of 5 parameters representative of the entire hard disk.

56 static struct hd_struct {


57 long start_sect;
58 long nr_sects;

--189--
6.5 hd.c program

59 } hd [5 * MAX_HD ] = {{0,0},};
60
// read port port, nr words were read, stored in buf.
61 #define port_read (Port, buf , Nr) \
62 __asm ​__ ( " cld; rep; insw "::" d "( port), " D "( buf ) " c "( nr): " cx "," di ")
63
// write port port, nr words were written, fetch data from buf.
64 #define port_write (Port, buf , Nr) \
65 __asm ​__ ( " cld; rep; outsw "::" d "( port), " S "( buf ) " c "( nr): " cx "," si ")
6667 extern void hd_interrupt (Void);
// hard disk interrupt process (system_call.s, 221 lines).
68 extern void rd_load (Void); // create a virtual disk loading function (ramdisk.c, 71 lines).
6970 / * This may be used only once, enforced by 'static int callable' * /

/ * The following function is called once during initialization. Static variables callable as a call sign. * / // parameters of the function provided by the initialization program routine init init / main.c to

point at 0x90080, where setup.S // store the program acquired from the hard disk BIOS 2 basic parameters table (32 words section). See the following list of instructions after the hard disk

parameter table information. // This function is the main function of the hard disk parameter table and the CMOS read information to the hard disk partition structure is provided hd, virtual RAM

disk and loads the root file system and //.

71 int sys_setup (Void * BIOS)


72 {
73 static int callable = 1;
74 int i, drive;
75 unsigned char cmos_disks;
76 struct partition * P;
77 struct buffer_head * Bh;
78
// Initialization When callable = 1, the function is run when it is set to 0, so that this function can only be performed once.

79 if (! callable)
80 return -1;
81 callable = 0;
// If not defined in the config.h drive parameters, it is read from the 0x90080.
82 #ifndef HD_TYPE
83 for (drive = 0; drive <2; drive ++) {
84 hd_info [Drive] .cyl = * (unsigned short *) BIOS; // number of cylinders.

85 hd_info [Drive]. head = * (Unsigned char *) (2 + BIOS); // number of heads.

86 hd_info [Drive] .wpcom = * (unsigned short *) (5 + BIOS); // write precompensation front cylinder number.
87 hd_info [Drive] .ctl = * (unsigned char *) (8 + BIOS); // control byte.
88 hd_info [Drive] .lzone = * (unsigned short *) (12 + BIOS); // Number cylinder head landing zone.
89 hd_info [Drive] .sect = * (unsigned char *) (14 + BIOS); // the number of sectors per track.

90 BIOS + = 16; // parameter table of each disk 16 bytes long, where BIOS points to the next table.

91 }
// setup.S program in the hard disk parameter table information taken in the BIOS, if only a hard disk, will correspond to the second 16-byte hard disk // cleared. Thus here as long as

the second hard disk is determined whether the cylinder number 0 can not know the second hard drive.

92 if ( hd_info [1] .cyl)


93 NR_HD = 2; // set number of hard disk 2.

94 else
95 NR_HD = 1;
96 #endif
// Set the start sector number and the total number of sectors per disk. Wherein the meaning of number i * 5 refer to the procedure described after.

97 for (i = 0; i < NR_HD ; I ++) {


98 hd [I * 5] .start_sect = 0; // hard starting sector.
99 hd [I * 5] .nr_sects = hd_info [I]. head *

--190--
6.5 hd.c program

100 hd_info [I] .sect * hd_info [I] .cyl; // total number of sectors of the hard disk.

101 }
102
103 /*
104 We querry CMOS about hard disks: it could be that
105 we have a SCSI / ESDI / etc controller that is BIOS
106 compatable with ST-506, and thus showing up in our
107 BIOS table, but not register compatable, and therefore
108 not present in CMOS.
109
110 Furthurmore, we will assume that our ST-506 drives
111 <If any> are the primary drives in the system, and
112 the ones reflected as drive 1 or 2.
113
114 The first drive is stored in the high nibble of CMOS
115 byte 0x12, the second in the low nibble. This will be
116 either a 4 bit drive type or 0xf indicating use byte 0x19
117 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
118
119 Needless to say, a non-zero value means we have
120 an AT controller hard disk for that drive.
121122123

*/
/*
* We have some doubts about the information on the hard drive CMOS: may be the case, we have a SCSI / ESDI / etc.

* The controller, which is based on ST-506 is compatible with the way the BIOS, which will appear in our BIOS parameter table, but not

* Register are compatible, these parameters do not exist in CMOS.


* Further, we assume that ST-506 drive (if any) is the basic drive system, i.e. to drive 1 or 2
* Drive appears.
* A first drive parameters stored in the CMOS byte 0x12 nibble, the second byte is stored in the lower half. The nibble
* Information can be a drive type, it may only be 0xf. 0xf indication of 0x19 bytes as the CMOS driver 8 1
* Type byte, as used in CMOS drive type byte 0x1A 2 bytes.
* In short, a non-zero value means that we have an AT-compatible hard disk drive controller.
*/
124
// Here is detected based on the principles of hard drives in the end whether it is compatible with the AT controller. CMOS-related information, see Section 4.2.3.1.

125 if ((cmos_disks = CMOS_READ (0x12)) & 0xf0)


126 if (cmos_disks & 0x0f)
127 NR_HD = 2;
128 else
129 NR_HD = 1;
130 else
131 NR_HD = 0;
// If NR_HD = 0, then two hard disks are not compatible with the AT controller, hard disk data structure is cleared. // If NR_HD = 1, then

the second hard disk parameters cleared.

132 for (i = NR_HD ; I <2; i ++) {


133 hd [I * 5] .start_sect = 0;
134 hd [I * 5] .nr_sects = 0;
135 }
Each hard disk // read a first data (first one sector is useful), acquires the partition table information therein. // function firstly Bread () disk read the first block of

data (fs / buffer.c, 267), the hard disk parameter 0x300 major number // (see list following description). The first two bytes and a hard disk at the sector position

0x1fe whether '55AA' to determine

--191--
6.5 hd.c program

// This sector is located 0x1BE beginning of the partition table is valid. Finally, the hard disk partition information into the partition table data structure in hd.

136 for (drive = 0; drive < NR_HD ; Drive ++) {


137 if (! (bh = bread (0x300 + drive * 5,0))) {// 0x300, 0x305 logical device number.
138 printk ( ' Unable to read partition table of drive% d \ n \ r ",
139 drive);
140 panic ( "");
141 }
142 if (bh-> b_data [510]! = 0x55 || (unsigned char)
143 bh-> b_data [511]! = 0xAA) { // hard determination information is valid flag '55AA'.

144 printk ( ' Bad partition table on drive% d \ n \ r ", drive);


145 panic ( "");
146 }
147 p = 0x1BE + (void *) bh-> b_data; // hard disk partition table is located at the first sector 0x1BE.

148 for (i = 1; i <5; i ++, p ++) {


149 hd [I + 5 * drive] .start_sect = p-> start_sect;
150 hd [I + 5 * drive] .nr_sects = p-> nr_sects;
151 }
152 brelse (Bh); // release the memory page buffer for storing disk blocks and application.

153 }
154 if ( NR_HD ) // if the hard disk is present and has been read partition table, partition table information correctly printed.

155 printk ( ' Partition table% s ok. \ N \ r ", ( NR_HD > 1)? " s ":" ");
156 rd_load (); // Load (create) RAMDISK (kernel / blk_drv / ramdisk.c, 71).
157 mount_root (); // root file system is mounted (fs / super.c, 242).
158 return (0);
159 }
160
//// wait cycle is determined and the drive is ready.

// read status register hard disk controller port HD_STATUS (0x1f7), and loop detection and the drive controller ready bit busy bit. // If the return value is 0,

then wait timeout error, otherwise OK.

161 static int controller_ready (Void)


162 {
163 int retries = 10000;
164
165 while (--retries && ( inb_p ( HD_STATUS !) & 0xc0) = 0x40);
166 return (retries); // returns the number of wait cycles.

167 }
168
//// hard state after detecting the command execution. (Win_ an acronym that stands Winchester hard disk)

// read status register command execution result status. 0 indicates a normal return, an error has occurred. If you execute the wrong command, // read the error

register HD_ERROR (0x1f1).

169 static int win_result (Void)


170 {
171 int i = inb_p ( HD_STATUS ); // get status information.
172
173 if ((i & ( BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT ))
174 == ( READY_STAT | SEEK_STAT ))
175 return (0); / * ok * /
176 if (i & 1) i = inb ( HD_ERROR ); // if ERR_STAT set, the read error register.
177 return (1);
178 }
179
//// sends a command to the hard disk controller block (see list following description). // call parameters: drive -

hard disk number (0-1); nsect - read the number of sectors;

--192--
6.5 hd.c program

// sect - start sector; head - head number;


// cyl - Cylinder number; cmd - a command code (see control command list, table 6.3);
// * intr_addr () - C handler when an interrupt occurs in the hard disk handler to be called.
180 static void hd_out (Unsigned int drive, unsigned int nsect, unsigned int sect,
181 unsigned int head , Unsigned int cyl, unsigned int cmd,
182 void (* intr_addr) (void))
183 {
184 register int port asm ( " dx "); // port register corresponding to the variable dx.

185
186 if (drive> 1 || head > 15) // If the drive letter (0,1)> 1 or head number> 15, it does not support.
187 panic ( ' Trying to write bad sector ");
188 if (! controller_ready ()) // If you wait a period of time is still not ready errors, crashes.

189 panic ( ' HD controller not ready ");


190 do_hd = intr_addr; // do_hd function pointer will be called a program interruption in the hard disk.

191 outb_p ( hd_info [Drive] .ctl, HD_CMD ); // the control byte to the output control register (0x3f6).

192 port = HD_DATA ; // dx is set to port data register (0x1f0).


193 outb_p ( hd_info [Drive] .wpcom >> 2, ++ port); // Parameter: Write precompensation cylinder number (required except 4).

194 outb_p (Nsect, ++ port); // Parameters: read / write total number of sectors.

195 outb_p (Sect, ++ port); // parameters: start sector.


196 outb_p (Cyl, ++ port); // Parameter: cylinder number lower 8 bits.

197 outb_p (Cyl >> 8, ++ port); // Parameter: cylinder number 8 high.

198 outb_p (0xA0 | (drive << 4) | head , ++ port); // parameters: number + the drive head number.

199 outb (Cmd, ++ port); // command: hard disk control command.

200 }
201
//// wait for the hard disk is ready. I.e. wait cycle master controller is busy status flag is reset. If only ready or seek end flag // set, success,

returns 0. If after a period of time is still busy, it returns 1.

202 static int drive_busy (Void)


203 {
204 unsigned int i;
205206
for (i = 0; i <10000; i ++) // loop waiting ready flags.
207 if ( READY_STAT == ( inb_p ( HD_STATUS ) & ( BUSY_STAT | READY_STAT )))
208 break;
209 i = inb ( HD_STATUS ); // then take the main controller status byte.

210 i & = BUSY_STAT | READY_STAT | SEEK_STAT ; // detect busy bit, ready position and seek end position.

211 if (i == READY_STAT | SEEK_STAT ) // If only Ready or seek end flag, it returns 0.


212 return (0);
213 printk ( ' HD controller times out \ n \ r "); // Otherwise wait timeout, display information. And return 1.

214 return (1);


215 }
216
//// diagnostic reset (re-calibration) hard disk controller.

217 static void reset_controller (Void)


218 {
219 int i;
220
221 outb (4, HD_CMD ); // transmission control byte (4- reset) to the port control registers.

222 for (i = 0; i <100; i ++) nop (); // wait a period of time (cycle no operation).
223 outb ( hd_info [0] .ctl & 0x0f, HD_CMD ); // normal control byte retransmission (retry does not prohibit, re-read).
224 if ( drive_busy ()) // If the hard disk is ready to wait for a timeout, an error message is displayed.

225 printk ( ' HD-controller still busy \ n \ r ");


226 if ((i = inb ( HD_ERROR ))! = 1) // get error register, if not equal to 1 (no error) is an error.

--193--
6.5 hd.c program

227 printk ( ' HD-controller reset failed:% 02x \ n \ r ", I);


228 }
229
//// hard reset nr. First reset (re-calibration) hard disk controller. Hard disk controller then sends a command "established drive parameters", // where
recal_intr () is a hard disk interrupt handler recalibration handler call.
230 static void reset_hd (Int nr)
231 {
232 reset_controller ();
233 hd_out (Nr, hd_info [Nr] .sect, hd_info [Nr] .sect, hd_info [Nr]. head -1,
234 hd_info [Nr] .cyl, WIN_SPECIFY , & recal_intr );
235 }
236
//// unexpected hard disk interrupt call the function.

// interrupt occurs when an unexpected hard disk, hard disk interrupt handler C default handler calls. In the called function pointer is null // call the

function. See (kernel / system_call.s, 241 lines).

237 void unexpected_hd_interrupt (Void)


238 {
239 printk ( ' Unexpected HD interrupt \ n \ r ");
240 }
241
//// read and write hard disk failure handling function is called.

242 static void bad_rw_intr (Void)


243 {
244 if (++ CURRENT -> errors> = MAX_ERRORS ) // number of times if an error in reading the sector greater than or equal 7,

245 end_request (0); // the end of the request wake-up process and wait for the request, and the

corresponding buffer // update flag is reset (not updated).

246 if ( CURRENT -> errors> MAX_ERRORS / 2) // if the number of times an error reading a sector has more than 3 times.

247 reset = 1; // hard disk controller is required to perform a reset operation.

248 }
249
//// read interrupt function is called. The process is called interrupt triggered at the end of the hard disk read command.

// This function first determines whether the read command operation error. If the command controller further after the end of a busy state or command error, the hard disk operation // the

process failures, then requests for the hard reset request and performs other processing items.

// If the command is not the read error, the data from the port data register to read a sector in a buffer request entry, and decrements the value requested item // sectors need to be read. If after

decrementing is not equal to 0, indicates that this data item request and did not get finished, then return directly after the interruption // wait another sector of data read out in the hard disk.

Otherwise, all sectors showed that the required items are reading this request, then the processing of this request item // end matters. The last call do_hd_request again (), to handle requests

other hard items. // Note: row statement 256 257 refers to the memory word, i.e. 512 bytes.

250 static void read_intr (Void)


251 {
252 if ( win_result ()) { // If the controller is busy reading and writing the wrong command or wrong,

253 bad_rw_intr (); // the hard disk read and write process fails

254 do_hd_request (); // then requests the hard disk accordingly (reset) for again.

255 return;
256 }
257 port_read ( HD_DATA , CURRENT -> buffer, 256); // request to read data from the data buffer register port structure.
258 CURRENT -> errors = 0; // clear the number of errors.

259 CURRENT -> buffer + = 512; // adjust the buffer pointer to the new empty area.

260 CURRENT -> sector ++; // start sector number is incremented by 1,

261 if (- CURRENT -> nr_sectors) { Sector // If the desired readout number has not yet finished, the

262 do_hd = & read_intr ; // set again hard to call a C function pointer read_intr ()
263 return; // because the hard drive when the interrupt handler do_hd each call

264 } // The function pointers are blank. See system_call.s

--194--
6.5 hd.c program

265 end_request (1); // if all sector data has been read, the process issues the request ends,

266 do_hd_request (); // perform other hard drive operations requested.

267 }
268
//// sector write interrupt function is called. Hard disk is called the interrupt handler.

// After the write command is executed, the hard disk will generate an interrupt signal, the interrupt handler performs a hard disk, in this case the hard disk // C interrupt handler function pointer

do_hd () call has been directed write_intr (), thus completes the write operation after (or error), the function is executed.

269 static void write_intr (Void)


270 {
271 if ( win_result ()) { // returns an error message if the hard disk controller,

272 bad_rw_intr (); // the first hard disk read and write process fails,

273 do_hd_request (); // then again requests the hard disk for the corresponding (reset) process,

274 return; // then return (also withdrew from the hard disk interrupts).

275 }
276 if (- CURRENT -> nr_sectors) { // Otherwise, the number of sectors to be written minus 1, if there is to write the sector, the

277 CURRENT -> sector ++; +1 // start sector number of the current request,

278 CURRENT -> buffer + = 512; // buffer pointer adjustment request,


279 do_hd = & write_intr ; // set the hard disk interrupt program calls the function pointer write_intr (),

280 port_write ( HD_DATA , CURRENT -> buffer, 256); // port data register again write 256 words.
281 return; // return until the hard-completed interrupt handling after the write operation again.

282 }
283 end_request (1); // if all sector data has been written, the end of the request process issues,

284 do_hd_request (); // perform other hard drive operations requested.

285 }
286
//// hard disk recalibrate (RESET) interrupt function is called. Hard disk is called the interrupt handler.

// returns an error message if the hard disk controller, the hard disk is first read failure processing, and accordingly requests the hard disk (reset) process.

287 static void recal_intr (Void)


288 {
289 if ( win_result ())
290 bad_rw_intr ();
291 do_hd_request ();
292 }
293
//// drives the reader performs the requested operation.

// If the requested item is a piece of equipment, then the request entry pointer of the current block device (see ll_rw_blk.c, 28 line) directly to the // request entries, and call this function will

immediately perform read and write operations. Otherwise, in a read or write operation to complete the process of interruption caused by the hard disk, the request // if there are items need

to be addressed, it will call this function during the interruption. See kernel / system_call.s, 221 line.

294 void do_hd_request (Void)


295 {
296 int i, r;
297 unsigned int block, dev;
298 unsigned int sec, head , Cyl;
299 unsigned int nsect;
300
// Check the legitimacy of the item request, Ruoyi not request entry to exit (see blk.h, 127).

301 INIT_REQUEST ;
// get sub-device number (device number described after the hard see list) of the device number. Sub-device number that is the number of partitions on the hard disk.

302 dev = MINOR ( CURRENT -> dev); // CURRENT defined as blk_dev [MAJOR_NR] .current_request.
303 block = CURRENT -> sector ; // start sector requests.
// If the sub-device number does not exist or is greater than the starting sector number of sectors -2 partition, the request is ended, and the jump to the label // repeat (INIT_REQUEST

defined at the beginning). 2 because of a requirement to read and write sectors (512 bytes * 2), so that the requested sector number is not greater than the partition // penultimate last sector

number.

--195--
6.5 hd.c program

304 if (dev> = 5 * NR_HD || block + 2> hd [Dev] .nr_sects) {


305 end_request (0);
306 goto repeat; // the label in blk.h last.
307 }
// start sector number by adding this partition, you will be required to read the entire block corresponding to the absolute sector number of the hard disk.

308 block + = hd [Dev] .start_sect;


309 dev / = 5; // At this resolution dev denotes a hard disk (hard disk is a first (0) or a second (1)).

// The following code is embedded in the assembly used to calculate the track sector number // (sec), where the cylinder number (CYL) and head number (head) from the

hard disk information structure according to the start sector number and the number of sectors per track .

310 __asm ​__ ( " divl% 4 ":" = a "( block), "= d "( sec): "" (block), " 1" ( 0),
311 "R" ( hd_info [Dev] .sect));
312 __asm ​__ ( " divl% 4 ":" = a "( cyl), "= d "( head ): "" (Block), " 1" ( 0),
313 "R" ( hd_info [Dev]. head ));
314 sec ++;
315 nsect = CURRENT -> nr_sectors; // To read / write the number of sectors.

// If the reset flag is set, the reset operation is performed. And resetting the hard disk controller, and the correction flag is set need to return.

316 if ( reset ) {
317 reset = 0;
318 recalibrate = 1;
319 reset_hd ( CURRENT_DEV );
320 return;
321 }
// If recalibration flag (Recalibrate) is set, then the flag is reset first, and then resend correction command to the hard disk controller. // This command will perform seek

operations, so that the head is moved to anywhere in 0 cylinders.

322 if ( recalibrate ) {
323 recalibrate = 0;
324 hd_out (Dev, hd_info [ CURRENT_DEV ] .Sect, 0,0,0,
325 WIN_RESTORE , & recal_intr );
326 return;
327 }
// if the current request is a write sector operation, a write command is sent, the status register read cycle information and determines whether the requested service // DRQ_STAT

flag is set. DRQ_STAT requests a service disk status register bit, indicates that the drive be ready to transfer a word of data between a host and // or a byte of data ports.

328 if ( CURRENT -> cmd == WRITE ) {


329 hd_out (Dev, nsect, sec, head , Cyl, WIN_WRITE , & write_intr );
330 for (i = 0; i <3000 && (r =! inb_p ( HD_STATUS ) & DRQ_STAT ); I ++)
331 / * Nothing * /;
// if the service request DRQ is set to exit the loop. Wait until the end of the cycle if there is no set, it means that the write operation failed hard disk, hard disk to the // process the next

request. Otherwise, the data of one sector is written to the hard disk controller port data register HD_DATA.

332 if (! r) {
333 bad_rw_intr ();
334 goto repeat; // The label on the final surface blk.h file, that jumps to 301 lines.

335 }
336 port_write ( HD_DATA , CURRENT -> buffer, 256);
// if the current request is a read hard disk sector, the sector transmits a read command to the hard disk controller.

337 } Else if ( CURRENT -> cmd == READ ) {


338 hd_out (Dev, nsect, sec, head , Cyl, WIN_READ , & read_intr );
339 } Else
340 panic ( ' unknown hd-command ");
341 }
342
// initialize the hard disk system.

343 void hd_init (Void)

--196--
6.5 hd.c program

344 {
345 blk_dev [ MAJOR_NR ] .Request_fn = DEVICE_REQUEST ; // do_hd_request ().
346 set_intr_gate (0x2E, & hd_interrupt ); // Set the door hard disk interrupt vector int 0x2E (46).
// hd_interrupt in (kernel / system_call.s, 221).
347 outb_p ( inb_p (0x21) & 0xfb, 0x21); // Reset the mask bits 8259A int2 main pick-linked, allowing the sheet // interrupt

request signal.

348 outb ( inb_p (0xA1) & 0xbf, 0xA1); // reset the hard disk interrupt request mask bits (from the on-chip), allowing the hard disk //

controller sends an interrupt request signal.

349 }
350

6.5.3 Other Information

6.5.3.1 AT Hard disk interface register

AT Programming register port of the hard disk controller are described in Table 6-2 Fig. Also see include / linux / hdreg.h head File.

table 6-2 AT And the role of hard disk controller register interface

port name Read Write

0x1f0 HD_DATA Data register -- Sector data (read, write, format)

0x1f1 HD_ERROR Error register (error status) Pre-register before the write compensation

0x1f2 HD_NSECTOR Sector Number Register -- The number of sectors (read, write, test, formatting)

0x1f3 HD_SECTOR Sector Number Register -- Starting sector (read, write, test)

0x1f4 HD_LCYL Cylinder number register -- Low byte cylinder number (read, write, test, formatting)

0x1f5 HD_HCYL Cylinder number register -- High byte cylinder number (read, write, test, formatting)

0x1f6 HD_CURRENT Drive / head register - Drive number / head number ( 101dhhhh, d = Drive letter, h = Head number)

0x1f7 HD_STATUS Main Status Register ( HD_STATUS) Command Register ( HD_COMMAND)

0x3f6 HD_CMD --- A hard disk control register ( HD_CMD)

0x3f7 Digital input register (with 1.2M Floppy disk combination) ---

Next, each port registers described in detail. ◆

Data Register ( HD_DATA , 0x1f0 )

This is a pair 16 Bit high speed PIO Data transmitter for a sector read, write and format operations track. CPU Written to or read from the hard disk to the hard disk via the

data register 1 Data sectors, i.e. to the command ' rep outsw ' or' rep insw ' Repeat read / write cx = 256 word. ◆ error register (read) / write pre-compensation before the register

(write) ( HD_ERROR , 0x1f1 )

When reading this register storing 8 Error Status bit. But only when the main status register ( HD_STATUS , 0x1f7) Bit 0 = 1

Data in the register is valid. Different meaning when other command when performing diagnostic controller command. Table 6-3 Fig.

table 6-3 Hard disk controller error Error register

value When the diagnosis command When other commands

0x01 No error Data loss mark

0x02 Controller error Tracks 0 wrong

0x03 Sector Buffer wrong

0x04 ECC Wrong parts Give up command

0x05 Control processor error

0x10 ID Not found

--197--
6.5 hd.c program

0x40 ECC error

0x80 Bad sector

In the write operation, i.e., the register as register before a write precompensation. It records the write precompensation starting cylinder number. Substantially

corresponds to the hard disk parameter table displacement 0x05 At a word, to be in addition to 4 After the output. ◆ Sector Number Register ( HD_NSECTOR , 0x1f2 )

This register stores read, write, verify, and format commands specified number of sectors. When used in a multi-sector operation, each completed 1 The operation of the

sector register is decremented 1 Until it is 0 . If the initial value 0 , Then the maximum number of sectors transmission 256 . ◆ Sector Number Register ( HD_SECTOR , 0x1f3 )

This register stores read, write, verify operations sector number specified by the command. When multi-sector operation, is stored in the start sector number, and each

completed 1 Automatically by operation of a sector 1 . ◆ cylinder number register ( HD_LCYL , HD_HCYL , 0x1f4 , 0x1f5 )

The two cylinder number registers are stored with a low number of cylinders 8 And high bit 2 Bit. ◆

drive / head register ( HD_CURRENT , 0x1f6)

This register stores read, write, test, and a seek command format specified drive and head number. Its place in the format 101dhhhh . among them 101 He expressed using ECC

And each check code sectors 512 byte; d It represents the selected drive ( 0 or 1 ); hhhh It represents the head selection.

◆ master status register (read) / command register (Write) ( HD_STATUS / HD_COMMAND , 0x1f7)

When reading, corresponding to a 8 Main bit status register. Reflecting the operation state of the hard disk controller before and after the execution of the command.

Members meaning Table 6-4 Fig.

table 6-48 Status bit main register

Place name DESCRIPTION mask

Command execution error. DESCRIPTION previous command when an error bit to the end. At this time, the syndrome register
0 ERR_STAT 0x01
bits and status register contains some information that caused the error.

1 INDEX_STAT 0x02 Received index. When the disk rotation index mark will encounter this bit is set.

ECC Parity error. When faced with a recoverable data errors and has been corrected, it will set this bit. This does not interrupt a
2 ECC_STAT 0x04
multi-sector read operation.

Data request service. When this bit is set, it indicates that the drive be ready to transfer a byte or a word of data between a
3 DRQ_STAT 0x08
host and a data port.

Drive seek an end. When this bit is set, it indicates a seek operation has been completed, the magnetic head has been stopped on

4 SEEK_STAT 0x10 the specified track. When an error occurs, this bit does not change. Only after the host reads the status register, this bit will indicate

the current state of complete seek again.

Drive failure (write error). When an error occurs, this bit does not change. Only after the host reads the status register, the bit
5 WRERR_STAT 0x20
error will indicate the current state of the write operation again.

Drive ready (ready). It indicates that the drive is ready to receive commands. When an error occurs, this bit does not change.

Only after the host reads the status register, this bit will indicate the current drive again ready state. When turned on, this bit
6 READY_STAT 0x40
should be reset until the drive accelerates to normal and can receive commands.

Controller busy. When the drive is operating This bit is set by the drive controller. When the host can not send the command

block. Read operations to any command register will return the status register. This bit is set under the following conditions: a

7 BUSY_STAT 0x80 machine reset signal RESET Becomes negative or device control registers SRST After being set 400 Nanoseconds or less. After

reset, this bit machine status can not exceed 30 second.

--198--
6.5 hd.c program

Recalibration host command register to write, read, read buffer, initializes the drive parameters and perform diagnostics

command 400 Nanoseconds or less.

During a write operation, the write buffer or Format Track commands transmitted 512 Bytes of data 5 Within microseconds.

When performing a write operation, the command register corresponds to the port, accepts CPU Hard disk control command is issued, a total of 8 Types of commands, see Table 6-5

Fig. The last one for the operation of the controller after the end of the corresponding command taken (that caused the break or do nothing).

table 6-5 AT Hard disk controller command list

Byte Command Code


Command Name The default value of the command execution ends
high 4 Place D3 D2 D1 D0 form

WIN_RESTORE Drive recalibrate (reset) 0x1 RRRR 0x10 Interrupt

WIN_READ Read Sector 0x2 0 0 LT 0x20 Interrupt

WIN_WRITE Write Sector 0x3 0 0 LT 0x30 Interrupt

WIN_VERIFY Inspection Sector 0x4 000T 0x40 Interrupt

WIN_FORMAT Format Track 0x5 0000 0x50 Interrupt

WIN_INIT Controller initialization 0x6 0000 0x60 Interrupt

WIN_SEEK Seek 0x7 RRRR 0x70 Interrupt

WIN_DIAGNOSE Controller Diagnostic 0x9 0000 0x90 Controller free

WIN_SPECIFY Establish drive parameters 0x9 0001 0x91 Controller free

Table low byte command code 4 Bit is an additional parameter, its meaning is:

R It is stepping rate. R = 0 , The stepping rate is 35us ; R = 1 for 0.5ms Order volume increased. The default program R = 0 .

L Is the data model. L = 0 It indicates a read / write sectors 512 byte; L = 1 It indicates a read / write sectors 512 plus 4 Byte ECC code. The default is the program L = 0 .

T A retry mode. T = 0 Retry is expressed; T = 1 Retry is prohibited. Programs take T = 0 . ◆ hard disk control

register (write) ( HD_CMD , 0x3f6 )

This register is write-only. A hard disk used to store the control byte and controls reset operation. Displacement table which defines the basic parameters of the hard disk 0x08

The description of the same bytes, see Table 6-6 Fig.

table 6-6 Hard disk control byte Meaning

Displacement size Explanation

Control byte (the drive selection step) bits 0

Unused

Place 1 Reserved ( 0) ( shut down IRQ)

Place 2 Allow reset

0x08 byte Place 3 If the number of heads greater than 8 The home 1

Place 4 Unused ( 0)

Place 5 If the number of cylinders + 1 FIG bad area at the manufacturer, then set 1

Place 6 Ban ECC Retry

Place 7 Forbidden try again.

6.5.3.2 AT Hard disk controller programming

When operation control of the hard disk controller, need to send parameters and commands. The command format Table 6-7 Fig. First send

--199--
6.5 hd.c program

6 Byte parameters, and finally sent 1 Byte command code. Whatever this command require the complete output 7 Command block bytes sequentially write port 0x1f1 - 0x1f7 . .

table 6-7 Command Format

port Explanation

0x1f1 Write precompensation starting cylinder number

0x1f2 The number of sectors

0x1f3 Start sector number

0x1f4 Cylinder number low byte

0x1f5 High byte cylinder number

0x1f6 Drive number / head number

0x1f7 Command code

First of all CPU The port control register ( HD_CMD) 0x3f6 Output control byte, hard to establish the appropriate control mode. The above embodiment can be established

after the order of transmission parameters and commands. The steps of: detecting an idle state controller: CPU By reading the main status register, if the bit 7 for 0 Indicating that

the controller is idle. If within the prescribed time controller has been in a busy state, the penalty for a timeout error. Test the drive is ready: CPU Analyzing the main status register

bit 6 Whether 1 To see whether the drive is ready. for 1 You can output parameters and commands.

Output command block: in order respectively to a corresponding output port and the output parameter command.

CPU Wait interrupt: command execution, interrupt request signal is generated by the hard disk controller ( IRQ14 - The corresponding interrupt int46 ) Or the controller state is set

to idle, or indicates a request indicating that the operation end sector transmission (multi-sector read / write). Detection Result: CPU The main status register is read again, if the bit 0

equal 0 It means that the command is successful, otherwise fail. If the failure can be further query error register ( HD_ERROR) Take error code.

6.5.3.3 The basic hard disk parameter table

Interrupt vector table, int 0x41 Interrupt vector location ( 4 * 0x41 = 0x0000: 0x0104 ) Address stored in the program is not interrupted but the first hard disk basic

parameter table, Table 6-8 Fig. for 100% Compatible BIOS , Here kept the first address array of hard disk parameter table F000h: E401h . The second hard disk parameter table

base address stored in the entry int 0x46 Interrupt vector.

table 6-8 The basic parameters of the hard disk information table

Displacement size Explanation

0x00 word Number of cylinders

0x02 byte Number of heads

0x03 word The write current begins to decrease cylinder (only PC XT Use, the other for 0)

0x05 word Before beginning to write pre-compensation cylinder number (multiply 4 )

0x07 byte maximum ECC The burst length (only XT Use, the other for 0 )

Control byte (the drive selection step) bits 0

Unused

Place 1 Reserved ( 0) ( shut down IRQ)

0x08 byte Place 2 Allow reset

Place 3 If the number of heads greater than 8 The home 1

Place 4 Unused ( 0)

Place 5 If the number of cylinders + 1 FIG bad area at the manufacturer, then set 1

- 200 -
6.5 hd.c program

Place 6 Ban ECC Retry

Place 7 Forbidden try again.

0x09 byte Standard timeout value (only XT Use, the other for 0 )

0x0A byte Formatting timeout value (only XT Use, the other for 0 )

0x0B byte Drive timeout value detector (only XT Use, the other for 0 )

0x0C word Head-landing (stop) cylinder number

0x0E byte The number of sectors per track

0x0F byte Reservations.

6.5.3.4 No hard disk device naming

The major number is hard 3 . Major number of other devices are:

1- RAM, 2- Disk, 3- hard disk, 4-ttyx, 5-tty, 6- Parallel port, 7- Due to non-named pipes 1 A hard disk can exist 1--4 Partition, so the hard disk partition also be specified

depending on the partition with minor number. Thus the hard disk logical device number consists of the following ways:

Master device number = device number * 256 + Minor

number that is dev_no = (major << 8) + minor

Two drives all logical device number in Table 6-9 Fig.

table 6-9 Hard disk logical device number

Logical device number The corresponding device description file

0x300 / Dev / hd0 The first representative of the 1 Hard drive

0x301 / Dev / hd1 Represents 1 The first hard disk 1 Partition

0x302 / Dev / hd2 Represents 1 The first hard disk 2 Partition

0x303 / Dev / hd3 Represents 1 The first hard disk 3 Partition

0x304 / Dev / hd4 Represents 1 The first hard disk 4 Partition

0x305 / Dev / hd5 The first representative of the 2 Hard drive

0x306 / Dev / hd6 Represents 2 The first hard disk 1 Partition

0x307 / Dev / hd7 Represents 2 The first hard disk 2 Partition

0x308 / Dev / hd8 Represents 2 The first hard disk 3 Partition

0x309 / Dev / hd9 Represents 2 The first hard disk 4 Partition

among them 0x300 with 0x305 Which does not correspond to the partition, but on behalf of the entire hard disk. From linux Kernel 0.95 After using this version is

no longer cumbersome naming, but now using the same naming method.

6.5.3.5 Hard disk partition table

In order to realize a plurality of operating systems to share resources hard disk, the hard disk can be logically divided into 1--4 Partitions. Between the sector number of

each partition are contiguous. The partition table 4 Table entries, each entry is made 16 Byte, information corresponding to a partition, partition size and storing the cylinder

number, track number and sector number of the start and end, Table 6-10 Fig. Stored in the hard disk's partition table 0 cylinder 0 Head first 1 Sectors

0x1BE - 0x1FD Place.

table 6-10 Hard disk partition table structure

position name Size Description

0x00 boot_ind byte Boot flags. 4 Partition at the same time only one partition is bootable.

--201--
6.6 ll_rw_blk.c program

0x00- Not boot the operating system from the partition; 0x80- Operating system from the boot partition.

0x01 head byte Partition start head number.

0x02 sector byte Partition start sector number (bits 0-5) And high starting cylinder number 2 Bit (Bit 6-7) .

0x03 cyl byte Low partition start cylinder number 8 Bit.

0x04 sys_ind byte Partition type byte. 0x0b-DOS; 0x80-Old Minix; 0x83-Linux ...

0x05 end_head byte The end of the head number of the partition.

0x06 end_sector byte End sector number (bits 0-5) And high-end cylinder number 2 Bit (Bit 6-7) .

0x07 end_cyl byte Low end cylinder number 8 Bit.

0x08--0x0b start_sect Long word Partition start physical sector number.

0x0c - 0x0f nr_sects Long word The number of sectors occupied by partitions.

6.6 ll_rw_blk.c program

6.6.1 Functional Description

The main program block device for performing low-level read / write operation, a chapter all block devices and other parts of the system interface program. Other program

functions through the lower block calls to read and write the program ll_rw_block () Reading and writing data to the block device. The main function of the device function is to create a

block write request entry as a block device, and the device is inserted into the specified block in the request queue. The actual read and write operations are requested item by the

device handler request_fn () carry out. For the operation of the hard disk, the function is do_hd_request () ; For floppy operations, the function is do_fd_request () ; For the virtual disk is do_rd_request

() . If the ll_rw_block () Is a block device to establish a requested item, and tested in block device entry pointer of the current request is determined when the device is idle empty, the

new request will be provided for the current item request entries, and to direct calls request_fn ()

Operate the requested item. Otherwise it will use the new algorithm to lift request entry into the request necklace table of the device for processing. And when request_fn () End

processing of a request for entry, it will put the request to delete items from the list.

due to request_fn () At the end of each requested item processing will break through the callback C Function (mainly read_intr () with

write_intr () ) Called again request_fn () Request itself to process the remaining items in the list, so long as the request table necklace apparatus (or as queues) in the presence of a

pending request entries, all of which will be processed until the request table of the device is a necklace empty. When requested necklace empty table, request_fn () It will not send

commands to the drive controller, but quit immediately. Therefore, request_fn () This concludes the cycle calling function. Referring to FIG. 6-4 Fig.

--202--
6.6 ll_rw_blk.c program

ll_rw_block ()

make_request () Establishment request items

Add the requested item

The first request item?

Triggered interrupts
Table interrupt request necklace Call request_fn () interrupted process

Data copy operation is

drop out Triggered interrupts

Requested item processing is terminated

Call request_fn ()

Map 6-4 ll_rw_block Calling sequence

For virtual disk device, because of its read and write operations do not involve the above hardware synchronization with the outside world, so there is no such interrupt

processing. Entry of the current request read and write operations in the virtual device entirely do_rd_request () Implemented.

6.6.2 Code comments

program 6-4 linux / kernel / blk_drv / ll_rw_blk.c

1/*
2 * Linux / kernel / blk_dev / ll_rw.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * This handles all read / write requests to block devices


9*/
/*
* The program processing block device all read / write operations.

*/
10 #include <errno.h> // error number header files. The system comprises various error number. (Linus from the introduction of minix)

11 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

12 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

13 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

1415 #include " blk.h "


// file header block device. Definition request data structure, the data structure of a block device like functions and macros.

1617 / *

18 * The request-struct contains all necessary data


19 * To load a nr of sectors into memory
20 * /

--203--
6.6 ll_rw_blk.c program

/*
* Request structure that contains all the necessary information is loaded nr sector data into memory.

*/
twenty one struct request request [ NR_REQUEST ];
2223 / *

twenty four * Used to wait on when there are no free requests


25 * /
/ * Is a temporary waiting at the process when there is no request for an array of free entry * /

26 struct task_struct * wait_for_request = NULL ;


2728 / * Blk_dev_struct is:

29 * do_request-address
30 * next-request
31 * /
/ * Blk_dev_struct block device structure: (kernel / blk_drv / blk.h, 23)
* do_request-address // pointer to the corresponding request handler major number.

* current-request // next request of the device.


*/
// array using the index number as the master device. The actual content of the various blocks filled in when the device driver initialization. For example, a hard

disk driver // initialize (hd.c, 343 lines), i.e., a first statement for setting blk_dev [3] content.

32 struct blk_dev_struct blk_dev [ NR_BLK_DEV ] = {


33 { NULL , NULL }, / * No_dev * / // 0 - no equipment.
34 { NULL , NULL }, / * Dev mem * / // 1 - Memory.
35 { NULL , NULL }, / * Dev fd * / // 2 - floppy device.
36 { NULL , NULL }, / * Dev hd * / // 3 - hard disk device.
37 { NULL , NULL }, / * Dev ttyx * / // 4 - ttyx equipment.
38 { NULL , NULL }, / * Dev tty * / // 5 - tty device.
39 { NULL , NULL } / * Dev lp * / // 6 - lp printer devices.
40 };
41
// lock the specified buffer bh. If the specified buffer has been locked by other tasks, so that their sleep (non-interruptible wait), // until the task is executed
unlocked buffer explicitly wake.
42 static inline void lock_buffer (Struct buffer_head * Bh)
43 {
44 cli (); // Clear interrupt permission.

45 while (bh-> b_lock) // If the buffer is locked, then sleep until the buffer is unlocked.
46 sleep_on (& Bh-> b_wait);
47 bh-> b_lock = 1; // immediately lock the buffer.
48 sti (); // open the interruption.

49 }
50
// release (unlocked) lock buffers.
51 static inline void unlock_buffer (Struct buffer_head * Bh)
52 {
53 if (! bh-> b_lock) // If the buffer is not locked, then print an error message.
54 printk ( ' ll_rw_block.c: buffer not locked \ n \ r ");
55 bh-> b_lock = 0; // clear lock flag.
56 wake_up (& Bh-> b_wait); // wake task waiting for the buffer.
57 }
5859 / *

60 * Add-request adds a request to the linked list.

--204--
6.6 ll_rw_blk.c program

61 * It disables interrupts so that it can muck with the


62 * Request-lists in peace.
63 * /
/*
* add-request () added to a request list. It will shut down interrupt,
* So it can safely handle the request list * /
*/
//// requested item was added to the list. Dev parameter specifies block device, req is a request for configuration information entry pointer.

64 static void add_request (Struct blk_dev_struct * Dev, struct request * Req)


65 {
66 struct request * Tmp;
6768
req-> next = NULL ;
69 cli (); // disable interrupts.

70 if (req-> bh)
71 req-> bh-> b_dirt = 0; // clear buffer "dirty" flag.
// If the current sub-segment dev request (current_request) is empty, then the device is not currently requested item, this is the first request entries // 1, and therefore the device can block

the current request pointer entry directly to the request, and immediately function execution request corresponding device.

72 if (! (tmp = dev-> current_request)) {


73 dev-> current_request = req;
74 sti (); // open the interruption.

75 (Dev-> request_fn) (); // function execution apparatus a request for a hard disk is do_hd_request ().

76 return;
77 }
// If present, the device has been requested items are waiting, first use the elevator algorithm searches for the best insertion position, and then insert the current request // the request list. The

role of the elevator algorithm is to make the smallest disk head movement distance, thereby improving hard disk access time.

78 for (; tmp-> next; tmp = tmp-> next)


79 if (( IN_ORDER (Tmp, req) ||
80 ! IN_ORDER (Tmp, tmp-> next)) &&
81 IN_ORDER (Req, tmp-> next))
82 break;
83 req-> next = tmp-> next;
84 tmp-> next = req;
85 sti ();
86 }
87
//// create the requested item and insert the request queue. The parameters are: major number major, command rw, bh store buffer data head pointer.

88 static void make_request (Int major, int rw, struct buffer_head * Bh)
89 {
90 struct request * Req;
91 int rw_ahead;
9293 / * WRITEA / READA is special case - it is not really needed, so if the * /

94 / * Buffer is locked, we just forget about it, else it's a normal read * /
/ * WRITEA / READA is a special case - they do not need, so if the buffer has been locked * / / * We can not ignore it and quit, otherwise

the implementation of the general read / write operations. * /

// Here 'READ' and meaning 'WRITE' behind the 'A' character on behalf of the English word Ahead, indicate in advance the pre-read / write data blocks. // For the command is case

READA / WRITEA when the specified buffer is in use and has been locked, abandoned pre-read / write requests. // otherwise operate as normal READ / WRITE command.

95 if (rw_ahead = (rw == READA || rw == WRITEA )) {


96 if (bh-> b_lock)
97 return;

--205--
6.6 ll_rw_blk.c program

98 if (rw == READA )
99 rw = READ ;
100 else
101 rw = WRITE ;
102 }
// If the command is not a READ or WRITE said kernel is wrong, an error message and crashes.

103 if (rw! = READ && rw! = WRITE )


104 panic ( ' Bad block dev command, must be R / W / RA / WA ");
// lock the buffer, if the buffer has been locked, the current task (process) will sleep until it is explicitly awakened.
105 lock_buffer (Bh);
// If the command is a write buffer and data is not dirty (not modified), or the command is read and buffer data is updated, // you do not add this request.
The buffer is unlocked and exit.
106 if ((rw == WRITE &&! Bh-> b_dirt) || (rw == READ && bh-> b_uptodate)) {
107 unlock_buffer (Bh);
108 return;
109 }
110 repeat:
111 / * We do not allow the write-requests to fill up the queue completely:
112 * We want some room for reads: they take precedence The last third.
113 * Of the requests are only for reads.
114 * /
/ * We can not let the queue all write request entries: We need to keep some space for read requests: Read

* It is a priority. After the third space is a read request queue is prepared.


*/
// requested item is a request from the end of the array began to fill the empty entry search. According to the above requirements, for a read request command, directly from the

end of the queue // start operation, and a write request from the search to only fill an empty entry at the head of the queue queue 2/3.

115 if (rw == READ )


116 req = request + NR_REQUEST ; // read requests, the queue pointer to the tail of the queue.

117 else
118 req = request + (( NR_REQUEST * 2) / 3); // For a write request, the queue pointers to 2/3 of the queue.
119 / * Find an empty request * /
/ * Search for an empty request item * /

// search forward from the rear, when dev field value of the request structure request = -1 indicates that unoccupied.

120 while (--req> = request )


121 if (req-> dev <0)
122 break;
123 / * If none found, sleep on new requests: check for rw_ahead * /
/ * If free entry is not found, so that the second new request Sleep: need to check in advance whether the read / write * / // If no one is idle (at this time request an array of

pointers has been searched over the head), then view this times whether the request is // read ahead / write (READA or WRITEA), if it is to give up the request. Otherwise, make

this request sleep (wait request queue // make room for items), after a while again search request queue.

124 if (req < request ) { // If there is no empty request queue entry, then

125 if (rw_ahead) { // If it is ahead of the read / write requests, then unlock the buffer exit.

126 unlock_buffer (Bh);


127 return;
128 }
129 sleep_on (& wait_for_request ); // otherwise make this request sleep, and then I would go see the request queue.

130 goto repeat;


131 }
132 / * Fill up the request-info, and add it to the queue * /
/ * Fill in the request information item to the idle request, and added to a queue * /

// program execution to here indicates an idle request to find items. See request structure (kernel / blk_drv / blk.h, 23).
133 req-> dev = bh-> b_dev; // Device No.

--206--
6.7 ramdisk.c program

134 req-> cmd = rw; // command (READ / WRITE).


135 req-> errors = 0; // number of errors generated during operation.

136 req-> sector = Bh-> b_blocknr << 1; // start sector. Block number is converted into sector number (sector 2 = 1).

137 req-> nr_sectors = 2; // read the number of sectors.

138 req-> buffer = bh-> b_data; // data buffer.


139 req-> waiting = NULL ; // wait for local operations performed tasks completed.

140 req-> bh = bh; // header buffer pointer.


141 req-> next = NULL ; // points to the next request entry.

142 add_request (Major + blk_dev , Req); // added to the request queue entry (blk_dev [major], req).
143 }
144
//// low-level function blocks to read and write data, a block device interface to the rest of the system function.

// This function is called fs / buffer.c in. The main function is to create a block write request entry device and the device is inserted into the specified block in the request queue. // actual reading

and writing operations is () function is performed by request_fn device. For the operation of the hard disk, the function is do_hd_request (); // for floppy operations, the function is do_fd_request

(); for the virtual disk is do_rd_request (). // Further, it is necessary to read / write block device information has been saved in the buffer header structure, such as device number, block number.

// Parameters: rw - READ, READA, WRITE command or WRITEA; bh - Data block header buffer pointer.

145 void ll_rw_block (Int rw, struct buffer_head * Bh)


146 {
147 unsigned int major; // main equipment (for a hard disk is 3).
148
// If the master device does not exist or the number of read and write operations of the function device does not exist, an error message and returns.

149 if ((major = MAJOR (Bh-> b_dev))> = NR_BLK_DEV ||


150 ! ( blk_dev [Major] .request_fn)) {
151 printk ( ' Trying to read nonexistent block-device \ n \ r ");
152 return;
153 }
154 make_request (Major, rw, bh); // Create the requested item and insert the request queue.

155 }
156
//// block device initialization function, invoked by the initialization program main.c (init / main.c, 128). // array initialization request, the request

entry into an idle all items (dev = -1). There are 32 (NR_REQUEST = 32).

157 void blk_dev_init (Void)


158 {
159 int i;
160
161 for (i = 0; i < NR_REQUEST ; I ++) {
162 request [I] .dev = -1;
163 request [I] .next = NULL ;
164 }
165 }
166

6.7 ramdisk.c program

6.7.1 Functional Description

This document is a virtual memory disk ( Ram Disk ) Driver by Theodore Ts'o prepared by. A virtual disk apparatus to simulate the actual physical memory using the disk

storage data. Its main purpose is to increase the speed of read and write operations on the "Disk" data. In addition to the need

--207--
6.7 ramdisk.c program

Some take up valuable memory resources, its main drawback is that once a system crash or shut down all virtual disk data will be lost. Therefore, the virtual disk is usually stored

some of the commonly used system commands such as utilities or temporary data, rather than an important input document.

When linux / Makefile File defines constants RAMDISK , Kernel initialization program will draw a constant value that specifies the size of the virtual memory area for storing

data in the disk memory. DETAILED located position of the virtual disk in physical memory is determined at the kernel initialization phase ( init / main.c , 123 Line), which is located

between the kernel buffer cache and main memory area. If the operation of the machine contains 16MB Physical memory, the virtual disk area will be set in memory 4MB At the

beginning of the virtual disk capacity that is equal to RAMDISK Value ( KB ). If the

RAMDISK = 512 , See the case where the memory 6-5 Fig.

Kernel Module Cache Virtual disk The primary bank

end 0 640K 1M 4M 4.5M 16M

Memory and BIOS ROM rd_start rd_length

Map 6-5 Virtual disk 16MB Specific memory location in which the system

Virtual disk read and write access to the device operate in full accordance with the principle of common disk operations, but also need to follow the way of access to the

block device to read and write operations. Since not involved in the realization of synchronous operation with the controller or an external device, and therefore it is relatively

simple implementation. For data only need to perform memory copy operations to data blocks in the "transmission" between the system and device.

This program includes 3 Functions. rd_init () It will be at system initialization init / main.c Program calls for determining the position and size of the specific virtual disk in

physical memory; do_rd_request () Requested item is a function of the operation of the virtual disk apparatus, the current request access to virtual disk data entry operation; rd_load

() It is a virtual root file loading function. In the system initialization, the function is used to attempt to block position designated disk from the beginning of the boot disk to load a

root file system to the virtual disk. In function, the start position is defined as disk blocks

256 . Of course, you can also change this value according to their specific requirements, as long as the disk capacity specified in this value can hold the kernel image file.

Such a boot image file by the kernel ( Bootimage ) Plus root file system image file ( Rootiamge ) A combination of "combo" disc, you can start like DOS As the system disk to

boot Linux system. About this way of making composite disc left to the reader to consider.

Before the normal root file system load is performed, the system will first perform rd_load () Function, the first attempt from disk 257 Root file system reads the block

superblock. If successful, put the root file virtual disk image file into memory, and the root file system device mark

ROOT_DEV As a virtual disk device ( 0x0101 ), Otherwise exit rd_load () The system continues to perform root from the other device file load operation.

6.7.2 Code comments

program 6-5 linux / kernel / blk_drv / ramdisk.c

1/*
2 * Linux / kernel / blk_drv / ramdisk.c
3*
4 * Written by Theodore Ts'o, 12/2/91
5*/
/ * Compiled by Theodore Ts'o, 12/2/91
*/

--208--
6.7 ramdisk.c program

// Theodore Ts'o (Ted Ts'o) is the linux community of famous people. Linux is popular in the world has his big // credit, back in the Linux operating system
has just come out, and he with great enthusiasm to provide for the development of linux maillist, and // first established in North America the linux ftp site
(tsx-11.mit.edu), and remains, to provide services for the majority of linux users //. One of the greatest contribution he has made to linux is proposed and
implemented ext2 file system. The file system has become the de facto world // linux file system standard. He recently launched the ext3 file system,
greatly improving the efficiency // stability and access to the file system. As respected for his first 97 (2002) Journal of linuxjournal him as a // Cover, and
interviewed him. Currently, he is the IBM linux Technology Center, and engaged in work on LSB // (Linux Standard Base) and other aspects. (His home
page: http: //thunk.org/tytso/)

67 #include <string.h>
// string header file. Mainly defines the built-in functions related to operation of the string.

89 #include <linux / config.h> // kernel configuration file header. Define the keyboard language and hard disk type (HD_TYPE) option.

10 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

11 #include <linux / fs.h> // file system header files. Table structure definition file (file, buffer_head, m_inode, etc.).
12 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

13 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

14 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

15 #include <asm / memory.h> // memory copy header files. Containing memcpy () macros embedded assembly function.

1617 #define MAJOR_NR 1


// RAM disk is a major number. Main equipment must be defined before blk.h.

18 #include " blk.h "


1920 char
* rd_start ; // starting position of a virtual disk in memory. () In line 52 // initialization function determines rd_init.
See (init / main.c, 124) (abbreviation rd_ behalf ramdisk_).
twenty one int rd_length = 0; // virtual disk share memory size (bytes).
twenty two

// virtual disk function of the current term operation request. Program structure and do_hd_request () is similar to (hd.c, 294). // After the establishment of a virtual disk (rd) in the claims, the

terms lower block device interface function ll_rw_block () and added to the list in rd, // This function is called rd the current request for processing items. The function first calculates the

value of the byte length corresponding to the number of sectors the current len ​requested item specified in the start position corresponding to the start sector @ addr requirements and

which virtual disk memory, and in accordance with the request command entry // operation. If the write command WRITE, put the request referred to in subparagraph data buffer is copied

directly to the memory location addr // place. If the read operation and vice versa. End_request can directly call the data has been copied () to make this request entry process ends. // then

jump to the beginning of the function at a request entry process again.

twenty three void do_rd_request (Void)

twenty four {

25 int len;
26 char * Addr;
27
// Check the legitimacy of the item request, Ruoyi not request entry to exit (see blk.h, 127).

28 INIT_REQUEST ;
// The following statement is made corresponding to the start sector ramdisk memory start position and length of the memory.

// sector << 9 wherein represents sector * 512, CURRENT defined as (blk_dev [MAJOR_NR] .current_request).
29 addr = rd_start + ( CURRENT -> sector << 9);
30 len = CURRENT -> nr_sectors << 9;
// if the number is not sub> 1 at the end of a virtual disk or a memory corresponding to the start position, the end of the request, and to repeat the jump. // repeat reference defined

within the macro INIT_REQUEST, located at the beginning of the macro, see blk.h, 127 rows.

31 if (( MINOR ( CURRENT -!> Dev) = 1) || (addr + len> rd_start + rd_length )) {


32 end_request (0);
33 goto repeat;
34 }
// If a write command (the WRITE), then the content items requested to be copied to the buffer at addr for len bytes.

35 if ( CURRENT -> cmd == WRITE ) {

--209--
6.7 ramdisk.c program

36 (Void) memcpy (Addr,


37 CURRENT -> buffer,
38 len);
// If the command is a read (the READ), then copied to the start addr content item request buffer for len bytes.
39 } Else if ( CURRENT -> cmd == READ ) {
40 (Void) memcpy ( CURRENT -> buffer,
41 addr,
42 len);
// Otherwise display command does not exist, the crash.

43 } Else
44 panic ( ' unknown ramdisk-command ");
After successful treatment // requested item, set the update flag. And proceed to the next processing device of the present entry request.

45 end_request (1);
46 goto repeat;
47 }
4849 / *

50 * Returns amount of memory which needs to be reserved.


51 * /
/ * Returns the amount of memory required for the virtual disk memory ramdisk * /

// virtual disk initialization function. Determining a virtual disk memory starting address, length. And the entire virtual disk area cleared.

52 long rd_init (Long mem_start, int length)


53 {
54 int i;
55 char * Cp;
5657
blk_dev [ MAJOR_NR ] .Request_fn = DEVICE_REQUEST ; // do_rd_request ().
58 rd_start = (Char *) mem_start; // For 16MB system, the value of 4MB.
59 rd_length = Length;
60 cp = rd_start ;
61 for (i = 0; i <length; i ++)
62 * cp ++ = '\ 0 ';
63 return (length);
64 }
6566 / *

67 * If the root device is the ram disk, try to load it.


68 * In order to do this, the root device is originally set to the
69 * Floppy, and we later change it to be ram disk.
70 * /
/*
* If the root file system device (root device) is a ramdisk, then try to load it. root device originally point
* Floppy disk, we will change it to point to ramdisk.

*/
//// try to load the root file system to a virtual disk.
// This function () is called (hd.c, 156 lines) is provided in the kernel function setup. Further, a disk block = 1024 bytes.
71 void rd_load (Void)
72 {
73 struct buffer_head * Bh; // pointer to the cache block header.

74 struct super_block s; // File superblock structure.


75 int block = 256; / * Start at block 256 * /
76 int i = 1; / * The root file system image file represents the beginning of the boot disk of the disk blocks 256 * /

77 int nblocks;

--210--
6.7 ramdisk.c program

78 char * Cp; / * Move pointer * /


7980
if (! rd_length ) // If the length of the ramdisk is zero, then exit.
81 return;
82 printk ( ' Ram disk:% d bytes, starting at 0x% x \ n ", rd_length ,
83 (Int) rd_start ); // display and memory size ramdisk starting position.
84 if ( MAJOR ( ROOT_DEV )! = 2) // If the device is not the root file at this time a floppy disk, then exit.

85 return;
// read floppy disk block 256 1,256,256 + + 2. breada () for reading the specified block of data, and also need to read the block mark, then // return buffer pointer

contains data block. If it returns NULL, then the data block is unreadable (fs / buffer.c, 322). // here refers to the super block + 1 blocks on the disk.

86 bh = breada ( ROOT_DEV , Block + 1, block, block + 2, -1);


87 if (! bh) {
88 printk ( ' Disk error while looking for ramdisk \ n ")!;
89 return;
90 }
S // The buffer pointed disk superblock. (Superblock structure d_super_block disk).
91 * ((Struct d_super_block *) & S) = * ((struct d_super_block *) Bh-> b_data);
92 brelse (Bh);
93 if (s.s_magic! = SUPER_MAGIC ) // If not the magic number in the superblock, the description is not minix file system.

94 / * No ram disk image present, assume normal floppy boot * /


/ * No disk ramdisk image file, usually a floppy boot make way execution * /
95 return;
// = number of blocks of logical blocks (the number of sections) * 2 ^ (power number of blocks per section).

// If the number of blocks is greater than the number of memory blocks can be accommodated in the virtual disk is not loaded, an error message and returns. Otherwise, display // Load data

block information.

96 nblocks = s.s_nzones << s.s_log_zone_size;


97 if (nblocks> ( rd_length >> BLOCK_SIZE_BITS )) {
98 printk ( ' Ram disk image too big! (% D blocks,% d avail) \ n ",
99 nblocks, rd_length >> BLOCK_SIZE_BITS );
100 return;
101 }
102 printk ( ' Loading% d bytes into ram disk ... 0000k ",
103 nblocks << BLOCK_SIZE_BITS );
// cp at the start point to the virtual disk, and then copy the root file system image file on the disk to the virtual disk.

104 cp = rd_start ;
105 while (nblocks) {
106 if (nblocks> 2) // if the number of blocks to be read more than 3 Pilot Pre fast read mode is used to read the data block.

107 bh = breada ( ROOT_DEV , Block, block + 1, block + 2, -1);


108 else // otherwise single block read.

109 bh = bread ( ROOT_DEV , Block);


110 if (! bh) {
111 printk ( ' I / O error on block% d, aborting load \ n ",
112 block);
113 return;
114 }
115 (Void) memcpy (Cp, bh-> b_data, BLOCK_SIZE ); // copy the data in the buffer to the cp.
116 brelse (Bh); // release the buffer.
117 printk ( "\ 010 \ 010 \ 010 \ 010 \ 010% 4dk ", I); // print the block count value is loaded.

118 cp + = BLOCK_SIZE ; // virtual disk pointer forward.

119 block ++;


120 nblocks--;
121 i ++;

--211--
6.8 floppy.c program

122 }
123 printk ( "\ 010 \ 010 \ 010 \ 010 \ 010done \ n ");
124 ROOT_DEV = 0x0101; // modify ROOT_DEV to point to a virtual disk ramdisk.
125 }
126

6.8 floppy.c program

6.8.1 Functional Description

This procedure is the floppy disk controller driver. As with other block device drivers, the program also function operation request entry

do_fd_request () Based, read or write to the data on the floppy disk.

Considering the floppy disk drive motors typically does not turn on when not working, so before you can actually read and write to a floppy disk drive, we need to wait for

the motor to start and reach normal operating speed. Compared with the running speed of the computer, the longer this period of time, usually required 0.5

Or so seconds.
Further, when a disk read and write operation is complete, and we need to stop the rotation of the drive, the disk surface to reduce friction paint. But we can not operate on

the disk immediately after it is stopped. Because, you may soon need to be read and write operations. Therefore, after a drive that does not need to drive or operate idle for some

time, waiting for the possible arrival of read and write operations, if the drive is not operating in a longer period of time, the program to make it stop. This time can be set to maintain

the rotation of about 3 Or so seconds.

When a disk read and write error occurs, or some other cases cause a drive motor is not turned off. At this point we also need to let the system automatically after

a certain time to turn it off. Linus In this program, the delay value is set 100 second.

Thus, when the floppy disk drive will be used to operate a lot of delay (timing) of operation. Thus the timing involves more processing functions in the driver. There are

several functions that deal with the relationship between the timing was placed relatively close kernel / sched.c (Line 201-262 ). This is the biggest difference between the hard disk

and floppy disk driver the driver, floppy driver is complex reasons than the hard disk driver.

While this procedure is relatively complicated, but the principle has a floppy disk read and write operations with other blocks are the same devices. This procedure is the

use of the request and the request entries necklace table structure to handle all read and write operations of the floppy disk. Thus the function key operation request do_fd_request

() It remains one of the important functions of this program. In reading should be the function of the main line. In addition, a floppy disk controller is more complex, involving many

execution state flag and a controller. Therefore, when reading, the need for a description with reference to the program file header, and frequently the Program include / linux /

fdreg.h . This file defines all parameters constant floppy disk controller, and explains the meaning of these constants.

6.8.2 Code comments

program 6-6 linux / kernel / blk_drv / floppy.c

1/*
2 * Linux / kernel / floppy.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * 02.12.91 - Changed to static variables to indicate need for reset


9 * And recalibrate. This makes some things easier (output_byte reset
10 * Checking etc), and means less interrupt jumping in case of errors,
11 * So the code is hopefully easier to understand.
12 * /
/*

--212--
6.8 floppy.c program

* 02.12.91 - Modify a static variable, and to accommodate the reset correction operation again. This makes certain things

* Make it more convenient (output_byte reset inspection), and means that the interrupt jump on error

* To be less, so I hope the code easier to understand.


*/
1314 / *

15 * This file is certainly a mess. I've tried my best to get it working,


16 * But I do not like programming floppies, and I have only one anyway.
17 * Urgel. I should check for more errors, and do more graceful error
18 * Recovery. Seems there are problems with several drives. I've tried to
19 * Correct them. No promises.
20 * /
/*
* This file is of course a bit confusing. I've tried my best to make it work, but I do not like the floppy drive programming,

* And I have only one floppy drive. Also, I should do more troubleshooting work, as well as to correct more errors.
* For some floppy disk drives, this procedure if there are some problems. I have tried to be corrected,
* But we can not guarantee that the problem has disappeared.

*/
2122 / *

twenty three * As with hd.c, all routines within this file can (and will) be called
twenty four * By interrupts, so extreme caution is needed. A hardware interrupt
25 * Handler may not sleep, or a kernel panic will happen. Thus I can not
26 * Call "floppy-on" directly, but have to set a special timer interrupt
27 * Etc.
28 *
29 * Also, I'm not certain this works on more than floppy 1. Bugs may
30 * Abund.
31 * /
/*
* As hd.c files, all routines in the file can be interrupted calls, so they need special
* Be careful. Hardware interrupt handlers can not sleep, otherwise the kernel silly out (crash) ☺ . It is not
* Direct call "floppy-on", but only to set up a special timer interrupt and so on.

*
* In addition, I can not guarantee that the program can work on more than one floppy drive systems, there may be errors.

*/
3233 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

34 #include <linux / fs.h> // file system header files. Table structure definition file (file, buffer_head, m_inode, etc.).
35 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

36 #include <linux / fdreg.h> // floppy header. Definitions of parameters comprises the floppy disk controller.

37 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

38 #include <asm / io.h> // io header files. Defined hardware port I / O macro assembler statements.

39 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

4041 #define MAJOR_NR 2


// floppy major number is 2.
42 #include " blk.h " // file header block device. Definition request data structure, the data structure of a block device like functions and macros.

4344 static int recalibrate = 0;


// flags: the need for recalibration.

45 static int reset = 0; // flags: the need for a reset operation.


46 static int seek = 0; // flags: the need to seek execution.

47

--213--
6.8 floppy.c program

// current digital output register (Digital Output Register), defined in sched.c, 204 rows. // This variable is an important indicator of the

variable floppy operation, description of the DOR register, see after the procedure.

48 extern unsigned char current_DOR ;


4950 #define immoutb_p (Val, port) \
// byte direct output (embedded macro assembler language).

51 __asm ​__ ( " outb% 0,% 1 \ n \ tjmp 1f \ n1: \ tjmp 1f \ n1: "::" a "(( char) (val)), " i "( port))
52
// definition of these two devices for computing the floppy disk number. Minor number = TYPE * 4 + DRIVE. See the list after the calculation method.

53 #define TYPE ( x ) (( x ) >> 2) // floppy drive (2--1.2Mb, 7--1.44Mb).


54 #define DRIVE ( x ) (( x ) & 0x03) // number floppy (0--3 corresponding to A - D).

55 / *
56 * Note that MAX_ERRORS = 8 does not imply that we retry every bad read
57 * Max 8 times - some types of errors increase the errorcount by 2,
58 * So we might actually retry only 5-6 times before giving up.
59 * /
/*
* Note that the following definitions MAX_ERRORS = 8 does not mean trying to up to eight times for each read errors - some types

* Error error count value will be multiplied by 2, so we really just try 5-6 times before giving up operation can be.
*/
60 #define MAX_ERRORS 8
6162 / *

63 * Globals used by 'result ()'


64 * /
/ * The following is the function 'result ()' using global variables * /

// each bit in the status byte of these parameters, see include / linux / fdreg.h header file.
65 #define MAX_REPLIES 7 // FDC return result information up to 7 bytes.
66 static unsigned char reply_buffer [ MAX_REPLIES ]; // store the result response information returned by the FDC.
67 #define ST0 ( reply_buffer [0]) // Returns status byte 0.
68 #define ST1 ( reply_buffer [1]) // Returns status byte 1.
69 #define ST2 ( reply_buffer [2]) // Returns status byte 2.
70 #define ST3 ( reply_buffer [3]) // Returns status byte 3.
7172 / *

73 * This struct defines the different floppy types. Unlike minix


74 * Linux does not have a "search for right type" -type, as the code
75 * For that is convoluted and weird. I've got enough problems with
76 * This driver as it is.
77 *
78 * The 'stretch' tells if the tracks need to be boubled for some
79 * Types (ie 360kB diskette in 1.2MB drive etc). Others should
80 * Be self-explanatory.
81 * /
/*
* The following structure defines a floppy diskette different types. The difference is that with minix, linux no

* "Search for the correct type" - type of code to handle because of its puzzling and strange. This program
* I have encountered many problems.
*
* Some types of flexible disk (for example, a 360kB 1.2MB floppy disk drive, etc.), 'stretch' for
* Detecting whether a track require special handling. Other parameters should be self-explanatory.

*/
// floppy disk parameters:
// size Size (number of sectors);

--214--
6.8 floppy.c program

// sect The number of sectors per track;

// head Number of heads;

// track Track number;

// stretch To track whether special treatment (flag);


// gap Sector gap length (number of bytes);

// rate Data transmission rate;

// spec1 Parameters (four high step rate, lower four head unloading time).

82 static struct floppy_struct {


83 unsigned int size, sect, head , track , Stretch;
84 unsigned char gap, rate, spec1;
85 } floppy_type [] = {
86 { 0, 0,0, 0,0,0x00,0x00,0x00}, / * No testing * /
87 {720, 9,2,40,0,0x2A, 0x02,0xDF}, / * 360kB PC diskettes * /
88 {2400,15,2,80,0,0x1B, 0x00,0xDF}, / * 1.2 MB AT-diskettes * /
89 {720, 9,2,40,1,0x2A, 0x02,0xDF}, / * 360kB in 720kB drive * /
90 {1440, 9,2,80,0,0x2A, 0x02,0xDF}, / * 3.5 "720kB diskette * /
91 {720, 9,2,40,1,0x23,0x01,0xDF}, / * 360kB in 1.2MB drive * /
92 {1440, 9,2,80,0,0x23,0x01,0xDF}, / * 720kB in 1.2MB drive * /
93 {2880,18,2,80,0,0x1B, 0x00,0xCF}, / * 1.44MB diskette * /
94 };
95 / *
96 * Rate is 0 for 500kb / s, 2 for 300kbps, 1 for 250kbps
97 * Spec1 is 0xSH, where S is stepping rate (F = 1ms, E = 2ms, D = 3ms etc),
98 * H is head unload time (1 = 16ms, 2 = 32ms, etc)
99 *
100 * Spec2 is (HLD << 1 | ND), where HLD is head load time (1 = 2ms, 2 = 4 ms etc)
101 * And ND is set means no DMA. Hardcoded to 6 (HLD = 6ms, use DMA).
102 * /
/*
* The above rate rate: 0 indicates 500kb / s, 1 represents 300kbps, 2 denotes 250kbps.

* Spec1 parameter is 0xSH, where S is the step rate (F-1 millisecond, E-2ms, D = 3ms, etc.),

* H is a head unloading time (1 = 16ms, 2 = 32ms, etc.)


*
* spec2 is (HLD << 1 | ND), wherein the head load HLD is the time (1 = 2ms, 2 = 4ms, etc.)
* ND is not set, indicates the use of DMA (No DMA), hard-coded in the program to 6 (HLD = 6ms, using DMA).
*/
103104 extern void floppy_interrupt (Void);
// system_call.s interrupt the process in the floppy drive label.

105 extern char tmp_floppy_area [1024]; // boot / head.s 132 at line buffer floppy defined.
106107 / *

108 * These are global variables, as that's the easiest way to give
109 * Information to interrupts. They are the data used for the current
110 * Request.
111 * /
/*
* Here are some global variables, because this is the information to interrupt the program the easiest way. They are

* Item data for the current request.

*/
112 static int cur_spec1 = -1;
113 static int cur_rate = -1;
114 static struct floppy_struct * floppy = floppy_type ;
115 static unsigned char current_drive = 0;

--215--
6.8 floppy.c program

116 static unsigned char sector = 0;


117 static unsigned char head = 0;
118 static unsigned char track = 0;
119 static unsigned char seek_track = 0;
120 static unsigned char current_track = 255; // current head where the track number.

121 static unsigned char command = 0;


// Floppy selected logo. Before handling a floppy request items need to first select a floppy drive.

122 unsigned char selected = 0;


123 struct task_struct * wait_on_floppy_select = NULL ;
124
//// deselect the floppy drive. Reset floppy mark selected is selected.

// lower 2 bits digital output register (the DOR) for specifying the selected floppy (0-3 corresponds AD).

125 void floppy_deselect (Unsigned int nr)


126 {
127 if (nr! = ( current_DOR & 3))
128 printk ( ' floppy_deselect: drive not selected \ n \ r ");
129 selected = 0;
130 wake_up (& wait_on_floppy_select );
131 }
132 133 /
*
134 * Floppy-change is never called from an interrupt, so we can relax a bit
135 * Here, sleep etc. Note that floppy-on tries to set current_DOR to point
136 * To the desired drive, but it will probably not survive the sleep if
137 * Several floppies are used at the same time: thus the loop.
138 * /
/*
* floppy-change () is not called from an interrupt routine, so here we can relax, sleep and so on.
* Note floppy-on () will try to set the desired drive current_DOR point, but at the same time using several

* When the floppy disk can not sleep: So at this time can only use round-robin fashion.

*/
//// floppy diskette replace the specified detection conditions. If the disk is replaced returns 1, otherwise it returns 0.

139 int floppy_change (Unsigned int nr)


140 {
141 repeat:
142 floppy_on (Nr); // Start the specified floppy nr (kernel / sched.c, 251).
// If the currently selected floppy drive is not specified floppy nr, and has selected other floppy drive, then let the current task can be interrupted // enter the wait state.

143 while (( current_DOR & 3)! = Nr && selected )


144 interruptible_sleep_on (& wait_on_floppy_select );
// if not currently selected other floppy or current task is awakened, the current floppy is still not designated floppy nr, the circular wait.

145 if (( current_DOR & 3)! = Nr)


146 goto repeat;
// get the digital input value register, if the most significant bit (bit 7) is set, it indicates that the floppy disk has been replaced, this time off the motor and a return exit. // return 0 otherwise shut

down the motor quit.

147 if ( inb ( FD_DIR ) & 0x80) {


148 floppy_off (Nr);
149 return 1;
150 }
151 floppy_off (Nr);
152 return 0;
153 }
154

--216--
6.8 floppy.c program

//// copy the memory buffer block, a total of 1024 bytes.

155 #define copy_buffer (From, to) \


156 __asm ​__ ( " cld; rep; movsl "\
157 :: " c "( BLOCK_SIZE / 4), " S "(( long) (from)), " D "(( long) (to)) \
158 : " cx "," di "," si ")
159
//// setting (initialization) disk DMA channel.
160 static void setup_DMA (Void)
161 {
162 long addr = (long) CURRENT -> buffer; item buffer located in memory location (address) // current request.
163
164 cli ();
// If the buffer memory is above 1M place, then the DMA buffer region is provided in the temporary buffer (tmp_floppy_area) at. // Because the 8237A chip can only be addressed

within the 1M address range. If the disk is write command, you need to take to copy data to the staging area.

165 if (addr> = 0x100000) {


166 addr = (long) tmp_floppy_area ;
167 if ( command == FD_WRITE )
168 copy_buffer ( CURRENT -> buffer, tmp_floppy_area );
169 }
170 / * Mask DMA 2 * / / * 2 * DMA channel shielding /

// port single channel mask register 0x10. Bits 0-1 specify the DMA channel (0--3), Bit 2: 1 for shielding, 0 indicates permission request.

171 immoutb_p (4 | 2,10);


172 / * Output command byte. I do not know why, but everyone (minix, * /
173 / * Sanches & canton) output this twice, first to 12 then to 11 * /
/ * Output command byte. I do not know why, but everyone (minix, * / / * sanches and canton) are output twice, first 12, then 11 * / //
embed the following assembly code to the DMA controller ports 12 and 11 write the way the word (read the disk 0x46, write disk
0x4A).
174 __asm ​__ ( " outb %% al, $ 12 \ n \ tjmp 1f \ n1: \ tjmp 1f \ n1: \ t "
175 "Outb %% al, $ 11 \ n \ tjmp 1f \ n1: \ tjmp 1f \ n1:" ::
176 "A" (( char) (( command == FD_READ )? DMA_READ : DMA_WRITE )));
177 / * 8 low bits of addr * / / * Address Low bits 0-7 * /

// write to DMA channel 2 group / current address register (port 4).


178 immoutb_p (Addr, 4);
179 addr >> = 8;
180 / * Bits 8-15 of addr * / / * Address High bits 8-15 * /

181 immoutb_p (Addr, 4);


182 addr >> = 8;
183 / * Bits 16-19 of addr * / / * Bit * Address 16-19 /
// DMA can only address 1M of memory space in which the high address bits 16-19 into the required page register (Port 0x81).

184 immoutb_p (Addr, 0x81);


185 / * Low 8 bits of count-1 (1024-1 = 0x3ff) * / / * Counter low byte (1024-1 = 0x3ff) * /
// write to DMA channel 2 group / current byte counter value (port 5).
186 immoutb_p (0xff, 5);
187 / * High 8 bits of count-1 * / / * Counter high byte * /
// transmit a total of 1024 bytes (two sectors).
188 immoutb_p (3,5);
189 / * Activate DMA 2 * / / * Open request DMA channel 2 * /
// reset the shielding of the DMA channel 2, DMA2 open request signal DREQ.

190 immoutb_p (0 | 2,10);


191 sti ();
192 }
193
//// output a byte (command or parameter) to the floppy disk controller.

--217--
6.8 floppy.c program

// before sending a byte to the controller, the controller needs to be in the ready state, and data transmission direction is CPU FDC, // so the controller must first read

the status information. This uses the query cycle ways to make appropriate delay.

194 static void output_byte (Char byte)


195 {
196 int counter;
197 unsigned char status;
198
199 if ( reset )
200 return;
// main loop reads the status controller FD_STATUS (0x3f4) state. If the status is STATUS_READY and STATUS_DIR = 0 // (CPU FDC), then the designated

output port to the bytes of data.

201 for (counter = 0; counter <10000; counter ++) {


202 status = inb_p ( FD_STATUS ) & ( STATUS_READY | STATUS_DIR );
203 if (status == STATUS_READY ) {
204 outb (Byte, FD_DATA );
205 return;
206 }
207 }
// If the loop 10,000 times the end can not be transmitted, the reset flag is set, and prints an error message.

208 reset = 1;
209 printk ( ' Unable to send byte to FDC \ n \ r ");
210 }
211
//// read result information FDC execution.

// up to 7 bytes of the result information, stored in reply_buffer [] in. Returns the number of bytes to read the result, if the return value // = -1 indicates an error. Program

processing functions similar manner as described above.

212 static int result (Void)


213 {
214 int i = 0, counter, status;
215
// If the reset flag has been set, then immediately quit.

216 if ( reset )
217 return -1;
218 for (counter = 0; counter <10000; counter ++) {
219 status = inb_p ( FD_STATUS ) & ( STATUS_DIR | STATUS_READY | STATUS_BUSY );
// If the controller is READY state, has no data showing Preferably, it returns the number of bytes read.

220 if (status == STATUS_READY )


221 return i;
// If the controller is the direction of the state flag is set (CPU FDC), is ready, busy, it indicates that data can be read. // then the resulting data is read into the

controller the response result array. Read up MAX_REPLIES (7) bytes.

222 if (status == ( STATUS_DIR | STATUS_READY | STATUS_BUSY )) {


223 if (i> = MAX_REPLIES )
224 break;
225 reply_buffer [I ++] = inb_p ( FD_DATA );
226 }
227 }
228 reset = 1;
229 printk ( ' Getstatus times out \ n \ r ");
230 return -1;
231 }
232
//// floppy disk operation error interrupt function is called. Floppy interrupted by a call handler.

233 static void bad_flp_intr (Void)

--218--
6.8 floppy.c program

234 {
235 CURRENT -> errors ++; // current request item number by 1 error.

// If the current request item number of errors greater than the maximum allowed number of errors, then deselect the current floppy drive, and ends the request item (// buffer zone

contents have not been updated).

236 if ( CURRENT -> errors> MAX_ERRORS ) {


237 floppy_deselect ( current_drive );
238 end_request (0);
239 }
// if the current request is greater than half the maximum entry number of errors allowed number of errors, then the reset flag is set, the need for floppy reset operation, // try again. Otherwise

floppy need to recalibrate it, try again.

240 if ( CURRENT -> errors> MAX_ERRORS /2)


241 reset = 1;
242 else
243 recalibrate = 1;
244 }
245 246 /
*
247 * Ok, this interrupt is called after a DMA read / write has succeeded,
248 * So we check the results, and copy any buffers.
249 * /
/*
* OK, the following interrupt handler is in the DMA read / write call after the success, so that we can check the results,
* And copy the data in the buffer.
*/
//// floppy disk read and write operations interrupt function is called.

It is called (Bottom half) // interrupt processing operation at the end of the floppy disk controller triggered in.

250 static void rw_interrupt (Void)


251 {
// Read result information FDC execution. If the number of bytes returned result is not equal to 7, or status bytes 0, 1 or 2 // error flag is present, then, if the write protect error

message is displayed, the current drive is released, and ends the current request entry. Otherwise, execution error // counting process. Then proceed to the floppy request

entry operation. The meaning of the following states see fdreg.h file. // (0xf8 = ST0_INTR | ST0_SE | ST0_ECE | ST0_NR)

// (0xbf = ST1_EOC | ST1_CRC | ST1_OR | ST1_ND | ST1_WP | ST1_MAM, should be 0xb7) // (0x73 = ST2_CM | ST2_CRC |
ST2_WC | ST2_BC | ST2_MAM)
252 if ( result ()! = 7 || ( ST0 & 0xf8) || ( ST1 & 0xbf) || ( ST2 & 0x73)) {
253 if ( ST1 & 0x02) { // 0x02 = ST1_WP - Write Protected.
254 printk ( ' Drive% d is write protected \ n \ r ", current_drive );
255 floppy_deselect ( current_drive );
256 end_request (0);
257 } Else
258 bad_flp_intr ();
259 do_fd_request ();
260 return;
261 }
// If the current request buffer items located 1M address above, then read the contents of the floppy disk is also placed in the temporary buffer // buffer needs to be copied to the item's

current request (because the DMA can only 1M addressable address range).

262 if ( command == FD_READ && (unsigned long) ( CURRENT -> buffer)> = 0x100000)
263 copy_buffer ( tmp_floppy_area , CURRENT -> buffer);
// release the current floppy drive (do not give up selected), execution of the current term ends request processing: Wake wait until the request items are, waiting wake empty // request free

entry process (if any), from the floppy device requests necklace table To remove this request item. A floppy disk and then continue with other requests // entry operation.

264 floppy_deselect ( current_drive );


265 end_request (1);

--219--
6.8 floppy.c program

266 do_fd_request ();


267 }
268
//// set up the DMA operation and outputs commands and parameters floppy (outputs 1-byte command parameter bytes + 0 ~ 7).

269 inline void setup_rw_floppy (Void)


270 {
271 setup_DMA (); // Initialize the floppy disk DMA channel.

272 do_floppy = rw_interrupt ; // set the floppy disk interrupt call the function pointer.

273 output_byte ( command ); // send command bytes.


274 output_byte ( head << 2 | current_drive ); // Parameter (head number + drive).
275 output_byte ( track ); // Parameter (track number).

276 output_byte ( head ); // Parameter (head number).

277 output_byte ( sector ); // parameters (starting sector number).

278 output_byte (2); / * Sector size = 512 * / // parameters (number of bytes (N = 2) 512 bytes).

279 output_byte ( floppy -> sect); // parameters (number of sectors per track).
280 output_byte ( floppy -> gap); // (sectors interval length).
281 output_byte (0xFF); / * Sector size (0xff when n! = 0?) * /
// parameters (when N = 0, the sector is defined byte length), here useless.

// reset when the flag is set, then proceed to the next floppy operation request.

282 if ( reset )
283 do_fd_request ();
284 }
285 286 /
*
287 * This is the routine called after every seek (or recalibrate) interrupt
288 * From the floppy controller. Note that the "unexpected interrupt" routine
289 * Also does a recalibrate, but does not come here.
290 * /
/*
* This subroutine is called after each seek floppy disk controller (or recalibration) interrupted. note
* "Unexpected interrupt" (unexpected interruption) will perform the recalibration routine operations, but not here.
*/
Function is called during the end //// seek treatment interruption.

// first transmission detector interrupt status command, status information to obtain location information ST0 and track the magnetic head. If the error count is performed // an error

detection process or cancel the operation request entry diskette. Otherwise, set the current track information according to the state variables, and then calls the function //

setup_rw_floppy () Set the floppy disk and outputs the DMA write and read commands and parameters.

291 static void seek_interrupt (Void)


292 {
293 / * Sense drive status * / / * * Drive status detector /
// interrupt status detected transmission command, the command without parameters. Return result message is two bytes: ST0 current track number and the head.

294 output_byte ( FD_SENSEI );


// Read result information FDC execution. If the number of bytes returned result is not equal to 2, or ST0 not seek is finished, the head or track where // (ST1) is not equal

to the set track, an error occurs, the error count detecting process is then performed, then continue floppy // request entry and exit.

295 if ( result ()! = 2 || ( ST0 & 0xF8)! = 0x20 || ST1 ! = seek_track ) {


296 bad_flp_intr ();
297 do_fd_request ();
298 return;
299 }
300 current_track = ST1 ; // set the current track.
301 setup_rw_floppy (); // set up the DMA and diskette operation command and output parameters.

302 }
303

--220--
6.8 floppy.c program

304 / *
305 * This routine is called when everything should be correctly set up
306 * For the transfer (ie floppy motor is on and the correct floppy is
307 * Selected).
308 * /
/*
* This function is (that is after all the information in the floppy motor transport operations are set up properly invoked turned

* And you have selected the correct floppy disk (floppy drive).

*/
//// read and write data transfer function.

309 static void transfer (Void)


310 {
// see if the first parameter is the drive parameters specified drive current, is sent if it is set and the corresponding command drive parameters // parameters (1:

4 high step rate, lower four head unloading time; Parameter 2: head loading time).

311 if ( cur_spec1 ! = floppy -> spec1) {


312 cur_spec1 = floppy -> spec1;
313 output_byte ( FD_SPECIFY ); // send command to set the disk parameters.

314 output_byte ( cur_spec1 ); / * Hut etc * / // send parameters.

315 output_byte (6); / * Head load time = 6ms, DMA * /


316 }
// determines whether the current data transmission rate, if not specified sends the floppy drive is consistent with the specified data transmission rate value // Rate Control Register

(FD_DCR).

317 if ( cur_rate ! = floppy -> rate)


318 outb_p ( cur_rate = floppy -> rate, FD_DCR );
// If the return result information indicates an error, and then call the floppy request function, and return.

319 if ( reset ) {
320 do_fd_request ();
321 return;
322 }
// If the seek flag is zero (no tracking), is set DMA read and write operations and send appropriate commands and parameters, and then returns.

323 if (! seek ) {
324 setup_rw_floppy ();
325 return;
326 }
// otherwise perform seek treatment. Floppy disk interrupt handler function is set to seek an interrupt function calls.

327 do_floppy = seek_interrupt ;


// start track number is not equal to zero if the head seek commands and parameters sent

328 if ( seek_track ) {
329 output_byte ( FD_SEEK ); // send head seek command.
330 output_byte ( head << 2 | current_drive ); // transmission parameters: the current head number + number floppy.

331 output_byte ( seek_track ); // Send Parameters: track number.

332 } Else {
333 output_byte ( FD_RECALIBRATE ); // resend correction command (zero head).
334 output_byte ( head << 2 | current_drive ); // transmission parameters: the current head number + number floppy.

335 }
// If the reset flag is set, then continue with the floppy requested item.

336 if ( reset )
337 do_fd_request ();
338 }
339 340 /
*
341 * Special case - used after a unexpected interrupt (or reset)

--221--
6.8 floppy.c program

342 * /
/*
* For the unexpected interruption (or reset) process - a special case.

*/
//// floppy recalibration interrupt function is called.

// send first detection interrupt status command (no parameters), if the return results show an error, then reset flag is set, otherwise reset again // correction mark. Floppy disk and then

execute the request again.

343 static void recal_interrupt (Void)


344 {
345 output_byte ( FD_SENSEI ); // send detection interrupt status command.

346 if ( result ()! = 2 || ( ST0 & 0xE0) == 0x60) // if the number of results returned is not equal to 2 bytes or command

347 reset = 1; // ends abnormally, the reset flag set.


348 else // reset otherwise recalibration flag.
349 recalibrate = 0;
350 do_fd_request (); // Perform floppy requested item.

351 }
352
//// accident floppy disk interrupt request interrupt function is called.

// send first detection interrupt status command (no parameters), if the return results show an error, then reset flag is set, otherwise it is set to re-// correction mark.

353 void unexpected_floppy_interrupt (Void)


354 {
355 output_byte ( FD_SENSEI ); // send detection interrupt status command.

356 if ( result ()! = 2 || ( ST0 & 0xE0) == 0x60) // if the number of results returned is not equal to 2 bytes or command

357 reset = 1; // ends abnormally, the reset flag set.


358 else // otherwise set recalibration flag.

359 recalibrate = 1;
360 }
361
//// floppy recalibration handler.
// send commands and parameters recalibration, and resets the flag to recalibrate the floppy disk controller FDC.

362 static void recalibrate_floppy (Void)


363 {
364 recalibrate = 0; // Reset recalibration flag.
365 current_track = 0; // The current track number zero.

366 do_floppy = recal_interrupt ; // set the floppy disk interrupt call a function pointer to recalibrate the calling function.

367 output_byte ( FD_RECALIBRATE ); // send the command: recalibration.

368 output_byte ( head << 2 | current_drive ); // add transmission parameters :( head number) current drive letters.
369 if ( reset ) // If the error (the reset flag is set) proceed floppy request.
370 do_fd_request ();
371 }
372
//// floppy disk controller FDC reset interrupt function is called. In the floppy disk interrupt handler calls.

// first transmission detection interrupt status command (without parameters), then the readout results of bytes returned. Then send commands to set parameters // floppy and related

parameters, the last call execution floppy request again.

373 static void reset_interrupt (Void)


374 {
375 output_byte ( FD_SENSEI ); // send detection interrupt status command.

376 (Void) result (); // read byte command execution result.

377 output_byte ( FD_SPECIFY ); // send command to set the floppy drive parameters.

378 output_byte ( cur_spec1 ); / * Hut etc * / // Send parameters.


379 output_byte (6); / * Head load time = 6ms, DMA * /
380 do_fd_request (); // Call floppy execution request.

--222--
6.8 floppy.c program

381 }
382 383 /
*
384 * Reset is done by pulling bit 2 of DOR low for a while.
385 * /
/ * Reset by the FDC digital output register (the DOR) Bit 2 0 achieved while * / //// reset the floppy disk
controller.
386 static void reset_floppy (Void)
387 {
388 int i;
389
390 reset = 0; // reset flag set to zero.
391 cur_spec1 = -1;
392 cur_rate = -1;
393 recalibrate = 1; // recalibration flag.
394 printk ( ' Reset-floppy called \ n \ r "); // reset operation information display performed diskette.

395 cli (); // disable interrupts.

396 do_floppy = reset_interrupt ; // set the floppy disk interrupt handler function call.
397 outb_p ( current_DOR & ~ 0x04, FD_DOR ); // reset operation of the floppy disk controller FDC.

398 for (i = 0; i <100; i ++) // air operations, delay.


399 __asm ​__ ( " nop ");
400 outb ( current_DOR , FD_DOR ); // re-boot floppy controller.
401 sti (); // open the interruption.

402 }
403
//// floppy start timer interrupt function is called.

// first check digital output register (DOR), so as to select the specified drive current. Then call // function to perform read and write transfers floppy transfer ().

404 static void floppy_on_interrupt (Void)


405 {
406 / * We can not do a floppy-select, as that might sleep. We just force it * /
/ * We can not be set arbitrarily chosen floppy drive, as doing so may cause the process to sleep. We're just forcing it to choose * /

407 selected = 1; // set the current drive flag is selected.


// If the drive letter is different from the current digital output register DOR is, it is necessary to re-set the current drive DOR current_drive.

// timer tick time delayed by 2, then the transfer function calls to read and write a floppy disk transfer (). Otherwise called directly floppy disk read and write transfer function.

408 if ( current_drive ! = ( current_DOR & 3)) {


409 current_DOR & = 0xFC;
410 current_DOR | = current_drive ;
411 outb ( current_DOR , FD_DOR ); // output register DOR to the digital output current.

412 add_timer (2,& transfer ); // add a timer and execute the transfer function.

413 } Else
414 transfer (); // perform reading and writing floppy transfer function.

415 }
416
//// floppy disk write request entries handler. //

417 void do_fd_request (Void)


418 {
419 unsigned int block;
420
421 seek = 0;
// If the reset flag is set, a reset operation is performed floppy disk, and returns.

--223--
6.8 floppy.c program

422 if ( reset ) {
423 reset_floppy ();
424 return;
425 }
// If recalibration flag is set, then re-execute the floppy correction operation and return.

426 if ( recalibrate ) {
427 recalibrate_floppy ();
428 return;
429 }
// Check the legitimacy of the item request, Ruoyi not request entry to exit (see blk.h, 127).

430 INIT_REQUEST ;
// the type of floppy diskette request entry structure of the device number (MINOR (CURRENT-> dev) >> 2) to obtain a floppy disk as an index into the parameter block.

431 floppy = ( MINOR ( CURRENT -> dev) >> 2) + floppy_type ;


// If the current drive is not requested item specified drive, the flag is set seek, it indicates the need for a seek operation. // set then request entry

device is a current driver.

432 if ( current_drive ! = CURRENT_DEV )


433 seek = 1;
434 current_drive = CURRENT_DEV ;
// set the write starting sector. Because each block is read unit (1 into two sectors), it needs to start sector number of at least smaller than the total disk sectors @ 2 sectors. Otherwise,

the end of the second floppy disk requested item, a request to perform the next item.

435 block = CURRENT -> sector ; // get current item request floppy start sector number block.

436 if (block + 2> floppy -> size) { // If block + 2 is greater than the total number of disk sectors are

437 end_request (0); // end of this floppy requested item.

438 goto repeat;


439 }
// find the corresponding sector on the track number, head number, track number, track number search (for floppy disk reading different formats).

440 sector = Block% floppy -> sect; // start sector modulo the number of sectors per track, the track sector number obtained.

441 block / = floppy -> sect; // rounded start sector number of sectors per track to give the starting track number.

442 head = Block% floppy -> head ; // start track number modulo of the number of heads, the head number to obtain operation.

443 track = Block / floppy -> head ; // starting track number for the number of heads rounding operations to obtain the track number.

444 seek_track = track << floppy -> stretch; // corresponding to the type of the disk drive is adjusted to obtain tracking number.

// If the seek current head number of the track where different, the flag is set to require a seek seek.

445 if ( seek_track ! = current_track )


446 seek = 1;
447 sector ++; // the actual disk sector counter is counting from 1.

448 if ( CURRENT -> cmd == READ ) // If the request entry is a read operation, a read command code is set to a floppy disk.

449 command = FD_READ ;


450 else if ( CURRENT -> cmd == WRITE ) // If the request is a write operation key, diskette write command code is set.

451 command = FD_WRITE ;


452 else
453 panic ( ' do_fd_request: unknown command ");
// add a timer to the system. To be able to read and write to the floppy drive, the drive motor need to start and reach normal operating speed. // This will
take some time. Thus utilized herein ticks_to_floppy_on () calculates start delay time, a timer is set. // when the regular time, the function is called
floppy_on_interrupt ().
454 add_timer ( ticks_to_floppy_on ( current_drive ), & floppy_on_interrupt );
455 }
456
//// floppy disk system initialization.

// Set the request handler diskette block device (do_fd_request ()), and set the diskette interrupt gate (int 0x26, // hardware interrupt request signal corresponding to IRQ6), and then

cancel the interrupt mask signal, which allows the transmission floppy disk controller FDC interrupt request signal.

457 void floppy_init (Void)


458 {
459 blk_dev [ MAJOR_NR ] .Request_fn = DEVICE_REQUEST ; // = do_fd_request ().

--224--
6.8 floppy.c program

460 set_trap_gate (0x26, & floppy_interrupt ); // set the floppy disk interrupt gate int 0x26 (38).
461 outb ( inb_p (0x21) & ~ 0x40,0x21); // reset interrupt request mask bit floppy disk, the floppy disk controller

allows // send an interrupt request signal.

462 }
463

6.8.3 Other Information

6.8.3.1 Floppy disk drive device number

in Linux , The major number of floppy 2 Minor number = TYPE * 4 + DRIVE ,among them DRIVE for 0-3 , Respectively floppy A , B , C or D ; TYPE Is the type

of floppy, 2 Show 1.2M Floppy drive, 7 Show 1.44M Floppy drive, that is floppy.c in 85

Line defines diskette type ( floppy_type [] ) Array index value, see Table 6-11 Fig.

table 6-11 Floppy Disk Drive

Types of Explanation

0 No need to.

1 360KB PC Floppy drive.

2 1.2MB AT Floppy drive.

3 360kB in 720kB Used within the drive.

4 3.5 "720kB floppy disk.

5 360kB in 1.2MB Used within the drive.

6 720kB in 1.2MB Used within the drive.

7 1.44MB Floppy drive.

For example, because 7 * 4 + 0 = 28 ,and so / dev / PS0 (2,28) Refers 1.44MA Driver, which is a device number 0x021c . Similarly / dev / at0 (2,8) Refers 1.2MA

Driver, which is a device number 0x0208 .

6.8.3.2 Floppy disk controller

Programmed floppy disk controller is relatively cumbersome. For access to programming 4 Ports, respectively corresponding to one or more registers. for 1.2M

The table has a floppy disk controller 6-12 Some port.

table 6-12 Floppy disk controller port

I / O port Reading and writing of Register Name

0x3f2 just write Digital Output Register ( DOR ) (Digital Control Register)

0x3f4 Read-only FDC Main Status Register ( STATUS)

0x3f5 Read / Write FDC Data register ( DATA)

Read-only Digital input register ( DIR )


0x3f7
just write Disk Control Register ( DCR) ( A transmission rate control)

Digital Output DOR (Digital control port) is a 8 Bit register which controls the drive motor is turned on, the drive selection, start / reset FDC As well as enable /

disable DMA And interrupt request. Each bit of this register See Table 6-13 Fig.

table 6-13 Digital Output Register Definition

Bit Name Explanation

--225--
6.8 floppy.c program

7 MOT_EN3 Start Floppy D motor: 1- start up; 0- shut down.

6 MOT_EN2 Start Floppy C motor: 1- start up; 0- shut down.

5 MOT_EN1 Start Floppy B motor: 1- start up; 0- shut down.

4 MOT_EN0 Start Floppy A motor: 1- start up; 0- shut down.

3 DMA_INT allow DMA And interrupt request; 0- Ban DMA And interrupt request.

2 RESET Allowing the floppy disk controller FDC jobs. 0- Reset FDC .

1 DRV_SEL1 0

DRV_SEL0 00-11 For selecting a floppy disk drive AD .

FDC The status register is a main 8 Bit register is used to reflect the floppy disk controller FDC And a floppy disk drive FDD The basic state. Typically, CPU to FDC Before

sending a command or from FDC Before obtaining the operation result, the master must read the status register bits, to discriminate the current FDC Data register is ready and

determines the direction of data transfer. Table 6-14 Fig.

table 6-14 FDC Main state controller MSR definition

Bit Name Explanation

7 RQM Data port ready: Controller FDC Data register is ready.

6 DIO Transmission direction: 1- FDC CPU ; 0- CPU FDC

5 NDM non- DMA the way: 1- non- DMA the way; 0- DMA the way

4 CB Controller busy: FDC It is in command execution busy

3 DDB Floppy D busy

2 DCB Floppy C busy

1 DBB Floppy B busy

0 DAB Floppy A busy

FDC A plurality of registers corresponding to the data port (write only type parameter register and the command register, read-only result register), but any one time, only

one appears in the data port register 0x3f5 . When accessing the write-only register, the main state control DIO Direction bit must be 0 ( CPU FDC ), And vice versa when the read

access type register. When reading the results only in FDC After reading the results considered busy, usually resulting data Up 7 Bytes.

Data input register ( DIR ) Only bits 7 ( D7 ) Floppy effectively used to represent the state of the disk replacement. The remaining seven for a hard disk controller interface.

Disk Control Register ( DCR) Rate selection for data transmission disc for use on different types of drives. Use only low 2 Bit ( D1D0 ),

00 - 500kbps , 01 - 300kbps , 10 - 250kbps .


Linux 0.11 The kernel, the data transmission between the driver and the floppy disk by DMA Controller implemented. Before the read and write operations, need to initialize DMA

Controller, floppy disk controller and programming. for 386 compatible PC , Floppy controller uses hardware interrupts IR6 (Corresponding to the Interrupt Descriptor 0x26 ), And

using DMA Channel controller 2 . related DMA Control process see later section.

6.8.3.3 The floppy disk controller command

The floppy disk controller can accept a total of 15 Command. Each command through three stages: the command phase, implementation phase and the results stage.

Command stage CPU to FDC Send command byte and parameter bytes. The first byte of each command byte is always the command (command code). Thereafter followed 0--8 Byte

parameters.

--226--
6.8 floppy.c program

The implementation phase is FDC Perform the operation specified command. In the implementation phase CPU That without intervention, usually through FDC It issues an

interrupt request to know the end of the command execution. in case CPU dispatched FDC Command is transmitted data, FDC You can interrupt or DMA Conducted. Interrupt each

transfer 1 byte. DMA Way in DMA Controller Management, FDC Transmitting data to and from memory until all of the data transferred. at this time DMA Controller will signal the

transfer byte count termination FDC Finally, the FDC Issues an interrupt request signal inform CPU The implementation phase is completed.

The result is a stage CPU Read FDC Data register return value, to thereby obtain FDC The results of the command execution. Return result data length 0--7 byte. For data

command does not return results, should the FDC Interrupt Status command transmission detecting operation state is obtained.

due to Linux 0.11 Floppy disk driver use only 6 Command, so the commands used here only for description.

1. Recalibrate command ( FD_RECALIBRATE )

This command is used to allow the head to return 0 Track. Commonly used for the head is positioned in the floppy recalibration operation error. Its command code is

0x07 Parameter is specified drive number ( 0-3 ).

The command has no result phase, the program needs to get through the results of the command execution "detection interrupt state." Table 6-15 Fig.

table 6- 15 Again school positive Life make( F D _RECA LIBRATE )

stage sequence D7 D6 D5 D4 D3 D2 D1 D0 Explanation

0 0 0 0 0 0 1 1 1 Recalibrate command code: 0x07


command 1
0 0 0 0 0 0 US1 US2 Drive letter

carried out The head is moved to 0 Tracks

result no. Need to use the command to get the results.

2. Head seek command ( FD_SEEK )

This command allows the drive the selected head is moved to the specified track. The first 1 Parameter specifies the drive and head number, position 0-1 Is the drive

number, position 2 A head number, other unwanted bits. The first 2 Parameter specifies the track number.

The command also inconclusive stage, through the implementation of the program need to "detect interrupt status" to get the results of the command. Table 6-16

Fig.

table 6 - 16 magnetic Head hunt Road command( FD_ SEEK )

stage sequence D7 D6 D5 D4 D3 D2 D1 D0 Explanation

0 0 0 0 0 1 1 1 1 Head seek command code: 0x0F

command 1 0 0 0 0 0 HD US1 US2 Head number, a drive letter.

2 C Track number.

carried out The head is moved to the specified track.

result no. Need to use the command to get the results.

3. Sector data read command ( FD_READ )

This command is used to read the specified sector position from the disk, the DMA Control is transferred to system memory. Every time one sector is read, the parameters 4

( R ) Is automatically added 1 To continue to read the next sector until DMA The controller sends a signal to terminate the transfer count to the floppy disk controller. This command is

usually started after the head has head seek command is executed at the specified track. Table 6-17 Fig.

Return result, the track number C And sector number R It is the current head location. Since the start sector number of a sector after reading R Automatic gain 1 Therefore

results R Value is next unread sector number. If just reading the last sector on a track (i.e. EOT ), The track number will increase 1 ,and R Reset the value 1 .

--227--
6.8 floppy.c program

table 6- 1 7 Read Sector number According to life make ( FD _READ )

Phase sequence D7 D6 D5 D4 D3 D2 D1 D0 Explanation

0 MT MF SK 0 0 1 1 0 Read Order Code: 0xE6 ( MT = MF = SK = 1 )

1 0 0 0 0 0 0 US1 US2 Drive letter.

2 C Track number

3 H Head number

command 4 R Start sector number

5 N Sector bytes

6 EOT The maximum number of sectors on a track

7 GPL Length of the interval between sectors ( 3 )

8 DTL N = 0 When the number of bytes designated sector

carried out Data transfer from the disk to the system

1 ST0 Status byte 0

2 ST1 Status byte 1

3 ST2 Status byte 2

result 4 C Track number

5 H Head number

6 R Sector Number

7 N Sector bytes

among them MT , MF with SK Meaning are as follows:

MT It represents a multi-track operation. MT = 1 Representation allows continuous operation of the two heads on the same track.

MF It represents the recording mode. MF = 1 Selected express MFM Recording mode, otherwise it is FM Recording.

SK Skip delete flag indicating whether there are sectors. SK = 1 It means skip. Returns the status byte ST0 , ST1 with ST2 Meaning are shown in

Table 6-18 ,table 6-19 And Table 6-20 Fig.

table 6-18 Status byte 0 ( ST0 )

Place name Explanation

76
ST0_INTR Cause of the interruption. 00 - Command normal end; 01 - Command ends abnormally;
10 - Command is invalid; 11-- Floppy disk drive state changes.

5 ST0_SE Seek operation or recalibrate the end of the operation. ( Seek End )

4 ST0_ECE Error checking devices (track zero error correction). ( Equip. Check Error )

3 ST0_NR Floppy drive is not ready. ( Not Ready )

2 ST0_HA Head address. Head number interrupt. ( Head Address )

10 Select the drive number (an interrupt occurs drive letter). ( Drive Select )
ST0_DS
00--11 Respectively drive 0-3 .

table 6-19 Status byte 1 ( ST1 )

Place name Explanation

7 ST1_EOC Access to more than the maximum sector number on the track EOT . ( End of Cylinder )

6 Unused( 0 ).

5 ST1_CRC CRC Checksum error.

--228--
6.8 floppy.c program

4 ST1_OR Data transmission timeout, DMA Controller failure. ( Over Run )

3 Unused( 0 ).

2 ST1_ND The specified sector was not found. ( No Data - unreadable )

1 ST1_WP Write-protected. ( Write Protect )

0 ST1_MAM Sector address mark not found ID AM . ( Missing Address Mask )

table 6-20 Status byte 2 ( ST2 )

Place name Explanation

7 Unused( 0 ).

6 ST2_CM SK = 0 When reading data encountered delete flag. ( Control Mark = deleted )

5 ST2_CRC Sector data field CRC Checksum error.

4 ST2_WC Sector ID Track number information C It does not match. ( Wrong Cylinder )

3 ST2_SEH Search (scanning) conditions are met. ( Scan Equal Hit )

2 ST2_SNS The search condition does not meet the requirements. ( Scan Not Satisfied )

1 ST2_BC Sector ID Track number information C = 0xFF , Track bad. ( Bad Cylinder )

0 ST2_MAM Sector data flag is not found DATA AM . ( Missing Address Mask )

4. Sector data write command ( FD_WRITE )

This command is used to data in memory to disk. in DMA The transmission mode, the floppy disk controller data memory specified serially written to disk sectors. Complete

each sector, start sector number is automatically increased 1 And continue to write a sector until the floppy controller receives DMA Count termination signal of the controller. Table 6-21

Shown, wherein the same meaning as the abbreviated name and the read command.

table 6-21 write fan Area number According to life make ( FD _WRITE )

Phase sequence D7 D6 D5 D4 D3 D2 D1 D0 Explanation

0 MT MF 0 0 0 1 0 1 Write Data command code: 0xC5 ( MT = MF = 1 )

1 0 0 0 0 0 0 US1 US2 Drive letter.

2 C Track number

3 H Head number

command 4 R Start sector number

5 N Sector bytes

6 EOT The maximum number of sectors on a track

7 GPL Length of the interval between sectors ( 3 )

8 DTL N = 0 When the number of bytes designated sector

carried out Data transfer from the system to disk

1 ST0 Status byte 0

2 ST1 Status byte 1

3 ST2 Status byte 2

result 4 C Track number

5 H Head number

6 R Sector Number

7 N Sector bytes

5. Detection Interrupt Status Command ( FD_SENSEI )

--229--
6.8 floppy.c program

After sending the command floppy disk controller will immediately return to the normal results 1 with 2 (Ie state ST0 In which the track number and the head PCN ). They state

after execution of a command on the controller. Usually at the end of a command to be executed CPU Interrupt signals. For sector read, write track, write delete flag, reading

identification field, and formatting commands and scanning non- DMA Command transmission mode due to interrupt can be known directly from the interrupt flag of the main reasons

for the status register. For the driver changes the ready signal, a seek and re-calibration (zero return channel head) caused interrupted, because there is no return a result, it is

necessary to utilize the command execution controller reads the state information of the command. Table 6-22 Fig.

table 6 -twenty two Detect in Break shape State life make ( FD _SENSEI )

Phase sequence D7 D6 D5 D4 D3 D2 D1 D0 Explanation

command 0 0 0 0 0 1 0 0 0 Detection interrupt command code status: 0x08

carried out

1 ST0 Status byte 0


result 2
C Track number where the head

6. Drive parameters setting command ( FD_SPECIFY )

This command is used to set the initial value of the internal timer three floppy disk controller, and selects a transmission mode, i.e., the driving motor step rate ( STR ), The

head loading / unloading ( HLT / HUT ) Time and whether to adopt DMA Information way to transfer data into the floppy disk controller. Table 6-23 Fig.

table 6- twenty three Assume set drive Actuator Ginseng The number of commands ( F D_SPECIFY )

Phase sequence D7 D6 D5 D4 D3 D2 D1 D0 Explanation

0 0 0 0 0 0 0 1 1 Set the parameters of the command code: 0x03

command 1 SRT (unit 2ms ) HUT (unit 32ms ) The motor step rate, the head unloading time

2 HLT (unit 4ms ) ND Head load time, non- DMA the way

carried out Set controller, interrupt does not occur

result no no

6.8.3.4 Floppy Disk Controller Programming

in PC Machine, commonly used with the floppy disk controller NEC PD765 or Intel 8287A Compatible chip, for example, Intel of 82078 . Since a driver diskette complicated,

so for the following more detailed description of such programming is the floppy disk controller chips.

A typical operation of the control disk include not only wait for the controller to send commands and returns the results, the floppy disk drive is a low-level operations, it

needs to perform its program interference conditions at different stages.

◆ interactive command with the results of phase

Before being sent to the floppy disk controller in the above-described operation command or parameter, you must first query the master controller status register ( MSR ), In

order to know the drive and direction of data transfer ready state. Floppy disk driver uses a output_byte (byte) Function to specifically implement the operation. The function is the

equivalent diagram shown in Figure 6-6 Fig.

This function loops until the master state data port ready flag register RQM for 1 And direction signs DIO Yes 0 ( CPU FDC ), Then the controller had been ready to accept

commands and parameters bytes. From timeout counting function loop, to cope with the case where the controller does not respond. This cycles the driver would be provided 10000

Times. The choice of the number of cycles required careful to avoid making incorrect program timeout judgment. in Linux Kernel version 0.1x to 0.9x Often encounter the need to

adjust the number of cycles of this problem, because at that time people used PC Machine running speeds vary greatly ( 16MHz - 40MHz ), The actual delay cycle is also generated

a great difference. This can be seen early Linux Mailing list of many articles. To solve this problem, it is best to use the system hardware clock

--230--
6.8 floppy.c program

Generating a delay value of fixed frequency.

Results phase controller for reading the result of the byte string, also needed to send a command the same operation, but this time the direction of data transmission

requirements are set state flag ( FDC CPU ). This procedure is a function of the corresponding result () . This function reads the status byte result stored in the reply_buffer [] Byte

array.

Initialization Delay Count

read status register MSR

Y
MSR = 10XXXXXXb main

N Byte write data register

Count-up value

return
N
exceeds the set?

Y
Timeout error count

Map 6-6 Sending a command byte to the floppy disk controller or parameters

◆ floppy disk controller initialization

Initializing operation of the floppy disk drive controller includes appropriate parameters in the controller is reset. The controller is reset operation of the digital output

register means DOR Bit 2 (start up FDC Flag) 0 Then set 1 . After reset the machine, "specify drive parameters" command SPECIFY The value of the set is no longer valid, it is

necessary to re-establish. in floppy.c Program, reset operation function

reset_floppy () And interrupt handling C function reset_interrupt () in. Before a function for modifying DOR Bits 2 , So that the controller is reset, the function to be used after a reset

controller SPECIFY Command to re-establish a drive parameter controller. In the data transmission preparation phase, if it is judged from the actual disk size different, still

transfer function transfer () At the beginning of their separate re-set.

After reset the controller, the digital control registers should also DCR Sends the specified transmission rate value, to reinitialize the data transmission rate. If the machine

to perform a reset operation (e.g., hot start), the data transmission rate becomes the default value 250Kpbs . However, by the digital output register DOR Issued to the controller

reset operation does not affect the data transmission rate setting.

◆ drive head seek and recalibrate

Drive recalibrate ( FD_RECALIBRATE ) And head seek ( FD_SEEK) Two head positioning command. Re-correction command to zero so that the head is moved track, and the

head seek command allows the head is moved to the specified track. The two head positioning command with typical read / write command is different, because they are no results

stage. Once one of the two command is issued, the controller will immediately be in the main status register ( MSR ) Return to the ready state, and after performing head positioning

operation table form. After the positioning operation, the controller will generate an interrupt to request the service. At this point it should send a "detector interrupt status" command

to end the interruption state and the read positioning operation. And the drive motor is a direct enable signal from the Digital Output Register ( DOR ) Control, and therefore, if the

drive or motor has not started, then write DOR

The operation must be carried out before issuing positioning commands. Figure flowchart 6-7 Fig.

--231--
6.8 floppy.c program

DOR
start the motor

Transmission or drive recalibrate

Seek command

Wait for interrupt

Interrupt routine part


Send detect interrupt status command

ST0 and track number read result PCN

N
Status?

Y select driver and by


Seek failed
Seek complete

Map 6-7 Recalibration seek operation and

◆ data read / write operation

Data read or write operation requires several steps to complete. First, the drive motor need to turn on, and the head is positioned to the correct track, then initialize DMA Controller,

and finally send the data read or write command. In addition, the need to develop treatment options when an error occurs. Typical operation flow chart shown in Figure 6-8 Fig.

--232--
6.8 floppy.c program

DOR by starting the drive motor and

Setting the data transmission rate by DCR

Recalibrate

N
Motor starting time> 0.5s?

Y
DMA controller initialization

Send read or write command

Initialization timeout counter

Y
Counter overtime? failed controller timeout error

N
N
Detected a controller interrupt? Read / write cycles> 3 times?

Results Read status byte Recalibrate

N NN
Counter overtime? Seek retry> 3

Y YY

Read / write operation is complete Read / write operation

Map 6-8 Data read / write operation flowchart

Prior to the disk data transfer, disk drive motor must first reach normal operating speed. For most 3 ½ inch floppy drive is concerned, this start-up time

takes about 300ms ,and 5 ¼ inch floppy drive takes about 500ms . in floppy.c This program will become a start-up delay time setting 500ms .

After starting the motor, it is necessary to use a digital control register DCR Disk media provided with the current data transfer rate matching. If an implicit seek ways not

open, then you need to send a seek command FD_SEEK , The head is positioned to the correct track. At the end of the seek operation, the head takes some place (load) time. For

most drivers, this minimum delay time required 15ms . When using an implicit tracking mode, then you can use "specify drive parameters" command specifies the head loading time

( HLT ) To determine the minimum time the head in place. In the data transfer rate of e.g. 500Kbps Under the circumstances, if HLT = 8 , The effective time of the head in place 16ms .

Of course, if the head is already in place on the right track, there is no need to put in place to ensure that this time.

Then DMA Controller initialization operation, write command is also executed immediately. Typically, after completion of the data transfer, DMA The controller will issue a

terminal count ( TC ) Signal, then the floppy disk controller will complete the current data transfer and an interrupt request signal, indicating that the operation has reached the stage

results. If an error occurs during the operation or the last sector of the track number is equal to the last sector ( EOT ), Then the floppy disk controller will immediately enter the

stage results.

According to the above flowchart, if errors are found in the reading result of the status byte will reinitialize by DMA Controller, and then try to re-start performing a data read

or write command. Persistent error usually indicates a seek operation and did not let the head reaches the specified track, this time should be repeated recalibration of the head,

and the seek operation is performed again. Thereafter, or if an error, then the final write operation failed controller will report to the driver.

◆ disk format operation

--233--
6.8 floppy.c program

Linux 0.11 Although not implemented in the kernel of the floppy disk format operation, but as a reference, the disk format operation is here briefly described. During the

disk format operation comprises the head is positioned on each track, and creates a data field consisting of a (field 4 ) Fixed format field.

After the motor is started and set the correct data transfer rate, the magnetic head returns the zero track. At this time, the disk needs 500ms Reach normal operating speed

and stability of delay time.

Built on the disk during operation format identifier field ( ID Field) is in the implementation phase by the DMA Controller. DMA The controller is initialized to be provided for

each track sector identification field ( C ),magnetic head( H ), Sector number ( R ) And the value of the sector byte. For example, for each track having 9 Sectors of the disk, the size of

each sector is 2 ( 512 Bytes), if the magnetic head 1 Format Track 7 Then

DMA The controller should be programmed to transmit 36 Bytes of data ( 9 Sector x Per sector 4 Bytes), the data field should be: 7,1,1,2 ,

7,1,2,2 , 7,1,3,2 , ..., 7,1,9.2 . Because during the formatting command, the data floppy disk controller provides direct identification field will be recorded on the disk, the content data

may be arbitrary as. So some people take advantage of this feature to prevent the disk copy protection.

After each head on a track format operation have been performed, you need to be executed before a seek operation so that the head moves on to the next track, and the

format operation is repeatedly performed. Because the "Format Track" command does not contain implicit seek operation, the seek command must use SEEK . Similarly, the

magnetic head in place of the previously discussed time also set after each seek.

6.8.3.5 DMA Controller Programming

DMA ( Direct Memory Access) Yes " Direct memory access " abbreviation of. DMA The main function of the controller is to enhance the performance of the system by allowing

the external device data directly with memory transfer. It is generally made on the machine Intel 8237 Chip or a compatible chip. By DMA The controller is programmed data transfer

between peripherals and memory are not capable CPU Conducted under controlled conditions. Therefore, during the data transfer, CPU You can do other things. DMA Controller

transmits data during operation is as follows:

1 . initialization DMA Controller.

Program by DMA Controller port its initialization. The operations include: ① to DMA The controller transmits a control command; ② Start address memory transfer; ③ Data

length. Sending commands specified use for transmission DMA Channel, is transmitted to the peripheral memory (write) data transfer to the memory or peripheral, or a

single-byte transmission batch (block) transmission. for PC Machine, a floppy disk controller designated for use DMA aisle 2 . in Linux 0.11 Kernel, a floppy disk driver using a

single byte transmission mode. due to

Intel 8237 Only chip 16 Address pins (wherein 8 In combination with the root data line), and therefore can only address 64KB Memory space. In order to make it

accessible 1MB Address space, DMA A controller uses the page register 1MB Memory is divided into 16 Pages to operate, see Table 6-24 Fig. Thus the transmission must

be converted to the starting address of the memory in which the DMA Page offset address value of the page. Each time data transfer can not exceed the length of the 64KB .

table 6-24 DMA Page corresponding memory address range

DMA page Address range ( 64KB )

0x0 0x00000 - 0x0FFFF

0x1 0x10000 - 0x1FFFF

0x2 0x20000 - 0x2FFFF

0x3 0x20000 - 0x3FFFF

0x4 0x20000 - 0x4FFFF

0x5 0x20000 - 0x5FFFF

0x6 0x00000 - 0x6FFFF

0x7 0x00000 - 0x7FFFF

0x8 0x10000 - 0x8FFFF

0x9 0x20000 - 0x9FFFF

4 Explanatory information on the disk format, previously filed are translated into the field. In fact, for speaking programmers, which translated into a field or fields may be more pleasing to the ear of some. ☺

--234--
6.8 floppy.c program

0xA 0x20000 - 0xAFFFF

0xB 0x20000 - 0xBFFFF

0xC 0x20000 - 0xCFFFF

0xD 0x00000 - 0xDFFFF

0xE 0x00000 - 0xEFFFF

0xF 0x10000 - 0xFFFFF

2 . data transmission

After initialization is complete, to DMA The controller mask register set, open DMA aisle 2 ,thereby DMA The controller starts data transmission.

3 . End of Transmission

When the data transfer is complete all the required transmission, DMA Controller will generate an "operation complete" ( EOP ) Signal is sent to a floppy disk

controller. At this time, the floppy disk controller to perform operations: turn off the drive motor and CPU Transmitting an interrupt request signal.

in PC / AT Machine, DMA The controller has 8 Separate channels may be used, after which 4 Channels are 16 Bit. The floppy disk controller designated for use DMA aisle

2 . It must first be set before using a channel. This involves the operation of three ports, namely: page register port (offset) port address register and data count register ports.

due to DMA Register is 8 Bits, and the address and count values ​are 16 Bit, so each needs to be sent twice. Low byte sent first, then the high byte transmitted. Each channel

corresponding to port address table 6-25 Fig.

table 6-25 DMA Each channel used page Surface, and the address count register ports

DMA aisle Page register address register count register

0 0x87 0x00 0x01

1 0x83 0x02 0x03

2 0x81 0x04 0x05

3 0x82 0x06 0x07

4 0x8F 0xC0 0xC2

5 0x8B 0xC4 0xC6

6 0x89 0xC8 0xCA

7 0x8A 0xCC 0xCE

For the usual DMA Applications, there 4 Commonly used for controlling the registers DMA State controller. These are the command register, the register request,

a single mask register, and a mode register clears trigger byte pointer. Table 6-26 Fig. Linux 0.11 The kernel uses a table shaded 3 Port registers ( 0x0A, 0x0B, 0x0C ).

table 6-26 DMA Programming Frequently used DMA register

Port Address
name
(aisle 0-3 ) (aisle 4-7 )

Command register 0x08 0xD0

Request register 0x09 0xD2

Single Mask Register 0x0A 0xD4

Mode register 0x0B 0xD6

Clear has a trigger 0x0C 0xD8

--235--
6.8 floppy.c program

Command register for specifying DMA The controller chip operating requirements, set DMA The overall state of the controller. It is usually no need to change it after the

startup initialization. in Linux 0.11 After the kernel, floppy disk drivers directly use the Power ROM BIOS The set value. For reference, the meaning of each bit are listed here

command register, see Table 6-27 Fig. (At the port read, the content is obtained DMA

The controller status register information)

table 6-27 DMA Format command register

Place Explanation

7 DMA Peripheral response signal DACK : 0-DACK Active low; 1-DACK Active high.

6 Peripheral request DMA signal DREQ : 0-DREQ Active low; 1-DREQ Active high.

5 Write mode selection: 0- After selecting the write-behind; 1- Select Extended to write; X- If the bit 3 = 1 .

4 DMA Channel priority mode: 0- Fixed priority; 1- Rotary priority.

3 DMA Cycle Selection: 0- Normal timing period ( 5 ); 1- Compression timing period ( 3 ); X- If the bit 0 = 1 .

2 Open DMA Controller: 0- It allows the controller to work; 1- Prohibit controllers work.

1 aisle 0 Address hold: 0- Prohibition channel 0 Address hold; 1- It allows the channel 0 Address hold; X- If the bit 0 = 0 .

0 Memory transmission: 0- Memory-to-memory transmission is prohibited; 1- Mode allows the memory to memory transfer.

Peripheral request register for recording the channel signal requesting service DREQ . Each channel corresponds to one. when DREQ When the position corresponding to

the effective 1 , when DMA The position will be made in response to the controller 0 . If you do not use DMA Request signal DREQ Pin, may be provided directly by the corresponding

channel request bit to request programming DMA Service controller. in PC Machine, a floppy disk controller DMA

Channel controller 2 Direct request signal DREQ Connections, so Linux There is no need for the kernel register operation. For reference, here byte format requested

channel or service listed in Table 6-28 Fig.

table 6-28 DMA The meaning of each bit in the request register

Place Explanation

7-3 No need to.

2 Mask flag. 0 - Request bit; 1 - Request bit is reset (set 0 ).

10
Channel selection. 00-11 Were selected channel 0-3 .

Single-port register mask 0x0A (for 16 Bit channel is 0xD4 ). A Channel is masked, it refers to the use of the peripheral channel emitted DMA Request signal DREQ Can

not get DMA The controller's response, therefore, can not let DMA The controller operates the channel. Each bit of this register See Table 6-29 Fig.

table 6-29 DMA Each mask register single bit meaning

Place Explanation

7-3 No need to.

2 Mask flag. 1 - Masking the selected channel; 0 - Open the selected channel.

10
Channel selection. 00-11 Were selected channel 0-3 .

It is used to specify a mode register DMA Operation mode channel. in Linux 0.11 Kernel, which uses the read ( 0x46 ) And write ( 0x4A ) In two ways.

The meaning you register Table 6-30 Fig.

--236--
6.8 floppy.c program

table 6-30 DMA The meaning of each bit in the mode register

Place Explanation

76 Select transmission.

00- Request mode; 01- Single-byte pattern; 10- Byte block mode; 11- A series mode.

5 Address changes in the way. 0- Address diminishing; 1- Address increment.

4 Auto Preset (initialization). 0- Automatic preset; 1- Non-automatic presets.

32 Transmission type.

00-DMA check; 01-DMA Write transfer; 10-DMA Read transfer. 11- invalid.

10
Channel selection. 00-11 Were selected channel 0-3 .

Channel address and count registers can be read 16 Bits of data. Clear has a trigger port 0x0C It is used to write in a read / DMA

Before the controller or the address information of the byte count has initialized to the default trigger condition. When the trigger is byte 0 When the low byte is accessed; trigger

when the byte is 1 When, access high byte. Each visit once, it changes the trigger once. write 0x0C Port can be set to trigger 0 status.

In use DMA The controller typically required to follow certain steps, the following procedure is used in floppy disk drive DMA Way controller to illustrate:

1. Disable interrupts to rule out any interference;

2. Modified mask register (Port 0x0A ), To shield the need to use DMA aisle. For it is through floppy disk driver

Road 2 ;

3. to 0x0C Port write operation, the byte counter has a default state of the flip-flop;

4. Write mode register (port 0x0B ), To set the operating mode word specified channel. for;

5. Write Address Register (port 0x04 ), Set up DMA Offset address memory pages in use. The first to write low byte, written after the high word

Section;

6. Write page register (port 0x81 ), Set up DMA Memory pages used;

7. Write count register (Port 0x05 ), Set up DMA Number of bytes transferred. It should transfer length - 1 . The same need for high and low

Byte write once, respectively. Every book floppy driver requirements DMA Is the length of the transmission controller 1024 Bytes, so write

DMA Length value of the controller should be 1023 (which is 0x3FF );

8. Again modification mask register (Port 0x0A ) To open DMA aisle;

9. Finally, the interrupt is turned on to allow the system to the floppy disk controller issues an interrupt request after transmission.

--237--
7.1 Overview

The first 7 Chapter character device driver ( char driver)

7.1 Outline

in linux 0.11 The kernel, the character control equipment includes a terminal device and a serial terminal. Chapter is the code for operating these input and output

devices. Works related to the terminal driver may reference MJBach of" UNIX Operating System Design "section 10 Chapter 3 Section.

List 7-1 linux / kernel / chr_drv table of Contents

file name size Last Modified Time (GMT) Explanation

Makefile 2443 bytes 1991-12-02 03:21:41 Make profile

console.c 14568 bytes 1991-11-23 18:41:21 terminal handler

keyboard.S 12780 bytes 1991-12-04 15:07:58 keyboard interrupt handler

rs_io.s 2718 bytes Serial Line handler 1991-10-02 14:16:30

serial.c 1406 bytes 1991-11-17 21:49:05 serial terminal handler

tty_io.c 7634 bytes 1991-12-08 18:09:15 terminal IO handler


tty_ioctl.c 4979 bytes 1991-11-25 19:59:38 IO terminal control program

7.2 Overall Functional Description

This chapter can be divided into three. One is about RS-232 Serial line drivers, the program comprising rs_io.s with serial.c ; The other one is involved in console driver,

which includes a keyboard interrupt-driven program keyboard.S And the console display driver console.c ; Third part is a terminal driver interfaces with the upper portion, including

program input and output terminal tty_io.c And a terminal control program tty_ioctl.c . Below we first outlines the basic principles of the control terminal implemented driver, and

then divided into three parts which describe their basic function.

7.2.1. The terminal driver rationale

Terminal driver for controlling a terminal device, transmitting data between the terminal device and processes the transmitted data and perform some processing. The user

types on the keyboard of the original data ( Raw data ), After treatment using the terminal program is transmitted to a receiving process; process the data sent to the terminal, after

the terminal program processing, is displayed or transmitted over the serial link to the remote terminal on the terminal screen. Treatment of data in accordance with input or output

terminal program mode, the terminal can be divided into two operating modes. One is the mode specification ( canonical ), This time via the data terminal program conversion

processing is to be performed, and then sent out. For example, the TAB Extended character 8 A space character, with typed delete characters ( backspace ) Control to delete

characters such as typed earlier. Handler rules used generally called line ( line discipline)

Module. Another non-canonical mode or said original ( raw) mode. In this mode, only the line data transfer rules of procedure between the terminal and processes the data

conversion process without specification mode.

Driver in the terminal, according to their relationship to the device, and the position in the execution flow may be divided into direct character device driver interface

program and direct contact with the upper layer. We can use the map 7-1 Schematically this control relationship.

--239--
7.2 Overall Functional Description

write

Driver upper interface terminal

Line procedural rules

Device Drivers

Character device

Map 7-1 Driver terminal control flow

7.2.2 The basic data structure of the terminal

Each corresponds to a terminal device tty_struct Data structure, the terminal device mainly used to save the current parameter settings, foreground process belongs to the

group ID And character IO Message queue buffer and the like. This structure is defined in include / linux / tty.h File whose structure is shown below:

struct tty_struct {
struct termios termios ; // io terminal control characters and attribute data structure.

int pgrp; // belongs to the process group.

int stopped; // stop sign.


void (* write ) (Struct tty_struct * Tty); // tty write function pointer.
struct tty_queue read_q; // tty read queue.
struct tty_queue write_q; // tty write queue.
struct tty_queue secondary; // tty auxiliary queue (stored character sequence mode specification),

}; Specification may be called // (cooked) mode queue.

extern struct tty_struct tty_table []; // tty structure array.

Linux The kernel uses an array tty_table [] To store information of each terminal device in the system. Each array entry is a data structure

tty_struct , Corresponding to a system terminal. Linux 0.11 Kernel supports a total of three terminal devices. Is a console device, the other two are on the system using a

serial terminal two serial ports.

termios The structure for storing the corresponding terminal device io Attributes. For a detailed description of the structure see below. pgrp It is the process group ID that

indicates a process group session in the foreground, that currently owns the process of the terminal device group. pgrp The main job for process control operations. stopped It is a

flag indicating whether the corresponding terminal device has stopped using. Function pointer * write () That the output process function terminal device for the console terminal,

which is responsible for driving the display hardware, characters and the like on the information display screen. For a serial port connected to the terminal via a serial system,

which is responsible for the output characters sent to the serial port.

The data processing terminal is held in 3 More tty_queue Character buffer queue structure (or character table), are represented below:

struct tty_queue {
unsigned long data; // Wait for the current queue statistics data buffer. // For serial

terminal, then store the serial port address.

unsigned long head ; // data buffer head pointer.


unsigned long tail; // data buffer tail pointer.
struct task_struct * Proc_list; // Wait for the process queue buffer list. Process read /

--240--
7.2 Overall Functional Description

char buf [1024]; // buffer queue.


};

Each character is a buffer queue length 1K byte. Wherein the read buffer queue read_q For temporarily storing an original from the keyboard or the serial input terminal ( raw )

Sequence of characters; write buffer queue write_q Written to the console for storage or display of data to a serial terminal; according

ICANON Signs, auxiliary queue secondary Used to store from read_q Data taken out through line program processing rules (filters) before, or cooked called ( cooked) Mode data. This

is the raw data line rules of procedure of the special characters such as deleted ( backspace ) Specification data is input character conversion, character is read in units supply for use

by applications. The upper terminal read function tty_read () I.e., for reading

secondary Queue characters.

When the user types the data is read, the interrupt processing program is only responsible for the compilation of the original character data in the input buffer queue, and

called by the interrupt handling process C function( copy_to_cooked () ) To deal with change jobs characters. For example, when the process of writing data to a terminal, the

terminal driver will call the line function rules copy_to_cooked () , All the user data buffer into the write buffer queue, and the data sent to the terminal display. Characters on a

terminal key is pressed, the keyboard interrupt process triggered by the key scan codes corresponding to put into the read queue read_q And calls the handler specification mode read_q

Characters processed then into secondary queue secondary in. At the same time, if the terminal device is set up Echo flag ( L_ECHO ), It can also put the character into the write

queue write_q

And calls the write function to end the character displayed on the screen. In addition to generally as type the password or other special requirements beyond, echoing the flag is

set. We can modify the terminal termios Information structure to change the flag value.

In the above tty_struct Structure further comprises a termios Structure, which is defined in the include / termios.h Header file, the contents of its fields follows:

struct termios {
unsigned long c_iflag; / * Input mode flags * / // input mode flag.
unsigned long c_oflag; / * Output mode flags * / // output mode flag.
unsigned long c_cflag; / * Control mode flags * / // control mode flag.
unsigned long c_lflag; / * Local mode flags * / // local mode flag.
unsigned char c_line; / * Line discipline * / // line discipline (rate).
unsigned char c_cc [ NCCS ]; / * Control characters * / // control character array.
};

among them, c_iflag Input mode flag is set. Linux 0.11 The kernel implements POSIX.1 All definitions 11 Input flags, see termios.h

Header file description. Terminal device driver using these flags to control how characters by converting the input terminal (filtration). For example, whether the input of line

breaks ( NL ) Into a carriage ( CR ), The need to convert uppercase to lowercase character entry (because in the past some terminal equipment can only uppercase characters)

and so on. in Linux 0.11 Kernel, function is a correlation process tty_io.c

File copy_to_cooked () .
c_oflag Output mode flag is set. Terminal device driver uses these flags to control how characters output to the terminal. c_cflag

Control mode flag is set. Mainly used to define the characteristics of serial transmission terminal, including baud rate, stop bits, and number of bits of a character and the like. c_lflag

Local mode flag is set. User interaction with the main driver for controlling. For example, the need for echo ( Echo ) Character, in addition to the need to paint the characters

displayed directly on the screen, whether the need to type the characters on the terminal control signal is generated. These operations also in the

copy_to_cooked () Function is implemented.

Above-mentioned 4 Type of the markers are set unsigned long , Each bit may represent a marker, so that each may have a flag set up

32 Input flag. All of these flags and their meanings can be found in termios.h head File.

c_cc [] An array containing all the special characters that can be modified. For example, you can modify the interrupt character (^ C ) Produced by the other keys. among

them NCCS Is the array length value.

Therefore, the use of system calls ioctl Or use the correlation function ( tcsetattr ()) We can modify termios Information structure to change the setting parameters of the

terminal. Row rules function that is operating in accordance with these set parameters. For example, if you want to control terminal of the characters typed

--241--
7.2 Overall Functional Description

Echoed back, setting the baud rate of a serial transmission terminal, and a write buffer queue empty read buffer queue.

When the user terminal to modify the parameters, the canonical mode flag is reset, then the terminal will be set to operate in the original mode, where the user will type the

rows procedural rules intact data transmitted to the user, but also when the carriage as an ordinary character. Therefore, the user uses the system call read When, we should make

some kind of decision-making programs to determine system calls read What if considered complete and return. This will be terminal

termios Structure VTIME with VMIN Control characters decide. These two timeout timer value read operation. VMIN That in order to satisfy a read operation, the minimum number

of characters to be read; VTIME Is a read wait timer value.

We can use the command stty To view the current terminal equipment termios Set case flag structure. in Linux 0.1x System command line prompt, type stty Command

displays the following information:

[/ Root] # stty
- - - - - - - - - Characters --------- INTR:
'^ C' QUIT: '^ \' ERASE: '^ H' KILL: '^ U' EOF: '^ D'
TIME: 0 MIN: 1 SWTC: '^ @' START: '^ Q' STOP: '^ S'
SUSP: '^ Z' EOL: '^ @' EOL2: '^ @' LNEXT: '^ V'
DISCARD: '^ O' REPRINT: '^ R' RWERASE: '^ W'
- - - - - - - - - - Control Flags ---------
- CSTOPB CREAD -PARENB -PARODD HUPCL -CLOCAL -CRTSCTS Baud rate:
9600 Bits: CS8
- - - - - - - - - - Input Flags ----------
- IGNBRK -BRKINT -IGNPAR -PARMRK -INPCK -ISTRIP -INLCR -IGNCR ICRNL -IUCLC
IXON - IXANY IXOFF -IMAXBEL
- - - - - - - - - Output Flags ---------
OPOST -OLCUC ONLCR -OCRNL -ONOCR -ONLRET -OFILL -OFDEL Delay modes:
CR0 NL0 TAB0 BS0 FF0 VT0
- - - - - - - - - - - Local Flags ---------
ISIG ICANON -XCASE ECHO -ECHOE -ECHOK -ECHONL -NOFLSH
- TOSTOP ECHOCTL ECHOPRT ECHOKE -FLUSHO -PENDIN -IEXTEN rows 0 cols 0

Which with a minus sign means no. In addition to the current Linux System, you need to type 'Stty -a' To display all of this information, and display formats differ.

The relationship between the main data structures used by the terminal program and they are visible in FIG. 7-2 Fig.

--242--
7.2 Overall Functional Description

structure tty_queue structure

termios structure Other field data

header (head) end


Other fields write
array 2 tty_table
of data (tail) buffer
function pointer
Console
(buf)
tty read queue
Serial terminal 1
(read_q) tty_struct
(secondary)

Serial terminal

tty write queue


(write_q)

tty auxiliary queue

Map 7-2 Data structure of the terminal program

7.2.3 Noncanonical and canonical mode mode

7.2.3.1 Specification mode

when c_lflag middle ICANON When the flag is set, the pattern that is processed in accordance with the terminal specification data input. At this time, the input character is

assembled in a row, the read process in the form of character row. When his characters input terminal driver returns immediately. There delimiter line NL ,

EOL , EOL2 with EOF . Which, among the last EOF (End of file) will be deleted handler, the other four characters will be used as the last line of a character

returned to the caller.

In the specification mode, the input terminal of the character to be processed: ERASE , KILL , EOF , EOL , REPRINT , WERASE

with EOL2 .
ERASE In addition to paint a character ( Backspace ). In the specification mode, when copy_to_cooked () In case of a function deletes the last character input buffer queue

when the input characters. If the queue is the last character of the character line (for example, NL ), Not any treatment. After the characters are ignored, not into the buffer queue.

KILL Line character is deleted. It deletes the queue last line of characters. Since the character is ignored.

EOF It is the end of file. in copy_to_cooked () The function of the character and end of line character EOL with EOL2 They will be treated as carriage returns to deal with. The

encounter characters read function will return immediately. EOF Characters are not placed in the queue but was ignored.

REPRINT with WERASE Specification is extended to identify the character mode. REPRINT Let all unread input is output. and

WERASE In addition to paint word (skip blank character). in Linux 0.11 , The program ignores the two-character recognition and processing.

7.2.3.2 Non-canonical mode

in case ICANON Is in the reset state, the terminal program works noncanonical mode. At this time, the terminal processing program does the character, but they will be

treated as an ordinary character. Input data is also no line concept. When the terminal program returns process is read by the MIN with

TIME The determined value. These two variables are c_cc [] An array of variables. They can be changed by modifying the way in dealing with the process of noncanonical mode

read characters.

MIN Indicates a read operation requires a minimum number of characters to be read; TIME Waiting to read a specified character timeout value (unit of measurement is 1/10 second).

They can be divided according to the value of four cases will be described.

1. MIN> 0 , TIME> 0
at this time TIME Is a character timeout interval timer value to be used after the receipt of the first character. Before the timeout, if the first

--243--
7.2 Overall Functional Description

Received the MIN Characters, the read operation returns immediately. If the receipt MIN Time out, the read operation returns the number of characters has been received

before the characters. At this point at least be able to return a character. Therefore, prior to receiving a character if secondary Empty, the read process will be blocked

(sleep).

2. MIN> 0 , TIME = 0
Only in this case received MIN Characters read operation before returning. Otherwise wait indefinitely (blocking).

3. MIN = 0 , TIME> 0
at this time TIME Timeout timer value is a read operation. Upon receipt of a character or has timed out, the read operation returns immediately. If a timeout is

returned, the read operation returns 0 Characters.

4. MIN = 0 , TIME = 0
In this arrangement, if there is data in the queue can be read, the read operation reads the desired character. Otherwise, it returns immediately 0 A number of

characters.

In the above case Fourth, MIN Only indicate the minimum number of characters read. If the process requires more than reading MIN To many characters, as long as there

is a queue process could meet the current demand. For a read operation processing of the terminal device, see the program tty_io.c middle

tty_read () function.

7.2.4 Console drivers

in Linux 0.11 Kernel, drivers relates to the console terminal keyboard.S with console.c program. keyboard.S For processing the characters typed by the user, put them into

the read buffer queue read_q And calls copy_to_cooked () Function reads read_q Characters, after converted into secondary buffer queue secondary . console.c Output processing

program implements the console terminal.

For example, when the user types a character on the keyboard, will cause keyboard interrupt response (interrupt request signal IRQ1, Corresponding to the interrupt number

INT 33 ), This time will the keyboard interrupt handler reads the corresponding keyboard scan codes from the keyboard controller, and then translated into the corresponding

character according to the keyboard scan code mapping table to be used, into tty Read queue read_q in. Then call the interrupt handler C function do_tty_interrupt () , Calling it a

direct line rules function copy_to_cooked () The character filter process, and put tty Auxiliary queue secondary While the character into the tty Write queue write_q And calls the write

function console con_write () . At this time, if the terminal echo ( echo ) Property is set, the character will be displayed on the screen. do_tty_interrupt () with copy_to_cooked () Function tty_io.c

Implemented. See the whole operation of the process 7-3 Fig.

Keyboard interrupt handling process

put_queue Placed in the queue

do_tty_interrupt
read_q
copy_to_cooked

secondary
con_write
Keyboard hardware interrupt

write_q

Output to the screen

Map 7-3 Console keyboard interrupt handling process

--244--
7.2 Overall Functional Description

For the execution process tty Write operation, a terminal driver is processed character by character. In the write buffer queue write_q When not full, it takes a

character from the user buffer, processed into write_q in. When all the data into the user write_q At this queue, or write_q Full, call termination structure tty_struct Specified in

the write function, the write_q Output buffer queue data to the console. For the console terminal, its function is to write con_write () ,in console.c Program implementation.

For drivers console terminal operation, involving two main programs. One is the keyboard interrupt handler keyboard.S , Mainly for the user typed characters and

put read_q Buffer queue; the other is a screen display processing program console.c For from write_q

Queues the fetched character and displayed on the screen. All relationships between the three character buffer queue or file with the above function can be used in FIG. 7-4 Clearly

represented.

system call read, write keyboard read write.c


File system

Character device interface char_dev.c

tty_write () tty_read ()
tty_io.c Character device driver
secondary
Note: The function tty_write (),

copy_to_cooked () tty_read () and


Echo echo
copy_to_cooked () were
write_q read_q
in tty_io.c

con_write () put_queue ()
console.c keyboard.S

Terminal display Terminal Console terminal equipment

Map 7-4 The relationship between the character buffer queues, and console terminal functions and procedures

7.2.5 Serial terminal driver

Program processing operation of the terminal with a serial serial.c with rs_io.s . serial.c Program is responsible for the serial port initialization. Further, by the removal of

Transmit Holding Register empty interrupt enable mask for the character on the serial interrupt transmission operation. rs_io.s Program is a serial interrupt process. According

caused major disruption 4 Kinds of reasons are processed separately.

Case of serial interrupt occurs causing the system are: a. due to modem The state has changed; b. Since the line status changes;

c. Since the character is received; d. Since the interrupt enable flag register is set Transmit Holding Register interrupt enable flag needs to send characters. Processing of the first

two cases caused the interrupt by reading a register value corresponding to the status, so that it is reset. For the case where the result of receiving a character, the program first

reads the character into buffer queue read_q Then call copy_to_cooked () Converted into a function to regulate the behavior of the character mode in units of character into the

auxiliary queue secondary in. In the case of the characters to be sent, the program first from the write buffer queue write_q Remove the tail pointer of one character is sent out, and

then determines whether the write buffer queue is empty, if there are characters in the loop transmission operation performed.

For the access terminal through a serial port of the system, in addition to processing similar to the console, but also the need for an input / output processing operation of

the serial communication. Data is read from the serial interrupt handler into the read queue read_q And subsequently performing an operation the same console terminal.

For example, for a serial port connected 1 On the terminal, the first character type transmitted over the serial link to the host, causing the host serial port 1 Interrupt

request. At this time, the serial port interrupt handler will put the character serial terminal 1 of tty Read queue read_q Then

--245--
7.2 Overall Functional Description

Call the interrupt handler C function do_tty_interrupt () , Calling it a direct line rules function copy_to_cooked () The character filter process, and put tty Auxiliary queue secondary

While the character into the tty Write queue write_q And calls write the serial terminal 1 The function rs_write () . The function will turn back to the characters serial terminal,

then echoing If the terminal ( echo ) Attribute is set, the character will be displayed on the screen of the serial terminal.

When the process time required to write data to a serial terminal, the terminal is similar to the write operation, but this time the terminal tty_struct Data structure write

function is the function to write a serial terminal rs_write () . The cancel function allows the Transmit Holding Register empty interrupt mask, thereby transmitting the serial interrupt

to occur will cause the holding register is empty. And the serial interrupt process according to the reason for the cause of the interruption from write_q

Write buffer queue into the send out a character and character transmission operation holding register. During this operation is an interrupt to send a character to the last write_q Mask

will empty Transmit Holding Register empty interrupt bit allows again, thereby inhibiting the occurrence of such an interrupt.

Write function serial terminal rs_write () in serial.c Program implementation. Serial interrupt program rs_io.s Implemented. Relationship serial character buffer queue and

three terminal functions, procedures, see FIG. 7-5 Fig.

system call read, write keyboard read write.c


File system

Character device interface char_dev.c

tty_write () tty_read () tty_io.c


Character device driver
secondary
Note: The function tty_write (),
copy_to_cooked ()
tty_read () and
Echo echo
copy_to_cooked () were
write_q read_q
in tty_io.c

write_char rs_io.s read_char:

Terminal display Terminal Serial terminal device

Map 7-5 The relationship between the function of the buffer queue character serial terminal device

Seen from the figure, the main difference between the serial console terminal and the terminal using a serial processing procedure rs_io.s Substituted program console

operator display and the keyboard console.c with keyboard.S , The rest of the process is exactly the same.

7.2.6 Terminal driver interface

Typically, the user is dealing with the device via the file system, each device has a file name, the file system accordingly also occupies an inode ( i Node), but the i Node file

type is the device type, to be distinguished from other normal files. Users can directly use the file system calls to access the device. The terminal driver also aim to provide a call to

the file system interface functions for this purpose. Interface to other programs and a terminal driver system is used tty_io.c Files in generic functions to achieve. Wherein the read

terminal function implemented tty_read () And write terminal function tty_write () And the input line rules function copy_to_cooked () . In addition, tty_ioctl.c Program, input-output control

to achieve the function to modify the parameters of the terminal (or system call) tty_ioctl () . Setting parameters of the terminal is on the terminal data structure termios Structure in

which more parameters, but also more complex, refer to include / termios.h Instructions in the file.

For different terminal devices may have different rules of procedure matching rows. However, Linux 0.11 Only one line rule function, so termios Field

line structure rules' c_line ' Ineffective, are set to 0 .

--246--
7.3 Makefile file

7.3 Makefile file

7.3.1 Functional Description

Compile manager character device drivers. by Make Tools software.

7.3.2 Code comments

program 7-1 linux / kernel / chr_drv / Makefile

1#
2 # Makefile for the FREAX-kernel character device drivers.
3#
4 # Note! Dependencies are done automagically by 'make dep', which also
5 # Removes any old dependencies. DO NOT put your own dependencies here
6 # Unless it's something special (ie not a .c file).
7#
# Makefile file FREAX (Linux) kernel device driver characters.
# note! Dependency is performed by the 'make dep' automatically, which will automatically remove the original dependency information. Do not put your own

# Dependency information on here, unless it is (that is not a message .c file) special file.
89 AR
= Gar # GNU binary file processing program for creating, modifying and extracting files from the archive.
10 AS = Gas # GNU assembler.
11 LD = Gld # The GNU linker.
12 LDFLAGS = -s -x # connection program all the parameters, -s omitted all symbols output file information. -x Delete all local symbols.

13 CC = Gcc # GNU C language compiler.


# The next line is the C compiler options. -Wall display all warnings; -O optimization option, to optimize code size and execution time;
# - fstrength-reduce execution code optimization cycle, excluding iteration variable; -fomit-frame-pointer will be omitted to save unnecessary

# The frame pointers; -fcombine-regs merge register, reduce the use of register class; -finline-functions all Jane
# Single short code embedded function calls the program; -mstring-insns Linus own filling optimization options, will no longer use;
# - nostdinc -I ../ include not using the default path contains the file, and use the specified directory (../../include).
14 CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
15 - finline-functions -mstring-insns -nostdinc -I ../../ include
# C pre-processing options. -E C only run pre-treatment, pre-treatment and the results for all of the specified program is output to the standard output C

# The apparatus or a specified output file; -nostdinc -I ../../ include op.


16 CPP = Gcc -E -nostdinc -I ../../ include
17
# The following rule indicates that make use of the following command will compile all .c files generated .s Assembler. The rule of command

# Refers gcc CFLAGS using the specified options compiled C code is compiled without stops (-S), thereby generating
# C each corresponding to the input file assembler code file. Assembler default file name is generated by the original file name C
# Remove .c and .s suffix plus. -o represented followed by the name of the output file. Of which $ *. S (or $ @ ) is automatic target variable,

# $ <Represents the first prerequisite here that is qualified * .c files.


18 .cs:
19 $ (CC) $ (CFLAGS) \
20 - S -o $ *. S $ <
# The following rule means that all .s assembler .o files compiled into object files. Line 22 is a command to achieve the specific operation.

twenty one .so:

twenty two $ (AS) -c -o $ *. O $ <


twenty three .co: # . Similar to the above, * c files - * .o object files. Not connect.
twenty four $ (CC) $ (CFLAGS) \
25 - c -o $ *. o $ <
26

--247--
7.3 Makefile file

27 OBJS = tty_io.o console.o keyboard.o serial.o rs_io.o \ # Define the target file variable OBJS.
28 tty_ioctl.o
2930 chr_drv.a: $ (OBJS)
# Use the following command to connect to the target file in the library with chr_drv.a prerequisite OBJS.

31 $ (AR) rcs chr_drv.a $ (OBJS)


32 sync
33
# Kerboard.S assembler for pretreatment. -traditional option is used to make changes to the program to support traditional C compiler.
# Program, a renamed kernboard.s.
34 keyboard.s: keyboard.S ../../include/linux/config.h
35 $ (CPP) -traditional keyboard.S -o keyboard.s
36
# The following rules for the cleanup. When executing 'make clean', the following command will remove all compiled
# Connection file generated. 'Rm' command is to delete the file, meaning -f option is to ignore the file does not exist, and does not delete the information.

37 clean:
38 rm -f core * .o * .a tmp_make keyboard.s
39 for i in * .c; do rm -f `basename $$ i .c`.s; done
40
# Here was the objective or rules for checking dependencies between files. Methods as below:

# Sed string editing program for the Makefile (i.e. are files), and outputs for deletion Makefile
# File '### Dependencies' all rows behind rows (48 rows from the beginning of the next), and generates tmp_make
# Temporary files (action line 44). Gcc preprocessing operation is then performed for each file in the C kernel / chr_drv / directory.
# - M flag tells the preprocessor output description of the rules relating to each target file, and make compliance with these rules syntax.

# For each source file, the output of preprocessor make a rule, the result is a certain form of the corresponding source file
# File name plus its dependencies - lists all the header files included in the source file. The pretreatment results are added to the temporary

# Tmp_make file, and then copy the temporary file into a new file Makefile.
41 dep:
42 sed '/ \ # \ # \ # Dependencies / q' <Makefile> tmp_make
43 (For i in * .c; do echo -n `echo $$ i | sed '.. S, \ c, \ s,'` ""; \
44 $ (CPP) -M $$ i; done) >> tmp_make
45 cp tmp_make Makefile
4647 ### Dependencies:

48 console.s console.o: console.c ../../include/linux/sched.h \


49 . . /../include/linux/head.h ../../include/linux/fs.h \
50 . . /../include/sys/types.h ../../include/linux/mm.h ../../include/signal.h \
51 . . /../include/linux/tty.h ../../include/termios.h ../../include/asm/io.h \
52 . . /../include/asm/system.h
53 serial.s serial.o: serial.c ../../include/linux/tty.h ../../include/termios.h \
54 . . /../include/linux/sched.h ../../include/linux/head.h \
55 . . /../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
56 . . /../include/signal.h ../../include/asm/system.h ../../include/asm/io.h
57 tty_io.s tty_io.o: tty_io.c ../../include/ctype.h ../../include/errno.h \
58 . . /../include/signal.h ../../include/sys/types.h \
59 . . /../include/linux/sched.h ../../include/linux/head.h \
60 . . /../include/linux/fs.h ../../include/linux/mm.h ../../include/linux/tty.h \
61 . . /../include/termios.h ../../include/asm/segment.h \
62 . . /../include/asm/system.h
63 tty_ioctl.s tty_ioctl.o: tty_ioctl.c ../../include/errno.h ../../include/termios.h \
64 . . /../include/linux/sched.h ../../include/linux/head.h \
65 . . /../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
66 . . /../include/signal.h ../../include/linux/kernel.h \
67 . . /../include/linux/tty.h ../../include/asm/io.h \

--248--
7.4 keyboard.s program

68 . . /../include/asm/segment.h ../../include/asm/system.h

7.4 keyboard.s program

7.4.1 Functional Description

The keyboard driver assembler including keyboard interrupt handler. In English usage, the make It represents a key is pressed; break It represents a bond is released

(release).

The program first special key The keyboard (e.g. Alt , Shift , Ctrl , Caps Key) status is set to use later in the program state flag variable mode Value, and then according to the

keyboard interrupt causes the key scan code, the corresponding call has been arranged into scan code table processing routine jumps, the scan code corresponding to the read

character into character train ( read_q )in. Next call C Handler do_tty_interrupt () ( tty_io.c ,
342 Line), which contains only one function row protocol function copy_to_cooked () It calls. The main function of the role is to line discipline

read_q Buffer queue read characters into proper treatment mode specification queue (queue auxiliary secondary ), And in the process, if the corresponding terminal echo

flag is set, the character will be written into the queue ( write_q ), So that will show just typed characters on the terminal screen.

for AT The keyboard scan code when the key is pressed, the corresponding key scan code is sent, but when the key release will be sent two bytes, the first one is 0xf0 The

first 2 It is a scan code when pressed. For backwards compatibility, the designers AT Keyboard scan code conversion issue has become old-fashioned PC / XT Standard keyboard

scan codes. So here only PC / XT The scan code to be processed. For a description of keyboard scan codes, see the description of the program list after.

7.4.2 Code comments

program 7-2 linux / kernel / chr_drv / keyboard.S

1/*
2 * Linux / kernel / keyboard.S
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8* Thanks to Alfred Leung for US keyboard patches


9* Wolfgang Thiel for German keyboard patches
10 * Marc Corsini for the French keyboard
11 * / / *

* Thank Alfred Leung added a US keyboard patches;


* Wolfgang Thiel added German keyboard patches;
* Marc Corsini added a French keyboard patch.
*/
1213 #include <linux / config.h> // kernel configuration file header. Define the keyboard language and hard disk type (HD_TYPE) option.

1415 .text

16 .globl _keyboard_interrupt
17

--249--
7.4 keyboard.s program

18 / *
19 * These are for the keyboard read functions
20 * / / *

* These are the keyboard for a read operation.

*/
// size of the keyboard buffer is the length (number of bytes).

twenty one size 1024 = / * Must be a power of two! And MUST be the same
twenty two as in tty_io.c !!!! * /
/ * Values ​must be a power of 2! And match the value in tty_io.c !!!! * /
// These are the offset of the buffer queue structure * /
twenty three head = 4 // offset buffer pointer field header.
twenty four tail = 8 // offset buffer tail pointer field.
25 proc_list = 12 // wait for the buffer process queue field offset.
26 buf = 16 // buffer field offset.
27
// mode is to press the keyboard status flags of special keys.

// shows a state case shift key (caps), the exchange key (alt), the control key (Ctrl) and the shift key (Shift) of. // Bit 7 caps key is

pressed;

// status bit key 6 caps (should be the same as the corresponding flag bit leds); // Right Bit 5
alt key is pressed; // 4-bit left alt key is pressed; // 3-bit right-ctrl key is pressed; bit 2 // left
ctrl key is pressed; // 1 bit right shift key is pressed; 0 // bit left shift key is pressed.

28 mode: . byte 0 / * Caps, alt, ctrl and shift mode * /


// Num Lock keys (num-lock), the case shift key (caps-lock) and the Scroll Lock key status LED light tube (scroll-lock) a. // bits 7-3 all-0 no; // bit
2 caps-lock;

// bit 1 num-lock (initially set to 1, i.e. set the number lock key (num-lock) as a bright arc tube); // bit 0
scroll-lock.
29 leds: . byte 2 / * Num-lock, caps, scroll-lock mode (nom-lock on) * /
@ When the code is scanned 0xe0 0xe1 or when the flag is set. Thereafter it represents 1 or even went with two character scan code, see list described later. Bit 1 = 1 //

0xe1 received flag; // bit 0 = 1 0xe0 received flag.

30 e0: . byte 0
3132 / *

33 * Con_int is the real interrupt routine that reads the


34 * Keyboard scan-code and converts it into the appropriate
35 * Ascii character (s).
36 * / / *

* con_int actual interrupt handling routine, for reading and converting keyboard scan codes
* To the corresponding ascii characters.

*/
//// keyboard interrupt handler entry point.

37 _keyboard_interrupt:
38 pushl% eax
39 pushl% ebx
40 pushl% ecx
41 pushl% edx

--250--
7.4 keyboard.s program

42 push% ds
43 push% es
44 movl $ 0x10,% eax // The ds, es segment register is set to the kernel data segment.

45 mov% ax,% ds
46 mov% ax,% es
47 xorl% al,% al / *% Eax is scan code * / / * eax is the scan code * /
48 inb $ 0x60,% al // read the scan code al.
49 cmpb $ 0xe0,% al // The scan code is 0xe0 it? If the flag is set then jumps to the code at e0.
50 je set_e0
51 cmpb $ 0xe1,% al // scan code is 0xe1 it? If the flag is set then jumps to the code at e1.
52 je set_e1
53 call key_table (,% eax, 4) // calls the key handler ker_table + eax * 4 (see below line 502).
54 movb $ 0, e0 // reset e0 flag.
// The following code (lines 55-65) is used for the PC 8255A's standard keyboard processing circuit performs hardware reset. 0x61 // 8255A port is the output port B address, bit 7

(PB7) for inhibiting the output port of the keyboard and allows the processing of data. // This program is used to make a response to the scan code received. First method is prohibited

keyboard, and then immediately re-enables the keyboard to work.

55 e0_e1: inb $ 0x61,% al // take PPI Status Port B, for which 7 bits enable / disable (0/1) keyboard.

56 jmp 1f // delay for a while.


57 1: jmp 1f
58 1: orb $ 0x80,% al // al Bit 7 set (Prohibition keyboard work).
59 jmp 1f // then delayed for a while.

60 1: jmp 1f
61 1: outb% al, $ 0x61 // make PPI PB7 bit.
62 jmp 1f // delay for a while.
63 1: jmp 1f
64 1: andb $ 0x7F,% al // al Bit 7 is reset.
65 outb% al, $ 0x61 // make PPI PB7 bit is reset (to allow the keyboard work).

66 movb $ 0x20,% al // send to 8259 interrupts chip EOI (End Of Interrupt) signal.

67 outb% al, $ 0x20


68 pushl $ 0 // console tty number = 0, as a parameter stack.

69 receive the call _do_tty_interrupt // copy the data into a canonical specification character pattern data and stored in the buffer queue.

70 addl $ 4,% esp // discard the parameters onto the stack, and pop the register reservations, and interrupt return.

71 pop% es
72 pop% ds
73 popl% edx
74 popl% ecx
75 popl% ebx
76 popl% eax
77 iret
78 set_e0: movb $ 1, e0 // receive scan 0xe0 preamble, set e0 flag (bit 0).
79 jmp e0_e1
80 set_e1: movb $ 2, e0 // receive scan preamble 0xe1, set e1 flag (bit 1).
81 jmp e0_e1
8283 / *

84 * This routine fills the buffer with max 8 bytes, taken from
85 *% Ebx:% eax (% edx is high) The bytes are written in the..
86 * Order% al,% ah,% eal,% eah,% bl,% bh ... until% eax is zero.
87 * / / *

* The following subroutine to ebx: eax up to eight characters in the insertion of the buffer queue. (Edx is

* The sequence of characters is written al, ah, eal, eah, bl, bh ... until eax equal to 0.

*/

--251--
7.4 keyboard.s program

88 put_queue:
89 pushl% ecx // save ecx, edx content.
90 pushl% edx // get console tty structure read buffer queue pointer.

91 movl _table_list,% edx # read-queue for console


92 movl head (% edx),% ecx // fetch buffer queue head pointer ecx.
93 1: movb% al, buf (% edx,% ecx) // al characters into the buffer at a queue head pointer location.

94 incl% ecx // head pointer forward one byte.

95 andl $ size-1,% ecx // pointer to the buffer size adjustment head (if exceeded starts the return buffer).

96 cmpl tail (% edx),% ecx # buffer full - discard everything // == head pointer tail
pointer right (buffer queue is full)?
97 je 3f // If full, not back into the characters all abandoned.
98 shrdl $ 8,% ebx,% eax The ebx // 8 bits to 8-bit-right in eax, ebx but unchanged.
99 je 2f // There are characters? If not (equal to 0) is the jump.

100 shrl $ 8,% ebx // ebx in the right eight bits, and a jump to the label to continue.
101 jmp 1b
102 2: movl% ecx, head (% edx) // Ruoyi all the characters are placed in a queue, save the head pointer.

103 movl proc_list (% edx),% ecx // pointer to the queue of waiting processes?

104 testl% ecx,% ecx // pointer detection task structure is empty (there waiting for the queue process?).

105 je 3f // no, then jump;


106 movl $ 0, (% ecx) // Yes, the process is set to be ready for operation (wake up the process).

107 3: popl% edx // pop reserved registers and returns.


108 popl% ecx
109 ret
110
// The following code or scan code ctrl alt respectively provided in the corresponding mode flag bit. If the scan code is received before the scan code //
0xe0 (E0 flag is set), then press the alt key or ctrl right keyboard is provided corresponding // ctrl or alt bits in mode flags in the mode .

111 ctrl: movb $ 0x04,% al // 0x4 mode flag is a schematic left ctrl key corresponding bits (2 bits).
112 jmp 1f
113 alt: movb $ 0x10,% al // 0x10 mode flag is a schematic left alt key corresponding bits (4 bits).
114 1: cmpb $ 0, e0 // e0 flag is set yet (or press ctrl alt key is to the right of it)?
115 je 2f // not the turn.
116 addb% al,% al // is the corresponding flag bit is set then change to the right (position 3 or position 5).

117 2: orb% al, mode // set flag bit pattern corresponding mode.
118 ret
// This code processing ctrl or alt key scan code released, the corresponding bit in the mode flag reset mode. When processing according // e0 flag is set to

determine whether the right ctrl or alt key keyboard.

119 unctrl: movb $ 0x04,% al // left mode flag pattern corresponding to the ctrl key bit (bit 2).
120 jmp 1f
121 unalt: movb $ 0x10,% al // 0x10 mode flag is a schematic left alt key corresponding bits (4 bits).
122 1: cmpb $ 0, e0 // e0 flag is set yet (the release is ctrl or alt key to the right of it)?
123 je 2f // not, then turn.
124 addb% al,% al // it is the corresponding flag bit is reset to the right (position 3 or position 5).

125 2: notb% al // reset mode flag bit corresponding mode.


126 andb% al, mode
127 ret
128 129 lshift:

130 orb $ 0x01, mode // left shift key is pressed, the corresponding setting mode flag (bit 0).
131 ret
132 unlshift:
133 andb $ 0xfe, mode // left shift key is released the reset mode corresponding flag bit (bit 0).
134 ret

--252--
7.4 keyboard.s program

135 rshift:
136 orb $ 0x02, mode // right shift key is pressed, the corresponding setting mode flag (1 bit).
137 ret
138 unrshift:
139 andb $ 0xfd, mode // right shift key is released the reset mode corresponding flag bit (bit 1).

140 ret
141142 caps:
testb $ 0x80, mode // mode in the test mode flag bit is already set 7 (pressed state).
143 jne 1f // If the pressed state, return (ret).
144 xorb $ 4, leds // leds flip caps-lock flag bits (2 bits).
145 xorb $ 0x40, mode // flip caps mode key is pressed in the flag bit (bit 6).
146 orb $ 0x80, mode // set the mode flag caps key has been pressed flag (bit 7).
// This code flag according leds, LED indicators on or off.
147 set_leds:
148 call kb_wait // wait for the keyboard controller input buffer empty.

149 movb $ 0xed,% al / * Set leds command * / / * set the LED command * /
150 outb% al, $ 0x60 // send keyboard commands 0xed to 0x60 ports.

151 call kb_wait // wait for the keyboard controller input buffer empty.

152 movb leds,% al // take leds flag as a parameter.


153 outb% al, $ 0x60 // send the parameter.

154 ret
155 uncaps: andb $ 0x7f, mode // caps release the key, the corresponding mode flag is reset bit (bit 7) mode of.

156 ret
157 scroll:
158 xorb $ 1, leds // scroll key is pressed, corresponding to the inverted bit (bit 0) leds the flag.

159 jmp set_leds // re-open or closed based on LED indicator leds flag.
160 num: xorb $ 2, leds // num key is pressed, corresponding to the inverted bit (bit 1) leds the flag.

161 jmp set_leds // re-open or closed based on LED indicator leds flag.
162 163 / *

164 * Curosr-key / numeric keypad cursor keys are handled here.


165 * Checking for numeric keypad etc.
166 * / / *

* Here the process direction keys / numeric keyboard arrow keys, numeric keypad and the like is detected.

*/
167 cursor:
168 subb $ 0x47,% al // scan code is the key on the numeric keypad (its scan code> = 0x47) issued?

169 jb 1f // If not less than the process returns.


170 cmpb $ 12,% al // If the scan code> 0x53 (0x53 - 0x47 = 12), then
171 ja 1f // scan code value exceeds 83 (0x53), no processing, and returns.

172 jne cur2 / * Check for ctrl-alt-del * / / * check if ctrl-alt-del * / // if equal to 12, then the del key has
been pressed then determine whether alt ctrl // press and .

173 testb $ 0x0c, mode // There ctrl key is pressed it?

174 je cur2 // no, then jump.


175 testb $ 0x30, mode // There alt key is pressed it?

176 jne reboot // Yes, jump to the restart process.


177 cur2: cmpb $ 0x01, e0 / * E0 forces cursor movement * / / * e0 set, indicates that the cursor * / // e0 flag is set yet?

178 je cur // set up, jump cursor moving process at cur.


179 testb $ 0x02, leds / * Not num-lock forces cursor * / / * num-lock key is not allowed * / // test leds flag
num-lock key flag is set.

--253--
7.4 keyboard.s program

180 je cur // If not set (num LED is not lit), the cursor moving process be performed.
181 testb $ 0x03, mode / * Shift forces cursor * / / * shift key also moves the cursor * / // test mode flag in
the mode flag shift pressed.
182 jne cur // if the shift key is pressed, the cursor moving process be performed.

183 xorl% ebx,% ebx // inquiry scan or digital form (line 199), to take a digital ASCII code corresponding to the key.

184 movb num_table (% eax),% al Eax // to as the index value, the corresponding numeric characters take al.

185 jmp put_queue // The character into buffer queue.


186 1: ret
187
// This code processing to move the cursor.

188 cur: movb cur_table (% eax),% al // substitution character al cursor in the character table corresponding key.

189 cmpb $ '9,% al // If the character <= '9', is described Previous, Next, insert or delete key,
190 ja ok_cur // the functions to be included on a sequence of characters in the character '-'.

191 movb $ '~,% ah


192 ok_cur: shll $ 16,% eax // move the contents of the ax in eax high word.

193 movw $ 0x5b1b,% ax // put in the ax 'esc [' character, and word high characters eax movement sequence.

194 xorl% ebx,% ebx


195 jmp put_queue // The character into buffer queue.
196 197 #if defined (KBD_FR)

198 num_table:
199 . ascii "789 456 1230." @ Keys on the numeric keypad corresponding to an ASCII code table.

200 #else
201 num_table:
202 . ascii "789 456 1230,"
203 #endif
204 cur_table:
205 . ascii "HA5 DGC YB623" @ Numeric keypad on the moving direction of insertion and deletion key or keys represent the corresponding character table.

206 207 / *

208 * This routine handles function keys


209 * /
// The following subroutine processing function keys.

210 func:
211 pushl% eax
212 pushl% ecx
213 pushl% edx
214 call _show_stat // call the function display of each task status (kernl / sched.c, 37).

215 popl% edx


216 popl% ecx
217 popl% eax
218 subb $ 0x3B,% al // function key 'F1' is a scan code 0x3B, so at this time is al index function key.
219 jb end_func // If the scan code is less than 0x3B, no processing, and returns.

220 cmpb $ 9,% al // function keys F1-F10?


221 jbe ok_func // yes, then jump.
222 subb $ 18,% al // function keys F11, F12 do?
223 cmpb $ 10,% al // function keys F11?
224 jb end_func // No, not processed, returned.
225 cmpb $ 11,% al // function keys F12?
226 ja end_func // No, not processed, returned.
227 ok_func:
228 cmpl $ 4,% ecx / * Check that there is enough room * / * check whether there is sufficient space
*/

--254--
7.4 keyboard.s program

229 jl end_func // need to put four character sequence, if fit, will be returned.
230 movl func_table (,% eax, 4),% eax // fetch function keys corresponding to the sequence of characters.

231 xorl% ebx,% ebx


232 jmp put_queue // put buffer queue.
233 end_func:
234 ret
235 236 / *

237 * Function keys send F1: 'esc [[A' F2: 'esc [[B' etc.
238 * / / *

* Scan code sent by function key, F1 key is: 'esc [[A', F2 key as: 'esc [[B' and the like.
*/
239 func_table:
240 . long 0x415b5b1b, 0x425b5b1b, 0x435b5b1b, 0x445b5b1b
241 . long 0x455b5b1b, 0x465b5b1b, 0x475b5b1b, 0x485b5b1b
242 . long 0x495b5b1b, 0x4a5b5b1b, 0x4b5b5b1b, 0x4c5b5b1b
243
// scan code -ASCII Character Map.
// definition of the config.h keyboard type (FINNISH, US, GERMEN, FRANCH), the corresponding key scan code mapping to ASCII characters //.

244 #if defined (KBD_FINNISH) // The following Finnish

keyboard scan code mapping table.

245 key_map:
246 . byte 0,27 // scan code 0x00,0x01 ASCII code corresponding to;

247 . ascii "1234567890+ '" // scan code 0x02, ... 0x0c, 0x0d corresponding ASCII code, similar to the following.

248 . byte 127,9


249 . ascii "qwertyuiop}"
250 . byte 0,13,0
251 . ascii "asdfghjkl | {"
252 . byte 0,0
253 . ascii " 'zxcvbnm, .-"
254 . byte 0, '*, 0,32 / * 36-39 * / / * 0x36-0x39 scan code corresponding to ASCII code * /

255 . fill 16,1,0 / * 3A-49 * / / * 0x3A-0x49 scan code corresponding to ASCII code * /

256 . byte '-, 0,0,0,' + / * 4A-4E * / / * 0x4A-0x4E scan code corresponding to ASCII code * /

257 . byte 0,0,0,0,0,0,0 / * 4F-55 * / / * 0x4F-0x55 scan code corresponding to ASCII code * /

258 . byte '<


259 . fill 10,1,0
260
// shift key is pressed while the mapping table.

261 shift_map:
262 . byte 0,27
263 . ascii "! \" # $% & / () =? `"
264 . byte 127,9
265 . ascii "QWERTYUIOP] ^"
266 . byte 13,0
267 . ascii "ASDFGHJKL \\ ["
268 . byte 0,0
269 . ascii "* ZXCVBNM;: _"
270 . byte 0, '*, 0,32 / * 36-39 * /
271 . fill 16,1,0 / * 3A-49 * /
272 . byte '-, 0,0,0,' + / * 4A-4E * /
273 . byte 0,0,0,0,0,0,0 / * 4F-55 * /

--255--
7.4 keyboard.s program

274 . byte '>


275 . fill 10,1,0
276
// alt key while pressing the mapping table.

277 alt_map:
278 . byte 0,0
279 . ASCII "\ 0 @ \ $ 0 \ 0 \ 0 {[]} 0 \\\"
280 . byte 0,0
281 . byte 0,0,0,0,0,0,0,0,0,0,0
282 . byte '~, 13,0
283 . byte 0,0,0,0,0,0,0,0,0,0,0
284 . byte 0,0
285 . byte 0,0,0,0,0,0,0,0,0,0,0
286 . byte 0,0,0,0 / * 36-39 * /
287 . fill 16,1,0 / * 3A-49 * /
288 . byte 0,0,0,0,0 / * 4A-4E * /
289 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
290 . byte '|
291 . fill 10,1,0
292 293 #elif defined (KBD_US)

294
// The following is a US keyboard scan code mapping table.

295 key_map:
296 . byte 0,27
297 . ascii "1234567890- ="
298 . byte 127,9
299 . ascii "qwertyuiop []"
300 . byte 13,0
301 . ascii "asdfghjkl; '"
302 . byte ' `, 0
303 . ascii "\\ zxcvbnm,. /"
304 . byte 0, '*, 0,32 / * 36-39 * /
305 . fill 16,1,0 / * 3A-49 * /
306 . byte '-, 0,0,0,' + / * 4A-4E * /
307 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
308 . byte '<
309 . fill 10,1,0
310311312 shift_map:

313 . byte 0,27


314 . ASCII " ! @ # $% ^ & * () _ +"
315 . byte 127,9
316 . ascii "QWERTYUIOP {}"
317 . byte 13,0
318 . ascii "ASDFGHJKL: \" "
319 . byte '~, 0
320 . ascii "| ZXCVBNM <>?"
321 . byte 0, '*, 0,32 / * 36-39 * /
322 . fill 16,1,0 / * 3A-49 * /
323 . byte '-, 0,0,0,' + / * 4A-4E * /
324 . byte 0,0,0,0,0,0,0 / * 4F-55 * /

--256--
7.4 keyboard.s program

325 . byte '>


326 . fill 10,1,0
327 328 alt_map:

329 . byte 0,0


330 . ASCII "\ 0 @ \ $ 0 \ 0 \ 0 {[]} 0 \\\"
331 . byte 0,0
332 . byte 0,0,0,0,0,0,0,0,0,0,0
333 . byte '~, 13,0
334 . byte 0,0,0,0,0,0,0,0,0,0,0
335 . byte 0,0
336 . byte 0,0,0,0,0,0,0,0,0,0,0
337 . byte 0,0,0,0 / * 36-39 * /
338 . fill 16,1,0 / * 3A-49 * /
339 . byte 0,0,0,0,0 / * 4A-4E * /
340 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
341 . byte '|
342 . fill 10,1,0
343 344 #elif defined (KBD_GR)

345
// The following is a German keyboard scan code mapping table.

346 key_map:
347 . byte 0,27
348 . ascii "1234567890 \\ '"
349 . byte 127,9
350 . ASCII " qwertzuiop @ +"
351 . byte 13,0
352 . ascii "asdfghjkl [] ^"
353 . byte 0, '#
354 . ascii "yxcvbnm, .-"
355 . byte 0, '*, 0,32 / * 36-39 * /
356 . fill 16,1,0 / * 3A-49 * /
357 . byte '-, 0,0,0,' + / * 4A-4E * /
358 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
359 . byte '<
360 . fill 10,1,0
361 362 363 shift_map:

364 . byte 0,27


365 . ascii "! \" # $% & / () =? `"
366 . byte 127,9
367 . ascii "QWERTZUIOP \\ *"
368 . byte 13,0
369 . ascii "ASDFGHJKL {} ~"
370 . byte 0, ''
371 . ascii "YXCVBNM;: _"
372 . byte 0, '*, 0,32 / * 36-39 * /
373 . fill 16,1,0 / * 3A-49 * /
374 . byte '-, 0,0,0,' + / * 4A-4E * /
375 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
376 . byte '>

--257--
7.4 keyboard.s program

377 . fill 10,1,0


378 379 alt_map:

380 . byte 0,0


381 . ASCII "\ 0 @ \ $ 0 \ 0 \ 0 {[]} 0 \\\"
382 . byte 0,0
383 . byte '@, 0,0,0,0,0,0,0,0,0,0
384 . byte '~, 13,0
385 . byte 0,0,0,0,0,0,0,0,0,0,0
386 . byte 0,0
387 . byte 0,0,0,0,0,0,0,0,0,0,0
388 . byte 0,0,0,0 / * 36-39 * /
389 . fill 16,1,0 / * 3A-49 * /
390 . byte 0,0,0,0,0 / * 4A-4E * /
391 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
392 . byte '|
393 . fill 10,1,0
394 395 396 #elif defined (KBD_FR)

397
// The following French keyboard scan code mapping table.

398 key_map:
399 . byte 0,27
400 . ascii "& {\" '(-} _ / @) = "
401 . byte 127,9
402 . ascii "azertyuiop ^ $"
403 . byte 13,0
404 . ascii "qsdfghjklm |"
405 . byte ' `, 0,42 / * Coin sup gauche, do not know, [* | mu] * /
406 . ascii "wxcvbn,;:!"
407 . byte 0, '*, 0,32 / * 36-39 * /
408 . fill 16,1,0 / * 3A-49 * /
409 . byte '-, 0,0,0,' + / * 4A-4E * /
410 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
411 . byte '<
412 . fill 10,1,0
413 414 shift_map:

415 . byte 0,27


416 . ascii "1234567890] +"
417 . byte 127,9
418 . ascii "AZERTYUIOP <>"
419 . byte 13,0
420 . ascii "QSDFGHJKLM%"
421 . byte '~, 0,' #
422 . ascii "WXCVBN? ./ \\"
423 . byte 0, '*, 0,32 / * 36-39 * /
424 . fill 16,1,0 / * 3A-49 * /
425 . byte '-, 0,0,0,' + / * 4A-4E * /
426 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
427 . byte '>
428 . fill 10,1,0

--258--
7.4 keyboard.s program

429 430 alt_map:

431 . byte 0,0


432 . ascii "\ 0 ~ # {[|` \\ ^ @]} "
433 . byte 0,0
434 . byte '@, 0,0,0,0,0,0,0,0,0,0
435 . byte '~, 13,0
436 . byte 0,0,0,0,0,0,0,0,0,0,0
437 . byte 0,0
438 . byte 0,0,0,0,0,0,0,0,0,0,0
439 . byte 0,0,0,0 / * 36-39 * /
440 . fill 16,1,0 / * 3A-49 * /
441 . byte 0,0,0,0,0 / * 4A-4E * /
442 . byte 0,0,0,0,0,0,0 / * 4F-55 * /
443 . byte '|
444 . fill 10,1,0
445 446 #else

447 #error "KBD-type not defined"


448 #endif
449 / *
450 * Do_self handles "normal" keys, ie keys that do not change meaning
451 * And which have just one character returns.
452 * / / *

* do_self for handling "normal" key, that meaning has not changed and only a return key characters.
*/
453 do_self:
// 454-460 mode for selecting one row alt_map, shift_map or key_map mapping table according to the mode flag.

454 lea alt_map,% ebx // alt key while mapping table base when pressed alt_map ebx.
455 testb $ 0x20, mode / * Alt-gr * / / * the right alt key while pressing the? * /
456 jne 1f // yes, forward jump to number 1.
457 lea shift_map,% ebx Base address mapping table when // shift key while pressing shift_map ebx.

458 testb $ 0x03, mode // the shift key while pressing there yet?

459 jne 1f // There is a forward jump to number 1.


460 lea key_map,% ebx // otherwise the general mapping table key_map.

// get the scan code mapping table ASCII characters, if no corresponding character, is returned (transferred none).

461 1: movb (% ebx,% eax),% al // The scan code value as an index, taking the ASCII code corresponding al.

462 orb% al,% al // Check to see if there is a corresponding ASCII code.

463 je none // If not (= 0 corresponding to the ASCII code) is returned.

// if the key is pressed or ctrl caps lock key, and the characters 'a' - '}' in the range of (0x61-0x7D), then it is transferred to uppercase // (0x41-0x5D).

464 testb $ 0x4c, mode / * Ctrl or caps * / / * control key has been pressed or caps bright? * /

465 je 2f // no, then jumps forward at the numeral 2.

466 cmpb $ 'a,% al Al // the characters is compared with 'a'.

467 jb 2f // If the value of al < 'a', the numeral 2 the transfer.

468 cmpb $ '},% al Al // The characters '}' compared.


469 ja 2f Al // If value> '}', the numeral 2 the transfer.

470 subb $ 32,% al // Convert al uppercase characters (minus 0x20).

// If the ctrl key has been pressed, and the characters '' '--'_' between (0x40-0x5F) (uppercase characters), it is converted into control characters // (0x00-0x1F).

471 2: testb $ 0x0c, mode / * Ctrl * / / * ctrl key while pressing yet? * /
472 je 3f // If not then go to number 3.

--259--
7.4 keyboard.s program

473 cmpb $ 64,% al // al and the '@' (64) comparison character (i.e., character belongs is determined range).

474 jb 3f If the value of // < '@', then go to reference numeral 3.

475 cmpb $ 64 + 32,% al // al and the '' '(96) comparison character (i.e., character belongs is determined range).

476 jae 3f // If the value of> = ' `', turn the numeral 3.

477 subb $ 64,% al // Otherwise al value minus 0x40,

// character is about to be converted to a control character between 0x00-0x1f.

// If the alt key while pressing the left, then bit 7 set of characters.

478 3: testb $ 0x10, mode / * Left alt * / / * alt key while pressing the left? * /
479 je 4f // No, turn the key 4.
480 orb $ 0x80,% al // 7-bit character set.
// al characters into the read buffer queue.
481 4: andl $ 0xff,% eax // clear the high word of eax and ah.

482 xorl% ebx,% ebx // clear ebx.


483 call put_queue // characters into the buffer queue.
484 none: ret
485 486 / *

487 * Minus has a routine of it's own, as a 'E0h' before


488 * The scan code for minus means that the numeric keypad
489 * Slash was pushed.
490 * / / *

* Minus has its own processing subroutine, because 0xe0 minus sign before the scan code

* It means pressing the slash key on the numeric keypad.

*/
491 minus: cmpb $ 1, e0 // e0 flag is set yet?
492 jne do_self // no, the call do_self to the minus symbol for normal processing.

493 movl $ '/,% eax // Otherwise, the '/' Alternatively minus '-' al.

494 xorl% ebx,% ebx


495 jmp put_queue // and character into the buffer queue.
496 497 / *

498 * This table decides which routine to call when a scan-code has been
499 * Gotten. Most routines just call do_self, or none, depending if
500 * It is make or break.
501 * /
/ * Here is a subroutine address of the jump table. When the scan code after obtaining call processing routine corresponding scan code in accordance with this table.

* Most subroutine call is do_self, or none, which must then play button (make) or the release button (break).
*/
502 key_table:
503 . long none, do_self, do_self, do_self / * 00-03 s0 esc 1 2 * /
504 . long do_self, do_self, do_self, do_self / * * 04-073456 /
505 . long do_self, do_self, do_self, do_self / * 08-0B 7 8 9 0 * /
506 . long do_self, do_self, do_self, do_self / * 0C-0F + 'bs tab * /
507 . long do_self, do_self, do_self, do_self / * 10-13 qwer * /
508 . long do_self, do_self, do_self, do_self / * 14-17 tyui * /
509 . long do_self, do_self, do_self, do_self / * 18-1B op} ^ * /
510 . long do_self, ctrl, do_self, do_self / * 1C-1F enter ctrl as * /
511 . long do_self, do_self, do_self, do_self / * 20-23 dfgh * /
512 . long do_self, do_self, do_self, do_self / * 24-27 jkl | * /
513 . long do_self, do_self, lshift, do_self / * 28-2B {para lshift, * /
514 . long do_self, do_self, do_self, do_self / * 2C-2F zxcv * /
515 . long do_self, do_self, do_self, do_self / * 30-33 bnm, * /

--260--
7.4 keyboard.s program

516 . long do_self, minus, rshift, do_self / * 34-37 -. Rshift * * /


517 . long alt, do_self, caps, func / * 38-3B alt sp caps f1 * /
518 . long func, func, func, func / * 3C-3F f2 f3 f4 f5 * /
519 . long func, func, func, func / * 40-43 f6 f7 f8 f9 * /
520 . long func, num, scroll, cursor / * 44-47 f10 num scr home * /
521 . long cursor, cursor, do_self, cursor / * 48-4B up pgup - left * /
522 . long cursor, cursor, do_self, cursor / * 4C-4F n5 right + end * /
523 . long cursor, cursor, cursor, cursor / * 50-53 dn pgdn ins del * /
524 . long none, none, do_self, func / * 54-57 sysreq? <F11 * /
525 . long func, none, none, none / * 58-5B f12??? * /
526 . long none, none, none, none / * 5C-5F???? * /
527 . long none, none, none, none / * 60-63???? * /
528 . long none, none, none, none / * 64-67???? * /
529 . long none, none, none, none / * 68-6B???? * /
530 . long none, none, none, none / * 6C-6F???? * /
531 . long none, none, none, none / * 70-73???? * /
532 . long none, none, none, none / * 74-77???? * /
533 . long none, none, none, none / * 78-7B???? * /
534 . long none, none, none, none / * 7C-7F???? * /
535 . long none, none, none, none / * 80-83? Br br br * /
536 . long none, none, none, none / * 84-87 br br br br * /
537 . long none, none, none, none / * 88-8B br br br br * /
538 . long none, none, none, none / * 8C-8F br br br br * /
539 . long none, none, none, none / * 90-93 br br br br * /
540 . long none, none, none, none / * 94-97 br br br br * /
541 . long none, none, none, none / * 98-9B br br br br * /
542 . long none, unctrl, none, none / * 9C-9F br unctrl br br * /
543 . long none, none, none, none / * A0-A3 br br br br * /
544 . long none, none, none, none / * A4-A7 br br br br * /
545 . long none, none, unlshift, none / * A8-AB br br unlshift br * /
546 . long none, none, none, none / * AC-AF br br br br * /
547 . long none, none, none, none / * B0-B3 br br br br * /
548 . long none, none, unrshift, none / * B4-B7 br br unrshift br * /
549 . long unalt, none, uncaps, none / * B8-BB unalt br uncaps br * /
550 . long none, none, none, none / * BC-BF br br br br * /
551 . long none, none, none, none / * C0-C3 br br br br * /
552 . long none, none, none, none / * C4-C7 br br br br * /
553 . long none, none, none, none / * C8-CB br br br br * /
554 . long none, none, none, none / * CC-CF br br br br * /
555 . long none, none, none, none / * D0-D3 br br br br * /
556 . long none, none, none, none / * D4-D7 br br br br * /
557 . long none, none, none, none / * D8-DB br??? * /
558 . long none, none, none, none / * DC-DF???? * /
559 . long none, none, none, none / * E0-E3 e0 e1?? * /
560 . long none, none, none, none / * E4-E7???? * /
561 . long none, none, none, none / * E8-EB???? * /
562 . long none, none, none, none / * EC-EF???? * /
563 . long none, none, none, none / * F0-F3???? * /
564 . long none, none, none, none / * F4-F7???? * /
565 . long none, none, none, none / * F8-FB???? * /
566 . long none, none, none, none / * FC-FF???? * /
567 568 / *

--261--
7.4 keyboard.s program

569 * Kb_wait waits for the keyboard controller buffer to empty.


570 * There is no timeout - if the buffer does not empty, we hang.
571 * / / *

* Kb_wait subroutine for waiting for the keyboard controller buffer empty. There is no time-out process - if

* Buffer never empty, the program will wait forever (dead).


*/
572 kb_wait:
573 pushl% eax
574 1: inb $ 0x64,% al // read keyboard controller state.

575 testb $ 0x02,% al // test whether the input buffer is empty (equal to 0).

576 jne 1b // if not empty, then jump circular wait.


577 popl% eax
578 ret
579 / *
580 * This routine reboots the machine by asking the keyboard
581 * Controller to pulse the reset-line low.
582 * / / *

* This subroutine is provided by the keyboard controller, outputs a negative pulse reset line, to reset the system restart (reboot).

*/
583 reboot:
584 call kb_wait // First wait keyboard controller input buffer is empty.

585 movw $ 0x1234,0x472 / * Do not do memory check * /


586 movb $ 0xfc,% al / * Pulse reset and A20 low * /
587 outb% al, $ 0x64 // negative pulse to the reset line and A20.
588 die: jmp die // crash.

7.4.3 Other Information

7.4.3.1 AT Keyboard Interface Programming

The host system keyboard controller board is used intel 8042 Chip or a compatible chip, which diagram, see FIG. 7-6 Fig. Wherein the output port P2 They are used

for other purposes. Place 0 (P20 Pin) for implementing CPU Reset operation, the bit 1 ( P21 Pin) for control A20 On signal line or not. When the bit output port 0 for 1 When it is

turned on (Strobe) a A20 Signal line, as 0 Is prohibited A20

A signal line. See the boot program in the chapter on A20 Detailed description of the signal line.

--262--
7.4 keyboard.s program

Input port P1

8-bit CPU P10 NC NC NC NC


P11 system board RAM
P12 jumper mounted
ROM & RAM P13 display type key
P14 lock
P15
P16
(0x60) output buffer P17

Output port P2
Data (0x60) input buffer
Bus P20 A20 reset NC NC strobe output
P21 buffer full (the IRQ1) input buffer
(0x64) input buffer P22 empty (unused)
P23
P24
P25
(0x64) Status Register
P26 Keyboard clock (two-way)
P27 Keyboard Data (bidirectional)

Address, read and


T
write control logic test
T1

Map 7-6 Keyboard Controller 804X Schematic

Assigned to the keyboard controller IO Port range is 0x60-0x6f ,But in fact IBM CP / AT Use only 0x60 with 0x64 Two port address ( 0x61 , 0x62 with 0x63 And for XT Compatibility

purposes) Table 7-1 Shown, together with the meaning of the read and write operations of different ports, and thus may have major 4 Different operations. Keyboard controller is

programmed, the chip will involve status register, an input buffer and an output buffer.

table 7-1 Keyboard Controller 804X port

port Read / Write name use

Is a 8 Bit read-only register. When the controller receives the keyboard scan codes from the keyboard or a command
Data port or an output buffer
0x60 read response, the status register bit is set on the one hand 0 = 1 On the other hand generate an interrupt IRQ1 . Generally should

only state port bit 0 = 1 When reading.

For transmitting the command and / or subsequent parameter to a keyboard or write parameters to the keyboard controller.
0x60 write The input buffer
There are keyboard commands 10 And more, see the table after the description. Usually in the state should only port bit 1 = 0 When writing.

The port 0x61 Yes 8255A Output port B The address is for use / compatible 8255A of PC Standard keyboard processing

circuit performs hardware reset. The port is used to make a response to the scan code received. First method is prohibited

keyboard, and then immediately re-enabled keyboard. The operation data is: Bit 7 = 1 Prohibition keyboard; = 0 Allows the
0x61 Read / Write
keyboard; bit 6 = 0 Forcing the keyboard clock is low, so the keyboard can not send any data. Place 5-0 These bits are

independent of the keyboard, for a programmable parallel interface ( PPI) .

Is a 8 Bit read-only register bit fields which are meanings: Bit 7 = 1 Parity error data transmitted

from the keyboard; bits 1 6 = Receive Timeout (keyboard transfer has not occurred IRQ1) ; Bit 5

= 1 Send Timeout (keyboard does not respond); Bit 4 = 1 Keyboard interface keyboard lock is

disabled; [a = ?? 0 When] Bit 3 = 1 Data is written to the input buffer is a command (via port 0x64)
0x64 read Status Register
;

= 0 Data is written into the input buffer parameters (through port 0x60) ; Bit 2 System flag

status: 0 = On power-up or reset; 1 = Self-checking;

--263--
7.4 keyboard.s program

Place 1 = 1 Input Buffer Full ( 0x60 / 64 Mouth to 8042 Data); Bit 0 = 1 Output buffer full

(data port 0x60 There are data to the system).

Write command to the keyboard controller. You can take a parameter, the parameter from the port 0x60 Write. Keyboard
0x64 write The input buffer
controller command has 12 Article, see the table illustrates.

7.4.3.2 Keyboard command

In the port system 0x60 Write 1 Byte, it is to send keyboard commands. After receiving a command keyboard 20ms Response should be within that returns a command

response. After some commands need to keep up a parameter (also written to the port). Command List Table 7-2 Fig. Note that unless otherwise specified, all commands are sent

back to a 0xfa Response code ( ACK) .

table 7-2 Keyboard command list

Command code Parameter Function

Set / reset mode indicator. Put 1 Open, 0 shut down. Parameters byte: Bit 7-3 Are all

reserved 0 ; Bit 2 = caps-lock Key; bit 1 = num-lock Key; bit 0 = scroll-lock key.

0xed Have

0xee no Diagnostic response. Keyboard should be sent back 0xee .

0xef Are reserved.

Read / Set scan code set. Parameter byte is equal to:

0x00 - Select the current scan-code set;

0xf0 Have 0x01 - Selection scan code set 1( For PCs , PS / 2 30 Wait);

0x02 - Selection scan code set 2( For AT , PS / 2 , It is the default);

0x03 - Selection scan code set 3 .

0xf1 Are reserved.

0xf2 no Read the keyboard identification number (read 2 Bytes). AT Keyboard returns a response code 0xfa .

Rate and delay time setting scan code sent continuously. The meaning of parameter byte: Bit 7 Leave 0 ; Bit 6-5 Delay

value: Order C = Place 6-5 , There is a formula: latency value = ( 1 + C) * 250ms ; Bit 4-0 Scan code rate

transmitted continuously; Order B = Place 4-3 ; A = Place 2-0 , There is the formula: Rate = 1 / ((8 + A) * 2 ^ B *
0xf3 Have
0.00417) . The default parameter value 0x2c .

0xf4 no Open the keyboard.

0xf5 no Prohibited keyboard.

0xf6 no Set the default keyboard parameters.

0xf7-0xfd Are reserved.

0xfe no Retransmission scan code. When the system detects the keyboard to transmit data is an error, send the command.

Reset operation performed on a keyboard, called the basic assurance tests ( BAT) . During operation as follows:

1. Response is sent immediately after receiving the keyboard command 0xfa ;

0xff no 2. Keyboard controller so that the keyboard clock and data lines is asserted high;

3. Keyboard started BAT operating;

4. If completed normally, the keyboard sends 0xaa ; Otherwise transmit 0xfd And stop scanning.

--264--
7.4 keyboard.s program

7.4.3.3 The keyboard controller command

The system input buffer (port 0x64) Write 1 Byte, i.e. sends a command to the keyboard controller. You can take a parameter. Parameters is by writing 0x60

Sent by the port. Table 7-3 Fig.

table 7-3 The keyboard controller command list

command Parameter Function

0x20 no The last byte of a read command to the keyboard controller, on the port 0x60 For the system to read.

0x21-0x3f no Low read by the command 5 Bits specified internal controller RAM Commands.

Write keyboard controller command byte. The default value parameter byte :( 0x5d ) Bit 7 Leave 0 ; Bit 6 IBM PC Compatibility

mode (parity, the system is converted to a scan code, one-byte PC Disconnect code); Bit 5 PC Mode (without scan code

parity; the system is not converted into a scan code); Bit 4 Working disable the keypad (keyboard so that the clock is low); Bit

3 Beyond prohibited ( override) , Keyboard lock converter ineffective; bit 2 System flag; 1 Indicates that the controller works

0x60-0x7f Have correctly; bit 1 Leave 0 ; Bit 0 It allows the output register full interrupt.

0xaa no Keyboard controller initialization self-test. Successful return 0x55 ; Failure to return 0xfc .

Initialize keyboard interface test. Return bytes:

0x00 Error-free;

0x01 Keyboard clock line low (always low, low adhesion);


0xab no
0x02 Keyboard clock line is high;

0x03 Keyboard data line low;

0x04 Keyboard data line is high;

0xac no Diagnostic dump. 804x of 16 byte RAM , An output port, the input port are sequentially output to the system state.

0xad no Prohibition keyboard work (set command byte bit 4 = 1 ).

0xae no Allow the keyboard operation (Reset Command Byte Bit 4 = 0 ).

0xc0 No Reading 804x Input port P1 And placed 0x60 For reading;

0xd0 No Reading 804x Output port P2 And placed 0x60 For reading;

0xd1 Write 804x Output port P2 ,original IBM PC Using bit output port 2 control A20 door. Note that the bit 0 ( system
System Reset) should always set bit.

0xe0 no Read test end T0 with T1 An input buffer for the system to send the read output.
Place 1 Keyboard data; bit 0 Keyboard clock.

control led status. Put 1 Open, 0 shut down. Parameters byte: Bit 7-3 Are all

reserved 0 ; Bit 2 = caps-lock Key; bit 1 = num-lock Key; bit 0 = scroll-lock key.

0xed Have

Send pulses to the output port. The output port control command sequence P20-23 Line, the keyboard controller logic see FIG. To make

0xf0-0xff no what a negative output pulse ( 6 Sec), i.e., the bit is set 0 . That is the order of the low 4 Control the position of the negative pulse. For

example, to reset the system, you need to issue the command 0xfe (P20 Low) can be.

7.4.3.4 Keyboard scan codes

PC It is non-coding machine keyboard. Each key has a position number on the keyboard, from left to right from top to bottom. and PC XT

--265--
7.4 keyboard.s program

Machine and AT Keypad code location varies greatly. The microprocessor in the system is sent to the keyboard corresponding to the key scan code. When the key is pressed, the

keyboard scan code output is called ON ( make) Scan code when the key is sent is called loosening off ( break) Scan code. XT Each key keyboard scan code table 7-4 Fig.

Each key on the keyboard has a low byte contains 7 Bit (Bit 6-0 ) Corresponding scan code. At a high level (position 7 ) Represents a key or button is released. Place 7 = 0 Represents

just pressed the key scan code bits 7 = 1 It represents a scan code of the key release. For example, if someone had just ESC

Key is pressed, the scan code is transmitted to the system would be 1 ( 1 Yes ESC Key scan code), when releasing the key will produce 1 + 0x80 = 129 Scan code.

for PC , PC / XT Standard 83 Key keyboard, the key scan code number ON (key position code) is the same. And with 1 Bytes. E.g" A "Key, the key position number is 30 ,

Access code scan code is 0x1e . And it is on its off code is the scan code plus 0x80 , which is 0x9e . for AT Used machine 84/101/102 Extended keyboard, and then PC / XT Standard

keyboard vary widely.

For some "extended" keys, the situation is somewhat different. When an extended key is pressed, an interrupt is generated and the keyboard port outputs an

"extended" scan code prefix 0xe0 And on the next "break" will be given. For example, for PC / XT Standard keyboard, the left control key ctrl The scan code is 29 , And the

right of "extended" control key ctrl The scan code having a spreading 29 . This rule is also suitable for alt Arrow keys.

In addition, there are two key processing is very special. PrtScn Key and Pause / Break key. Press PrtScn Key keyboard program will be interrupted to send * 2* Extended

characters, 42 (0x2a) with 55 (0x37) , So the actual byte sequence will be 0xe0 , 0x2a , 0xe0 , 0x37 . However, transmitting only the spreading code is generated when the key repeat 0x37

. When the key is released again sent two plus extension 0x80 Code ( 0xe0 ,

0xaa , 0xe0 , 0xb7 ). when prtscn When the key is pressed, if shift or ctrl Key is also pressed, only the transmitted 0xe0 , 0x37 And transmits only upon release 0xe0 , 0xb7) .

for Pause / Break key. If you press this button while also pressing the Control key, the line will expand as key 70 , While it sends a character sequence in

other cases 0xe1 , 0x1d , 0x45 , 0xe1 , 0x9d , 0xc5 . The Press and will not repeat the scan code, but also does not release any key scan code.

Thus, it can be used to view and handle: scan code 0xe0 It means that there is a character followed, and the scan code 0xe1 It said later followed 2 Characters.

for AT Keyboard scan codes, and PC / XT Slightly different. When the key is pressed, the corresponding key scan code is sent, but the key is released, will be sent two

bytes, the first one is 0xf0 The first 2 A key scan code is the same. Designers now use the keyboard 8049 As a AT Keyboard input processor for backwards compatibility will AT Keyboard

scan code conversion issue has become old-fashioned PC / XT Standard keyboard scan codes.

AT There are three separate keyboard scan code set: one is that we described above ( 83 Key mapping, increases have extra keys 0xe0 Code), an almost sequence, there is

a but only 1 Bytes! The last one kind of problem is caused by only the left shift , caps ,left ctrl And left alt Release the key code is transmitted. The default keyboard scan code set is

the scan code set 2 , You can use the command change.

For the scan code set 1 with 2 With special code 0xe0 with 0xe1 . They have the keys for the same function. For example: left control key ctrl Location is 0x1d ( for PC /

XT) The control keys on the right is 0xe0 , 0x1d . This is to PC / XT Program compatibility. Please note that the only use 0xe1 The time when it means a temporary control keys, this

situation also has a 0xe0 version of.

table 7 - 4 X T key plate sweep Trace Stopwatch

F1 F2 `123 4 5 6 7 8 9 0 -= \ BS ESC NUML SCRL SYSR


3B 3C 29020 3 0 4 0 5 0 6 0 7 0 8 0 9 0 A 0 B 0 C 0D 2B 0E 01 45 46 **
F3 F4 TAB QW E R T Y U I O P [ ] Home ↑ PgUp PrtSc
3D 3E 0F 1 0 1 1 1 2 1 3 1 4 1 51 6 1 71 8 1 9 1 A 1 B 47 48 49 37
F5 F6 CNTL A S D F G H J K L ; ' ENTER ←5 → -
3F 40 1D 1 E 1 F 2 0 2 1 2 2 232 4 2 5 2 6 2 7 2 8 1C 4B 4C 4D 4A
F7 F8 LSHFT Z X C V B N M , ./ RSHFT End ↓ PgDn +
4142 2A 2 C 2D 2E 2F 30 31 32 33 34 3 53 6 4F 50 51 4E
F9 F0 ALT Space CAPLOCK Ins Del
3F 40 1D 39 3A 52 53

--266--
7.5 console.c program

7.5 console.c program

7.5.1 Functional Description

This is one of the longest in the kernel, but relatively simple function. All of which are routine in order to achieve the terminal screen write function con_write () And a

terminal initialization.

function con_write () From the terminal will tty_struct Write buffer queue structure write_q Remove the characters or character sequences, depending on the nature and

character (ordinary characters or escape sequences), the characters are displayed on the terminal screen, or some cursor movement, character control operation screens such as

an erasable.

Terminal screen initialization function con_init () The system is based on information obtained during system initialization, settings related to the basic parameters of the

screen, for con_write () Operation function.

For a description of the terminal device may be found in the character buffer queue include / linux / tty.h head File. Wherein the data structure is given character buffer

queue tty_queue The data structure of the terminal tty_struct And some of the value of the control characters. There are also a number of macro definition buffer queue operation.

Its schematic buffer queue operation Referring to FIG. 7-9 Fig.

7.5.2 Code comments

program 7-3 linux / kernel / chr_drv / console.c

1/*
2 * Linux / kernel / console.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8* console.c
9*
10 * This module implements the console io functions
11 * 'Void con_init (void)'
12 * 'Void con_write (struct tty_queue * queue)'
13 * Hopefully this will be a rather complete VT102 implementation.
14 *
15 * Beeping thanks to John T Kohl.
16 * /
/*
* The console module for input and output functions

* 'Void con_init (void)'


* 'Void con_write (struct tty_queue * queue)'
* Hopefully this is a very complete VT102 achieved.

*
* Thanks John T Kohl realized beep indication.
*/
1718 / *

19 * NOTE !!! We sometimes disable and enable interrupts for a short while
20 * (To put a word in video IO), but this will work even for keyboard

--267--
7.5 console.c program

twenty one * Interrupts. We know interrupts are not enabled when getting a keyboard
twenty two * Interrupt, as we use trap-gates. Hopefully all is well.
twenty three * /

/*
* Note !!! We sometimes briefly interrupts disabled and enabled (in a word (word) into the video IO), but even

* It is also possible for the keyboard interrupt work. Because we use a trap door, so we get to know in a
* When the keyboard interrupt is not allowed. I hope everything were normal.

*/
2425 / *

26 * Code to check for different video-cards mostly by Galen Hunt,


27 * < [email protected] >
28 * /
/*
* Detect different code cards are mostly written Galen Hunt,
* < [email protected] >
*/
2930 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

31 #include <linux / tty.h> // tty header file, which defines tty_io, aspects of the serial communication parameters constant.

32 #include <asm / io.h> // io header files. Defined hardware port I / O macro assembler statements.

33 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

3435 / *

36 * These are set up by the setup-routine at boot-time:


37 * /
/*
* These parameters are set setup subroutine disposed at system boot:
*/
38
// See the reading of the boot / setup.s notes, and setup procedures and keep the parameter list.

39 #define ORIG_X (* (Unsigned char *) 0x90000) // cursor column.


40 #define ORIG_Y (* (Unsigned char *) 0x90001) // cursor line number.

41 #define ORIG_VIDEO_PAGE (* (Unsigned short *) 0x90004) // display the page.


42 #define ORIG_VIDEO_MODE ((* (Unsigned short *) 0x90006) & 0xff) // display mode.
43 #define ORIG_VIDEO_COLS // number of characters in a column (((* (unsigned short *) 0x90006) & 0xff00) >> 8).

44 #define ORIG_VIDEO_LINES (25) // display the number of rows.

45 #define ORIG_VIDEO_EGA_AX (* (Unsigned short *) 0x90008) // [??]


46 #define ORIG_VIDEO_EGA_BX (* (Unsigned short *) 0x9000a) // display memory size and color mode.
47 #define ORIG_VIDEO_EGA_CX (* (Unsigned short *) 0x9000c) // show Carter parameters.
48
// definition of display monochrome / color constant symbol type display mode.

49 #define VIDEO_TYPE_MDA 0x10 / * Monochrome Text Display * / / * Monochrome text * /


50 #define VIDEO_TYPE_CGA 0x11 / * CGA Display * / / * CGA monitor * /
51 #define VIDEO_TYPE_EGAM 0x20 / * EGA / VGA in Monochrome Mode * / / * EGA / VGA monochrome * /

52 #define VIDEO_TYPE_EGAC 0x21 / * EGA / VGA in Color Mode * / / * EGA / VGA color * /
5354 #define NPAR 16

5556 extern void keyboard_interrupt (Void);


// keyboard interrupt handler (keyboard.S).
5758 static unsigned char
video_type ; / * Type of display being used */

--268--
7.5 console.c program

/ * Display type used * /


59 static unsigned long video_num_columns ; / * Number of text columns */
/ * Screen number of columns of text * /

60 static unsigned long video_size_row ; / * Bytes per row */


/ * Number of bytes per line use * /

61 static unsigned long video_num_lines ; / * Number of test lines */


/ * Screen Lines of text * /
62 static unsigned char video_page ; / * Initial video page */
/ * Initial display page * /
63 static unsigned long video_mem_start ; / * Start of video RAM */
/ * Start address of the display memory * /

64 static unsigned long video_mem_end ; / * End of video RAM (sort of) */


/ * End of the display memory (terminal) address * /

65 static unsigned short video_port_reg ; / * Video register select port */


/ * Index register display control port * /
66 static unsigned short video_port_val ; / * Video register value port */
/ * Display control port data register * /
67 static unsigned short video_erase_char ; / * Char + Attrib to erase with */
/ * Erase character attributes and character (0x0720) * /

68
// the following variables are used to screen scrolling operations.

69 static unsigned long origin ; / * Used for EGA / VGA fast scroll * / // scr_start. / * For EGA / VGA fast
scrolling * / // scroll starting memory address.
70 static unsigned long scr_end ; / * Used for EGA / VGA fast scroll * /
/ * For EGA / VGA fast scrolling * / // Scroll end memory address.
71 static unsigned long pos ; // current cursor position corresponding to the display memory.

72 static unsigned long x,y; // the current cursor position.

73 static unsigned long top , bottom ; // top-line number when scrolling; bottom line number.

// state for the current step indicated at process ESC escape sequence. npar, par [] for storing intermediate processing parameters ESC sequence.

74 static unsigned long state = 0; // ANSI escape sequences processing status.

75 static unsigned long npar , par [ NPAR ]; // ANSI escape sequence number of parameters and the parameter array.

76 static unsigned long ques = 0;


77 static unsigned char attr = 0x07; // character attributes (white on black).

7879 static void sysbeep (Void);


// system beep function.
8081 / *

82 * This is what the terminal answers to a ESC-Z or csi0c


83 * Query (= vt100 response).
84 * /
/*
* The following is a response to the terminal response ESC-Z or csi0c request (= vt100 response).

*/
// csi - preamble sequence control (Control Sequence Introducer).
85 #define RESPONSE "\ 033 [1;? 2c"
8687 / * NOTE! Gotoxy thinks x == video_num_columns is ok * /

/ * Note! gotoxy function think x == video_num_columns, that's right * / //// tracking the current
cursor position.
// Parameters: new_x - cursor column number; new_y - cursor line number.

// Update the current cursor position variables x, y, and correction points corresponding to the position pos cursor in the display memory.

88 static inline void gotoxy (Unsigned int new_x, unsigned int new_y)
89 {

--269--
7.5 console.c program

// If the cursor is beyond the number of the input line number display column, or cursor line number exceeds the maximum number of lines displayed, exit.

90 if (new_x> video_num_columns || new_y> = video_num_lines )


91 return;
// Update the current cursor variable; update the cursor position in the display memory corresponding to the position of the variable pos.

92 x = New_x;
93 y = New_y;
94 pos = origin + y * video_size_row + ( x << 1);
95 }
96
//// scroll start display memory address is provided.

97 static inline void set_origin (Void)


98 {
99 cli ();
// First select the display control data register r12, then scrolling writing start address high byte. 9 moved to the right, rightward indicates // 8 divided by two (2 bytes represent

characters on a screen). With respect to the default display memory operations.

100 outb_p (12, video_port_reg );


101 outb_p (0xff & (( origin - video_mem_start ) >> 9), video_port_val );
// select the display control data register r13, and then write the start address bottom scrolling bytes. Move one to the right represents a divide by two.

102 outb_p (13, video_port_reg );


103 outb_p (0xff & (( origin - video_mem_start ) >> 1), video_port_val );
104 sti ();
105 }
106
//// scroll up one line (the window moves down the screen). // screen window down one line.

See a list of instructions after the procedure.

107 static void scrup (Void)


108 {
// If the display type is EGA, do the following.
109 if ( video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM )
110 {
// If the mobile start line top = 0, moving the bottom row bottom = video_num_lines = 25, it means that the entire screen window is moved downward.

111 if (! top && bottom == video_num_lines ) {


// adjust the screen memory corresponding to the start position pointer memory location corresponding to the origin of the screen down one line of characters, but also the current cursor

position adjustment // memory location corresponding to the end of the last line of the screen and the character pointers scr_end.

112 origin + = video_size_row ;


113 pos + = video_size_row ;
114 scr_end + = video_size_row ;
// If the end of the last one display screen corresponding to the character display memory pointer beyond the end scr_end actual display memory, then the contents of the screen memory data

// moved to the display memory at the starting position video_mem_start, and appear on a new line fill the space character.

115 if ( scr_end > video_mem_end ) {


//% 0 - eax (erase character attributes +);% 1 - ecx (number of characters (character display rows -1), corresponding to / 2, is a longword move); //% 2 - edi (Display memory start

position video_mem_start);% 3 - esi (the contents of the screen memory corresponding to the starting position of origin). @ Moving direction: [edi] [esi], the mobile ecx longword.

116 __asm ​__ ( " cld \ n \ t " // clear direction bit.

117 "Rep \ n \ t" // Repeat the current screen data memory


118 "Movsl \ n \ t" // moved to the display memory at the start.

119 "Movl _video_num_columns,% 1 \ n \ t" // ecx = 1 line characters.


120 "Rep \ n \ t" // fill the space character on a new line.

121 "Stosw"
122 :: " a "( video_erase_char ),
123 "C" (( video_num_lines -1)* video_num_columns >> 1),
124 "D" ( video_mem_start ),
125 "S" ( origin )

--270--
7.5 console.c program

126 : " cx "," di "," si ");


The situation after the // screen memory data movement, readjust the current screen corresponding to the memory start pointer, a cursor position pointer and the corresponding end of the

screen memory pointers // scr_end.

127 scr_end - = origin - video_mem_start ;


128 pos - = origin - video_mem_start ;
129 origin = video_mem_start ;
130 } Else {
// If the end of the screen memory corresponding to the adjusted pointer does not exceed the display memory scr_end end video_mem_end, simply fill in the erased // new line characters

(space character).

//% 0 - eax (erase character attributes +);% 1 - ecx (number of character rows in the display);% 2 - edi (corresponding to the last line of the screen at the start of memory);

131 __asm ​__ ( " cld \ n \ t " // clear direction bit.

132 "Rep \ n \ t" // Repeat, emerging on the line


133 "Stosw" // Fill the erase character (space character).

134 :: " a "( video_erase_char ),


135 "C" ( video_num_columns ),
136 "D" ( scr_end - video_size_row )
137 : " cx "," di ");
138 }
Memory start position value corresponding to the new screen content is written to the display controller //.

139 set_origin ();


// otherwise not represent the entire screen movement. That means that all rows starting from the top row designated row 1 is moved upward (to delete one line). // At this time, directly

corresponding to the screen will move from the top row to the end of the specified screen display memory data of all rows up one line, and rub // fill in the row of characters in addition to

emerging.

//% 0-eax (erase character attributes +);% 1-ecx (top row rows beginning at row 1 to the last line of the screen memory corresponding to the length of words); //% 2-edi (top row at

memory location);% 3-esi (top + 1 rows in which the memory location).

140 } Else {
141 __asm ​__ ( " cld \ n \ t " // clear direction bit.

142 "Rep \ n \ t" // cycles, the bottom line to the top + 1


143 "Movsl \ n \ t" // the corresponding memory block is moved at the beginning of top row.

144 "Movl _video_num_columns, %% ecx \ n \ t" // ecx = 1 line characters.


145 "Rep \ n \ t" // Fill the erase character on a new line.

146 "Stosw"
147 :: " a "( video_erase_char ),
148 "C" (( bottom - top -1)* video_num_columns >> 1),
149 "D" ( origin + video_size_row * top ),
150 "S" ( origin + video_size_row * ( top +1))
151 : " cx "," di "," si ");
152 }
153 }
// If the display type is not EGA (a MDA), is performed following the move operation. Because MDA display controller automatically adjusts the display case exceeds the range // around, i.e.

automatically scrolling pointer, corresponding to the case where the memory does not exceed the contents of the screen display memory separately. // processing method and the

non-movement of the entire screen exactly the same EGA.

154 else / * Not EGA / VGA * /


155 {
156 __asm ​__ ( " cld \ n \ t "
157 "Rep \ n \ t"
158 "Movsl \ n \ t"
159 "Movl _video_num_columns, %% ecx \ n \ t"
160 "Rep \ n \ t"
161 "Stosw"
162 :: " a "( video_erase_char ),
163 "C" (( bottom - top -1)* video_num_columns >> 1),
164 "D" ( origin + video_size_row * top ),

--271--
7.5 console.c program

165 "S" ( origin + video_size_row * ( top +1))


166 : " cx "," di "," si ");
167 }
168 }
169
//// scroll down one line (window screen upward movement).

// window moves up one line screen, the screen display content moving down one line, a new line appeared to be moved over the start line. Description See the list of programs // later.

Processing method scrup () is similar to, but does not appear to display data in a mobile cover case error // condition, copying is performed when the reverse direction the data memory, i.e., the

reciprocal of the last character of the line from the copied second start screen

170 static void scrdown (Void)


171 {
// If the display type is EGA, the following operation is performed.

// [?? if and else seems to operate exactly the same ah! Why were you deal with it? Is it relevant to the task switching? ]

172 if ( video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM )


173 {
//% 0-eax (erase character attributes +);% 1-ecx (top row to the start line of the screen the number of memory words long last line corresponding to the row -1); lower right

corner //% 2-edi (Screen Finally, a long word location);% 3-esi (screen penultimate line last word length position). @ Moving direction: [esi] [edi], the mobile ecx longword.

174 __asm ​__ ( " std \ n \ t " // set direction bit.


175 "Rep \ n \ t" // repeat the operation, the line is moved downward from the top row to the bottom-1

176 "Movsl \ n \ t" // corresponding memory data.

177 "Addl $ 2, %% edi \ n \ t" / *% Edi has been decremented by 4 * /


/ *% Edi has been reduced 4, because the direction is to fill the erase character * /

178 "Movl _video_num_columns, %% ecx \ n \ t" // Ecx = 1 is set number of lines of characters.

179 "Rep \ n \ t" // erases the character to fill the top of the new line.

180 "Stosw"
181 :: " a "( video_erase_char ),
182 "C" (( bottom - top -1)* video_num_columns >> 1),
183 "D" ( origin + video_size_row * bottom -4)
184 "S" ( origin + video_size_row * ( bottom -1) -4)
185 : " ax "," cx "," di "," si ");
186 }
// If not EGA display type, do the following (at present exactly the same as above).
187 else / * Not EGA / VGA * /
188 {
189 __asm ​__ ( " std \ n \ t "
190 "Rep \ n \ t"
191 "Movsl \ n \ t"
192 "Addl $ 2, %% edi \ n \ t" / *% Edi has been decremented by 4 * /
193 "Movl _video_num_columns, %% ecx \ n \ t"
194 "Rep \ n \ t"
195 "Stosw"
196 :: " a "( video_erase_char ),
197 "C" (( bottom - top -1)* video_num_columns >> 1),
198 "D" ( origin + video_size_row * bottom -4)
199 "S" ( origin + video_size_row * ( bottom -1) -4)
200 : " ax "," cx "," di "," si ");
201 }
202 }
203
//// position of the cursor down one line (lf - line feed newline).
204 static void lf (Void)
205 {

--272--
7.5 console.c program

// If the cursor was not in the penultimate line, the current line of the cursor directly modify the variable y ++, and adjusts the display memory location corresponding to the cursor // POS (plus

screen memory corresponding to the character line length).

206 if ( y +1 < bottom ) {


207 y ++;
208 pos + = video_size_row ;
209 return;
210 }
// Otherwise, we need to move up one row on the screen contents.

211 scrup ();


212 }
213
//// cursor up one line (ri - reverse line feed reverse line feed).
214 static void ri (Void)
215 {
// If the cursor is not on the first line, directly modifying the current cursor row scalar-y -, and adjusts the display memory corresponding to the cursor position POS, the length of bytes by

subtracting the number of memory // row of characters on the screen corresponds.

216 if ( y > top ) {


217 y -;
218 pos - = video_size_row ;
219 return;
220 }
// otherwise you need to screen content down one line.

221 scrdown ();


222 }
223
// cursor back to the first one (0) left end (cr - carriage return carriage return).
224 static void cr (Void)
225 {
Column No. 2 // cursor i.e. 0 * memory byte length corresponding to the column where the cursor.

226 pos - = x << 1;


227 x = 0;
228 }
229
// cursor erasing the previous character (with spaces substitute) (del - delete delete).

230 static void del (Void)


231 {
// If the cursor is not at 0, then the cursor pointer memory location corresponding to retracted pos 2 bytes (corresponding to a character on the screen), then the cursor // Variables value

minus 1, and the cursor position of a character erase .

232 if ( x ) {
233 pos - = 2;
234 x -;
235 * (Unsigned short *) pos = video_erase_char ;
236 }
237 }
238
//// delete portions associated with the cursor position on the screen, in screen units. csi - preamble sequence control (Control Sequence // Introducer).

// ANSI escape sequences: 'ESC [sJ' (s = 0 to the bottom of the screen cursor is deleted; 1 starts to remove the screen cursor; 2 deleted the entire screen). // Parameters: par - corresponding

to the above s.

239 static void csi_J (Int par )


240 {
241 long count __asm ​__ ( " cx "); // set to register variables.
242 long start __asm ​__ ( " di ");

--273--
7.5 console.c program

243
// first need to remove were set according to the number of characters and three cases of display memory deletion start position.

244 switch ( par ) {


245 case 0: / * erase from cursor to end of display * / / * Erasing the cursor to the bottom of the screen * /

246 count = ( scr_end - pos ) >> 1;


247 start = pos ;
248 break;
249 case 1: / * erase from start to cursor * / / * Deleted from the screen to start the character at the cursor * /

250 count = ( pos - origin ) >> 1;


251 start = origin ;
252 break;
253 case 2: / * erase whole display * / / * Delete characters on the entire screen * /

254 count = video_num_columns * video_num_lines ;


255 start = origin ;
256 break;
257 default:
258 return;
259 }
// then use the erase character to delete characters to fill in place.

//% 0 - ecx (the number of characters you want to delete count);% 1 - edi (delete start address);% 2 - eax (fill in the erase character).

260 __asm ​__ ( " cld \ n \ t "


261 "Rep \ n \ t"
262 "Stosw \ n \ t"
263 :: " c "( count ),
264 "D" ( start), " a "( video_erase_char )
265 : " cx "," di ");
266 }
267
//// delete some associated with the cursor position within the line to a line unit.

// ANSI escape sequences: 'ESC [sK' (s = 0 to the end of the line deleted; 1 removed from the beginning; delete whole line 2).

268 static void csi_K (Int par )


269 {
270 long count __asm ​__ ( " cx "); // set the register variable.
271 long start __asm ​__ ( " di ");
272
// first need to remove were set according to the number of characters and three cases of display memory deletion start position.

273 switch ( par ) {


274 case 0: / * erase from cursor to end of line * / / * Delete the cursor to the end of line characters * /

275 if ( x > = video_num_columns )


276 return;
277 count = video_num_columns - x ;
278 start = pos ;
279 break;
280 case 1: / * erase from start of line to cursor * / / * Deleted from the beginning of the line to the cursor * /

281 start = pos - ( x << 1);


282 count = ( x < video_num_columns )? x : video_num_columns ;
283 break;
284 case 2: / * erase whole line * / / * The entire line of characters all deleted * /

285 start = pos - ( x << 1);


286 count = video_num_columns ;
287 break;
288 default:
289 return;

--274--
7.5 console.c program

290 }
// then use the erase character to delete characters to fill in place.

//% 0 - ecx (the number of characters you want to delete count);% 1 - edi (delete start address);% 2 - eax (fill in the erase character).

291 __asm ​__ ( " cld \ n \ t "


292 "Rep \ n \ t"
293 "Stosw \ n \ t"
294 :: " c "( count ),
295 "D" ( start), " a "( video_erase_char )
296 : " cx "," di ");
297 }
298
//// allow translation (reproduce) (permission to reset the character display, such as bold, underline, blinking, reverse video, etc.). // ANSI escape sequences:

'ESC [nm'. n = 0 normal display; 1 bold; 4 underlined; reverse display 7; 27 normal display.

299 void csi_m (Void)


300 {
301 int i;
302
303 for (i = 0; i <= npar ; I ++)
304 switch ( par [I]) {
305 case 0: attr = 0x07; break;
306 case 1: attr = 0x0f; break;
307 case 4: attr = 0x0f; break;
308 case 7: attr = 0x70; break;
309 case 27: attr = 0x07; break;
310 }
311 }
312
//// The setting cursor is displayed.

// The display memory corresponding to the cursor position pos, set the display position of the cursor controller.

313 static inline void set_cursor (Void)


314 {
315 cli ();
// first index register is used to select the display control port data register R14 (high byte of the current cursor display position), and then write the current position cursor // high byte (9

move to the right indicates low byte and then moved to the high byte divided by 2). With respect to the default display memory operations.

316 outb_p (14, video_port_reg );


317 outb_p (0xff & (( pos - video_mem_start ) >> 9), video_port_val );
// then using the index register selection r15, and the current cursor position wherein the low byte is written.

318 outb_p (15, video_port_reg );


319 outb_p (0xff & (( pos - video_mem_start ) >> 1), video_port_val );
320 sti ();
321 }
322
//// VT100 terminal transmits a response to the sequence. // read the

response sequence into the buffer queue.

323 static void respond (Struct tty_struct * Tty)


324 {
325 char * p = RESPONSE ;
326
327 cli (); // disable interrupts.

328 while (* p) { // sequence of characters written into the queue.

329 PUTCH (* P, tty-> read_q);


330 p ++;
331 }

--275--
7.5 console.c program

332 sti (); // open the interruption.

333 copy_to_cooked (Tty); // pattern into a canonical (into the auxiliary queue).

334 }
335
//// insert a space character at the cursor position.

336 static void insert_char (Void)


337 {
338 int i = x ;
339 unsigned short tmp, old = video_erase_char ;
340 unsigned short * p = (unsigned short *) pos ;
341
// all the characters after the cursor one space to the right, and the erase character is inserted at the cursor. // if the line has a

character, then the line will not be the last character modifiers ☺?

342 while (i ++ < video_num_columns ) {


343 tmp = * p;
344 * P = old;
345 old = tmp;
346 p ++;
347 }
348 }
349
//// row is inserted at the cursor (the cursor is on the new blank line). // the screen cursor to row

from the bottom of the screen to scroll down one line.

350 static void insert_line (Void)


351 {
352 int oldtop, oldbottom;
353
354 oldtop = top ; // Save the original top, bottom value.

355 oldbottom = bottom ;


356 top = y ; // set the screen to scroll the start line.

357 bottom = video_num_lines ; // set the screen to scroll the last line.

358 scrdown (); // From the beginning of the cursor, the contents of the screen to scroll down one line.

359 top = Oldtop; // restore the original top, bottom value.

360 bottom = Oldbottom;


361 }
362
//// delete a character at the cursor.
363 static void delete_char (Void)
364 {
365 int i;
366 unsigned short * p = (unsigned short *) pos ;
367
// If the cursor is beyond the rightmost column of the screen, is returned.

368 if ( x > = video_num_columns )


369 return;
// Right from the cursor one character to the beginning of the end of the line all the characters to the left one space.

370 i=x;
371 while (++ i < video_num_columns ) {
372 * p = * (p + 1);
373 p ++;
374 }
// Fill erase the last character of the character (the space character).

375 * P = video_erase_char ;

--276--
7.5 console.c program

376 }
377
//// cursor to delete rows.
// volume line from the start line where the cursor onscreen.

378 static void delete_line (Void)


379 {
380 int oldtop, oldbottom;
381
382 oldtop = top ; // Save the original top, bottom value.

383 oldbottom = bottom ;


384 top = y ; // set the screen to scroll the start line.

385 bottom = video_num_lines ; // set the screen to scroll the last line.

386 scrup (); // From the beginning of the cursor, the contents of the screen to scroll up one line.

387 top = Oldtop; // restore the original top, bottom value.

388 bottom = Oldbottom;


389 }
390
//// nr characters inserted at the cursor. // ANSI escape
sequences: 'the ESC [ n-@ '. Nr = n // parameters above.

391 static void csi_at (Unsigned int nr)


392 {
// If the number of characters greater than the number of inserted characters of a line, the number of characters of a line is cut; if the number of characters inserted nr is 0, then insert a character.

393 if (nr> video_num_columns )


394 nr = video_num_columns ;
395 else if (! nr)
396 nr = 1;
// Loop insert specified number of characters.

397 while (nr--)


398 insert_char ();
399 }
400
//// rows inserted at the cursor position nr. // ANSI
escape sequences 'ESC [nL'.
401 static void csi_L (Unsigned int nr)
402 {
// If the number of rows is greater than the maximum number of insert rows of the screen, then truncated to the number of lines displayed; if the number of rows inserted nr is 0, then insert a row.

403 if (nr> video_num_lines )


404 nr = video_num_lines ;
405 else if (! nr)
406 nr = 1;
// Loop inserts the specified number of rows nr.

407 while (nr--)


408 insert_line ();
409 }
410
//// delete nr character at the cursor. // ANSI
escape sequences: 'ESC [nP'.
411 static void csi_P (Unsigned int nr)
412 {
// If the number of characters to delete is greater than the number of characters in a row, the cut-off line for the number of characters; if the number of characters to delete nr is zero, one character is deleted.

413 if (nr> video_num_columns )


414 nr = video_num_columns ;

--277--
7.5 console.c program

415 else if (! nr)


416 nr = 1;
// Loop delete the specified number of characters nr.

417 while (nr--)


418 delete_char ();
419 }
420
//// delete the cursor at the line nr. // ANSI escape
sequences: 'ESC [nM'.
421 static void csi_M (Unsigned int nr)
422 {
// If the number of lines to delete is greater than the maximum number of lines the screen, the screen displays the number of lines to cut; if deleted rows nr is 0, then delete one line.

423 if (nr> video_num_lines )


424 nr = video_num_lines ;
425 else if (! nr)
426 nr = 1;
// Loop delete the specified number of rows nr.

427 while (nr--)


428 delete_line ();
429 }
430 431 static int saved_x = 0;
// Save the cursor column.
432 static int saved_y = 0; // cursor line number saved.

433
//// it saves the current cursor position.

434 static void save_cur (Void)


435 {
436 saved_x = x ;
437 saved_y = y ;
438 }
439
//// restore the saved cursor position.

440 static void restore_cur (Void)


441 {
442 gotoxy ( saved_x , saved_y );
443 }
444
//// console write function.
// write buffer queue corresponding to the terminal from the tty fetch characters and displayed on the screen.

445 void con_write (Struct tty_struct * Tty)


446 {
447 int nr;
448 char c;
449
// get first write buffer queue existing number of characters nr, then processed for each character.

450 nr = CHARS (Tty-> write_q);


451 while (nr--) {
// get a character from the write queue c, respectively, according to the processing status of characters previously processed state. Conversion between state: // state =

0: an initial state; originally state or 4; or a state originally, but not the character '['; //

1: 0 state was originally, and the character is an escape character ESC (0x1b = 033 = 27);

// 2: 1 was originally state, and the character is a '[';

// 3: 2 was originally state; state or was originally 3, and the character is a ';' or digital.

// 4: 3 originally state, and the character is not a ';' or digital;

--278--
7.5 console.c program

452 GETCH (Tty-> write_q, c);


453 switch ( state ) {
454 case 0:
// If the character is not a control character (c> 31), and is not extended characters (c <127), then

455 if (c> 31 && c <127) {


// if the current cursor is beyond the end of row or end of column head will move the cursor downward. And adjusting the cursor position memory pointer corresponding to pos.

456 if ( x > = video_num_columns ) {


457 x - = video_num_columns ;
458 pos - = video_size_row ;
459 lf ();
460 }
// display the character c is written at the memory pos, and the cursor right one, but also 2 bytes pos move correspondingly.

461 __asm ​__ ( " movb _attr, %% ah \ n \ t "


462 "Movw %% ax,% 1 \ n \ t"
463 :: " a "( c), " m "(* ( short *) pos )
464 : " ax ");
465 pos + = 2;
466 x ++;
// If the character c is the escape character ESC, the conversion state to state 1.

467 } Else if (c == 27)


468 state = 1;
// If the character c is a line feed (10), or vertical tab VT (11), or a page break FF (12), move the cursor to the next line.
469 else if (c == 10 || c == 11 || c == 12)
470 lf ();
// If c is a carriage return character CR (13), then the cursor moves to the head column (0).

471 else if (c == 13)


472 cr ();
// If the character c is a DEL (127), then the right of the cursor erasing a character (a space character), and move the cursor position is erased.

473 else if (c == ERASE_CHAR (Tty))


474 del ();
// If the character c is a BS (backspace, 8), then the cursor right frame 1, and adjusts the cursor pointer memory location corresponding to pos.

475 else if (c == 8) {
476 if ( x ) {
477 x -;
478 pos - = 2;
479 }
// If the character c is a horizontal tab TAB (9), the cursor will be a multiple of 8 columns. If the cursor is at this time the number of columns exceeds the maximum number of columns of the

screen, then // cursor to the next line.

480 } Else if (c == 9) {
481 c = 8- ( x & 7);
482 x + = C;
483 pos + = C << 1;
484 if ( x > video_num_columns ) {
485 x - = video_num_columns ;
486 pos - = video_size_row ;
487 lf ();
488 }
489 c = 9;
// If the character c is the bell character BEL (7), beep function is called, is the sound from the speakers.

490 } Else if (c == 7)
491 sysbeep ();
492 break;
// 0 if the original state, and the character is an escape character ESC (0x1b = 033 = 27), then the process moves to a state 1.

--279--
7.5 console.c program

493 case 1:
494 state = 0;
// If character c is '[', the state will go to state 2.
495 if (c == '[')
496 state = 2;
// If the character c is 'E', then move to the next row at the beginning (0).

497 else if (c == ' E ')


498 gotoxy (0, y +1);
// If the character c is 'M', the cursor up one line.
499 else if (c == ' M ')
500 ri ();
// If the character c is 'D', then the cursor down one line.

501 else if (c == ' D ')


502 lf ();
// If the character c is a 'Z', then the terminal transmits a response character sequence.

503 else if (c == ' Z')


504 respond (Tty);
// If the character c is '7', then save the current cursor position. Note that this code is wrong! It should be (c == '7').

505 else if ( x == ' 7 ')


506 save_cur ();
// If the character c is '8', then return to the original saved cursor position. Note that this code is wrong! It should be (c == '8').

507 else if ( x == ' 8')


508 restore_cur ();
509 break;
// If the original state is 1, and the character is a '[', go to state 2 treated.
510 case 2:
// first array of processing parameters par ESC escape sequences used in [] is cleared, the index variable to point npar first item, and the setting state // 3. If the character is not at this

time '?', Then go directly to the state 3 to deal with, or to read a character, and then to state 3 at handling code.

511 for ( npar = 0; npar < NPAR ; npar ++)


512 par [ npar ] = 0;
513 npar = 0;
514 state = 3;
515 if ( ques = (C == '?'))
516 break;
// If the original state is 2; or that the original state 3, but the original character is ';' or number, in the following process.

517 case 3:
// If the character c is a semicolon ';', and par full array, the index value plus one.

518 if (c == ';' && npar < NPAR -1) {


519 npar ++;
520 break;
C // if the character is a numeric character '0' - '9', then the character is converted into an index value and the items with the composition npar decimal.

521 } Else if (c> = '' && c <= ' 9') {


522 par [ npar ] = 10 * par [ npar ] + C- '';
523 break;
// otherwise go to state 4.
524 } Else state = 4;
// If the original state is state 3, and the character is not a ';' or digital, the process moves to a state 4. First reset state = 0.

525 case 4:
526 state = 0;
527 switch (c) {
// If the character c is a 'G' or '' ', the PAR [] the first parameter represents a column number. If the column number is not zero, then the cursor right one space.

528 case ' G ': case ' `':


529 if ( par [0]) par [0] -;

--280--
7.5 console.c program

530 gotoxy ( par [0], y );


531 break;
// If the character c is 'A', the first parameter represents the number of shifts in the cursor line. If the parameter is 0 move up one row.

532 case ' A ':


533 if (! par [0]) par [0] ++;
534 gotoxy ( x , y - par [0]);
535 break;
// If the character c is a 'B' or 'e', ​the first parameter represents a number of lines of the cursor down. If the parameter is 0 down one line.

536 case ' B ': case ' e ':


537 if (! par [0]) par [0] ++;
538 gotoxy ( x , y + par [0]);
539 break;
// If the character c is a 'C' or 'a', the first parameter represents a number of cells of the cursor right. If the parameter is 0 to the right of a cell.

540 case ' C ': case ' a ':


541 if (! par [0]) par [0] ++;
542 gotoxy ( x + par [0], y );
543 break;
// If the character c is 'D', the first parameter represents the number of the cell cursor to the left. If the parameter is 0 character left.

544 case ' D ':


545 if (! par [0]) par [0] ++;
546 gotoxy ( x - par [0], y );
547 break;
// If the character c is 'E', the number of rows in the first parameter represents a downward movement of the cursor, and back to 0. If the parameter is 0 down one line.

548 case ' E ':


549 if (! par [0]) par [0] ++;
550 gotoxy (0, y + par [0]);
551 break;
// If the character c is 'F', the first parameter represents the number of rows in the cursor upward, and returned to 0. If the parameter is 0 move up one row.

552 case ' F ':


553 if (! par [0]) par [0] ++;
554 gotoxy (0, y - par [0]);
555 break;
// If the character c is a 'd', then the first parameter represents the cursor in the desired line number (from 0).

556 case ' d ':


557 if ( par [0]) par [0] -;
558 gotoxy ( x , par [0]);
559 break;
// If the character c is 'H' or 'f', then the first parameter represents a line number of the cursor, the second parameter represents the column number of the cursor.

560 case ' H ': case ' f ':


561 if ( par [0]) par [0] -;
562 if ( par [1]) par [1]--;
563 gotoxy ( par [1], par [0]);
564 break;
// If the character c is a 'J', the first parameter represents the cursor position in the screen is cleared by:

// ANSI escape sequences: 'ESC [sJ' (s = 0 to the bottom of the screen cursor is deleted; 1 starts to remove the screen cursor; 2 deleted the entire screen).

565 case ' J ':


566 csi_J ( par [0]);
567 break;
// If the character c is 'K', the first parameter represents the position of the cursor to row deletion processing mode characters. // ANSI escape sequences: 'ESC

[sK' (s = 0 to the end of the line deleted; 1 removed from the beginning; delete whole line 2).

568 case ' K ':


569 csi_K ( par [0]);
570 break;

--281--
7.5 console.c program

// If the character c is 'L', n represents a row insert (ANSI escape sequences 'ESC [nL') at the cursor position.

571 case ' L ':


572 csi_L ( par [0]);
573 break;
// If the character c is 'M', n represents the deleted row (ANSI escape sequences 'ESC [nM') at the cursor position.

574 case ' M ':


575 csi_M ( par [0]);
576 break;
// If the character c is a 'P', n denotes deleted characters (ANSI escape sequences 'ESC [nP') at the cursor position.

577 case ' P ':


578 csi_P ( par [0]);
579 break;
// If a character c '@' represent insertion n characters (ANSI escape sequences 'the ESC [at the cursor position n @ ').

580 case '@':


581 csi_at ( par [0]);
582 break;
// If the character c is 'm', represents a change of character at cursor display attribute, such as bold, underline, blinking, reverse video and the like. // ANSI escape

sequences: 'ESC [nm'. n = 0 normal display; 1 bold; 4 underlined; reverse display 7; 27 normal display.

583 case ' m ':


584 csi_m ();
585 break;
// If the character c is 'r', said set starting line number and the end line number with the two parameters of scrolling.

586 case ' r ':


587 if ( par [0]) par [0] -;
588 if (! par [1]) par [1] = video_num_lines ;
589 if ( par [0] < par [1] &&
590 par [1] <= video_num_lines ) {
591 top = par [0];
592 bottom = par [1];
593 }
594 break;
// If the character c is 's', it means to save the current cursor position.

595 case ' s':


596 save_cur ();
597 break;
// If the character c is a 'u', it indicates that the cursor is restored to the original position stored.

598 case ' u ':


599 restore_cur ();
600 break;
601 }
602 }
603 }
// Finally, according to the cursor position set above, the display controller transmits the cursor display position.

604 set_cursor ();


605 }
606 607 /
*
608 * Void con_init (void);
609 *
610 * This routine initalizes console interrupts, and does nothing
611 * Else. If you want the screen to clear, call tty_write with
612 * The appropriate escape-sequece.
613 *

--282--
7.5 console.c program

614 * Reads the information preserved by setup.s to determine the current display
615 * Type and sets everything accordingly.
616 * /
/*
* void con_init (void);
* The console initialization routines interrupted, the other does nothing. If you want to clean the screen, then use
* Appropriate escape sequence to call tty_write () function.

*
* Setup.s reading information stored procedure to determine the current display type, and provided all relevant parameters.

*/
617 void con_init (Void)
618 {
619 register unsigned char a;
620 char * display_desc = "????";
621 char * display_ptr;
622
623 video_num_columns = ORIG_VIDEO_COLS ; // display shows the number of characters in the column.

624 video_size_row = video_num_columns * 2; // need to use the number of bytes per row.

625 video_num_lines = ORIG_VIDEO_LINES ; // display shows the number of characters in the line.

626 video_page = ORIG_VIDEO_PAGE ; // currently displayed page.

627 video_erase_char = 0x0720; // erase character (0x20 character display, 0x07 is the attribute).

628
// If the original display mode is equal to 7, then a monochrome display.

629 if ( ORIG_VIDEO_MODE == 7) / * Is this a monochrome display? * /


630 {
631 video_mem_start = 0xb0000; // Set single significant memory starting address mapping.

632 video_port_reg = 0x3b4; // Set the index register substantially single port.

633 video_port_val = 0x3b5; // Set single significant port data register.

// According to the information display mode BIOS interrupt 0x12 int 0x10 function obtained judgment monochrome display card or display card color display card. // If the above-described

interrupt register BX function obtained return value is not equal to 0x10, it indicates that the EGA card. Therefore the initial display types EGA // monochrome; memory mapped address used

for the terminal 0xB8000; display description string of juxtaposed 'EGAm'. // display during system initialization string will be described top-right corner of the screen.

634 if (( ORIG_VIDEO_EGA_BX & 0xff)! = 0x10)


635 {
636 video_type = VIDEO_TYPE_EGAM ; // set the display type (EGA monochrome).
637 video_mem_end = 0xb8000; // set the display end address memory.

638 display_desc = " EGAm "; // set the display character string is described.

639 }
// If the value of the BX register equals 0x10, it indicates that the monochrome display card MDA. It is set corresponding parameters.

640 else
641 {
642 video_type = VIDEO_TYPE_MDA ; // set the display type (MDA monochrome).

643 video_mem_end = 0xb2000; // set the display end address memory.

644 display_desc = "* MDA "; // set the display character string is described.

645 }
646 }
// If the display mode is not 7, for the color mode. At this time, the start address of the display memory is used 0xb800; // display control index register port addresses

0x3d4; port data register address 0x3d5.

647 else / * If not, it is color. * /


648 {
649 video_mem_start = 0xb8000; // start address of the display memory.

650 video_port_reg = 0x3d4; // set the color display port index register.
651 video_port_val = 0x3d5; // set the color display port data register.

--283--
7.5 console.c program

// then judge the graphics card category. If BX is not equal to 0x10, it indicates that the EGA graphics card.

652 if (( ORIG_VIDEO_EGA_BX & 0xff)! = 0x10)


653 {
654 video_type = VIDEO_TYPE_EGAC ; // set the display type (EGA color).
655 video_mem_end = 0xbc000; // set the display end address memory.

656 display_desc = " EGAc "; // set the display character string is described.

657 }
// If the value of the BX register equals 0x10, it indicates that the CGA graphics card. It is set corresponding parameters.

658 else
659 {
660 video_type = VIDEO_TYPE_CGA ; // set the display type (CGA).
661 video_mem_end = 0xba000; // set the display end address memory.

662 display_desc = "* CGA "; // set the display character string is described.

663 }
664 }
665
666 / * Let the user known what kind of display driver we are using * /
/ * Let the user know that we're using what kind of display driver * /

667
// in the upper right corner of the screen displays the description string. The method used is to directly write the string at a position corresponding to the display memory. // first the pointer is

displayed to the screen of the first row display_ptr means 4 characters at the right end of the differential (2 bytes required for each character, so minus 8).

668 display_ptr = ((char *) video_mem_start ) + video_size_row - 8;


// then recycled copy string of characters, and character of each breaker have a copy attribute byte.

669 while (* display_desc)


670 {
671 * display_ptr ++ = * display_desc ++; // Copy the characters.

672 display_ptr ++; // open space attribute byte position.

673 }
674
675 / * Initialize the variables used for scrolling (mostly EGA / VGA) * /
/ * Initialize variables used for scrolling (mainly for EGA / VGA) * /

676
677 origin = video_mem_start ; // start scrolling display memory address.

678 scr_end = video_mem_start + video_num_lines * video_size_row ; // Scroll to end the memory address.
679 top = 0; // the top row of numbers.

680 bottom = video_num_lines ; // the bottom line numbers.

681
682 gotoxy ( ORIG_X , ORIG_Y ); // initialize the cursor position x, y and the corresponding memory location pos.

683 set_trap_gate (0x21, & keyboard_interrupt ); // set the keyboard interrupt trap door.
684 outb_p ( inb_p (0x21) & 0xfd, 0x21); // cancel the 8259A keyboard interrupt masking, allowing IRQ1.

685 a = inb_p (0x61); // delay reading the keyboard port 0x61 (8255A port PB).

686 outb_p (A | 0x80,0x61); // set up no keyboard work (bit 7 set),


687 outb (A, 0x61); Then // allowed keyboard work, to reset keyboard.
688 }
689 / * From bsd-net-2: * /
690
//// stop beeping.
// reset bit PB 8255A 1 and bit 0 of port.
691 void sysbeepstop (Void)
692 {
693 / * Disable counter 2 * / / * Disable Timer 2 * /
694 outb ( inb_p (0x61) & 0xFC, 0x61);
695 }

--284--
7.5 console.c program

696 697 int beepcount = 0;

698
// opened the beep.

Bit 1 is used as a speaker opening signal 8255A chip @ PB port; Timer bit 0 as 8253 is a gate signal 2, the output pulse of the timer // sent to the speaker, as
the speaker sound frequency. So make the speaker beeps two steps: first open port PB // bit 0 and bit 1 (bit set), then set the timer transmission timing
frequency can be constant.

699 static void sysbeep (Void)


700 {
701 / * Enable counter 2 * / / * On Timer 2 * /
702 outb_p ( inb_p (0x61) | 3, 0x61);
703 / * Set command for counter 2, 2 byte write * / / * Set the timer to send 2 commands * /
704 outb_p (0xB6, 0x43);
705 / * Send 0x637 for 750 HZ * / / * Set frequency of 750HZ, therefore send timer value 0x637 * /
706 outb_p (0x37, 0x42);
707 outb (0x06, 0x42);
708 / * 1/8 second * / / * Time is 1/8 second beep * /
709 beepcount = HZ /8;
710 }
711

7.5.3 Other Information

7.5.3.1 Display control card programming

Just to give instructions and instructions compatible display card port. Described MDA , CGA , EGA with VGA Display control card common programming ports, which are

related to CGA in use MC6845 Compatible chip, and uses the name table 7-5 Fig. Among them,

CGA / EGA / VGA Ports ( 0x3d0-0x3df) As an example, MDA The port is 0x3b0 - 0x3bf .

The basic steps of the display control card is programmed: firstly to write register index card, select one set of the internal registers of the display control

( r0-r17) , Which is then written to parameter port data register. I.e. the port data register card can only display a card internal register operation. Table internal

registers 7-6 Fig.

table 7-5 CGA Port register the name and role

port Read / Write Name and purpose

0x3d4 write CRT (6845) Index register. For selection by the port 0x3b5 Each accessed data register ( r0-r17) .

CRT (6845) Data register. Wherein the data register r12-r15 It can also be read. Each data
0x3d5 write
register function described below.

Mode control register. Place 7-6 Unused; bits 5 = 1 Allow flashing; bits 4 *

200 = 1640 Graphics mode; bit 3 = 1 Allow video; bit 2 = 1 Monochrome

display; digit 1 = 1 Graphics mode; = 0 Text mode; bit 0 = 180 * 25 Text

mode; = 040 * 25 Text mode.


0x3d8 Read / Write

CGA Palette register. Select the color used. Place 7-6 Unused;
0x3d9 Read / Write

--285--
7.5 console.c program

Place 5 = 1 Set to activate color: green ( cyan) ,purple( magenta) ,White( white) ;

= 0 Set to activate color: red ( red) ,green( green) ,blue( blue) ; Bit 4 = 1 Enhanced display graphics, text

background color; bit 3 = 1 Enhanced display 40 * 25 Border, 320 * 200 Background, 640 * 200 Foreground

color; bit 2 = 1 Red: 40 * 25 Border, 320 * 200 Background, 640 * 200 Prospects; bit 1 = 1 Green: 40 * 25 Border, 320

* 200 Background, 640 * 200 Prospects; bit 0 = 1 Blue: 40 * 25 Border, 320 * 200 Background, 640 * 200 Prospects;

CGA Display state register. Place 7-4 Unused; bits 3 = 1 In the vertical retrace phase; Bit 2 = 1 Light pen switch is

turned off; = 0 Light pen switch is turned on; bit 1 = 1 Valid strobe light pen; Bit 0 = 1 Display may not interfere

with access to the display memory; = 0 Do not use this time to display memory.
0x3da read

0x3db write Clear latch light pen (light pen register reset).

0x3dc Read / Write Latch preset light pen (light pen strobe active force).

table 7-6 MC6845 Inside Ministry data register And the initial value register

Numbering name Units read / write 40 * 25 mode 80 * 25 Mode graphics mode

r0 The total number of horizontal Character Write 0x38 0x71 0x38

r1 character display character Character Write 0x28 0x50 0x28

r2 number of horizontal sync Character 0x2d 0x5a 0x2d

r3 horizontal position of the horizontal sync pulse width Character 0x0a 0x0a 0x0a

r4 Vertical total number of Character Write 0x1f 0x1f 0x7f

r5 characters vertical row scan Write 0x06 0x06 0x06

r6 synchronizing pulse width of line 0x19 0x19 0x64

r7 character
the vertical position of the vertical synchronizing the number of line character
characters line
displayed 0x1c 0x1c 0x70

r8 Interlaced / progressive selection write 0x02 0x02 0x02

r9 The maximum number of scanning lines Write scan lines 0x07 0x07 0x01

r10 End position the cursor Scan line Write 0x06 0x06 0x06

r11 start position of the cursor scan lines 0x07 0x07 0x07

r12 Display memory start position (high) Write 0x00 0x00 0x00

r13 memory display end position (Low) 0x00 0x00 0x00

r14 The current cursor position Read / write read / write


variable
r15 (High) the current cursor position (Low)

r16 The current position of the Read


variable
r17 light pen (high) current position of the light pen (low)

7.5.3.2 Scroll principle of operation

It refers to an operation of scrolling text contents of the specified start and ending lines in the upward movement (scroll up scroll up) Or downward movement (scroll down scroll

down) If the screen is viewed as a window displayed on the screen corresponding to the contents of the memory, then the contents of the screen window that is moved upward along

the display memory is moved downward; screen content that is moved downwardly move the window down. Display start position of the memory is re-set in the program in the

display controller origin And adjusting the corresponding variables in the program. For both operations each have two cases.

--286--
7.5 console.c program

For Scroll up, when the display memory corresponding to the screen displayed in the window is still within the memory range where after the downward movement, i.e., the

position corresponding to the memory block in the current screen display memory is always the starting position ( video_mem_start) And terminal position video_mem_end Between,

then only need to adjust the position of the display memory controller can start display. However, when the memory block corresponding to a position beyond the end of the

screen is actually displayed when the memory is moved downward ( video_mem_end) This case, it is necessary to move the display data corresponding to the memory, the current

screen to ensure that all the data fall within the display memory range. In this second case, the program is moved to the data memory corresponding to the screen at the start

position of the actual display memory ( video_mem_start) .

The actual program process carried out in three steps. First, adjust the screen display start position origin ; Screen memory is then judged whether the corresponding

display memory data exceeds the lower bound ( video_mem_end) Start position, if the data out of memory corresponding to the screen will move to the actual display memory ( video_mem_start)

; Finally, after moving to a new line appears on the screen is filled with space characters. See Fig. 7-7 Fig. Wherein FIG. ( a)

The first corresponds to a simple case, in FIG. ( b) It corresponds to the case when the data memory needs to be moved.

Display memory start position


New origin
video_mem_start

origin

New origin

blanks
Content display screen
corresponding to the memory block
After scrolling the display
screen corresponding to the contents of memory New scr_end fill in

scr_end Fill in blanks


origin
New scr_end

Copy block
scr_end

Display memory terminal


video_mem_end
Beyond the end of the display memory

(A) on a volume generally (B) moving the screen where required data

Map 7-7 Scroll up screen ( scroll up) Action Illustration

Scroll down operation screen similar to the upward scrolling, both will encounter a similar situation, but since the shift windows on the screen, so there will be a blank line

at the top of the screen, and beyond the display memory content on the screen corresponding to the memory screen data memory block needs to be moved to the end position of

the display memory when the down range.

7.5.3.3 ANSI Escape sequence control

Terminal usually has two functions, namely as a computer input device information (keyboard) and the output settings (display). The terminal may have a number of

control commands, so that the terminal to perform certain operations instead of just a character displayed on the screen. This way, the computer can instruct the mobile terminal to

perform the cursor, switching the display mode and the ringing operation. In order to understand the processing execution program, the terminal control command following simple

description. First, the meaning of control characters and control sequences.

Control characters are ASCII Code at the beginning of table 32 Characters ( 0x00 - 0x1f or 0-31) And character DEL (0x7f or 127) See Appendix ASCII Code table. Typically a

specific type of terminal which will be adopted as a subset of the control characters, the control characters and the other will not work. For example, for VT100 Terminal control

characters used in Table 7-7 Fig.

--287--
7.5 console.c program

table 7-7 Control characters

Control characters Octal Hex Action taken

NUL 000 0x00 Ignored on input (not stored in the input buffer).

ENQ 005 0x05 Transmitting a reply message.

BEL 007 0x07 Send sound from the keyboard.

BS 010 0x08 Move the cursor to the left at a character position. If the cursor is already at the left edge, no motion.

HT 011 0x09 Move the cursor to the next tab stop. If the right side has no tab stops, then moves to the right edge.

LF 012 0x0a This code causes a carriage return or line feed operation (see wrap mode).

VT 013 0x0b Role as LF .

FF 014 0x0c Role as LF .

CR 015 0x0d Move the cursor to the left edge of the current line.

SO 016 0x0e Used by SCS Design of the control sequences G1 character set.

SI 017 0x0f select G0 character set. by ESC Sequence selection.

XON 021 0x11 So that the terminal re-transmission.

XOFF 023 0x13 In addition to sending the interrupt XOFF with XON Other than off all the other codes.

If sent during the control sequence, the sequence will not be executed immediately terminated. And it will display an error
CAN 030 0x18
characters.

SUB 032 0x1a The same effect CAN .

ESC 033 0x1b Generating a control sequence.

DEL 177 0x7f Ignored on input (not stored in the input buffer).

It has been controlled by the sequence ANSI ( American National Standards Institute American National Standards Institute) The development of the standard:

X3.64-1977 . Control sequence refers to a special character sequence of control characters consisting of non-terminal upon receiving them directly This sequence is not displayed

on the screen, but take a certain control operation, for example, moving the cursor, deleting the character, deleting row, insert a character row or insert operation. ANSI The control

sequence consists of the following basic elements:

The control code sequence is introduced ( Control Sequence Introducer - CSI) : Indicates a transfer sequence, provide additional control and influence in itself is a prefix

followed by a series of consecutive characters to explain the meaning of. Typically, general CSI Use ESC [ .

parameter( Parameter) : Zero or more characters of a numeric value. The numerical parameters ( Numeric Parameter) : Represents a number of parameters, use n Representation.

Select parameter ( Selective Parameter) : A sub-function for selecting a function from a subset, generally used s Representation. Typically, the role of a control sequence

having a plurality of selected parameters generated, as several separate control sequence. E.g: CSI sa; sb; sc F The role and CSI sa F CSI sb F CSI sc F exactly the same.

Parameter string ( Parameter String) : Semicolon ';' parameter string separated. Defaults( Default) : When not explicitly specify a value or a value 0 It would specify a value

associated with the function. The last character ( Final character) : For terminating an escape or control sequence. Map 7-8 Is an example of a control sequence: Cancel

property of all the characters, then turned and underscore the highlighted property. ESC [0; 4; 7m

--288--
7.5 console.c program

delimiter

Delimiter

ESC [0; 4; 7 m

Select Parameters

Parameter string

CSI character

Map 7-8 Examples of control sequences

table 7-8 Are some of the commonly used control sequences lists. among them E Show 0x1b ,in case n Yes 0 Then, it can be omitted: E [0J == E [J

table 7-8 often Control sequence Row

Escape Sequences Features Escape Sequences Function

E [nA Move Cursor n Row E [nK Delete part or the entire line:

E [nB Cursor down n Row n = 0 Point to the end of the row from

E [nC Cursor right n Character position n = 1 From the beginning to the cursor line

E [nD Cursor left n Character position n = 2 Entire row

E [n` Move the cursor to the character n position E [nX delete n Characters

E [na Cursor right n Character position E [nS Scroll up screen n Line (screen down)

E [nd Move the cursor to the line n on E [nT Scroll down the screen n Line (move on screen)

E [ne Cursor down n Row E [nm Set character display attributes:

E [nF Move Cursor n OK, stop at the beginning of the line n = 0 General Property (no property)

E [nE Cursor down n OK, stop at the beginning of the line n = 1 Crude( bold )

E [y; xH Move the cursor x, y position n = 4 Underline ( underscore )

E [H Move the cursor to the upper left corner of the screen n = 5 flicker( blink )

E [y; xf The cursor position x, y n = 7 Anti-significant ( reverse )

E [nZ Cursor backward n Tab stops n = 3X Set the foreground color display

E [nL insert n Article blank line n = 4X Set Background color display

E [ the n-@ insert n Space character X = 0 black black X = 1 red red

E [nM delete n Row X = 2 green green X = 3 Palm brown

E [nP delete n Characters X = 4 blue blue X = 5 purple magenta

E [nJ Sassafras part or all of the display character except: X = 6 green cyan X = 7 White white

n = 0 From the cursor to the bottom of the screen; Semicolon plurality of attributes may be provided at the same time,

n = 1 From the top of the screen to the cursor; E.g: E [0; 1; 33; 40m

n = 2 All the characters on the screen. E [s Save Cursor Position

E [u Restore last saved cursor position

--289--
7.6 serial.c program

7.6 serial.c program

7.6.1 Functional Description

This program distribution system, the serial port initialization, ready to work using a serial terminal. in rs_init () Initialization function, set the default serial communication

parameters, and sets the serial port interrupt trap door (interrupt vector). rs_write () Function terminal device for the serial write buffer queue character is sent to the remote terminal

apparatus via a serial line.

rs_write () Will be used to be called when the operation character device file in the file system. When a serial device to program / dev / tty64 File performs a write operation,

it will perform system calls sys_write () (in fs / read_write.c In), and this system call when it is judged that the read file is a character device file that will call rw_char () Function (in fs

/ char_dev.c ), The function of which will be based on the read device information of the sub-device number and the like, the device is called by the character reader function table

(device switch table) rw_tty () Final call here to write a serial terminal function rs_write () .

rs_write () Function is actually just open the serial transmit holding register empty interrupt flag, in UART The data is sent an interrupt signal to allow hair. Specific operation

is transmitted rs_io.s Completion of the procedure.

7.6.2 Code comments

program 7-4 linux / kernel / chr_drv / serial.c

1/*
2 * Linux / kernel / serial.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8* serial.c
9*
10 * This module implements the rs232 io functions
11 * void rs_write (struct tty_struct * queue);
12 * void rs_init (void);
13 * And all interrupts pertaining to serial IO.
14 * /
/*
* serial.c
* Input and output functions of the program for realizing rs232

* void rs_write (struct tty_struct * queue);


* void rs_init (void);
* And a relationship with the transmission of all IO interrupt handler.

*/
1516 #include <linux / tty.h>
// tty header file, which defines tty_io, aspects of the serial communication parameters constant.

17 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

18 #include <asm / system.h> // operating segment header files. For embedded segment register defines the operation assembly function.

19 #include <asm / io.h> // io header files. Defined hardware port I / O macro assembler statements.

2021 #define WAKEUP_CHARS ( TTY_BUF_SIZE / 4) when the write queue // contains WAKEUP_CHARS characters, starts transmitting.

twenty two

--290--
7.6 serial.c program

twenty three extern void rs1_interrupt (Void); // serial port interrupt handler (rs_io.s, 34) 1 a.
twenty four extern void rs2_interrupt (Void); // 2 serial port interrupt handler (rs_io.s, 38).
25
//// initialize the serial port
// port: Serial 1 - 0x3F8, Serial 2 - 0x2F8.
26 static void init (Int port)
27 {
28 outb_p (0x80, port + 3); / * Set DLAB of line control reg * /
/ * Set DLAB bit line control register (bit 7) * /
29 outb_p (0x30, port); / * LS of divisor (48 -> 2400 bps * /
/ * Low byte transmit baud rate factor, 0x30-> 2400bps * /
30 outb_p (0x00, port + 1); / * MS of divisor * /
/ * Baud transmission factors high byte, 0x00 * /

31 outb_p (0x03, port + 3); / * Reset DLAB * /


/ * Reset DLAB bit, 8 data bits * /
32 outb_p (0x0b, port + 4); / * Set DTR, RTS, OUT_2 * /
/ * Set DTR, RTS, assist a user output 2 * /
33 outb_p (0x0d, port + 1); / * Enable all intrs but writes * /
/ * Besides writing (writing remain empty) outside, allowing all interrupt sources interrupt * /

34 (Void) inb (Port); / * Read data port to reset things (?) * /


/ * Read data port, to a reset operation (?) * /
35 }
36
//// initialize the serial interrupt routine and serial interfaces.

37 void rs_init (Void)


38 {
39 set_intr_gate (0x24, rs1_interrupt ); // set the serial port interrupt vector door (IRQ4 hardware signal 1).
40 set_intr_gate (0x23, rs2_interrupt ); // set the serial port interrupt vector door (hardware signal IRQ3. 2).
41 init ( tty_table [1] .read_q.data); // initialize the serial port 1 (.data port number).
42 init ( tty_table [2] .read_q.data); // Initialize the serial port 2.

43 outb ( inb_p (0x21) & 0xE7,0x21); // master 8259A chip allows IRQ3, IRQ4 interrupt request signal.

44 }
4546 / *

47 * This routine gets called when tty_write has put something into
48 * The write_queue. It must check wheter the queue is empty, and
49 * Set the interrupt register accordingly
50 *
51 * void _rs_write (struct tty_struct * tty);
52 * /
/*
* In tty_write () has been data output (write) will call the following subroutine queue. Must first
* Write checks whether the queue is empty, and set the interrupt register.

*/
//// output serial data transmission.

// really just open the serial transmit holding register empty interrupt flag, allowing the hair UART interrupt signal after the data sent.

53 void rs_write (Struct tty_struct * Tty)


54 {
55 cli (); // disable interrupts.

// If the write queue is not empty, from 0x3f9 (or 0x2f9) first read the interrupt enable register contents, add Transmit Holding Register interrupt enable flag after // (1 bit), and then

write back to the register. This will allow serial devices due to write (send) the character and cause disruption.

56 if (! EMPTY (Tty-> write_q))


57 outb ( inb_p (Tty-> write_q.data + 1) | 0x02, tty-> write_q.data + 1);

--291--
7.6 serial.c program

58 sti (); // open the interruption.

59 }
60

7.6.3 Other Information

7.6.3.1 Asynchronous serial communication chip UART

PC Asynchronous serial communication using the serial communication chip microcomputer is INS 8250 or NS16450 Compatible chips, collectively referred to as UART ( Universal

Asynchronous Receiver Transmitter). Correct UART Programming is actually read and write operations of its internal registers. It can be UART It sets as a set of registers,

comprising sending, receiving, and the control of three parts. UART Internal 10 Registers for CPU by IN / OUT Instructions to access it. Table port and uses these registers 7-9 Fig.

Which port 0x3f8-0x3fe A microcomputer COM1 Serial port, 0x2f8-0x2fe correspond COM2 port. condition DLAB (Divisor Latch Access Bit) It is the Divisor Latch Access Bit, bit line

control register means of 7 .

table 7-9 UART Use the corresponding port and internal registers

port Read / Write Conditions of Use

0x3f8 (0x2f8) write DLAB = 0 Write Transmit Holding Register. Containing the character to be sent.

read DLAB = 0 Reading the receive buffer register. It contains characters received.

Read / Write DLAB = 1 Read / write low byte baud factor ( LSB ).

0x3f9 (0x2f9) Read / Write DLAB = 1 Read / Write Byte high baud rate factor ( MSB ).

Read / Write Interrupt Enable register. Place 7-4 all 0 Remain

unused; bits 3 = 1 modem State interrupt enable; bit 2 = 1 Receiver

line status interrupt enable; bit 1 = 1 Transmit Holding


Read / Write DLAB = 0
Register empty interrupt enable; bit 0 = 1 Interrupt Enable

data has been received.

Read interrupt identification register. The interrupt handler is used to determine the break 4

What kind of species. Place 7-3 all 0 (No); bit 2-1

Determining the priority interrupt;

0x3fa (0x2fa) read 11 = Wrong interrupt receive status, the highest priority;

10 = Interrupt data has been received, the first priority 2 ;

01 = Transmit Holding Register Empty first priority 3 ;

= 00 modem Status change interrupt, the first priority 4 . Place 0 = 0 Pending

interrupts; = 1 Without interruption.

Write line control register. Place 7 = 1 Divisor Latch

Access Bit ( DLAB) .

0 Receiver, transmitter or to maintain Interrupt Enable register access;

Bit 1 6 = Allow intermittent; bit 5 = 1 To maintain parity; bit 4 = 1 Even parity; = 0 Odd

parity; bit 3 = 1 Allow parity; = 0 No parity; bits 2 = 1 1 Stop bit; = 0 None Stop bit;
0x3fb (0x2fb) write
bit 1-0 Data bit length:

= 005 Data bits;

--292--
7.7 rs_io.s program

= 016 Data bits;

= 107 Data bits;

= 118 Data bits.

write modem Control register. Place 7-5 all 0 Reserved; bit 4 = 1 Chip diagnostic mode of

operation is in a feedback loop; bit 3 = 1 Auxiliary user-specified output 2 ,allow INTRPT

To the system; bit 2 = 1 Auxiliary user-specified output 1 , PC Machine is not used; bit 1

0x3fc (0x2fc) write = 1 That the request RTS Effective; Bit 0 = 1 The Data Terminal Ready DTR effective.

Reading the line status register. Place 7 = 0 Reserved; bit 1 6 = Transmit shift

register is empty; bits 5 = 1 Transmit holding register empty, character

transmission can take; Bit 4 = 1 Intermittently received bit sequence satisfying

the conditions; bit 3 = 1 A frame format error; Bit 2 = 1 Parity Error; Bit 1 = 1 Beyond

0x3fd (0x2fd) read coverage error; Bit 0 = 1 The receiver data is ready, the system can read.

read modem Status register. δ A signal indicative of changes. Place 7 = 1 Carrier

Detect ( CD) Effective; Bit 1 6 = Ring Indicator ( RI) Effective; Bit 5 = 1 Data

Set Ready ( DSR) Effective; Bit 4 = 1 Clear to Send ( CTS ) Valid; bits 3 = 1 detected

δ Carrier; bit 2 = 1 Ring detected signal edge; bit 1 = 1 δ Data Set Ready ( DSR)

0x3fe (0x2fe) read ; Bit 0 = 1 δ Clear to Send ( CTS) .

7.7 rs_io.s program

7.7.1 Functional Description

The assembler achieve rs232 Serial communication interrupt processing. During transit and storage of the character, the interrupt process mainly terminal read, write

buffer queue operation. Read it received from the serial line to the serial terminal into character buffer queue read_q

In the write buffer or queue write_q Characters to be sent out to the remote serial transmission terminal device through a serial line.

Serial interrupt occurs causing the system has 4 Species: a. due to modem The state has changed; b. Since the line status changes; c. Since the character is received; d. Since

the interrupt enable flag register is set Transmit Holding Register interrupt enable flag needs to send characters. Processing of the first two cases caused the interrupt by reading a

register value corresponding to the status, so that it is reset. For the case where the result of receiving a character, the program first reads the character into buffer queue read_q Then

call copy_to_cooked () Converted into a function to regulate the behavior of the character mode in units of character into the auxiliary queue secondary in. In the case of the

characters to be sent, the program first from the write buffer queue write_q At the end of the pointer is taken out a character is sent out, and then determines whether the write

buffer queue is empty, then if there are characters

--293--
7.7 rs_io.s program

Loop performs transmission operation.

Therefore, before reading this program, the best look at include / linux / tty.h head File. Wherein the data structure is given character buffer queue tty_queue The data

structure of the terminal tty_struct And some of the value of the control characters. There are also a number of macro definition buffer queue operation. Its schematic buffer queue

operation Referring to FIG. 7-9 Fig.

7.7.2 Code comments

program 7-5 linux / kernel / chr_drv / rs_io.s

1/*
2 * Linux / kernel / rs_io.s
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8* rs_io.s
9*
10 * This module implements the rs232 io interrupts.
11 * / / *

* The program modules rs232 O interrupt handler.


*/
1213 .text

14 .globl _rs1_interrupt, _rs2_interrupt


15
// size is the byte length of write buffer queue.
16 size 1024 = / * Must be power of two! Must be a power of 2 and needs
17 and must match the value matches the value in tty_io.c!
18 in tty_io.c !!! * /
1920 / * These are the offsets into the read / write buffer structures * /

/ * These are the offsets in the write buffer structure * /

// offset corresponding to each variable defined in the include / linux / tty.h tty_queue file structure.
twenty one rs_addr = 0 // offset serial port number field (or a port number is 0x3f8 0x2f8).
twenty two head = 4 // offset buffer pointer field header.
twenty three tail = 8 // offset buffer tail pointer field.
twenty four proc_list = 12 // wait for the buffering process field offset.

25 buf = 16 // buffer field offset.


2627 startup = 256
/ * Chars left in write queue when we restart it * / / * When the write queue 256 characters left space
(WAKEUP_CHARS), we can write * /
2829 / *

30 * These are the actual interrupt routines. They look where


31 * The interrupt is coming from, and take appropriate action.
32 * / / *

* These are the actual interrupt program. Program first checks the interrupt source, and then perform the appropriate

* Processing.
*/

--294--
7.7 rs_io.s program

33 .align 2
1 //// serial port interrupt handler entry point.
34 _rs1_interrupt:
35 pushl $ _table_list + 8 // tty serial read and write buffer corresponding to the table address of the stack pointer 1 (tty_io.c, 99).

36 jmp rs_int // character buffer queue structure format See include / linux / tty.h, line 16.
37 .align 2
//// 2 serial port interrupt handler entry point.
38 _rs2_interrupt:
39 pushl $ _table_list + 16 // tty Table 2 corresponding serial read and write pointer of the buffer queue address stack.

40 rs_int:
41 pushl% edx
42 pushl% ecx
43 pushl% ebx
44 pushl% eax
45 push% es
46 push% ds / * As this is an interrupt, we can not * /
47 pushl $ 0x10 / * Know that bs is ok. Load it * /
48 pop% ds / * Since this is an interrupt routine, we do not know the correct ds * /
49 pushl $ 0x10 / * So load them (let ds, es pointing to the kernel data segment * /

50 pop% es
51 movl 24 (% esp),% edx // pointer address is stored in the buffer queue register edx, i.e. // address on line 35 or

39 of the above first pushed onto the stack.

52 movl (% edx),% edx // fetch buffer queue structure pointer (address) edx. // For the serial terminal, data field stores the

address of the serial port (port number).

53 movl rs_addr (% edx),% edx // taken serial 1 (2 or serial) port number edx.
54 addl $ 2,% edx / * Interrupt ident. Reg * / / * edx points to the interrupt identification register * /
55 rep_int: // interrupt identification register port is 0x3fa (0x2fa), list information on the festival see.

56 xorl% eax,% eax // eax cleared.


57 inb% dx,% al // fetch interrupt flag byte, is used to determine the source of interrupts (there are four interruptions).

58 testb $ 1,% al // first determine the presence or absence of the interrupt pending (bit 0 = No interrupt 1; 0 = interrupt).

59 jne end // If there is no pending interrupt, it jumps to exit the process at the end.

60 cmpb $ 6,% al / * This should not happen, but ... * / / * this will not happen, but ... * /
61 ja end // al values> 6? Is a jump to the end (there is no such state).
62 movl 24 (% esp),% ecx // then take the buffer queue pointer address ecx.

63 pushl% edx // interrupt identification register port number 0x3fa (0x2fa) stack.

64 subl $ 2,% edx // 0x3f8 (0x2f8).


65 When the call jmp_table (,% eax, 2) / * NOTE! Not * 4, bit0 is 0 already * / / * not by 4, bit 0 is 0 * / // The above statement means that, when the pending interrupt, al bit

0 = 0, bits 2-1 are the interrupt type, and thus corresponds to the type of interrupt has been multiplied by the @ 2, then by 2 here, the jump table is obtained (line 79) corresponding to

each interrupt type address, and jump go there to be treated accordingly. // There are four interrupt sources: modem status changes; write (send) character; to read (receives)

character; line status changes. // To send a character is interrupted by setting the transmit holding register mark achieved. rs_write in serial.c program () function, // write buffer when

there is data in the queue, it will modify the interrupt enable register such that when the content, adding the transmit holding register interrupt enable flag, the system needs to send

character @ causing a serial interrupt occurs.

66 popl% edx // pop interrupt identification register port number 0x3fa (or 0x2fa).

67 jmp rep_int // Jump, continue to determine whether the pending interrupts and continue processing.

68 end: movb $ 0x20,% al // send complete interrupt instruction to the interrupt controller EOI.

69 outb% al, $ 0x20 / * EOI * /


70 pop% ds
71 pop% es
72 popl% eax
73 popl% ebx
74 popl% ecx
75 popl% edx

--295--
7.7 rs_io.s program

76 addl $ 4,% esp # jump over _table_list entry # discard buffer queue pointer address.
77 iret
78
// address each type of interrupt handlers jump table, there are four types of interrupt sources: // modem status change interrupt, the interrupt

character to write, read character interrupt, the interrupt line status in question.

79 jmp_table:
80 . long modem_status, write_char, read_char, line_status
81
// Since modem state changes triggered by the interruption. Modem reset operation is performed by reading the status register thereof.

82 .align 2
83 modem_status:
84 addl $ 6,% edx / * Clear intr by reading modem status reg * /
85 inb% dx,% al / * Reset (0x3FE) by reading the modem status register * /
86 ret
87
// because the line state changes caused by the serial interrupt. Reset operation is performed by reading the line status register thereof.

88 .align 2
89 line_status:
90 addl $ 5,% edx / * Clear intr by reading line status reg. * /
91 inb% dx,% al / * Reset (0x3FD) by reading the Line Status Register * /
92 ret
93
// Because the serial device (chip) received characters caused the outage. The received character is read into the buffer queue pointer // read_q head (head) at a

forward pointer and so that character position. If the head pointer has reached the end of the buffer, the buffer is allowed to the beginning of the // folded. Finally, call

C functions do_tty_interrupt () (i.e. copy_to_cooked ()), the read characters into // after a certain processing mode specification into buffer queue (buffer queue

auxiliary secondary) in.

94 .align 2
95 read_char:
96 inb% dx,% al / * Read characters al.
97 movl% ecx,% edx / * Current serial buffer queue pointer address edx.

98 subl $ _table_list,% edx // buffer queue pointer table first site - the current serial queue pointer address edx,

99 shrl $ 3,% edx // difference / 8. 1 is a serial port for, for port 2 is 2.


100 movl (% ecx),% ecx # read-queue # fetch address buffer queue structure ecx.
101 movl head (% ecx),% ebx // fetch buffer queue head pointer ebx.
102 movb% al, buf (% ecx,% ebx) // character position in the buffer of the head pointer.
103 incl% ebx // the head pointer forward one byte.

104 andl $ size-1,% ebx // modulo the buffer size head pointer manipulation. Pointer can not exceed the buffer size.

105 cmpl tail (% ecx),% ebx // buffer head pointer and a tail pointer comparison.

106 je 1f // If equal, indicates that the buffer is full, a jump to the label.

107 movl% ebx, head (% ecx) // save the modified head pointer.

108 1: pushl% edx // The serial number onto the stack (1, 2 serial - port 2), as a parameter,
109 call _do_tty_interrupt // C function call tty interrupt handling (tty_io.c, 242,145).
110 addl $ 4,% esp // discard stack parameters, and return.

111 ret
112
// the provision of the Transmit Holding Register interrupt flag allows caused the interruption. DESCRIPTION serial terminal corresponding to character buffer write queue // there are

characters to send. So to calculate the write current number of characters contained in the queue, if the number of characters is less than 256 then waits for the write operation // wake-up

process. A character transmitted was then removed from the tail of the queue write buffer, and adjust and save the tail pointer. If the write buffer queue is empty, then jump to

write_buffer_empty // at the handling of the write buffer queue empty.

113 .align 2
114 write_char:
115 movl 4 (% ecx),% ecx # write-queue # fetch address write buffer queue structure ecx.
116 movl head (% ecx),% ebx // get the write queue head pointer ebx.

--296--
7.8 tty_io.c program

117 subl tail (% ecx),% ebx // Pointer head - tail pointer = number of characters in the queue.

118 andl $ size-1,% ebx # nr chars in queue # pointer modulo operation.


119 je write_buffer_empty // If the tail pointer = head pointer, write queue no character described, jump processing.

120 cmpl $ startup,% ebx // number of characters in a queue more than 256?

121 ja 1f // exceeded, the jump processing.

122 movl proc_list (% ecx),% ebx # wake up sleeping process # wakeup process is waiting. // wait to take the process
of the queue pointer, and determines whether the air.

123 testl% ebx,% ebx # is there any? # have to wait for the process of it?
124 je 1f // is empty, forward jump to number 1.
125 movl $ 0, (% ebx) // Otherwise, the process is set to be operational state (wake-up process). .

126 1: movl tail (% ecx),% ebx // get the tail pointer.

127 movb buf (% ecx,% ebx),% al // al take a character from the buffer tail pointer.

128 outb% al,% dx // fed to the holding register to a port 0x3f8 (0x2f8).
129 incl% ebx // tail pointer forward.
130 andl $ size-1,% ebx // If the tail pointer to the end of the buffer, is folded back.

131 movl% ebx, tail (% ecx) // save the modified tail pointer.
132 cmpl head (% ecx),% ebx // head pointer and tail pointer comparison,

133 je write_buffer_empty // If equal, indicates that the queue is empty, then jump.

134 ret
// write buffer processing the queue write_q already empty. If waiting for write the serial terminal processes the wake-up, then the shield sent // Holding Register Empty interrupt, an

interrupt is generated to keep the Transmit Holding Register empty.

135 .align 2
136 write_buffer_empty:
137 movl proc_list (% ecx),% ebx # wake up sleeping process # wakeup process is waiting. // wait to take the process
of the queue pointer, and determines whether the air.

138 testl% ebx,% ebx # is there any? # have to wait for the process of it?
139 je 1f # No, jump to the forward reference numeral 1.

140 movl $ 0, (% ebx) # Otherwise, the process is set to be operational state (wake-up process).

141 1: incl% edx # Pointing port 0x3f9 (0x2f9).


142 inb% dx,% al # Read the interrupt enable register.

143 jmp 1f # A slight delay.


144 1: jmp 1f
145 1: andb $ 0xd,% al / * Disable transmit interrupt * / / * Transmit Holding Register
empty interrupt mask (1 bit) * /
146 outb% al,% dx // write 0x3f9 (0x2f9).
147 ret

7.8 tty_io.c program

7.8.1 Functional Description

Each tty Equipment 3 A buffer queues, each queue is a read buffer ( read_q ), Write buffer queue ( write_q ) And an auxiliary buffer queue ( secondary ), As defined in tty_struct

Structure ( include / linux / tty.h ). For each buffer queue, the read operation is to take the characters from the left end of the buffer queue, and the buffer queue tail ( tail ) Pointer

moves to the right. While the write operation is added to the right end of the character buffer queue, and also head ( head) Pointer moves to the right. These two pointers, when any

one of moving beyond the end of the buffer queue, the left end is folded back again. See Fig. 7-9 Fig.

--297--
7.8 tty_io.c program

character

tail pointer head pointer Buffer end

Read character, and the Written characters, and the

pointer to the right tail. right head pointer.

Map 7-9 tty Character buffer queue operation

This program includes an upper layer device interface function characters. The main terminal containing a read / write function tty_read () with tty_write () . Read line function

rules copy_to_cooked () Also realized here.

tty_read () with tty_write () Will be used to be called when the operation character device file in the file system. For example, when a program read / dev / tty

When the file, it will execute a system call sys_read () (in fs / read_write.c In), and this system call when it is judged that the read file is a character device file that will call rw_char () Function

(in fs / char_dev.c ), The function of which will be based on the read device information of the sub-device number and the like, the device is called by the character reader function

table (device switch table) rw_tty () Final call here a read operation of the terminal function tty_read () .

copy_to_cooked () Keyboard interrupt function is called by the process (by do_tty_interrupt () ), According to the terminal termios Structure is provided a character input /

output flag (e.g. INLCR , OUCLC )Correct read_q Characters in the queue are processed, converting the character pattern into a canonical sequence of characters in units of

characters, and the characters stored in the secondary buffer queue (buffer queue specification mode) ( secondary ), And into which the tty_read () Read. During the conversion

process, if the terminal flag echo L_ECHO Set, the character will be put into the write queue

write_q And calls the write function to end the character displayed on the screen. If a serial terminal, then write function will be rs_write () (in

serial.c , 53 Row). rs_write () Serial terminal will write queue serial character is sent to the terminal over the serial link, and displayed on the screen of the serial terminal. copy_to_cooked

() The last function will wake auxiliary buffer queue waiting for the process. Step to achieve the function as follows:

1. If the read queue is empty or auxiliary queue is full, go to the last step (the first 10 Step), otherwise perform the following operations;

2. Reading from the queue read_q The tail pointer to take a character, and the tail pointer forward one character position;

3. If the carriage return ( CR ) Or line ( NL ) Character, according to the terminal termios Configuration input flag ( ICRNL , INLCR ,

INOCR ) State, the character conversion accordingly. For example, if the read character is a carriage return and ICRNL Flag is set, and put it into the replacement

line character;

4. If uppercase lowercase sign turn IUCLC Is set, the characters are replaced put into corresponding lowercase characters;

5. If the specification mode flag ICANON Is set, then the character mode processing to regulate:

a. If the deleted line character (^ U ), Delete secondary A row of characters (queue head pointer is decremented, until it encounters a carriage return or

Wrap or until the queue is empty);

b. If an erasable character (^ H ), Delete secondary A character pointer at the head, the head pointer back one character position;

c. If the stop character (^ S ), Then set the terminal stop sign stopped = 1 ;

d. If the start character (^ Q ), The stop flag is reset terminal.

6. If the received signal symbol keyboard ISIG Is set to, for the process to generate a corresponding signal type control character;

7. If the line ending characters (for example, NL Or ^ D ), The secondary queue secondary The number of rows statistics data increase 1 ;

8. If the local echo flag is set, the characters are also put into the write queue write_q And calls the write function terminal noticeable on the screen

Shows the character;

9. Put the character into the auxiliary queue secondary , The return of the above 1 Step continue processing the read cycle queue other characters;

10. Sleep process on the secondary queue finally wake up.

When reading the following procedures can not help but look at first include / linux / tty.h head File. In the header file defines tty Character buffer queue

--298--
7.8 tty_io.c program

Data structures, and macros defined operation. It also defines the control characters ASCII Code value.

7.8.2 Code comments

program 7-6 linux / kernel / chr_drv / tty_io.c

1/*
2 * Linux / kernel / tty_io.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * 'Tty_io.c' gives an orthogonal feeling to tty's, be they consoles


9 * Or rs-channels. It also implements echoing, cooked mode etc.
10 *
11 * Kill-line thanks to John T Kohl.
12 * /
/*
* 'Tty_io.c' tty to a non-related sense, the console or serial channel. The program also
* Implements echo, specification (cooked) mode.

*
* Kill-line, thanks John T Kahl.
*/
13 #include <ctype.h> // character type header files. It defines some judgment about the character type and converting macros.

14 #include <errno.h> // error number header files. The system comprises various error number. (Linus imported from the minix).

15 #include <signal.h> // signal header files. Defined symbolic constant signal, the signal structure and the operation function prototype signal.

16
// The following presents a respective signal corresponding to the signal bits in the bitmap.

17 #define ALRMMASK (1 << ( SIGALRM -1)) // alert (Alarm) mask bit signal.
18 #define KILLMASK (1 << ( SIGKILL -1)) // terminated (the kill) mask bit signal.

19 #define INTMASK (1 << ( SIGINT -1)) // keyboard interrupt (int) signal mask bits.

20 #define QUITMASK (1 << ( SIGQUIT -1)) // keyboard to exit (quit) signal mask bits.
twenty one #define TSTPMASK (1 << ( SIGTSTP -1)) // stop the process (tty stop) tty emitted signal mask bit.
2223 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

twenty four #include <linux / tty.h> // tty header file, which defines tty_io, aspects of the serial communication parameters constant.

25 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

26 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

2728 #define _L_FLAG (Tty, f) ((tty) -> termios .c_lflag & f) // get local mode flag termios structure.

29 #define _I_FLAG (Tty, f) ((tty) -> termios .c_iflag & f) // takes input mode flag termios structure.
30 #define _O_FLAG (Tty, f) ((tty) -> termios .c_oflag & f) // Take output mode flag termios structure.
31
// get a flag termios structure local mode flag set.
32 #define L_CANON (Tty) _L_FLAG ((Tty), ICANON ) // get local mode flag centralized specification (cooked) mode flag.

33 #define L_ISIG (Tty) _L_FLAG ((Tty), ISIG ) // take the signal flags.
34 #define L_ECHO (Tty) _L_FLAG ((Tty), ECHO ) // retrieve significant character flags.

35 #define L_ECHOE (Tty) _L_FLAG ((Tty), ECHOE ) // When the mode specification, explicit struck retrieved flag.

36 #define L_ECHOK (Tty) _L_FLAG ((Tty), ECHOK ) When // specification mode, take KILL erase the current line flag.

37 #define L_ECHOCTL (Tty) _L_FLAG ((Tty), ECHOCTL ) // retrieve significant control character flags.

38 #define L_ECHOKE (Tty) _L_FLAG ((Tty), ECHOKE ) When // specification mode, take KILL erase lines and echo flag.

--299--
7.8 tty_io.c program

39
// termios structure take a flag bit in the input mode flag.
40 #define I_UCLC (Tty) _I_FLAG ((Tty), IUCLC ) // get input mode flag Concentrated written lowercase conversion flag.

41 #define I_NLCR (Tty) _I_FLAG ((Tty), INLCR ) // back to take a carriage CR newline NL flag.
42 #define I_CRNL (Tty) _I_FLAG ((Tty), ICRNL ) // retrieve a carriage CR turn line feed NL flag.
43 #define I_NOCR (Tty) _I_FLAG ((Tty), IGNCR ) // Ignore take carriage CR flag.
44
// termios structure take a flag bit in the output mode flag.
45 #define O_POST (Tty) _O_FLAG ((Tty), OPOST ) // Take output centralized execution mode flag output processing flag.

46 #define O_NLCR (Tty) _O_FLAG ((Tty), ONLCR ) // get the vehicle back newline newline NL CR-NL flag.

47 #define O_CRNL (Tty) _O_FLAG ((Tty), OCRNL ) // retrieve a carriage CR turn newline NL flag.

48 #define O_NLRET (Tty) _O_FLAG ((Tty), ONLRET ) // function to take the carriage return line breaks mark NL execution.

49 #define O_LCUC (Tty) _O_FLAG ((Tty), OLCUC ) // Take lowercase uppercase characters turn sign.

50
// tty_table tty array data structure. Wherein the initialization comprises three data items, corresponding to the console, the initialization serial data terminal 1 and the

terminal 2 // port.

51 struct tty_struct tty_table [] = {


52 {
53 { ICRNL , / * Change incoming CR to NL * / / * Input is converted to CR NL * /
54 OPOST | ONLCR , / * Change outgoing NL to CRNL * / / * The output NL turn CRNL * /
55 0 // control mode flag is initialized to 0.
56 ISIG | ICANON | ECHO | ECHOCTL | ECHOKE , // local mode flag.
57 0 / * Console termio * / // console termio.
58 INIT_C_CC }, // control character array.

59 0 / * Initial pgrp * / // initial process belongs to the group.

60 0 / * Initial stopped * / // initial stop sign.


61 con_write , // tty write function pointer.
62 {0,0,0,0, ""}, / * Console read-queue * / // tty console read queue.
63 {0,0,0,0, ""}, / * Console write-queue * / // tty console write queue.
64 {0,0,0,0, ""} / * Console secondary queue * / // tty console secondary (second) queue.
65 }, {
66 {0, / * no translation * / // input mode flag. 0, without conversion.
67 0, / * no translation * / // output mode flag. 0, without conversion.
68 B2400 | CS8 , // control mode flag. Baud rate is 2400bps, 8 data bits.
69 0 // local mode flag is 0.
70 0 0 // line discipline.
71 INIT_C_CC }, // control character array.

72 0 // initial process belongs to the group.

73 0 // initial stop sign.


74 rs_write , // serial port 1 tty write function pointer.

75 {0x3f8,0,0,0, ""}, / * Rs 1 * / // Serial terminal 1 reads the buffer queue.

76 {0x3f8,0,0,0, ""}, Serial terminal 1 // write buffer queue.

77 {0,0,0,0, ""} // auxiliary serial terminal buffer queue.

78 }, {
79 {0, / * no translation * / // input mode flag. 0, without conversion.
80 0, / * no translation * / // output mode flag. 0, without conversion.
81 B2400 | CS8 , // control mode flag. Baud rate is 2400bps, 8 data bits.
82 0 // local mode flag is 0.
83 0 0 // line discipline.
84 INIT_C_CC }, // control character array.

85 0 // initial process belongs to the group.

86 0 // initial stop sign.


87 rs_write , // 2 tty serial write function pointer.

--300--
7.8 tty_io.c program

88 {0x2f8,0,0,0, ""}, / * Rs 2 * / // Serial terminal 2 read buffer queue.


89 {0x2f8,0,0,0, ""}, Serial terminal 2 // write buffer queue.

90 {0,0,0,0, ""} // Auxiliary serial terminal 2 buffer queue.

91 }
92 };
9394 / *

95 * These are the tables used by the machine code handlers.


96 * You can implement pseudo-tty's or something by changing
97 * Them. Currently not done.
98 * /
/*
* The following is the buffer queue address table used by assemblers. You can achieve by modifying

* Pseudo-tty terminal or other terminal types. We have not yet done so.
*/
// tty buffer queue address table. rs_io.s assembler uses, for obtaining a read address buffer queue.

99 struct tty_queue * table_list [] = {


100 & tty_table [0] .read_q, & tty_table [0] .write_q, // console terminal read, write address buffer queue.
101 & tty_table [1] .read_q, & tty_table [1] .write_q, // read the serial port terminal 1, the write address buffer queue.
102 & tty_table [2] .read_q, & tty_table [2] .write_q // second terminal serial port read and write address buffer queue.
103 };
104
//// tty terminal initialization function. // initialize the serial port

terminal and console terminal.

105 void tty_init (Void)


106 {
107 rs_init (); // initialize the serial interrupt routine and serial interfaces 1 and 2. (Serial.c, 37)

108 con_init (); // Initialize the console terminal. (Console.c, 617)


109 }
110
//// tty keyboard interrupt (^ C) character handling functions.

(Reception) process mask signal group transmitted in all processes to the specified // specified tty structure, typically the signal is SIGINT. // Parameters: tty - tty terminal

corresponding structured pointer; mask - the mask bit signal.

111 void tty_intr (Struct tty_struct * Tty, int mask)


112 {
113 int i;
114
// If your tty process group number is less than or equal to 0, then exit.

// When pgrp = 0, it indicates that the process is the initial process init, it has no control terminal, and therefore should not be issued interrupt character.

115 if (tty-> pgrp <= 0)


116 return;
// array scanning task, process group (foreground process group) to a specified tty send a signal to all processes specified.

117 for (i = 0; i < NR_TASKS ; I ++)


// If the task pointer is not null, and tty equal to the group number of the group number, is set (sending) of the mask signal specified task.

118 if ( task [I] && task [I] -> pgrp == tty-> pgrp)
119 task [I] -> signal | = mask;
120 }
121
//// If the queue is empty buffer so that the process can be interrupted to enter the sleep state. // parameters:

queue - Specifies the queue pointer. // This function is called when the process of taking the character in the

queue buffer.

122 static void sleep_if_empty (Struct tty_queue * Queue)


123 {

--301--
7.8 tty_io.c program

124 cli (); // disable interrupts.

// If the current process does not signal to be processed and the specified queue buffer is empty, then let the process becomes interrupted sleep, and let the process // pointer to

the queue of waiting processes.

125 while (! current -> signal && EMPTY (* Queue))


126 interruptible_sleep_on (& Queue-> proc_list);
127 sti (); // open the interruption.

128 }
129
//// If the queue buffer is full then let the process go to sleep can be interrupted. // parameters: queue

- Specifies the queue pointer. // This function is called when the process is written to the queue

buffer.

130 static void sleep_if_full (Struct tty_queue * Queue)


131 {
// If the queue buffer dissatisfaction exit is returned.

132 if (! FULL (* Queue))


133 return;
134 cli (); // disable interrupts.

// If the process does not require the signal processing and the remaining area of ​the free queue buffer length <128, so that the process can be interrupted to enter the sleep state, and let //

process the queue pointer to the waiting process.

135 while (! current -> signal && LEFT (* Queue) <128)


136 interruptible_sleep_on (& Queue-> proc_list);
137 sti (); // open the interruption.

138 }
139
//// waiting for keys.
// If the console is read queue buffer is empty so that the process can be interrupted to enter the sleep state.

140 void wait_for_keypress (Void)


141 {
142 sleep_if_empty (& tty_table [0] .secondary);
143 }
144
//// replication into a canonical model character sequence.

// Specify the tty terminal character queue buffer copied into the specification (cooked) and stored in secondary queue character mode (mode specification queue). // Parameters: tty - tty

structure specified terminal.

145 void copy_to_cooked (Struct tty_struct * Tty)


146 {
147 signed char c;
148
// If the tty read queue buffer is not empty and the auxiliary queue buffer is empty, the following code is executed cyclically.

149 while (! EMPTY (Tty-> read_q) &&! FULL (Tty-> secondary)) {// read queue taken from the tail of a
character to c, and a tail pointer forward.
150 GETCH (Tty-> read_q, c);
// below to enter characters using the input mode flag set processing.

// If the character is a carriage return CR (13), then: if the transport line conversion flag is set, the conversion CRNL the newline character NL (10); // Ignore CR flag NOCR otherwise if

set, the character is ignored, continue to deal with other characters.

151 if (c == 13)
152 if ( I_CRNL (Tty))
153 c = 10;
154 else if ( I_NOCR (Tty))
155 continue;
156 else;
// If the character is a newline NL (10) and wraps back to a yield sign NLCR set, it is converted to a carriage CR (13).
157 else if (c == 10 && I_NLCR (Tty))

--302--
7.8 tty_io.c program

158 c = 13;
// If uppercase lowercase turn UCLC flag is set, then the characters are converted to lowercase.

159 if ( I_UCLC (Tty))


160 c = tolower (C);
// If the local concentration Specification mode flag (cooked) CANON mode flag is set, the following process is performed.

161 if ( L_CANON (Tty)) {


// If the character is a control character termination keyboard KILL (^ U), the processing of all the characters on the input line be deleted.

162 if (c == KILL_CHAR (Tty)) {


163 / * Deal with killing the input line * / / * Delete the entry line processing * /
// If the queue is not empty auxiliary tty, or the auxiliary queue last character is a newline NL (10), or the character is the end of file character // (^ D), the following code is

executed cyclically.

164 while (! ( EMPTY (Tty-> secondary) ||


165 (C = LAST (Tty-> secondary)) == 10 ||
166 c == EOF_CHAR (Tty))) {
// If the local ECHO Echo flag is set, then: if the character is a control character (value <32), then the write queue to tty // erase the characters placed ERASE. Then into a

character erase ERASE, and calls the write function of the tty, the function will write the output queue // write characters to the screen of the terminal. Further, since the

control characters when the write queue is placed (e.g., ^ V) with two characters, // require special control characters into a plurality ERASE.

167 if ( L_ECHO (Tty)) {


168 if (c <32)
169 PUTCH (127, tty-> write_q);
170 PUTCH (127, tty-> write_q);
171 tty-> write (Tty);
172 }
// The tty auxiliary queue head pointer is decremented by 1 byte.

173 DEC (Tty-> secondary. head );


174 }
175 continue; // continue to read and deal with other characters.

176 }
// If the character is deleted control characters ERASE (^ H), then:

177 if (c == ERASE_CHAR (Tty)) {


// If the tty subsidiary queue is empty, or its last newline NL (10), or the end of file, processing continues // other characters.

178 if ( EMPTY (Tty-> secondary) ||


179 (C = LAST (Tty-> secondary)) == 10 ||
180 c == EOF_CHAR (Tty))
181 continue;
// If the local ECHO Echo flag is set, then: if the character is a control character (value <32), then the write queue to tty // erase the characters placed ERASE. Then

into a character erase ERASE, and calls the write function of the tty.

182 if ( L_ECHO (Tty)) {


183 if (c <32)
184 PUTCH (127, tty-> write_q);
185 PUTCH (127, tty-> write_q);
186 tty-> write (Tty);
187 }
// The tty auxiliary queue head pointer is decremented by 1 byte, continuing with other characters.

188 DEC (Tty-> secondary. head );


189 continue;
190 }
// If the character is a stop character (^ S), then set tty stop sign, continue processing other characters.

191 if (c == STOP_CHAR (Tty)) {


192 tty-> stopped = 1;
193 continue;

--303--
7.8 tty_io.c program

194 }
// If the character is the beginning character (^ Q), then reset tty stop sign, continue processing other characters.

195 if (c == START_CHAR (Tty)) {


196 tty-> stopped = 0;
197 continue;
198 }
199 }
// If the input mode flag concentrated ISIG flag is set, the keyboard may generate a signal indicating that the terminal is receiving the INTR, QUIT, SUSP // or when the DSUSP

character, need to generate a corresponding signal for the process.

200 if ( L_ISIG (Tty)) {


// If the character is a keyboard interrupt character (^ C), the current process is sent to the keyboard interrupt signal, and continues with the next character.

201 if (c == INTR_CHAR (Tty)) {


202 tty_intr (Tty, INTMASK );
203 continue;
204 }
// If the character is quit character (^ \), the keyboard sends signals to exit the current process, and continues with the next character.

205 if (c == QUIT_CHAR (Tty)) {


206 tty_intr (Tty, QUITMASK );
207 continue;
208 }
209 }
// If the character is a newline NL (10), an end of file or EOF (4, ^ D), showing a row of characters has been processed, put // auxiliary character line buffer by a value contained

in the queue. In tty_read () if the character line removed, its value will be decremented by 1, see line 264.

210 if (c == 10 || c == EOF_CHAR (Tty))


211 tty-> secondary.data ++;
// If the local centralized mode flag ECHO Echo flag set, then, if the character is a newline NL (10), the NL line feed (10) and a carriage return // CR (13) into the write

queue buffer tty region; if the character is a control character (character value <32) and echo control characters // ECHOCTL flag is set, '^', and c + 64 characters into

character tty will write queue (i.e. displayed ^ C , ^ H, etc.); otherwise, directly into the character @ tty write buffer queue. Finally, call the write function of the tty.

212 if ( L_ECHO (Tty)) {


213 if (c == 10) {
214 PUTCH (10, tty-> write_q);
215 PUTCH (13, tty-> write_q);
216 } Else if (c <32) {
217 if ( L_ECHOCTL (Tty)) {
218 PUTCH ( '^', Tty-> write_q);
219 PUTCH (C + 64, tty-> write_q);
220 }
221 } Else
222 PUTCH (C, tty-> write_q);
223 tty-> write (Tty);
224 }
// the character into the secondary queue.

225 PUTCH (C, tty-> secondary);


226 }
// wake of the auxiliary buffer queue of waiting processes (if any).
227 wake_up (& Tty-> secondary.proc_list);
228 }
229
//// tty read function, from the terminal-assisted specified number of characters read buffer queue, into the buffer designated by the user. // Parameters: channel - the

sub-device number; buf - User buffer pointer; nr - the number of bytes to be read. // returns the number of bytes read.

230 int tty_read (Unsigned channel, char * buf , Int nr)

--304--
7.8 tty_io.c program

231 {
232 struct tty_struct * Tty;
233 char c, * b = buf ;
234 int minimum, time , Flag = 0;
235 long oldalarm;
236
This version // linux kernel only three sub-terminal device, respectively, the console (0), a serial terminal (1) and a serial terminal 2 (2). // so any child device number greater

than 2 is illegal. Number of bytes read, of course, can not be less than zero.

237 if (channel> 2 || nr <0) return -1; // tty device number corresponding to a


pointer to the sub-tty structure ttb_table table.
238 tty = & tty_table [Channel];
// the following scheduled time when the first save process, then the timeout timer value according to the control character set VTIME and VMIN characters read operation. // in

noncanonical mode, the two values ​is the value of the timeout timer. MIN that in order to satisfy the read operation, the minimum number of characters to be read. // TIME is a tenth of a

second timer count value. // first save of the current process (alarm) timing values ​(ticks).

239 oldalarm = current -> alarm ;


// read and set the timeout timing of the number of characters and the minimum value of time required to read a minimum.

240 time = 10L * tty-> termios .c_cc [ VTIME ];


241 minimum = tty-> termios .c_cc [ VMIN ];
// If the timeout timer value is set to read, but not set a minimum time to read the number of minimum, then at least one character or // read timing of the read operation will return

after a timeout immediately. So here set minimum = 1.

242 if ( time &&! Minimum) {


243 minimum = 1;
// If the scheduled process time + time value is 0 or less than the current system time value is a time when the original process, then the process resets the timing counter value of time + //

current system time, and the flag is set flag.

244 if (flag = (! oldalarm || time + jiffies <Oldalarm))


245 current -> alarm = time + jiffies ;
246 }
// If you set the minimum number of characters read> the number of characters to be read, then make it equal to the number of characters to be read.

247 if (minimum> nr)


248 minimum = nr;
// number of bytes to be read when a> 0, the loop performs the following operations.

249 while (nr> 0) {


// If the flag is not 0 (i.e., a time when the process is scheduled for the current time + 0 or a system time value is less than a time when the original process) and the process at this time in order

to receive a timing signal SIGALRM //, indicates that the timing has been set to time herein, the timing signal SIGALRM reset process and interrupt // cycle.

250 if (flag && ( current -> signal & ALRMMASK )) {


251 current -> signal & = ~ ALRMMASK;
252 break;
253 }
// If the flag is not set, or the current process has been set, but there are other signals to be processed, exit, return 0.

254 if ( current -> signal)


255 break;
// If the secondary buffer queue (queue specification mode) is empty, or specification mode flag is set and the subsidiary queue is 0 and the number of characters in the assist modes //

buffer queue free space> 20, the process proceeds interruptible sleep, returns to continue deal with.

256 if ( EMPTY (Tty-> secondary) || ( L_CANON (Tty) &&


257 ! Tty-> secondary.data && LEFT (Tty-> secondary)> 20)) {
258 sleep_if_empty (& Tty-> secondary);
259 continue;
260 }
// do the following operations take characters, number of characters required to read nr descending order until nr = 0 or auxiliary buffer queue is empty.

261 do {
// fetch buffer queue auxiliary character c, and you buffer queue secondary-> tail pointer is moved one character position (tail ++) to the right.

--305--
7.8 tty_io.c program

262 GETCH (Tty-> secondary, c);


// If the character is an end of file (^ D) or a line feed NL (10), put the auxiliary buffer queue value contained in the character line minus 1.

263 if (c == EOF_CHAR (Tty) || c == 10)


264 tty-> secondary.data--;
// If the character is EOF (^ D) and specification mode flag is set, it returns the number of characters read, and exit.

265 if (c == EOF_CHAR (Tty) && L_CANON (Tty))


266 return (b- buf );
// otherwise it represents an original mode (noncanonical mode), then the character buffer buf directly into the user data segment, and the number of characters to be read // Save 1. At this

point, if the number of characters to be read is 0, the cycle is aborted.

267 else {
268 put_fs_byte (C, b ++);
269 if (-! nr)
270 break;
271 }
272 } While (nr> 0 &&! EMPTY (Tty-> secondary));
// If the timeout timer value is not 0 and the time specification mode flag is not set (noncanonical mode), then:

273 if ( time &&! L_CANON (Tty))


// If the process is scheduled for a time when the 0 or the current system time + time value is less than the time when the original process, then set the timer value // reset process is time +

current system time and set the flag logo, to read the next character to do Timing preparation. Otherwise, the process shows that when the scheduled time // wait timer time a character is read

is smaller, may not have to wait until the scheduled time to process the characters come to than others. Therefore, at this time // It should be scheduled for a time when the recovery process

(oldalarm).

274 if (flag = (! oldalarm || time + jiffies <Oldalarm))


275 current -> alarm = time + jiffies ;
276 else
277 current -> alarm = Oldalarm;
// If the specification mode flag is set, then the Ruoyi read at least one character is interrupted cycle. Otherwise Ruoyi reads // greater than or equal to the minimum number of characters

required to read, you can also break the cycle.

278 if ( L_CANON (Tty)) {


279 if (b- buf )
280 break;
281 } Else if (b- buf > = Minimum)
282 break;
283 }
// Read tty character cycle operation is finished, let the process timing value recovery value.

284 current -> alarm = Oldalarm;


// if the process has not read the signal and any characters, the error number (interrupted) is returned.

285 if ( current -> signal && (b-! buf ))


286 return - EINTR ;
287 return (b- buf ); // returns the number of characters read.

288 }
289
//// tty write function. The user buffer of characters written in the write queue tty. // Parameters: channel - the sub-device

number; buf - buffer pointer; nr - the number of bytes written. // Returns the number of bytes written.

290 int tty_write (Unsigned channel, char * buf , Int nr)


291 {
292 static cr_flag = 0;
293 struct tty_struct * Tty;
294 char c, * b = buf ;
295
This version // linux kernel only three sub-terminal device, respectively, the console (0), a serial terminal (1) and a serial terminal 2 (2). // so any child device number greater than

2 is illegal. Of course, the number of bytes written can not be less than zero.

296 if (channel> 2 || nr <0) return -1;

--306--
7.8 tty_io.c program

// pointer to the tty device number corresponding to the sub-tty structure ttb_table table. The same effect as the first 238 lines of the statement.

297 tty = channel + tty_table ;


@ Character is a device for processing a character, so that the loop process where nr is greater than 0 for each character.

298 while (nr> 0) {


// If this time tty write queue is full, the current process to sleep can be interrupted.
299 sleep_if_full (& Tty-> write_q);
// If the current process the signal to be processed, exit, return 0.

300 if ( current -> signal)


301 break;
// when the number of bytes to write> 0 and the write queue is less than the cycle of the following tty.

302 while (nr> 0 &&! FULL (Tty-> write_q)) {


C // Take a byte from the user data segment in memory.

303 c = get_fs_byte (B);


// If the mode flag set terminal outputs an output process performed OPOST flag is set, the following output processing is executed.

304 if ( O_POST (Tty)) {


// If the character is a carriage return '\ r' (CR, 13) and a return line feed flag OCRNL transfer set, the newline character into // '\ n' (NL, 10); otherwise, if the character is

a newline character '\ n' (NL, 10) and wraps back cart functionality ONLRET set flag, then the @ character is replaced by a carriage return '\ r' (CR, 13).

305 if (c == '\ r '&& O_CRNL (Tty))


306 c = '\ n ';
307 else if (c == '\ n '&& O_NLRET (Tty))
308 c = '\ r ';
// If the character is a newline character '\ n' and press Enter sign cr_flag not set, wrapping back to the car - newline ONLCR set, then it will cr_flag // set and place to

write a carriage return queue. Then continue processing the next character.

309 if (c == '\ n '&&! cr_flag && O_NLCR (Tty)) {


310 cr_flag = 1;
311 PUTCH (13, tty-> write_q);
312 continue;
313 }
// If turn uppercase lowercase flag OLCUC set, then it is the turn of characters to uppercase characters.

314 if ( O_LCUC (Tty))


315 c = toupper (C);
316 }
// user data 1 byte buffer pointer b proceeds; the number of bytes to be written minus one byte; cr_flag flag is reset, and the TTY // byte into the write queue.

317 b ++; nr--;


318 cr_flag = 0;
319 PUTCH (C, tty-> write_q);
320 }
// If all bytes written, or the write queue is full, then the routine here. Call the corresponding tty write function, if there are bytes to write, write // wait queue

dissatisfaction, so call the scheduler, go perform other tasks.

321 tty-> write (Tty);


322 if (nr> 0)
323 schedule ();
324 }
325 return (b- buf ); // returns the number of bytes written.

326 }
327 328 /
*
329 * Jeh, sometimes I really like the 386.
330 * This routine is called from an interrupt,
331 * And there should be absolutely no problem
332 * With sleeping even in an interrupt (I hope).

--307--
7.9 tty_ioctl.c program

333 * Of course, if somebody proves me wrong, I'll


334 * Hate intel for all time :-). We'll have to
335 * Be careful and see to reinstating the interrupt
336 * Chips before calling this, though.
337 *
338 * I do not think we sleep here under normal circumstances
339 * Anyway, which is good, as the task sleeping might be
340 * Totally innocent.
341 * /
/*
* Oh, sometimes I really liked 386. The subroutines from an interrupt handler is called in, even in
* Sleep interrupt handler should be absolutely no problem (I hope so). Of course, if someone prove me
* Wrong, then I will hate forever intel ☺ . But we must be careful, to be before calling the subroutine
* To restore interrupted.

*
* I do not think under normal environment will sleep in here, so good, because the task sleep is completely arbitrary.

*/
//// tty interrupt handler calls the function - perform tty interrupt processing. //

Parameters: tty - tty specified terminal number (0, 1 or 2).

// Specify the tty terminal character queue buffer copied into the specification (cooked) and stored in secondary queue character mode (mode specification queue). // character in the

serial port interrupt (rs_io.s, 109) and keyboard interrupt (kerboard.S, 69) call.

342 void do_tty_interrupt (Int tty)


343 {
344 copy_to_cooked ( tty_table + Tty);
345 }
346
//// character device initialization function. Empty, to prepare for future expansion.

347 void chr_dev_init (Void)


348 {
349 }
350

7.8.3 Other Information

7.8.3.1 Control characters VTIME , VMIN

In the non-canonical mode, these two values ​is the number of the timeout timer value and the minimum reading characters. MIN That in order to satisfy the read operation,

the minimum number of characters to be read. TIME It is a tenth of a second timer count value. When both are set, the read operation will wait until it reads at least one character,

and then to read MIN Characters or the time TIME Out after reading the last character. If you set only MIN Then read MIN Read will not return before the characters. If you set only TIME

, The read returns immediately after reading at least one character, or when the timer expires. If both are not set, the read will return immediately, only gives the number of bytes

has been read. See details termios.h file.

7.9 tty_ioctl.c program

7.9.1 Functional Description

This document apparatus for controlling operation of the character, to achieve a function (system call) tty_ioctl () . You can modify the function by using a specified terminal termios

Setting a flag structure and other information.

--308--
7.9 tty_ioctl.c program

7.9.2 Code comments

program 7-7 linux / kernel / chr_drv / tty_ioctl.c

1/*
2 * Linux / kernel / chr_drv / tty_ioctl.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <errno.h>
// error number header files. The system comprises various error number. (Linus imported from the minix).

8 #include <termios.h> // function header file input and output terminal. The main terminal interface asynchronous communication define the control port.

910 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

11 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

12 #include <linux / tty.h> // tty header file, which defines tty_io, aspects of the serial communication parameters constant.

1314 #include <asm / io.h>


// io header files. Defined hardware port I / O macro assembler statements.

15 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

16 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

17
// This is the baud rate factor array (or an array called the divisor). The baud rate corresponding to the baud rate factor. See also the list of instructions.

18 static unsigned short quotient [] = {


19 0, 2304, 1536, 1047, 857,
20 768, 576, 384, 192, 96,
twenty one 64, 48, 24, 12, 6, 3
twenty two };

twenty three

//// modify the transmission rate.

// Parameters: tty - tty terminal corresponding to the data structure.

// DLAB divisor latch flag (Line Control Register bit 7) is set the case, the write // baud rate factor to the low and high bytes, respectively, through the UART port and

0x3f8 0x3f9.

twenty four static void change_speed (Struct tty_struct * Tty)


25 {
26 unsigned short port, quot;
27
// For the serial terminal, the data field of the read buffer queue tty structure which is stored in the serial port number (or 0x3f8 0x2f8).

28 if (! (port = tty-> read_q.data))


29 return;
// Fetch baud rate index number provided from the control mode flag tty termios structure, whereby to obtain // the appropriate baud rate the baud rate factor factor values ​from the

array. CBAUD control mode flag is concentrated baud bit mask.

30 quot = quotient [Tty-> termios .c_cflag & CBAUD ];


31 cli (); // disable interrupts.

32 outb_p (0x80, port + 3); / * Set DLAB * / // First set the divisor lock flag DLAB.
33 outb_p (Quot & 0xff, port); / * LS of divisor * / // Low byte of the output factor.
34 outb_p (Quot >> 8, port + 1); / * MS of divisor * / // High byte output factors.
35 outb (0x03, port + 3); / * Reset DLAB * / // reset DLAB.
36 sti (); // open the interruption.

37 }
38
//// refresh tty buffer queue.
// Parameters: gueue - specified buffer queue pointer.

--309--
7.9 tty_ioctl.c program

// make the buffer queue head pointer is equal to the tail pointer, so as to achieve the purpose of emptying the buffer (null characters).

39 static void flush (Struct tty_queue * Queue)


40 {
41 cli ();
42 queue-> head = Queue-> tail;
43 sti ();
44 }
45
//// waits for the character sent.
46 static void wait_until_sent (Struct tty_struct * Tty)
47 {
48 / * Do nothing - not implemented * / / * Did not do anything - not implemented * /
49 }
50
BREAK //// transmission control character.

51 static void send_break (Struct tty_struct * Tty)


52 {
53 / * Do nothing - not implemented * / / * Did not do anything - not implemented * /
54 }
55
//// take termios structure information terminal.

// Parameters: tty - tty structure pointer designated terminal; termios - termios structure buffer pointers user data area. // return 0.

56 static int get_termios (Struct tty_struct * Tty, struct termios * termios )


57 {
58 int i;
59
// first test whether the user's buffer pointer memory area is sufficient, such as not enough memory is allocated.

60 verify_area ( termios , Sizeof (* termios ));


// copy termios structure information specified tty structure termios structure to the user buffer.

61 for (i = 0; i <(sizeof (* termios )); I ++)


62 put_fs_byte (((Char *) & tty-> termios ) [I], i + (char *) termios );
63 return 0;
64 }
65
//// termios structure information terminal is provided.

// Parameters: tty - tty structure pointer designated terminal; termios - termios structure pointer user data area. // return 0.

66 static int set_termios (Struct tty_struct * Tty, struct termios * termios )


67 {
68 int i;
69
// first copy the user data area termios structure information to the specified tty structure.

70 for (i = 0; i <(sizeof (* termios )); I ++)


71 ((Char *) & tty-> termios ) [I] = get_fs_byte (I + (char *) termios );
// user may have modified tty serial port baud rate, the baud rate of the serial chip // Modify UART termios structure according to the control
mode flag c_cflag.
72 change_speed (Tty);
73 return 0;
74 }
75
//// read information termio structure.
// Parameters: tty - tty structure pointer designated terminal; termio - termio structure buffer pointers user data area.

--310--
7.9 tty_ioctl.c program

// return 0.
76 static int get_termio (Struct tty_struct * Tty, struct termio * termio )
77 {
78 int i;
79 struct termio tmp_termio;
80
// first test whether the user's buffer pointer memory area is sufficient, such as not enough memory is allocated.

81 verify_area ( termio , Sizeof (* termio ));


// copy information termios structure to the termio structure. Where the purpose is to set the type of mode conversion flag, i.e. // short integer type converted

from a long integer type termios to the termio.

82 tmp_termio.c_iflag = tty-> termios .c_iflag;


83 tmp_termio.c_oflag = tty-> termios .c_oflag;
84 tmp_termio.c_cflag = tty-> termios .c_cflag;
85 tmp_termio.c_lflag = tty-> termios .c_lflag;
// c_line and c_cc two structures [] field is identical.
86 tmp_termio.c_line = tty-> termios .c_line;
87 for (i = 0; i < NCC ; I ++)
88 tmp_termio.c_cc [i] = tty-> termios .c_cc [i];
// last copy termio structure information specified tty structure to buffer the user termio structure.

89 for (i = 0; i <(sizeof (* termio )); I ++)


90 put_fs_byte (((Char *) & tmp_termio) [i], i + (char *) termio );
91 return 0;
92 }
9394 / *

95 * This only works as the 386 is low-byt-first


96 * /
/*
* The following functions are available termio provided only in little endian mode 386.

*/
//// termio structure information terminal is provided.

// Parameters: tty - tty structure pointer designated terminal; termio - termio structure pointer user data area. // copy information
to the user buffer termio termios structure terminal. Return 0.
97 static int set_termio (Struct tty_struct * Tty, struct termio * termio )
98 {
99 int i;
100 struct termio tmp_termio;
101
// First copy user data area termio structure information to a temporary termio structure.

102 for (i = 0; i <(sizeof (* termio )); I ++)


103 ((Char *) & tmp_termio) [i] = get_fs_byte (I + (char *) termio );
// copy the information and then termio structure to the termios structure tty's. Where the purpose is to set the type of mode conversion flag, i.e. // converts from the short

integer type termio into long integer type of termios.

104 * (Unsigned short *) & tty-> termios .c_iflag = tmp_termio.c_iflag;


105 * (Unsigned short *) & tty-> termios .c_oflag = tmp_termio.c_oflag;
106 * (Unsigned short *) & tty-> termios .c_cflag = tmp_termio.c_cflag;
107 * (Unsigned short *) & tty-> termios .c_lflag = tmp_termio.c_lflag;
// c_line and c_cc two structures [] field is identical.
108 tty-> termios .c_line = tmp_termio.c_line;
109 for (i = 0; i < NCC ; I ++)
110 tty-> termios .c_cc [i] = tmp_termio.c_cc [i];
// user may have modified the tty serial port baud rate, the baud rate of the serial chip // Modify UART termios structure according to a control mode
flag set c_cflag.

--311--
7.9 tty_ioctl.c program

111 change_speed (Tty);


112 return 0;
113 }
114
//// ioctl function tty terminal device.
// parameters: dev - device number; cmd - ioctl command; arg - operating parameter pointers.

115 int tty_ioctl (Int dev, int cmd, int arg)


116 {
117 struct tty_struct * Tty;
// First, take the child tty device number. If the major number. 5 (tty terminal), the tty field is a sub-process, i.e. the device number; // if the process of the sub-tty device number is negative,

indicating that the process does not control the terminal, i.e. the ioctl calls can not be issued, the error crash.

118 if ( MAJOR (Dev) == 5) {


119 dev = current -> tty;
120 if (dev <0)
121 panic ( ' tty_ioctl: dev <0 ");
// otherwise remove the child device number directly from the device number.

122 } Else
123 dev = MINOR (Dev);
// the sub-device number may be 0 (console terminal), 1 (serial terminal 1), 2 (second terminal port). // point to make tty tty

structure corresponding sub-device number.

124 tty = dev + tty_table ; // processed separately


according to the tty ioctl command.
125 switch (cmd) {
126 case TCGETS :
// get information of the corresponding terminal termios structure.

127 return get_termios (Tty, (struct termios *) Arg);


128 case TCSETSF :
// termios before setting information, it is necessary to wait for all the output data processed in the queue, and refresh (clear) input queue. // then set.

129 flush (& Tty-> read_q); / * fallthrough * /


130 case TCSETSW :
// set the terminal termios before the information, it is necessary to wait for all the output queue processed data (depletion). In the case of modifying the parameters // will affect the

output, we need to use this form.

131 wait_until_sent (Tty); / * fallthrough * /


132 case TCSETS :
// setting information corresponding terminal termios structure.

133 return set_termios (Tty, (struct termios *) Arg);


134 case TCGETA :
// get information of the corresponding terminal termio structure.

135 return get_termio (Tty, (struct termio *) Arg);


136 case TCSETAF :
// termio before setting information, it is necessary to wait for all the output data processed in the queue, and refresh (clear) input queue. // then set.

137 flush (& Tty-> read_q); / * fallthrough * /


138 case TCSETAW :
// termio terminal before the information is provided, it is necessary to wait for all the output queue processed data (depletion). In the case of modifying the parameters // will affect the

output, we need to use this form.

139 wait_until_sent (Tty); / * fallthrough * / / * Continue * /


140 case TCSETA :
// setting information corresponding terminal termio structure.

141 return set_termio (Tty, (struct termio *) Arg);


142 case TCSBRK :
// wait queue processed output (null), if the parameter value is 0, then send a break.

--312--
7.9 tty_ioctl.c program

143 if (! arg) {
144 wait_until_sent (Tty);
145 send_break (Tty);
146 }
147 return 0;
148 case TCXONC :
// start / stop control. If the parameter value is 0, the output is suspended; If 1, then reopen the suspended output; if is 2, then the Suspend

// input; if it is 3, then re-open pending input.


149 return - EINVAL ; / * not implemented * / / * Unrealized * /
150 case TCFLSH :
// refresh output has been written but not yet sent or received but have not read data. If the parameter is 0, then refresh (clear) input queue; if it is 1, the refresh // output queue;

if is 2, the refresh input and output queues.

151 if (arg == 0)
152 flush (& Tty-> read_q);
153 else if (arg == 1)
154 flush (& Tty-> write_q);
155 else if (arg == 2) {
156 flush (& Tty-> read_q);
157 flush (& Tty-> write_q);
158 } Else
159 return - EINVAL ;
160 return 0;
161 case TIOCEXCL :
// set the terminal mode dedicated serial line.

162 return - EINVAL ; / * not implemented * / / * Unrealized * /


163 case TIOCNXCL :
// reset terminal dedicated serial line mode.

164 return - EINVAL ; / * not implemented * / / * Unrealized * /


165 case TIOCSCTTY :
// set control tty terminal. (TIOCNOTTY - tty prohibition control terminal).
166 return - EINVAL ; / * set controlling term NI * / / * Setting the control terminal NI * /
167 case TIOCGPGRP : // NI - Not Implemented.
// read the specified terminal device process group id. First, to authenticate the user buffer length, and then copy the tty pgrp fields to the user buffer.

168 verify_area ((Void *) arg, 4);


169 put_fs_long (Tty-> pgrp, (unsigned long *) arg);
170 return 0;
171 case TIOCSPGRP :
// set the designated terminal device process group id.

172 tty-> pgrp = get_fs_long ((Unsigned long *) arg);


173 return 0;
174 case TIOCOUTQ :
// returns the number of characters has not been sent in the output queue. First, to authenticate the user buffer length, then the number of characters in the replication queue to the user.

175 verify_area ((Void *) arg, 4);


176 put_fs_long ( CHARS (Tty-> write_q), (unsigned long *) arg);
177 return 0;
178 case TIOCINQ :
// Returns the number of characters in the input queue has not yet read. First, to authenticate the user buffer length, then the number of characters in the replication queue to the user.

179 verify_area ((Void *) arg, 4);


180 put_fs_long ( CHARS (Tty-> secondary),
181 (Unsigned long *) arg);
182 return 0;
183 case TIOCSTI :

--313--
7.9 tty_ioctl.c program

// analog input terminal. In the command pointer to a character as a parameter, and pretend to be the character typed on the terminal. // user must have superuser privileges or

have read permissions on the control terminal.

184 return - EINVAL ; / * not implemented * / / * Unrealized * /


185 case TIOCGWINSZ :
// Window size information reading terminal device (see winsize structure in termios.h).
186 return - EINVAL ; / * not implemented * / / * Unrealized * /
187 case TIOCSWINSZ :
// set the window size information terminal device (see winsize structure).

188 return - EINVAL ; / * not implemented * / / * Unrealized * /


189 case TIOCMGET :
// returns the current modem status control lead status bit flag set (see termios.h in rows 185-196).
190 return - EINVAL ; / * not implemented * / / * Unrealized * /
191 case TIOCMBIS :
// set control leads single modem status state (true or false).
192 return - EINVAL ; / * not implemented * / / * Unrealized * /
193 case TIOCMBIC :
// reset state control lead single modem state.
194 return - EINVAL ; / * not implemented * / / * Unrealized * /
195 case TIOCMSET :
// set the state of the modem status leads. If a bit position of the bit, the modem corresponding to the asserted state leads.

196 return - EINVAL ; / * not implemented * / / * Unrealized * /


197 case TIOCGSOFTCAR :
// read the software carrier detection flag (1 - Turn; 0 - off).
198 return - EINVAL ; / * not implemented * / / * Unrealized * /
199 case TIOCSSOFTCAR :
// Set the software carrier detection flag (1 - Turn; 0 - off).
200 return - EINVAL ; / * not implemented * / / * Unrealized * /
201 default:
202 return - EINVAL ;
203 }
204 }
205

7.9.3 Other Information

7.9.3.1 The baud rate and the baud rate factor

Baud Rate = 1.8432MHz / (16 * Baud rate factor). Program relation table corresponding to the baud rate and the baud rate factor 7-10 Fig.

table 7-10 Baud rate and wave Special rate because Table of correspondences

Baud rate factor Baud rate factor


Baud Rate MSB, LSB Baud Rate MSB, LSB
The combined value The combined value

50 0x09,0x00 2304 1200 0x00,0x60 96

75 0x06,0x00 1536 1800 0x00,0x40 64

110 0x04,0x17 1047 2400 0x00,0x30 48

134.5 0x03,0x59 857 4800 0x00,0x18 twenty four

150 0x03,0x00 768 9600 0x00,0x1c 12

200 0x02,0x40 576 19200 0x00,0x06 6

300 0x01,0x80 384 38400 0x00,0x03 3

600 0x00,0xc0 192

--314--
7.9 tty_ioctl.c program

--315--
8.1 Overview

The first 8 Chapter math coprocessor ( math)

8.1 Outline

Math coprocessor emulation file handling code in kernel directory kernel / math directory, but the program has not yet truly simulation code for a math

coprocessor, contains only a shell program, see the list 8-1 Fig.

List 8-1 linux / kernel / math table of Contents

name size Last Modified Time (GMT) Description

Makefile 936 bytes 1991-11-18 00:21:45


math_emulate.c 1023 bytes 1991-11-23 15:36:34

8.2 Makefile file

8.2.1 Functional Description

math Compile file directory management program.

8.2.2 Code comments

program 8-1 linux / kernel / math / Makefile

1#
2 # Makefile for the FREAX-kernel character device drivers.
3#
4 # Note! Dependencies are done automagically by 'make dep', which also
5 # Removes any old dependencies. DO NOT put your own dependencies here
6 # Unless it's something special (ie not a .c file).
7#
# Makefile file FREAX (Linux) kernel device driver characters.
# note! Dependency is performed by the 'make dep' automatically, which will automatically remove the original dependency information. Do not put your own

# Dependency information on here, unless it is (that is not a message .c file) special file.
89 AR
= Gar # GNU binary file processing program for creating, modifying and extracting files from the archive.
10 AS = Gas # GNU assembler.
11 LD = Gld # The GNU linker.
12 LDFLAGS = -s -x # connection program all the parameters, -s omitted all symbols output file information. -x Delete all local symbols.

13 CC = Gcc # GNU C language compiler.


# The next line is the C compiler options. -Wall display all warnings; -O optimization option, to optimize code size and execution time;
# - fstrength-reduce execution code optimization cycle, excluding iteration variable; -fomit-frame-pointer will be omitted to save unnecessary

# The frame pointers; -fcombine-regs merge register, reduce the use of register class; -finline-functions all Jane
# Single short code embedded function calls the program; -mstring-insns Linus own filling optimization options, will no longer use;

--317--
8.2 Makefile file

# - nostdinc -I ../ include not using the default path contains the file, and use the specified directory (../../include).
14 CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs \
15 - finline-functions -mstring-insns -nostdinc -I ../../ include
# C pre-processing options. -E C only run pre-treatment, pre-treatment and the results for all of the specified program is output to the standard output C

# The apparatus or a specified output file; -nostdinc -I ../../ include op.


16 CPP = Gcc -E -nostdinc -I ../../ include
17
# The following rule indicates that make use of the following command will compile all .c files generated .s Assembler. The rule of command

# Refers gcc CFLAGS using the specified options compiled C code is compiled without stops (-S), thereby generating
# C each corresponding to the input file assembler code file. Assembler default file name is generated by the original file name C
# Remove .c and .s suffix plus. -o represented followed by the name of the output file. Of which $ *. S (or $ @ ) is automatic target variable,

# $ <Represents the first prerequisite here that is qualified * .c files.


18 .cs:
19 $ (CC) $ (CFLAGS) \
20 - S -o $ *. S $ <
# The following rule means that all .s assembler .o files compiled into object files. Line 22 is a command to achieve the specific operation.

twenty one .so:

twenty two $ (AS) -c -o $ *. O $ <


twenty three .co: # . Similar to the above, * c files - * .o object files. Not connect.
twenty four $ (CC) $ (CFLAGS) \
25 - c -o $ *. o $ <
2627 OBJS = math_emulate.o
# Define the target file variable OBJS.
2829 math.a: $ (OBJS)
# Use the following command to connect to the target file in the library with math.a prerequisite OBJS.

30 $ (AR) rcs math.a $ (OBJS)


31 sync
32
# The following rules for the cleanup. When executing 'make clean', the following command will remove all compiled
# Connection file generated. 'Rm' command is to delete the file, meaning -f option is to ignore the file does not exist, and does not delete the information.

33 clean:
34 rm -f core * .o * .a tmp_make
35 for i in * .c; do rm -f `basename $$ i .c`.s; done
36
# Here was the objective or rules for checking dependencies between files. Methods as below:

# Sed string editing program for the Makefile (i.e. are files), and outputs for deletion Makefile
# File '### Dependencies' all rows behind, and generates a temporary file tmp_make. Then the kernel / math /
# Each file in the directory C gcc perform preprocessing operations.

# - M flag tells the preprocessor output description of the rules relating to each target file, and make compliance with these rules syntax.

# For each source file, the output of preprocessor make a rule, the result is a certain form of the corresponding source file
# File name plus its dependencies - lists all the header files included in the source file. The pretreatment results are added to the temporary

# Tmp_make file, and then copy the temporary file into a new file Makefile.
37 dep:
38 sed '/ \ # \ # \ # Dependencies / q' <Makefile> tmp_make
39 (For i in * .c; do echo -n `echo $$ i | sed '.. S, \ c, \ s,'` ""; \
40 $ (CPP) -M $$ i; done) >> tmp_make
41 cp tmp_make Makefile
4243 ### Dependencies:

--318--
8.3 math-emulation.c program

8.3 math-emulation.c program

8.3.1 Functional Description

Math coprocessor emulation processing code files. The program has not yet achieved simulation code for a math coprocessor. Only realized two called when the

coprocessor exception interrupt occurs C function. math_emulate () When only contains coprocessor instructions in the user program, the coprocessor is provided an abnormality

signal to the process.

8.3.2 Code comments

program 8-2 linux / kernel / math / math_emulate.c

1/*
2 * Linux / kernel / math / math_emulate.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * This directory should contain the math-emulation code.


9 * Currently only results in a signal.
10 * /
/*
* This directory should contain mathematical simulation code. Currently only produce a signal.

*/
1112 #include <signal.h>
// signal header files. Defined symbolic constant signal, the signal structure and the operation function prototype signal.

1314 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

15 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

16 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

17
//// coprocessor emulation functions.

// C interrupt handler function call, see (kernel / math / system_call.s, 169 lines).
18 void math_emulate (Long edi, long esi, long ebp, long sys_call_ret,
19 long eax, long ebx, long ecx, long edx,
20 unsigned short fs, unsigned short es, unsigned short ds,
twenty one unsigned long eip, unsigned short cs, unsigned long eflags,
twenty two unsigned short ss, unsigned long esp)
twenty three {

twenty four unsigned char first, second;


2526 / * 0x0007 means user code space * /

/ * 0x0007 * indicates a user code space /

// selector 0x000F represents a local descriptor table descriptor index value = 1, i.e. code space. If the segment register is not equal to 0x000F @ cs cs must be said selector

kernel code, the code in the kernel space, error display in this case cs: eip value and display information // "Mathematical simulation kernel needs" then enter the crash state.

27 if (cs! = 0x000F) {
28 printk ( ' math_emulate:% 04x:% 08x \ n \ r ", cs, eip);
29 panic ( ' Math emulation needed in kernel ");
30 }

--319--
8.3 math-emulation.c program

// get user data area stack data first and second, displays the data, and to the process set floating point exception signal SIGFPE.

31 first = get_fs_byte ((Char *) ((* & eip) ++));


32 second = get_fs_byte ((Char *) ((* & eip) ++));
33 printk ( "% 04x:% 08x% 02x% 02x \ n \ r ", cs, eip-2, first, second);
34 current -> signal | = 1 << ( SIGFPE -1);
35 }
36
//// coprocessor error handler.
// C interrupt handler function call, see (kernel / math / system_call.s, 145 lines).
37 void math_error (Void)
38 {
// coprocessor instructions. (In the form of a non-waiting) clears all exception flags, the busy flag, and bit 7 status word.

39 __asm ​__ ( " fnclex ");


// If the task coprocessors used, the upward transmission coprocessor task abnormality signal.

40 if ( last_task_used_math )
41 last_task_used_math -> signal | = 1 << ( SIGFPE -1);
42 }
43

--320--
9.1 Overview

The first 9 Chapter File System ( fs)

9.1 Outline

This chapter deals linux File system implementation code kernel and device for the block buffer cache manager. In the development linux 0.11

When the kernel file system, Linus Referring mainly to the Andrew S.Tanenbaum Significant " MINIX Operating Systems Design and Implementation, "a book, which was used MINIX File

system 1.0 Version. Therefore, in this chapter, you can refer to the book about MINIX The relevant sections of the file system. The works can be found in the buffer cache MJBach of"

UNIX Operating System Design "Chapter III.

List 9-1 linux / fs table of Contents

name size Last Modified Time (GMT) Description

Makefile 5053 bytes 1991-12-02 03:21:31 m

bitmap.c 4042 bytes 1991-11-26 21:31:53 m

block_dev.c 1422 bytes 1991-10-31 17:19:55 m

buffer.c 9072 bytes 1991-12-06 20:21:00 m

char_dev.c 2103 bytes 1991-11-19 09:10:22 m

exec.c 9134 bytes 1991-12-01 20:01:01 m

fcntl.c 1455 bytes 1991-10-02 14:16:29 m

file_dev.c 1852 bytes 1991-12-01 19:02:43 m

file_table.c 122 bytes 1991-10-02 14:16:29 m

inode.c 6933 bytes 1991-12-06 20:16:35 m

ioctl.c 977 bytes 1991-11-19 09:13:05

namei.c 16562 bytes 1991-11-25 19:19:59 m

open.c 4340 bytes 1991-11-25 19:21:01 m

pipe.c 2385 bytes 1991-10-18 19:02:33 m

read_write.c 2802 bytes 1991-11-25 15:47:20 m

stat.c 1175 bytes 1991-10-02 14:16:29 m

super.c 5628 bytes 1991-12-06 20:10:12 m


truncate.c 1148 bytes 1991-10-02 14:16:29 m

9.2 Overall Functional Description

This chapter of the amount of notes is large, but we can divide them into four parts from the function. The first part is related to a high speed buffer management program,

mainly realizes the function of the hard disk device block data cache access. This part focused on the buffer.c Program implemented; the second part function code describes the

general low level file system. Describes the inode file management, allocates disk blocks and release as well as the file name and i Conversion algorithm node; a third part of the

program is about to read and write data files, comprising

--321--
9.2 Overall Functional Description

Character devices, pipes, blocks access to read and write data in the file; implementation of the interface portion of the fourth program relates the file system calls, mainly related

to the file open, close, create directory, and system files related to the call operation.

The following first introduce MINIX The basic structure of the file system, and then were to illustrate these four sections.

9.2.1 MINIX File system

Currently MINIX Version is 2.0 File system used is 2.0 Edition, which with its 1.5 Different versions of the previous version of the system, its capacity has been expanded.

But because the book comments linux Kernel is MINIX File system 1.0 Version, so here it is only 1.0

Version of the file system for a brief introduction.

MINIX File system standard UNIX Basically the same file system. It consists of 6 Parts. For a 360K Floppy disk, see the distribution of its parts 9-1 Fig.

Guide block superblock

i-node A disk block

Data Area

i-node bit map logical block bitmap

Map 9-1 Has MINIX A file system 360K Schematic layout of various parts of the diskette file system

Drawing, by the guide block is started when the computer is powered ROM BIOS Automatically read execution code and data. However, not all disks are used as the boot

device, it is not used for guiding the disk, the disk can be free of the code block. However, the disk must contain no guide block, in order to maintain MINIX Unified file system format.

Superblock information for file system structure on the disk storage device, and the size of each part described. Structure shown in Figure 9-2 Fig.

Field Name type of data Explanation

s_ninodes short i nodes


s_nzones short The number of logical blocks (or the number of blocks)

s_imap_blocks short i-node number of blocks occupied by the bitmap

s_zmap_blocks short Logical blocks occupied block bitmap


field of memory
s_firstdatazone short A first logical block number

s_log_zone_size short Log 2( Number of blocks / logical blocks)

the plate and in the


s_max_size long The maximum file size

s_magic short File magic number system

s_imap [8] buffer_head * i-node bitmap cache block pointer array


in memory appears on s_zmap [8] buffer_head * bitmap logic block in the cache block pointer array
s_dev short Device where the super block number

s_isup m_inode * It is mounted file system root node i


Only the fields used
s_imount m_inode * The file system is mounted to the i-node

s_time long Change the time

s_wait task_struct * wait for the process according to the present pointer superblock

s_lock char Lock Flag


s_rd_only char Read-only flag

s_dirt char Has been modified (dirty) logo

--322--
9.2 Overall Functional Description

Map 9-2 MINIX The superblock structure

Seen from the figure, the most logical block bitmap using 8 Block buffer block ( s_zmap [8] ), And each block may represent a block buffer 8192 A disk block, therefore, MINIX

File system 1.0 The maximum supported block device capacity (length) is 64MB .

i Bitmap node for explaining i If the node is used, each bit represents a i node. for 1K In terms of disk block size, the block can be represented by a disc 8191 More

i Usage node.

Logic block bitmap for usage of each data block on the disk tray is described, a disk block data representative of each bit in the data area on the disc. Thus, one bit

represents a logical first block of bit map data on the disc area of ​the first data block of the disc. When a data block is occupied by the disc, the logic block bitmap corresponding

bit is set.

On the disc i The node portion of the file system to store the file (or directory) inode, each file (or directory) has a i

node. Each i Node structure stored in the corresponding related information files, such as files host id (uid) , File owning group id ( gid ), File access and modify the length of time.

The entire structure were used 32 Bytes, see FIG. 9-3 Fig.

Field Name type of data Explanation

i_mode short Types and attributes of the file (rwx bits)

i_uid short File host user id


i_size long File length (in bytes)
i_mtime long Modified (from 1970.1.1: 0 date, s)
i_gid char File host group id
The 32-byte
i_nlinks char Link count (the number of files in the directory entry points to the i-node)

i_zone [9] short Occupied by the file on the disk array of logical block numbers. Wherein: zone

[0] -zone [6] is a direct block number; zone [7] is a number of indirect block;

zone [8] is a second (double) indirect block number. Note: zone area is meant,

may be translated into a logical block or blocks.

Map 9-3 MINIX File system 1.0 Edition i Node structure

i_mode Field is used to save the file types and access to property. Which bits 15-12 To save the file type, bit 11-9 Information set when saving execute files,

bitmaps 8-0 It represents access to files. See specific information file include / sys / stat.h with

include / fcntl.h .
The data file is placed in the data area of ​the disk blocks, and a file name through the corresponding i Node associated with the data disk blocks, which blocks on the disk

numbers stored in i Logic block array node i_zone [] in. among them, i_zone [] Array used to store i Disk block number corresponding to the node of the file. i_zone [0] To i_zone [6] For

storing files started 7 Disk block number, known as direct block. If the document length or less 7K Bytes, according to which i Node can use it to find the disk blocks soon. If the file

is larger, the need to use a indirect block the ( i_zone [7] ), The disk block stored in the additional disk block number. for MINIX It can be stored in the file system 512 A disk block

number, thus addressing the 512 A disk block. If the file is larger, you need to use a secondary indirect disk block ( i_zone [8] ). A secondary effect of the indirect blocks similar to

block a disc tray indirect blocks, thus indirectly using a secondary disk blocks may be addressed 512 * 512 A disk block. Referring to FIG. 9-4 Fig.

--323--
9.2 Overall Functional Description

Other fields
Once indirect block
node i

i_zone [0]

i_zone [1]

i_zone [2]

Direct block number i_zone [3]

i_zone [4]

i_zone [5]

i_zone [6]

A second number of i_zone [7]


A second indirect blocks A second indirect blocks
i_zone
indirect block indirect block number [8] A block Two blocks

Map 9-4 i The functional logic block node (block) of the array

When all i When nodes are used to find idle i Function returns the value of the node 0 ,therefore, i Bitmap node and Least Significant Bit i node 0 Both when

idle and will create a file system i node 0 Bit bit.

for PC Machine is concerned, generally one sector length ( 512 Bytes) length data block as a block device. and MINIX The file system will be continuous 2 Data sectors ( 1024

Bytes) as a data processing block, called a disk block or disk blocks. The length of the buffer in the buffer cache block length the same. A disk block number is counted from the

first plate, i.e. boot blocks are 0 Disk block number. And said logic blocks or the block, the block is a disc 2 The power of multiples. A logical block length may be equal to 1 , 2 , 4 or 8 Disks

block length. For discussed in this book linux Core, the length of the logical block equal to the disk block length. Thus the same code comments both terms meaning. The term

logical blocks of data (or block data disks) device refers to the data portion on the disc, the disc from the first data block begins disk block numbers.

9.2.2 Types and attributes of the file

UNIX Class operating system files are usually divided into 6 class. If the shell Under execution " ls -l " Command, we can know the type of file from the file status

information listed. See Fig. 9-5 Fig.

File type '-' regular file 'd'


directory name 's' symbolic
link 'p' named pipes 'c'
character device file 'b'
block device file

groups and others permissions Link count Last Modified

-rwxr-xr-x 1 ftpadm ftp 47910 month 26 17:28 README

Others permission to users,


username group name File size file name

Group Permissions

User rights

Map 9-5 command' ls -l ' Display file information

FIG., The first byte indicates the type of command to display the file list. '-' indicates that the file is a regular (general) file. Regular files ( '-') is a type of file system

is a file for not be explained, with any length of the byte stream. For example source file,

--324--
9.2 Overall Functional Description

Binaries, documentation, and script files.


table of Contents(' d ' )in UNIX File system is a file, but the file system management can explain its content, so that people can see those files are

contained in a directory, and how they are organized together to form a hierarchical file system.

Symbolic link ( ' s' ) For using a different file name to refer to another document. Across a symbolic link file system, a file is connected to another file system. To

delete a symbolic link does not affect files that are linked. Another called "hard-wired", but it is the same as the file status to be connected, are treated as a general

document, but can not cross the file system (or device) is connected, and increments the count value of the file connected with here. Description link below face

counts.

Named Pipes ( ' p ' ) File is a file created when the system creates a named pipe. It can be used for communication between unrelated processes. Character device ( ' c ' ) File

is used in file access character operated device, e.g. tty Terminal, a memory device and a network device. Block device ( ' b ' ) File is used to access the device as hard disk,

floppy disk or the like. in UNIX Based operating system, a character block device file and the device file system are generally stored in / dev Directory.

in linux Kernel, file type information stored in the corresponding i Node i_mode Field, use high 4 Bit to indicate, using a number of macro file type is

determined, e.g. S_ISBLK , S_ISDIR Etc. These macros include / sys / stat.h Defined.

In the drawing after the file type of characters per set of three characters a set of three attributes configuration file permissions. Is used to represent the host file, the same

group and other users access to the file. ' rwx ' Respectively, a file is readable, writable and executable permissions. For catalog files, executable representation can enter the

directory. When to file permissions to operate, it is generally used to represent octal them. E.g' 755 ' It indicates that the file on the host file read / write / execute the same set of

users and others can read and execute files. in linux 0.11 Source code, file permissions information is also stored in the corresponding i Node i_mode Field, the field is used low 9 The

bit indicates three sets of permissions. And often use variables mode

To represent. Wang about file permissions in include / fcntl.h Defined.

FIG apos connection count "indicates the number of times the file is referenced hardwired. When the count reaches zero, the file is deleted. 'Username' indicates the file

name of the host, 'Group name' is the name of the user belongs.

9.2.3 High-speed buffer

Buffer cache block device is accessing data in a file system go through arteries. In order to access data on a block device file system, the kernel can access every piece of

equipment, a read or write operation. But each time I / O Time and memory operations and CPU The processing speed is very slow in comparison. In order to improve the

performance of the system, the kernel has opened up a high-speed data buffer (pool) in memory ( buffer cache ), And divides it into a number equal to the disk block size of the

buffer management block and used, in order to reduce the number of accesses to the block device. in linux

The kernel, the kernel code is located between the buffer cache and the main memory area, see Fig. 2.6 Fig. The cache data blocks stored in the respective block device recently

been used in. When the need to read data from a block device, the program first looks for buffer management in the cache. If the corresponding data is already in the buffer, you will

not have to read from the block device. If the data is not in the cache, a read command is issued block device, to read data in the cache. When it is desired to write data to a block

device, the system will apply a high-speed idle buffer block buffer to temporarily store these data. As for when the data is actually written to the device, it is through the device data

synchronization to achieve.

Linux Kernel implementation of the program is a high-speed buffer buffer.c . The file system to other programs calling block read and write functions by device number and

logical block number of data to be accessed is specified. These interface functions are: block read function bread () , Advance pre-reading function block breada () And a page read

function block bread_page () . Page block read function reads a buffer memory to hold a block ( 4 Piece).

9.2.4 Low-level file system function

Layer processing function of the file system contained in the following 4 A file:

bitmap.c Program includes i Bitmap node and the logical block bitmap release and occupied handlers. operating i Bitmap node is a function of

free_inode () with new_inode () , A logical operation function block bitmap is free_block () with new_block () .

inode.c Program includes distribution i Node function iget () And the release of the memory i Access nodes function iput () And according to i Take node information in the

data block corresponding to the logical block number on the device function bmap () .

namei.c The main function of the program include namei () . This function uses iget () , iput () with bmap () Given its file path name is mapped to i node.

--325--
9.2 Overall Functional Description

super.c A program designed to process the file system superblock, including functions get_super () , put_super () with free_super () Wait. Also includes several file

system load / offload processing functions and system calls, such as sys_mount () Wait. These documents are hierarchical relationship between the function shown in

Figure 9-6 Fig.

new_inode new_block get_super namei


free_inode free_block put_super
iget iput bmap

Map 9-6 Low-level file system hierarchy manipulation functions

9.2.5 The data file access operations

About file data access operation code, mainly related 5 Files: block_dev.c , file_dev.c , char_dev.c , pipe.c
with read_write.c . before 4 Documents can be considered as a block device, character device, plumbing and general interface program files and read and write system call, which

together achieve a read_write.c middle read () with write () System call. Determining by the operation of the file attributes, which are two system call calls these files correlating

process operation functions.

System call read () write ()

block_read () file_read () read_pipe ()


rw_char ()
block_write () file_write () write_pipe ()

Map 9-7 Data file access functions

block_dev.c The function block_read () with block_write () Is a special file read and write data in the block device. The parameters used to specify a device number to be

accessed, the write start position and length.

file_dev.c middle file_read () with file_write () Function is a formal document for access in general. By specifying a file corresponding i Nodes and file structure, which can

read and write pointers to know the current file number and the file is on a device.

pipe.c File read and write functions implemented in the pipeline read_pipe () with write_pipe () . It also enables the creation of system calls unnamed pipes pipe () . The main

conduit for transmitting data in a FIFO manner between processes, can also be used to perform the synchronization process. There are two types of pipes: anonymous pipes and

named pipes. Named pipes that use the file system open Call establishment, and the unnamed pipe system call is used pipe () To create. When using the pipe, then have a regular

file read () , write () with close () function. Only issue pipe

Call the offspring, in order to share access to anonymous pipes, and as long as all processes Licenses, you can access a named pipe.

For write pipeline it can be seen as a process of writing data from the end of the pipe, while another process reads data from the other end of the pipe. Kernel access data

from the pipeline access mode generally normal manner exactly as the data file. For the distribution pipeline and storage space is different from the regular file allocation of space

is to use only the pipeline i Direct block of the node. The kernel i Direct block node as a circular queue is managed by a read-write pointer for FIFO order.

For the character device file system calls read () with write () Will call char_dev.c middle rw_char () Function to operate. Character devices include console terminal ( tty ),

Serial terminal ( ttyx) Character and memory devices.

In addition, the kernel file structure file And file table file_table [] To access to the file management operations. File Structure file As follows.

--326--
9.3 Makefile file

struct file {
unsigned short f_mode; // file operation mode (RW bit)
unsigned short f_flags; // File Open and sign control.
unsigned short f_count; // the corresponding file handle (file descriptor) number.

struct m_inode * f_inode; // i pointing to the corresponding node.

off_t f_pos; // read and write files in the current pointer location.

};

For the file handle and i Establish a relationship between the nodes. File table is an array of file structure, in linux 0.11 The kernel file table can have a maximum 64 Item,

so the whole system up to simultaneously open 64 Files. While at the same time open up to each process 20 Files.

9.2.6 File and directory management system calls

Upper implement the relevant file system calls, basically includes map 9-8 in 5 Files.

exec.c fcntl.c
ioctl.c stat.c
open.c

Map 9-8 File system upper operating procedures

open.c Files used to implement file-related operating system calls. There are file was created, opened and closed, modify modified file access permissions of the file's

owner and attributes, file modification time operating system and file system root Changes and so on.

exec.c Program to achieve binary executable files and shell Load and execute the script file. One of the major function is a function

do_execve () It is a system interrupt call ( int 0x80) Function No. __ NR_execve () Call C Handler is exec () The main function of the realization function clusters.

fcntl.c Achieve the document control system call fcntl () And two file handles (descriptor) replication system call dup () with dup2 () . dup2 ()

Specify the value of the new handle, and dup () Current minimum value of unused handle is returned. Handle copy operation is mainly used in the standard input file I / O

redirection and operational aspects of the pipeline.

ioctl.c File implements the input / output control system call ioctl () . The main call tty_ioctl () Function of the terminal I / O Control.

stat.c Take file status information file for implementing the system call stat () with fstat () . stat () Natori is the use of file information, fstat () Using a file handle (descriptor) to

extract information.

9.3 Makefile file

9.3.1 Functional Description

makefile File System subdirectory is compiled administrative configuration file for compiling software management tools make use.

9.3.2 Code comments

program 9-1 linux / fs / Makefile

--327--
9.3 Makefile file

1 AR = Gar # GNU binary file processing program for creating, modifying and extracting files from the archive.
2 AS = Gas # GNU assembler.
3 CC = Gcc # GNU C language compiler.
4 LD = Gld # The GNU linker.

# C compiler options. -Wall display all warnings; -O optimization option, to optimize code size and execution time;
# - fstrength-reduce execution code optimization cycle, excluding iteration variable; -fomit-frame-pointer will be omitted to save unnecessary

# The frame pointers; -fcombine-regs merge register, reduce the use of register class; -mstring-insns Linus own
# Filling optimization options, will no longer use; -nostdinc -I ../ include not using the default path contains documents, the
# Here with the specified directory (../include).
5 CFLAGS = -Wall -O -fstrength-reduce -fcombine-regs -fomit-frame-pointer \
6 - mstring-insns -nostdinc -I ../ include

# C pre-processing options. -E C only run pre-treatment, pre-treatment and the results for all of the specified program is output to the standard output C

# The apparatus or a specified output file; -nostdinc -I ../ include op.


7 CPP = Gcc -E -nostdinc -I ../ include
8
# The following rule indicates that make use of the following command will compile all .c files generated .s Assembler. The rule of command

# Refers gcc CFLAGS using the specified options compiled C code is compiled without stops (-S), thereby generating
# C each corresponding to the input file assembler code file. Assembler default file name is generated by the original file name C
# Remove .c and .s suffix plus. -o represented followed by the name of the output file. Of which $ *. S (or $ @ ) is automatic target variable,

# $ <Represents the first prerequisite here that is qualified * .c files.


9 .cs:
10 $ (CC) $ (CFLAGS) \
11 - S -o $ *. S $ <
# We will compile all * .c * .o files into the target file. Not connect.
12 .co:
13 $ (CC) $ (CFLAGS) \
14 - c -o $ *. o $ <
# The following rule means that all .s assembler .o files compiled into object files. Line 16 is a command to achieve the specific operation.

15 .so:
16 $ (AS) -o $ *. O $ <
17
# Define the target file variable OBJS.
18 OBJS = open.o read_write.o inode.o file_table.o buffer.o super.o \
19 block_dev.o char_dev.o file_dev.o stat.o exec.o pipe.o namei.o \
20 bitmap.o fcntl.o ioctl.o truncate.o
twenty one

# Use the following prerequisites have after OBJS command to connect to the target fs.o

twenty two fs.o: $ (OBJS)

twenty three $ (LD) -r -o fs.o $ (OBJS)


twenty four

# The following rules for the cleanup. When performing 'make clean', will execute commands on the 26-27 line, remove all compiled
# Connection file generated. 'Rm' command is to delete the file, meaning -f option is to ignore the file does not exist, and does not delete the information.

25 clean:
26 rm -f core * .o * .a tmp_make
27 for i in * .c; do rm -f `basename $$ i .c`.s; done
28
# Here was the objective or rules for checking dependencies between files. Methods as below:

# Sed string editing program for the Makefile (where that is their own) for processing, the output is deleted Makefile
# File '### Dependencies' all rows behind the row (row 35 starting from below), and generates tmp_make
# Temporary files (for 30 lines). Gcc then performs a preprocessing operation on each file in the C fs / directory.
# - M flag tells the preprocessor output description of the rules relating to each target file, and make compliance with these rules syntax.

--328--
9.3 Makefile file

# For each source file, the output of preprocessor make a rule, the result is a certain form of the corresponding source file
# File name plus its dependencies - lists all the header files included in the source file. The pretreatment results are added to the temporary

# Tmp_make file, and then copy the temporary file into a new file Makefile.
29 dep:
30 sed '/ \ # \ # \ # Dependencies / q' <Makefile> tmp_make
31 (For i in * .c; do $ (CPP) -M $$ i; done) >> tmp_make
32 cp tmp_make Makefile
3334 ### Dependencies:

35 bitmap.o: bitmap.c ../include/string.h ../include/linux/sched.h \


36 . . /include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
37 . . /include/linux/mm.h ../include/signal.h ../include/linux/kernel.h
38 block_dev.o: block_dev.c ../include/errno.h ../include/linux/sched.h \
39 . . /include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
40 . . /include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
41 . . /include/asm/segment.h ../include/asm/system.h
42 buffer.o: buffer.c ../include/stdarg.h ../include/linux/config.h \
43 . . /include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
44 . . /include/sys/types.h ../include/linux/mm.h ../include/signal.h \
45 . . /include/linux/kernel.h ../include/asm/system.h ../include/asm/io.h
46 char_dev.o: char_dev.c ../include/errno.h ../include/sys/types.h \
47 . . /include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
48 . . /include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
49 . . /include/asm/segment.h ../include/asm/io.h
50 exec.o: exec.c ../include/errno.h ../include/string.h \
51 . . /include/sys/stat.h ../include/sys/types.h ../include/a.out.h \
52 . . /include/linux/fs.h ../include/linux/sched.h ../include/linux/head.h \
53 . . /include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
54 . . /include/asm/segment.h
55 fcntl.o: fcntl.c ../include/string.h ../include/errno.h \
56 . . /include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
57 . . /include/sys/types.h ../include/linux/mm.h ../include/signal.h \
58 . . /include/linux/kernel.h ../include/asm/segment.h ../include/fcntl.h \
59 . . /include/sys/stat.h
60 file_dev.o: file_dev.c ../include/errno.h ../include/fcntl.h \
61 . . /include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
62 . . /include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
63 . . /include/linux/kernel.h ../include/asm/segment.h
64 file_table.o: file_table.c ../include/linux/fs.h ../include/sys/types.h
65 inode.o: inode.c ../include/string.h ../include/sys/stat.h \
66 . . /include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
67 . . /include/linux/fs.h ../include/linux/mm.h ../include/signal.h \
68 . . /include/linux/kernel.h ../include/asm/system.h
69 ioctl.o: ioctl.c ../include/string.h ../include/errno.h \
70 . . /include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \
71 . . /include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
72 . . /include/signal.h
73 namei.o: namei.c ../include/linux/sched.h ../include/linux/head.h \
74 . . /include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
75 . . /include/signal.h ../include/linux/kernel.h ../include/asm/segment.h \
76 . . /include/string.h ../include/fcntl.h ../include/errno.h \
77 . . /include/const.h ../include/sys/stat.h
78 open.o: open.c ../include/string.h ../include/errno.h ../include/fcntl.h \

--329--
9.4 buffer.c program

79 . . /include/sys/types.h ../include/utime.h ../include/sys/stat.h \


80 . . /include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
81 . . /include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
82 . . /include/termios.h ../include/linux/kernel.h ../include/asm/segment.h
83 pipe.o: pipe.c ../include/signal.h ../include/sys/types.h \
84 . . /include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
85 . . /include/linux/mm.h ../include/asm/segment.h
86 read_write.o: read_write.c ../include/sys/stat.h ../include/sys/types.h \
87 . . /include/errno.h ../include/linux/kernel.h ../include/linux/sched.h \
88 . . /include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
89 . . /include/signal.h ../include/asm/segment.h
90 stat.o: stat.c ../include/errno.h ../include/sys/stat.h \
91 . . /include/sys/types.h ../include/linux/fs.h ../include/linux/sched.h \
92 . . /include/linux/head.h ../include/linux/mm.h ../include/signal.h \
93 . . /include/linux/kernel.h ../include/asm/segment.h
94 super.o: super.c ../include/linux/config.h ../include/linux/sched.h \
95 . . /include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
96 . . /include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
97 . . /include/asm/system.h ../include/errno.h ../include/sys/stat.h
98 truncate.o: truncate.c ../include/linux/sched.h ../include/linux/head.h \
99 . . /include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
100 . . /include/signal.h ../include/sys/stat.h

9.4 buffer.c program

9.4.1 Functional Description

buffer.c Procedure for cache area (cell) to operate and manage. Located between the kernel buffer cache and main memory area block, see FIG. 9-9 In FIG. Buffer cache

plays a role of a bridge between the device and the core block other programs. In addition to the device driver blocks, if the kernel needs to access data blocks in the device, you

will need to go through the buffer cache to indirectly operate.

Kernel Module Cache Virtual disk The primary bank

end 0 640K 1M 4M 4.5M 16M

Memory and BIOS ROM

Map 9-9 Located throughout the physical memory location in buffer cache

FIG starting position from the last paragraph of buffer cache kernel module end Label start, end During the kernel module is linked by the linker ( ld ) A value of the kernel

code symbol is not defined. When generating the connection system Module, ld Program digest_symbols ()

This function will generate symbol. This function is mainly used for assigning reference global variables, and calculates the size of each of which are connected to the start and the file,

--330--
9.4 buffer.c program

Which also set end Value, which is equal to data_start + datasize + bss_size , That the last paragraph of kernel modules.

Entire buffer cache is divided into 1024 -Byte cache block, just the same as the logical block size on disk block device. Cache using hash Table and an idle buffer block

queue management operations. In the buffer initialization process, from both ends of the buffer, while the buffer header structure are provided and divided into blocks

corresponding buffer. High-end buffer is divided into one 1024 Byte buffer block, respectively, to establish the low end of the buffer structure corresponding to each header block

buffer buffer_head ( include / linux / fs.h , 68 Line), for buffering attribute description of a corresponding block and the connector to list all buffers. Until they can no longer be divided

between the blocks until the buffer, see 9-10 Fig. And each

buffer_head It is linked into a doubly linked list of free buffer block structure. Detailed structure shown in Figure 9-11 Fig.

Buffer block

Low-end buffer High-end buffer

Cushion structure corresponding to It has no buffering block

division. Abandoned

Map 9-10 High-speed buffer initialization

Buffer block Buffer block Buffer block Buffer block

free_list
b_data b_data b_data b_data
other fields other fields other fields other fields
b_prev b_prev b_prev b_prev
Hash table entry pointer
b_next b_next b_next b_next
b_prev_free b_prev_free b_prev_free b_prev_free
b_next_free b_next_free b_next_free b_next_free

Map 9-11 Free way circular linked list structure buffer block

Cushion Structure "Other Fields" device includes a block number, a logical block number of the buffered data, the two fields uniquely identify the data corresponding to the

block buffer block device and data blocks. There are also several status flags: valid data (updated) flag, modify flag, the number of processes to be used and the present data

buffer block is locked flag.

When using the kernel buffer block in the buffer cache, the device number is designated ( dev) And the logical block number of data to be accessed by the device

--331--
9.4 buffer.c program

(Block) By calling bread () , bread_page () or breada () Function operates. These functions use the search buffer management function getblk () The function will be highlighted

below. When the system releases the buffering block, call brelse () function. These calls hierarchy buffer data access and management functions available map 9-12 To

describe.

bread, breada, bread_page

(Getblk)
brelse
get_hash_table, find_buffer etc.

Map 9-12 Hierarchical relationship between buffer management function

In order to quickly find the data block in the buffer if the request has been read into the buffer, buffer.c Program uses has

307 More buffer_head Pointer items hash Table Structure. The figure above buffer_head Pointer Structure b_prev , b_next It is used hash

Hash table bidirectional connection between a plurality of blocks on the same one buffer. Hash Hash function table used in combination with the device number and logical block

number from. DETAILED function used in the program is the device number :( ^ logical block number) Mod 307 . For dynamic hash Structural states of a time table can be found in

FIG. 9-13 Fig.

Hash array

Hashed Entry 1 Buffer head Buffer head Buffer head

Hashed Entry 2
Buffer head Buffer head

Hashed Entry 3

Buffer head Buffer head Buffer head Buffer head

Hashed Entry 307


Buffer head Buffer head Buffer head

free_list

Buffer head Buffer head Buffer head Buffer head

Map 9-13 A time kernel buffer queuing block hashes

Wherein the double arrow lines represent the same hash hash Entry pointer buffer bidirectional link between the block header structure. Dashed line indicates the current

connection in the free block list an idle buffer pointer link between the buffer block, free_list Is the head of the free list pointer. For operation on the hash queue buffer block, can be

found in reference [ 11] The first 3 Detailed description chapter.

The above-mentioned three functions are performed when the search function is called buffer block getblk () To obtain suitable buffer block. This function first calls get_hash_table

() Function, in hash Table queue buffer block searches whether the specified device number and logical block number exists. If there immediately returns the corresponding buffer

pointer head structure; if not, start over from the free list, the free list is scanned to find a free buffer block. In the process of looking also find an idle buffer block for comparison,

the compositions according to the modification flag and imparting the lock flag

--332--
9.4 buffer.c program

As weights, which compares the most suitable free block. If the free block found neither modified nor locked, do not continue to look up. If the free block is not found, the current

process to sleep, when to be looking again to continue. If the free block is locked, the process also need to go to sleep and wait for other processes to unlock. If in the process of

waiting for sleep, the buffer block has been used by another process, then start over again as long as the search buffer block. Otherwise, determine whether the buffer block has

been modified, and if so, then the block write disk, and wait for the block to unlock. At this point if the buffer block has been occupied by another process, then do give full power

again, we had to start over again executed getblk () . After a more than toss, then there may be another unforeseen circumstances, that is, when we sleep, we may have other

processes needed to add the buffer block hash Queue, so there needs to last search hash queue. If you really hash Queue buffering block find we need, then we have to find the

block of the buffer is above determination process, and therefore, needs to start over again performed getblk () . Finally, we found a considered process is not used, is not locked,

but is clean (modified flag is not set) free buffer block. So we set the number of reference in block 1 And several other flag is reset, the block buffer was then removed from the free

list head structure. After setting the device number and logical number corresponding to the buffer block belongs, put it in hash A first correspondence table and the free end of the

queue entries. Finally, return the buffer pointer to the block header. entire getblk () See Figure process 9-14 Fig.

getblk

Search hash table

Yes
Block in the cache in?

no
Search idle queue

no
Find the right block?

Yes

Wait (if already locked) Goes to sleep

Yes
But to somebody else?

no
Yes
The block has been modified?

no The data is written to the device


Yes
Already in the cache?

no Goes to sleep waiting

A reference count of the block is provided,

and the effective modification flag is reset, Yes


But to somebody else?
and this block is removed from the hash table and the free list

Set occupying the block number of the block number of the device

Reinsert the block hash table entry

corresponding to the head and the free end of the queue

Back head pointer buffer

Map 9-14 getblk () Execution Flow Function

--333--
9.4 buffer.c program

We can see from the above process, getblk () Buffer block may be returned to a new free block, also contain buffer block may be just what we need the data, it is already

present in the buffer area. Therefore, for reading data blocks operation ( bread ()) , Then we must update flag of the cache block is determined to see if valid data is contained, it is

effective if the data block can be directly returned to the application program. Otherwise, you need to call the low-level block device to read and write function ( ll_rw_block () ), And at

the same time let yourself go to sleep, waiting for the data to be read into the buffer block. In the wake of the then determine whether the data is valid. If so, this data can be returned

to the application program, or the device description of the read operation fails, the data is not taken. Thus, the release of the buffering block and returns NULL value. Map 9-15 Yes bread

() Function block diagram. breada ()

with bread_page () Function and bread () Similar functions.

bread

Get buffer block (getblk)

Yes
Block data is valid?

no

Call the low-level block write function

block device ll_rw_block ()

Goes to sleep waiting state

Yes
Block data is valid?

no
Releasing the buffer block Return header buffer pointer

Return NULL

Map 9-15 bread () Function execution flow diagram

When a program is no longer required to use a data buffer block, is called brelse () Function to release the buffer block and wakes up the process of waiting for the buffer

block and goes to sleep. Note that, the free buffer block buffer block in the linked list, are not free. Only when the disc is written refreshed, unlocked and when no other process

references (reference count = 0 ), To its intended purpose.

In summary, the buffer cache plays an important role in improving the efficiency of the block device access and increased data sharing. In addition to the driver, the kernel

of the other upper layer programs read and write operations to the block device requires a high-speed buffer achieved indirectly through the hypervisor. The main link between

them is a high-speed buffer management program bread () And the low-level function block device interface functions ll_rw_block () to realise. To access the program the upper

block through the device data is bread () Apply to the buffer management program. If the required data is already in the buffer cache, the data management program will be

returned directly to the program. If the required data is not yet in the buffer, then the manager will pass

ll_rw_block () Apply to the block device drivers, while allowing the process to sleep waiting for the corresponding program. Wait until the block device drivers specified data into the

cache area, the management program will not return to the upper layer. See Fig. 9-16 Fig.

--334--
9.4 buffer.c program

The upper core program High-speed buffer Block device

bread () ll_rw_block ()
Read and write operations

Map 9-16 Kernel program block device access operations

9.4.2 Code comments

program 9-2 linux / fs / buffer.c

1/*
2 * Linux / fs / buffer.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * 'Buffer.c' implements the buffer-cache functions. Race-conditions have


9 * Been avoided by NEVER letting a interrupt change a buffer (except for the
10 * Data, of course), but instead letting the caller do it. NOTE! As interrupts
11 * Can wake up a caller, some cli-sti sequences are needed to check for
12 * Sleep-on-calls. These should be extremely quick, though (I hope).
13 * /
/*
* 'Buffer.c' for implementing a buffer cache function. Buffer changes by not interrupting the process, but let the caller
* To perform, to avoid race conditions (except of course was changed data). note! Since the interrupt can wake up a caller,
* Hence the need for switch interrupt instruction (cli-sti) sequence returns to wait for the call is detected. But it requires very fast (hope so).

*/
1415 / *

16 * NOTE There is one discordant note here:! Checking floppies for


17 * Disk change. This is where it fits best, I think, as it should
18 * Invalidate changed floppy-disk-caches.
19 * /
/*
* note! Here is a program that should not belong here: detecting whether to replace the diskette. But I think there is

* The best place to place the program, because it is necessary to replace the diskette buffer has failed.

*/
2021 #include <stdarg.h>
// standard parameter header. In the form of macro variables defined parameter list. Mainly it described
- a type // (the va_list) and three macros (va_start, va_arg and va_end), for // vsprintf, vprintf, vfprintf
function.
2223 #include <linux / config.h> // kernel configuration file header. Define the keyboard language and hard disk type (HD_TYPE) option.

twenty four #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

25 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

26 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

27 #include <asm / io.h> // io header files. Defined hardware port I / O macro assembler statements.

28

--335--
9.4 buffer.c program

29 extern int end ; // ld by a linker to generate a variable indicating the end of the kernel code.

30 struct buffer_head * start_buffer = (Struct buffer_head *) & end ;


31 struct buffer_head * hash_table [ NR_HASH ]; // NR_HASH = 307 items.
32 static struct buffer_head * free_list ;
33 static struct task_struct * buffer_wait = NULL ;
34 int NR_BUFFERS = 0;
35
//// waiting for a specified buffer unlocked.

36 static inline void wait_on_buffer (Struct buffer_head * Bh)


37 {
38 cli (); // disable interrupts.

39 while (bh-> b_lock) // If you have been locked, the process goes to sleep, waiting to unlock it.

40 sleep_on (& Bh-> b_wait);


41 sti (); // open the interruption.

42 }
43
//// system call. Data synchronization apparatus and the cache memory.

44 int sys_sync (Void)


45 {
46 int i;
47 struct buffer_head * Bh;
4849
sync_inodes (); / * Write out inodes into buffers * / / * The write cache node i
*/
// all scan buffer cache, generates a write request for a disk cache block has been modified, will be synchronized with the data buffer device.

50 bh = start_buffer ;
51 for (i = 0; i < NR_BUFFERS ; I ++, bh ++) {
52 wait_on_buffer (Bh); // Wait for buffer unlocked (if the case is locked).
53 if (bh-> b_dirt)
54 ll_rw_block ( WRITE , Bh); // generates a write block request apparatus.

55 }
56 return 0;
57 }
58
//// device specified cache data synchronization with the data on the device.
59 int sync_dev (Int dev)
60 {
61 int i;
62 struct buffer_head * Bh;
6364
bh = start_buffer ;
65 for (i = 0; i < NR_BUFFERS ; I ++, bh ++) {
66 if (bh-> b_dev! = dev)
67 continue;
68 wait_on_buffer (Bh);
69 if (bh-> b_dev == dev && bh-> b_dirt)
70 ll_rw_block ( WRITE , Bh);
71 }
72 sync_inodes (); // the data written in the cache node i.
73 bh = start_buffer ;
74 for (i = 0; i < NR_BUFFERS ; I ++, bh ++) {
75 if (bh-> b_dev! = dev)
76 continue;

--336--
9.4 buffer.c program

77 wait_on_buffer (Bh);
78 if (bh-> b_dev == dev && bh-> b_dirt)
79 ll_rw_block ( WRITE , Bh);
80 }
81 return 0;
82 }
83
//// make the specified device data in a high speed buffer is invalid.

// all scan buffer block in the cache, the buffer for a given device, resets its active (Update) flag and the flags have been modified.

84 void inline invalidate_buffers (Int dev)


85 {
86 int i;
87 struct buffer_head * Bh;
8889
bh = start_buffer ;
90 for (i = 0; i < NR_BUFFERS ; I ++, bh ++) {
91 if (bh-> b_dev! = dev) // buffer block if not specified device, then
92 continue; // continue scanning the next block.

93 wait_on_buffer (Bh); // wait for the buffer to unlock (if it is locked).


// Since the process performed sleep wait, so we need to determine what the buffers are specified device.

94 if (bh-> b_dev == dev)


95 bh-> b_uptodate = bh-> b_dirt = 0;
96 }
97 }
9899 / *

100 * This routine checks whether a floppy has been changed, and
101 * Invalidates all buffer-cache-entries in that case. This
102 * Is a relatively slow routine, so we have to try to minimize using
103 * It. Thus it is called only upon a 'mount' or 'open'. This
104 * Is the best way of combining speed and utility, I think.
105 * People changing diskettes in the middle of an operation deserve
106 * To loose :-)
107 *
108 * NOTE! Although currently this is only for floppies, the idea is
109 * That any additional removable block-device will use this routine,
110 * And that mount / open need not know that floppies / whatever are
111 * Special.
112 * /
/*
* The subroutine checks whether the floppy disk has been replaced, it has been replaced in the cache so that the floppy

* All buffers corresponding invalid. This subroutine is relatively slow, so we have to try to use it less.
* So only in the implementation of 'mount' or 'open' when to call it. I think this is the combination of speed and practicality

* The best approach. If you replaced the floppy disk in the process of operation, it will lead to loss of data, which is to blame ☺ .

*
* note! Although only floppy this subroutine, block after any removable media device will use the
* Program, mount / open operation does not need to know whether any special floppy disk or other media.

*/
//// check whether to replace the disk, if it has been changed so that the corresponding high speed buffer is invalid.

113 void check_disk_change (Int dev)


114 {
115 int i;
116

--337--
9.4 buffer.c program

// floppy disk device? If not, then quit.


117 if ( MAJOR (Dev)! = 2)
118 return;
// test whether the corresponding floppy disk has been replaced, if there is no exit.

119 if (! floppy_change (Dev & 0x03))


120 return;
// diskette occupied buffer cache has been replaced, the i-node equipment releases the corresponding bitmap and the logical block bitmap; // i and nodes and data block information of

the device occupied by invalid buffer cache.

121 for (i = 0; i < NR_SUPER ; I ++)


122 if ( super_block [I] .s_dev == dev)
123 put_super ( super_block [I] .s_dev);
124 invalidate_inodes (Dev);
125 invalidate_buffers (Dev);
126 }
127
// hash function and macro definitions to calculate the hash table entries.

128 #define _hashfn (Dev, block) (((unsigned) (dev ^ block))% NR_HASH )


129 #define hash (Dev, block) hash_table [ _hashfn (Dev, block)]
130
//// removed from the specified cache block hash in the queue and the free buffer queue.

131 static inline void remove_from_queues (Struct buffer_head * Bh)


132 {
133 / * Remove from hash-queue * /
/ * Remove the blocks from the buffer hash queue * /

134 if (bh-> b_next)


135 bh-> b_next-> b_prev = bh-> b_prev;
136 if (bh-> b_prev)
137 bh-> b_prev-> b_next = bh-> b_next;
// If the first buffer is a block of the queue, so that the corresponding item in the hash table points to the next queue buffer present.

138 if ( hash (Bh-> b_dev, bh-> b_blocknr) == bh)


139 hash (Bh-> b_dev, bh-> b_blocknr) = bh-> b_next;
140 / * Remove from free list * /
/ * Remove the buffer from the free buffer block table * /

141 if (! (bh-> b_prev_free) ||! (bh-> b_next_free))


142 panic ( ' Free block list corrupted ");
143 bh-> b_prev_free-> b_next_free = bh-> b_next_free;
144 bh-> b_next_free-> b_prev_free = bh-> b_prev_free; // if the head of the free list
pointed to the present buffer, to point to the next buffer.
145 if ( free_list == bh)
146 free_list = Bh-> b_next_free;
147 }
148
//// specified buffer insertion into the free end of the list and hash queue.

149 static inline void insert_into_queues (Struct buffer_head * Bh)


150 {
151 / * Put at end of free list * /
/ * Placed at the end of the free list * /

152 bh-> b_next_free = free_list ;


153 bh-> b_prev_free = free_list -> b_prev_free;
154 free_list -> b_prev_free-> b_next_free = bh;
155 free_list -> b_prev_free = bh;
156 / * Put the buffer in new hash-queue if it has a device * /
/ * If the cache block corresponds to a device, it is inserted into the new hash queue * /

--338--
9.4 buffer.c program

157 bh-> b_prev = NULL ;


158 bh-> b_next = NULL ;
159 if (! bh-> b_dev)
160 return;
161 bh-> b_next = hash (Bh-> b_dev, bh-> b_blocknr);
162 hash (Bh-> b_dev, bh-> b_blocknr) = bh;
163 bh-> b_next-> b_prev = bh;
164 }
165
//// find a given device and the block buffers in the specified block in the cache. // If you find a pointer

to the buffer block is returned, otherwise it returns NULL.

166 static struct buffer_head * find_buffer (Int dev, int block)


167 {
168 struct buffer_head * Tmp;
169
170 for (tmp = hash (Dev, block); tmp =! NULL ; Tmp = tmp-> b_next)
171 if (tmp-> b_dev == dev && tmp-> b_blocknr == block)
172 return tmp;
173 return NULL ;
174 }
175 176 /
*
177 * Why like this, I hear you say ... The reason is race-conditions.
178 * As we do not lock buffers (unless we are readint them, that is),
179 * Something might happen to it while we sleep (ie a read-error
180 * Will force it bad). This should not really happen currently, but
181 * The code is ready.
182 * /
/*
* Why the code would be like this? I hear you ask ... because of race conditions. Since we do not have to
* Buffer locked (unless we're reading the data of them), then when we (the process) during sleep
* Buffer may be some problems occur (for example, a read error will cause the buffer error). Currently
* This situation is actually not going to happen, but the handling of the code is ready.
* / ////

183 struct buffer_head * get_hash_table (Int dev, int block)


184 {
185 struct buffer_head * Bh;
186
187 for (;;) {
// find the buffer of the given device and a specific block in the cache, if not found it returns NULL, exit.
188 if (! (bh = find_buffer (Dev, block)))
189 return NULL ;
// increment the reference count of the buffer, and wait for the buffer to unlock (if it is locked).

190 bh-> b_count ++;


191 wait_on_buffer (Bh);
// Since after the sleep state, it is necessary to verify the correctness of the block buffer, a buffer and returns the head pointer.

192 if (bh-> b_dev == dev && bh-> b_blocknr == block)


193 return bh;
// If the block number or the device number of the relevant buffer changes during sleep, revoking its reference count, re-find.

194 bh-> b_count--;


195 }
196 }

--339--
9.4 buffer.c program

197 198 /
*
199 * Ok, this is getblk, and it is not very clear, again to hinder
200 * Race-conditions. Most of the code is seldom used, (ie repeating),
201 * So it should be much more efficient than it looks.
202 *
203 * The algoritm is changed: hopefully better, and an elusive bug removed.
204 * /
/*
* OK, Here is getblk function, the function logic is not very clear, it is also because of concerns
* Competitive conditions problem. Most of the code is rarely used, (for example, repeat the statement), so it should

* Much more effective than it looks like.

*
* Algorithm has been changed: I hope to be better, but an elusive error has been removed.
*/
// The following macro definitions used to simultaneously determine the modification flag buffer and lock flag, and the right to modify the definition of vital signs larger than the lock flag.

205 #define BADNESS (Bh) (((bh) -> b_dirt << 1) + (bh) -> b_lock)
//// take the cache buffer specified.
// Check whether the specified buffer, if not, you need to create a new item in the corresponding cache in the cache. // returns the corresponding buffer head

pointer.

206 struct buffer_head * getblk (Int dev, int block)


207 {
208 struct buffer_head * Tmp, * bh;
209 210 repeat:

// search hash table, if the specified block is already in the cache, the buffer corresponding to the head pointer is returned, exit.

211 if (bh = get_hash_table (Dev, block))


212 return bh;
// free data blocks scan list, find free buffer. // Let tmp points to the first free
buffer head of the free list.
213 tmp = free_list ;
214 do {
// If this buffer is being used (reference count is not equal to 0), continue scanning the next.

215 if (tmp-> b_count)


216 continue;
// right if the buffer is empty bh head pointer, or a flag (modification, lock) the buffer head tmp meaning less weight than the weight bh header flags, then let // tmp bh points to the buffer

head. If the header indicates that the buffer tmp buffer neither modified nor locked flag is set, indicating that it has acquired the // corresponding to a block on the specified device buffer

cache, then exits the loop.

217 if (! bh || BADNESS (Tmp) < BADNESS (Bh)) {


218 bh = tmp;
219 if (! BADNESS (Tmp))
220 break;
221 }
222 / * And repeat until we find something good * / / * Repeat until you find a suitable buffer * /
223 } While ((tmp = tmp-> b_next_free)! = free_list );
// If all buffers are being used (the head of all the buffer reference count both> 0), then sleep, wait for a free buffer available.
224 if (! bh) {
225 sleep_on (& buffer_wait );
226 goto repeat;
227 }
// wait for the buffer to unlock (if it is locked, then).
228 wait_on_buffer (Bh);
// If the buffer is in turn used by other tasks, then had to repeat the process.

--340--
9.4 buffer.c program

229 if (bh-> b_count)


230 goto repeat;
// if the buffer has been modified, the data write disk, again and wait for the buffer to unlock. If this buffer has been using // other tasks, they then had to repeat

the process.

231 while (bh-> b_dirt) {


232 sync_dev (Bh-> b_dev);
233 wait_on_buffer (Bh);
234 if (bh-> b_count)
235 goto repeat;
236 }
237 / * NOTE !! While we slept waiting for this block, somebody else might * /
238 / * Already have added "this" block to the cache. Check it * /
/ * Note! ! When a process to sleep waiting for the buffer blocks, other processes may have the buffer block * /

* Was added into the cache, so to check this. * /


// Check whether the specified device and the buffer has been added to the block in the cache into the hash table. If so, repeat the above process again //.

239 if ( find_buffer (Dev, block))


240 goto repeat;
241 / * OK, FINALLY we know that this buffer is the only one of it's kind, * /
242 / * And that it's unused (b_count = 0), unlocked (b_lock = 0), and clean * /
/ * OK, finally we know that buffer is the only one designated parameter * /

/ * And has not been used (b_count = 0), not locked (b_lock = 0), and is clean (unmodified) * / // So let us take up this buffer.
Reference count is set to 1, the reset modify flag and valid (updated) flag.
243 bh-> b_count = 1;
244 bh-> b_dirt = 0;
245 bh-> b_uptodate = 0;
// out of the head from the buffer hash linked list of free blocks and queues, so that the buffer is used to specify the specified device and thereon.

246 remove_from_queues (Bh);


247 bh-> b_dev = dev;
248 bh-> b_blocknr = block;
// and based on this new device number and block number reinserted at a new location and hash the free list queue. Finally returns the head pointer and buffer.

249 insert_into_queues (Bh);


250 return bh;
251 }
252
//// release specified buffer.
// wait for the buffer to unlock. The reference count is decremented. Wake process waiting for free buffer.

253 void brelse (Struct buffer_head * buf )


254 {
255 if (! buf ) // If the buffer returns the head pointer is invalid.

256 return;
257 wait_on_buffer ( buf );
258 if (! ( buf -> b_count--))
259 panic ( ' Trying to free free buffer ");
260 wake_up (& buffer_wait );
261 }
262 263 /
*
264 * Bread () reads a specified block and returns the buffer that contains
265 * It. It returns NULL if the block was unreadable.
266 * /
/*
* Reading the specified block of data from the device and returns the buffer contains data. If the specified block does not exist

--341--
9.4 buffer.c program

* NULL is returned.
*/
//// reads the specified device from the specified data block.

267 struct buffer_head * bread (Int dev, int block)


268 {
269 struct buffer_head * Bh;
270
// apply for a buffer cache in. If the return value is NULL pointer, the core represents an error, crash.
271 if (! (bh = getblk (Dev, block)))
272 panic ( ' bread: getblk returned NULL \ n ");
// If the data in the buffer is valid (updated) may be used directly, it is returned.
273 if (bh-> b_uptodate)
274 return bh;
// Otherwise ll_rw_block call () function, the device generates a read block request. And wait for the buffer to unlock.

275 ll_rw_block ( READ , Bh);


276 wait_on_buffer (Bh);
// If the buffer is updated, the buffer head pointer is returned to exit.
277 if (bh-> b_uptodate)
278 return bh;
// otherwise indicate reading device fails, release the buffer, returns a NULL pointer, quit.

279 brelse (Bh);


280 return NULL ;
281 }
282
//// copying memory block.

// copy data from one location to the address from.


283 #define COPYBLK (From, to) \
284 __asm ​__ ( " cld \ n \ t "\
285 "Rep \ n \ t" \
286 "Movsl \ n \ t" \
287 :: " c "( BLOCK_SIZE / 4), " S "( from), " D "( to) \
288 : " cx "," di "," si ")
289 290 /
*
291 * Bread_page reads four buffers into memory at the desired address. It's
292 * A function of its own, as there is some speed to be got by reading them
293 * All at the same time, not waiting for one to be read, and then another
294 * Etc.
295 * /
/*
* a read buffer bread_page four memory blocks to read the contents of the specified address. It is a full function,
* Because the benefits of four simultaneous reading speed can be obtained without waiting for a read, I read a few weeks.

*/
//// read the content on a device page (4 buffer blocks) to the specified memory address.

296 void bread_page (Unsigned long address, int dev, int b [4])
297 {
298 struct buffer_head * Bh [4];
299 int i;
300
// loop executes four times, reading a content.

301 for (i = 0; i <4; i ++)


302 if (b [i]) {
// take the cache block in the buffer and the device number specified, the buffer data is invalid if a read request apparatus.

--342--
9.4 buffer.c program

303 if (bh [i] = getblk (Dev, b [i]))


304 if (bh [i] -!> b_uptodate)
305 ll_rw_block ( READ , Bh [i]);
306 } Else
307 bh [i] = NULL ;
// Copy the contents on the order of 4 to the buffer at the specified address.

308 for (i = 0; i <4; i ++, address + = BLOCK_SIZE )


309 if (bh [i]) {
310 wait_on_buffer (Bh [i]); // Wait for buffer unlocked (if the case has been locked).

311 if (bh [i] -> b_uptodate) // If the buffer data is valid, then the copy.
312 COPYBLK ((Unsigned long) bh [i] -> b_data, address);
313 brelse (Bh [i]); // release the buffer.
314 }
315 }
316 317 /
*
318 * Ok, breada can be used as bread, but additionally to mark other
319 * Blocks for reading as well. End the argument list with a negative
320 * Number.
321 * /
/*
* OK, breada as bread can be used as, but some of the blocks would be further pre-read. The function parameter list

* You need to use a negative number to indicate the end of the argument list.

*/
//// reading some of the blocks specified from the specified device.

It returns a pointer to the first buffer header // When successful, otherwise NULL.

322 struct buffer_head * breada (Int dev, int first, ...)


323 {
324 va_list args;
325 struct buffer_head * Bh, * tmp;
326
// variable parameter table take the first parameter (block number).

327 va_start (Args, first);


// take the cache block in the specified buffer and the device number. If the buffer is invalid data, the apparatus issues a read request for the data block.

328 if (! (bh = getblk (Dev, first)))


329 panic ( ' bread: getblk returned NULL \ n ");
330 if (! bh-> b_uptodate)
331 ll_rw_block ( READ , Bh);
// then sequentially take other variable parameter table prefetch block number, and the same treatment as the above, but does not reference. Note that there is a bug on the 336 line. Bh which

should tmp. Until this bug in version 0.96 of the kernel code was only rectified.

332 while ((first = va_arg (Args, int))> = 0) {


333 tmp = getblk (Dev, first);
334 if (tmp) {
335 if (! tmp-> b_uptodate)
336 ll_rw_block ( READA , Bh);
337 tmp-> b_count--;
338 }
339 }
// variable parameter table all the parameters processed. Waiting for the first one to unlock the buffer (if it is locked).

340 va_end (Args);


341 wait_on_buffer (Bh);
// If valid data in the buffer, the buffer header pointer is returned, exit. Otherwise release the buffer, returns NULL, exit.
342 if (bh-> b_uptodate)

--343--
9.4 buffer.c program

343 return bh;


344 brelse (Bh);
345 return ( NULL );
346 }
347
//// buffer initialization function.
// parameter buffer_end is the end of the specified buffer memory. For a system with 16MB of memory, the buffer end set to 4MB. // For systems with 8MB of memory,

the buffer is set to the end of 2MB.

348 void buffer_init (Long buffer_end)


349 {
350 struct buffer_head * H = start_buffer ;
351 void * b;
352 int i;
353
// If the buffer is equal to the high-end 1Mb, because from 640KB-1MB display memory and BIOS are occupied, so the actual available buffer memory // end should be 640KB. Otherwise, the

high-end memory must be greater than 1MB.

354 if (buffer_end == 1 << 20)


355 b = (void *) (640 * 1024);
356 else
357 b = (void *) buffer_end;
// This code is used to initialize the buffer, a ring buffer to establish the free list, and the system acquires the number of buffer blocks. // operation process is started from the

high-divided buffer size 1K buffer block, while the lower end in the buffer is developed to describe the structure buffer_head // buffer block, and the composition of these doubly linked

list buffer_head.

// h is a pointer to the buffer head structure, and h + 1 consecutive memory address pointing to the next buffer header address, it can be said outer terminal point h // buffer head. In

order to ensure sufficient length of the memory buffer to store a first configuration, required block of memory pointed b // address> head end cushioning = h, i.e. to> = h + 1.

358 while ((b - = BLOCK_SIZE )> = ((Void *) (h + 1))) {


359 h-> b_dev = 0; // use the device number of the buffer.

360 h-> b_dirt = 0; // dirty flag, that modifications to the buffer flag.

361 h-> b_count = 0; // This buffer reference count.


362 h-> b_lock = 0; // buffer lock mark.
363 h-> b_uptodate = 0; // buffer update flag (also known as the data valid flag).
364 h-> b_wait = NULL ; // point to wait for the buffer to unlock the process.

365 h-> b_next = NULL ; // point to the same hash value having a buffer head.
366 h-> b_prev = NULL ; // point before the same hash value having a buffer head.

367 h-> b_data = (char *) b; // points to a buffer of data blocks (1024 bytes), respectively.

368 h-> b_prev_free = h-1; // point to the list in the previous item.

369 h-> b_next_free = h + 1; // point to the next item in the list.

370 h ++; // h new points to the next buffer head position.

371 NR_BUFFERS ++; // blocks accumulated number of buffers.

372 if (b == (void *) 0x100000) If the address b // decrement equal to 1MB, skip 384KB,
373 b = (void *) 0xA0000; // leaving b pointing to address 0xA0000 at (640KB).
374 }
375 h--; // let the h points to the last valid buffer head.

376 free_list = start_buffer ; // Let the free list head pointing to head a buffer header.

377 free_list -> b_prev_free = h; A former head of the list // b_prev_free point (ie, the last one).
378 h-> b_next_free = free_list ; // h under a pointer to the first, forming a chain.
// initialize the hash table (hash table, the hash table), entry in the table all pointers to NULL.

379 for (i = 0; i < NR_HASH ; I ++)


380 hash_table [I] = NULL ;
381 }
382

--344--
9.5 bitmap.c program

9.5 bitmap.c program

9.5.1 Functional Description

Function and role of this procedure is simple and clear, it is mainly used for i Bitmap node and the logical block bitmap up processing and release. operating i Bitmap node is

a function of free_inode () with new_inode () , A logical operation function block bitmap is free_block () with new_block () .

function free_block () For the release of the specified device dev Logical block on a data region block . Specific operation is the reset logic block designated block

Bits corresponding to the logical block bitmap. It was first to take the specified device dev Superblock, and the device according to the range of logical blocks of data given on the

super block, the logical block number determined block Effectiveness. Then look in the high-speed buffer to see whether the specified logical block is now a high-speed buffer, and

if so, then the corresponding buffer block released. Then calculate block Logic block number of data from the data area start date (from 1 Counting), and the logical block (sector)

bitmap operation, corresponding to the reset bits. Finally a buffer block bitmap corresponding to the respective logical blocks in the buffer according to a logical block number flag

has been modified.

function new_block () For the equipment dev Apply a logical block, the logical block number returns. And sets the specified logical block block Corresponding logical block

bitmap bits. It was first to take the specified device dev Superblock. Then the entire logic block bitmap is then searched for a first 0

The bits. If not found, then the disk device runs out of space, return 0 . Otherwise, the bit position 1 It indicates data corresponding to the logical blocks occupied. And buffer block

where the bit flag is set has been modified. Then, it calculates the logical disk block number block, and apply the corresponding buffer area in the buffer block, and the block of the

buffer is cleared. Then set the buffer block has been updated and modified flags. Finally, releasing the buffer block, for use by other programs, and return the disk block number

(logical block number).

function free_inode () Designated for release i Node, and resets the corresponding i Bit bitmap node; new_inode () For the device

dev Establish a new i node. The new return i Pointer node. The main operation is in memory i Get a free node table i Node entries, and from i Find a node bitmap idle i node.

Processing the two functions of the above-described two similar functions, and therefore no need to repeat here.

9.5.2 Code comments

program 9-3 linux / fs / bitmap.c

1/*
2 * Linux / fs / bitmap.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / * Bitmap.c contains the code that handles the inode and block bitmaps * /

/ * Program containing code that handles bitmap.c node i and disk block bitmap * /

8 #include <string.h> // string header file. Mainly defines the built-in functions related to operation of the string.

9 // The main use of which memset () function.


10 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

11 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

12
//// specify a clear memory address (addr) at. Embedded assembler macros. // Input: eax = 0, ecx
= block size BLOCK_SIZE / 4, edi = addr.
13 #define clear_block (Addr) \
14 __asm ​__ ( " cld \ n \ t "\ // clear direction bit.

15 "Rep \ n \ t" \ // repeat the stored data (0).


16 "Stosl" \
17 :: " a "( 0), " c "( BLOCK_SIZE / 4), " D "(( long) (addr)): " cx "," di ")
18

--345--
9.5 bitmap.c program

Nr bits of the bit at offset //// set the specified address (nr may be greater than 32!). Return to the original bit (0 or 1). // Input:% 0 - eax
(return value),% 1 - eax (0);% 2 - nr, bit offset;% 3 - (addr), the contents of addr.
19 #define set_bit (Nr, addr) ({\
20 register int res __asm ​__ ( " ax "); \
twenty one __asm__ __volatile __ ( " btsl% 2,% 3 \ n \ tsetb %% al ": \
twenty two "= A" ( res): "" (0), " r "( nr), " m "(* ( addr))); \
twenty three res;})

twenty four

//// reset of nr bits specified bit offset address begins. Return to the original bit inverse code (0 or 1). // Input:% 0 - eax (return value),% 1
- eax (0);% 2 - nr, bit offset;% 3 - (addr), the contents of addr.
25 #define clear_bit (Nr, addr) ({\
26 register int res __asm ​__ ( " ax "); \
27 __asm__ __volatile __ ( " btrl% 2,% 3 \ n \ tsetnb %% al ": \
28 "= A" ( res): "" (0), " r "( nr), " m "(* ( addr))); \
29 res;})
30
//// starting at addr to find values ​of a 0 bit.
// Input:% 0 - ecx (return value);% 1 - ecx (0);% 2 - esi (addr).
// start address specified in the bitmap to find the first bit is a 0, and a distance addr bit offset value is returned in addr.
31 #define find_first_zero (Addr) ({\
32 int __res; \
33 __asm ​__ ( " cld \ n "\ // clear direction bit.

34 "1: \ tlodsl \ n \ t" \ // get [esi] eax.


35 "Notl %% eax \ n \ t" \ // eax in each negated.
36 "Bsfl %% eax, %% edx \ n \ t" \ // is the first bit 1 from the bit 0 in the scan eax, which offset value edx.
37 "Je 2f \ n \ t" \ If eax // 0 in all, the forward jump to the numeral two (line 40).
38 "Addl %% edx, %% ecx \ n \ t" \ // offset value added ecx (ecx is the first bitmap is the bit offset value is 0)
39 "Jmp 3f \ n" \ // forward jump to number 3 (end).
40 "2: \ taddl $ 32, %% ecx \ n \ t" \ // Bit 0 is not found, together with a long bit offset word 32 will ecx.
41 "Cmpl $ 8192, %% ecx \ n \ t" \ // has scanned 8192 (1024 bytes) yet?
42 "Jl 1b \ n" \ // If one has not been scanned data, the numeral 1 forward jump to continue.
43 "3:" \ // End. At this time, the bit offset is ecx.
44 : "= c "(__ res): " c "( 0), " S "( addr): " ax "," dx "," si "); \
45 __res;})
46
//// release device dev block on a logical block in the data area. // reset logic block specified logical

block block bitmap bits. // parameters: dev is the device number, block is a logical block number

(disk block number).

47 void free_block (Int dev, int block)


48 {
49 struct super_block * Sb;
50 struct buffer_head * Bh;
51
// the specified device dev superblock, and if the specified device is not present, an error crash.

52 if (! (sb = get_super (Dev)))


53 panic ( ' trying to free block on nonexistent device ");
// If the logical block number is less than the first logical block number or the total number is larger than a logical block on the device, then an error, crash.

54 if (block <sb-> s_firstdatazone || block> = sb-> s_nzones)


55 panic ( ' trying to free block not in datazone ");
// Find the block data from the hash table. If it is determined that found its effectiveness, and clear signs have been revised and updated, the release of the data block. // This code's main

purpose is that if the current logical block is present in the cache, the corresponding cache block is released.

56 bh = get_hash_table (Dev, block);


57 if (bh) {

--346--
9.5 bitmap.c program

58 if (bh-> b_count! = 1) {
59 printk ( ' trying to free block (% 04x:% d), count =% d \ n ",
60 dev, block, bh-> b_count);
61 return;
62 }
63 bh-> b_dirt = 0; // reset dirty (modified) flag.
64 bh-> b_uptodate = 0; // reset update flag.
65 brelse (Bh);
66 }
// calculation data logical block number (counting from 1) Block in the data area begins counting. Then logic block (block) bitmap operation, // reset the corresponding bit.

I.e. if the corresponding original bit is 0, an error, crash.

67 block - = sb-> s_firstdatazone - 1; // block = block - (-1);


68 if ( clear_bit (Block & 8191, sb-> s_zmap [block / 8192] -> b_data)) {
69 printk ( ' block (% 04x:% d) ", dev, block + sb-> s_firstdatazone-1);
70 panic ( ' free_block: bit already cleared ");
71 }
// set where the respective logical block bitmap flag buffer has been modified.

72 sb-> s_zmap [block / 8192] -> b_dirt = 1;


73 }
74
//// apply a logical block (disk block, block) to the device dev. Returns a logical block number (disk block number). // set bit logical

block specified logical block bit block of FIG.

75 int new_block (Int dev)


76 {
77 struct buffer_head * Bh;
78 struct super_block * Sb;
79 int i, j;
80
// superblock from the device dev, If a device does not exist, an error crash.
81 if (! (sb = get_super (Dev)))
82 panic ( ' trying to get new block from nonexistant device ");
// bitmap scan logic block, to find the first bit 0, to find free logical block, the acquisition block numbers of logical blocks is placed.

83 j = 8192;
84 for (i = 0; i <8; i ++)
85 if (bh = sb-> s_zmap [i])
86 if ((j = find_first_zero (Bh-> b_data)) <8192)
87 break;
// If not found all scanned (i> = 8 or j> = 8192) or bitmap buffer block where invalid (bh = NULL) return 0, // exit (no free logical blocks).

88 if (i> = 8 ||! bh || j> = 8192)


89 return 0;
// set up a new logical block corresponding to the logical block bits in the bitmap, if the corresponding bit has been set, then an error, crash.

90 if ( set_bit (J, bh-> b_data))


91 panic ( ' new_block: bit already set ");
// set the corresponding flag buffer block has been modified. If the new logical block is larger than the total number of logical blocks on the device, then the logical block designated in

the device is not present on the corresponding //. Application fails, it returns 0, quit.

92 bh-> b_dirt = 1;
93 j + = i * 8192 + sb-> s_firstdatazone-1;
94 if (j> = sb-> s_nzones)
95 return 0;
// read the new logical block data on a device (verification). If it fails then it crashes.

96 if (! (bh = getblk (Dev, j)))


97 panic ( ' new_block: can not get block ");

--347--
9.5 bitmap.c program

// count should refer to the new block is 1. Otherwise crash.

98 if (bh-> b_count! = 1)
99 panic ( ' ! New block: count is = 1 ");
// the new logical block is cleared, and the update flag is set and modified flags. Then release the corresponding buffer, returns a logical block number.

100 clear_block (Bh-> b_data);


101 bh-> b_uptodate = 1;
102 bh-> b_dirt = 1;
103 brelse (Bh);
104 return j;
105 }
106
//// i-node release specified. // reset the
corresponding bit bitmap node i.
107 void free_inode (Struct m_inode * Inode)
108 {
109 struct super_block * Sb;
110 struct buffer_head * Bh;
111
// If the node pointer i = NULL, then exits.
112 if (! inode)
113 return;
// if the device number field on the node i is 0, the node useless, with the 0 corresponding to the empty memory area occupied by the node i, and returns.

114 if (! inode-> i_dev) {


115 memset (Inode, 0, sizeof (* inode));
116 return;
117 }
// If there are other programs i-node references, you can not release, indicating that the core problem, crash.

118 if (inode-> i_count> 1) {


119 printk ( ' trying to free inode with count =% d \ n ", inode-> i_count);
120 panic ( ' free_inode ");
121 }
// If the file directory entry number of connections is not 0, then there are other files in the directory entry using this node, Should not be released, but should be back and so on.

122 if (inode-> i_nlinks)


123 panic ( ' trying to free inode with links ");
// i is taken as the node device superblock, the test device is present.

124 if (! (sb = get_super (Inode-> i_dev)))


125 panic ( ' trying to free inode on nonexistent device ");
// If the node number i = 0 or greater than the total number of node i on the device, the error (i-node number 0 Reserved not used).

126 if (inode-> i_num <1 || inode-> i_num> sb-> s_ninodes)


127 panic ( ' trying to free inode 0 or nonexistant inode ");
// If the node corresponding to the node i bitmap does not exist, an error.

128 if (! ([i_num inode-> >> 13] bh = sb-> s_imap))


129 panic ( ' nonexistent imap in superblock ");
// reset bit bitmap node corresponding to the node in the i, if the bit is already equal to 0, then an error.

130 if ( clear_bit (Inode-> i_num & 8191, bh-> b_data))


131 printk ( ' free_inode: bit already cleared \ n \ r ");.
// set where the buffer has been modified i-node bitmap flag, and clear the memory area occupied by the i-node structure.

132 bh-> b_dirt = 1;


133 memset (Inode, 0, sizeof (* inode));
134 }
135
//// i create a new node for the device dev. It returns a pointer to the new node i.

// Get a free entry in the i-node table memory node i, and find a node i from node i idle bitmap.

--348--
9.6 inode.c program

136 struct m_inode * new_inode (Int dev)


137 {
138 struct m_inode * Inode;
139 struct super_block * Sb;
140 struct buffer_head * Bh;
141 int i, j;
142
// Get a free entry node i (the inode) from the i-node table memory (inode_table) in.
143 if (! (inode = get_empty_inode ()))
144 return NULL ;
// read the specified device superblock structure.

145 if (! (sb = get_super (Dev)))


146 panic ( ' new_inode with unknown device ");
// bitmap scan node i, to find the first bit 0, hunts for an idle node acquires the node number of the node i is placed.

147 j = 8192;
148 for (i = 0; i <8; i ++)
149 if (bh = sb-> s_imap [i])
150 if ((j = find_first_zero (Bh-> b_data)) <8192)
151 break;
// If all the scanned not found, or the buffer where the invalid block bitmap (bh = NULL) return 0, exit (no free node i).
152 if (! bh || j> = 8192 || j + i * 8192> sb-> s_ninodes) {
153 iput (Inode);
154 return NULL ;
155 }
Bitmap node i // i correspond to the new set of nodes corresponding bit, if the bit is already set, then an error.

156 if ( set_bit (J, bh-> b_data))


157 panic ( ' new_inode: bit already set ");
// set buffer where the i-node bitmap logo has been modified.

158 bh-> b_dirt = 1; //


initialize the i-node structure.
159 inode-> i_count = 1; // reference count.
160 inode-> i_nlinks = 1; // file directory entry number of links.

161 inode-> i_dev = dev; // device number i node is located.

162 inode-> i_uid = current -> euid; // i node belongs to a user id.
163 inode-> i_gid = current -> egid; // set id.
164 inode-> i_dirt = 1; // modified flag.
165 inode-> i_num = j + i * 8192; // corresponding to the i-node number of the device.

166 inode-> i_mtime = inode-> i_atime = inode-> i_ctime = CURRENT_TIME ; // set the time.
167 return inode; // returns the i-node pointer.
168 }
169

9.6 inode.c program

9.6.1 Functional Description

The program includes processing i Function Node iget () , iput () And a block mapping function bmap () As well as some other auxiliary functions. iget () ,

iput () with bmap () Mainly used namei.c Path name to the program i Node mapping function namei () .

iget () Function is used from the device dev Reading the specified node number nr of i node. Which is below the operation flow of FIG. 9-17 Fig. The first function

--349--
9.6 inode.c program

First determine the parameters dev Effectiveness, and from i Take an idle node table i node. Then scan i Node table for the specified node number nr

of i Node, and the increment i A reference to the number of nodes. If the current scan i Device number is not equal to the specified node number or node number of the device is

not equal to the specified node number, scanning continues. Otherwise, it explained that it had to find the specified device number and node number i Node, the node will wait for

unlock (if the case is locked). Waiting for the unlocking phase node, the node table may change, at this time if the i Device number is not equal to the specified node number or

node number of the device is not equal to the specified number of nodes, the need to rescan the entire i Node table. Next, determine whether the i Whether the node is the mount

point other file systems.

If the i Node is the mount point of a file system, the super block table installed in this search i Superblock node. If the respective superblock is not found, an error message is

displayed, and the release of free nodes begin acquiring function returns the i Node pointer. If found respective superblock, then the i Node write disk. From then installed in this i The

device unit number on the super block node of the file system, and let i Node number 1 . Then again to re-scan the entire i Node table to take the root file system is mounted. If the i Installation

point node is not other file systems, then you have found a corresponding i Node, then you can give up idle provisional application i Node, and returns to find i node.

If the i Specifies the node table not found i Node, then the front idle use application i Node i Node table created in the node. And reading the corresponding device from the i

Node information. The return i node.

iput () The function coincided with the completion of the function iget () Instead, it is used to release a specified i Node (written back device). The operation flow performed

also with iget () similar.

--350--
9.6 inode.c program

nr)

Applying a temporary node i from i-node table

i-node table entry points to inode 1

no
inode <= end table entry?

The establishment of a temporary node node i Is iget (dev,


no
inode device number
The i-node information read from the device dev
Yes

no
The return node i the inode number = nr?

Yes
an inode points to the i-node table
Wait inode unlock (if locked)

inode device number

Yes

no
the inode number = nr?

Yes
i-node table entry points to inode 1
the inode reference count by 1

no
inode is the installation section

Yes
node releases Provisional Application
Looking superblock mounted in the

node table in the superblock


Returns the inode

whether
Find the corresponding superblock?

no dev = dev superblock; nr = 1

The release of provisional application of the i-node


inode table entry points to the first node. 1 i i

Returns the inode

Map 9-17 iget Function operation flowchart

_bmap () Function is used to process the data block is mapped to the disk block operations. Brought parameter inode File is i Node pointer, block

It is a data block in the document, create Is to create a flag indicating the corresponding file in the case of a data block that does not exist, the need to establish a corresponding

disk blocks on the disk. The return value of this function is the data block corresponding to the logical block number on the device (disk block number). when create = 0 When the

function is bmap () function. when create = 1 When it is create_block () function.

Regular data file is placed in the data area of ​the disk blocks, and a file name through the corresponding i Node associated with the data disk blocks, which blocks on the

disk numbers stored in i Node logic block array. _ bmap () The main function is i Node logic block (block) array i_zone [] Processes, and in accordance with i_zone [] Logical block

number (disk block number) set in the logic block to set the occupancy of the bitmap. See "Overall Functional Description" section of Figure 9.x . As previously described, i_zone [0] to

i_zone [6] For direct logical block number corresponding to the stored document; i_zone [7] Indirect for storing a logical block number; and i_zone [8] For storing a secondary indirect

logical block number. When the file is small (less than 7K ), The disc can be used by the file block number stored in the direct i Node 7 Direct block entries; number when the file is

slightly larger (up to 7K + 512K ), You need to use a indirect block items i_zone [7] ; When larger files, you need to use the quadratic term indirect block

i_zone [8] A. Therefore, hours compare files, linux Speed ​disk block addressed relatively faster.

--351--
9.6 inode.c program

9.6.2 Code comments

program 9-4 linux / fs / inode.c

1/*
2 * Linux / fs / inode.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <string.h>
// string header file. Mainly defines the built-in functions related to operation of the string.

8 #include <sys / stat.h> // File Status header file. Containing configuration file or system state stat {} and constants.

910 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

11 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

12 #include <linux / mm.h> // memory management header files. It contains the defined page size and page number of the release function prototypes.

13 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

1415 struct m_inode inode_table [ NR_INODE ] = {{0}};


// i-node table memory (NR_INODE = 32 entries).
1617 static void read_inode (Struct m_inode * Inode);

18 static void write_inode (Struct m_inode * Inode);


19
//// i wait for the specified node is available.

// if i node is locked, the current task is set to uninterruptible wait state. The i-node until unlocked.
20 static inline void wait_on_inode (Struct m_inode * Inode)
twenty one {

twenty two cli ();


twenty three while (inode-> i_lock)
twenty four sleep_on (& Inode-> i_wait);
25 sti ();
26 }
27
//// i-node for the specified lock (lock specified node i).
// if i node is locked, the current task is set to uninterruptible wait state. The i-node until unlocked, then locked it.
28 static inline void lock_inode (Struct m_inode * Inode)
29 {
30 cli ();
31 while (inode-> i_lock)
32 sleep_on (& Inode-> i_wait);
33 inode-> i_lock = 1; // set the lock flag.
34 sti ();
35 }
36
//// i unlock the specified node.
// reset the i-node lock flag, and clearly this i wake up the waiting process node.
37 static inline void unlock_inode (Struct m_inode * Inode)
38 {
39 inode-> i_lock = 0;
40 wake_up (& Inode-> i_wait);
41 }
42

--352--
9.6 inode.c program

//// i release of all nodes in the memory device dev.


// i-node table array memory scan, i if the specified node is released for use of the device.
43 void invalidate_inodes (Int dev)
44 {
45 int i;
46 struct m_inode * Inode;
4748
inode = 0+ inode_table ; // make pointer point to the i-node table first array of pointers to the first item.

49 for (i = 0; i < NR_INODE ; I ++, inode ++) { All nodes i // i-node table scanning array of pointers.
50 wait_on_inode (Inode); // wait for the i-node is available (unlocked).

51 if (inode-> i_dev == dev) { // If the specified device node i, then


52 if (inode-> i_count) // if its reference count is not 0, then display an error warning;

53 printk ( ' inode in use on removed disk \ n \ r ");


54 inode-> i_dev = inode-> i_dirt = 0; // releasing the node i (device number is set to 0, etc.).
55 }
56 }
57 }
58
//// i sync all nodes.
// synchronous memory information with all i-nodes on the device.

59 void sync_inodes (Void)


60 {
61 int i;
62 struct m_inode * Inode;
6364
inode = 0+ inode_table ; // make pointer point to the i-node table first array of pointers to the first item.

65 for (i = 0; i < NR_INODE ; I ++, inode ++) { // array of pointers scan i-node table.

66 wait_on_inode (Inode); // wait for the i-node is available (unlocked).

67 if (inode-> i_dirt &&! inode-> i_pipe) // if the node i has been modified and the node is not a pipe,
68 write_inode (Inode); // write the disk.
69 }
70 }
71
//// mapped to the data block processing operation of the disk block. (Block Bitmap handler, bmap - block map) // Parameters: inode - i node file; block - the data

block in the document; create - create a logo. // If you create a flag is set, then the corresponding disk blocks when you apply for a new logical block does not

exist. // returns the block corresponding to the logical block number of the data block (disk block number) on the device.

72 static int _bmap (Struct m_inode * Inode, int block, int create)
73 {
74 struct buffer_head * Bh;
75 int i;
76
// If the block number is less than 0, then the crash.

77 if (block <0)
78 panic ( "_ bmap: block <0 ");
// If the block number is larger than the number of direct indirect block number + + A second indirect block number of blocks, outside the file system indicates a range, the crash.

79 if (block> = 7 + 512 + 512 * 512)


80 panic ( "_ bmap: block> big ");

// If the block number is less than 7, the direct block represents.

81 if (block <7) {
// If the flag is set to create, and i-node in a logical block to be a block (sector) field is 0, the corresponding device to apply a magnetic disk // block (logical block, block), the logical

block and the disc number (disk block number) into logical blocks field. Then set the i-node modification time,

--353--
9.6 inode.c program

// set the i-node has been modified flag. Finally returned logical block number.

82 if (create &&! inode-> i_zone [block])


83 if (inode-> i_zone [block] = new_block (Inode-> i_dev)) {
84 inode-> i_ctime = CURRENT_TIME ;
85 inode-> i_dirt = 1;
86 }
87 return inode-> i_zone [block];
88 }

// If the block number> = 7, and less than + 7 512, then the block is a indirect. Next, a process of indirect block.
89 block - = 7;
90 if (block <512) {
// If it is created, indirect block and the corresponding field of the node i is 0, indicates that the file is the first time the use of indirect blocks, // need to apply a disk block for

storing information indirect block, and this block number filled in the actual disk indirect blocks field. Then set the i-node // modified logo and modification time.

91 if (create &&! inode-> i_zone [7])


92 if (inode-> i_zone [7] = new_block (Inode-> i_dev)) {
93 inode-> i_dirt = 1;
94 inode-> i_ctime = CURRENT_TIME ;
95 }
// At this time, if node i indirect block field is 0, indicating a failure to apply a disk block, returns 0 exit.

96 if (! inode-> i_zone [7])


97 return 0;
A device on indirect block // read.
98 if (! (bh = bread (Inode-> i_dev, inode-> i_zone [7])))
99 return 0;
// take the logical block number (disk block number) of the indirect blocks of the first block entry.

100 i = ((unsigned short *) (bh-> b_data)) [block];


// If you are creating a logical block number and block entry of indirect block is then 0, then apply a disk block (logical block), and let // item block indirect block is equal to the

new logical block number. Then the set flag indirect block has been modified.

101 if (create &&! i)


102 if (i = new_block (Inode-> i_dev)) {
103 ((Unsigned short *) (bh-> b_data)) [block] = i;
104 bh-> b_dirt = 1;
105 }
// finally releases the indirect blocks, returns to block corresponding to the block number of the logical blocks on the disk new applications.

106 brelse (Bh);


107 return i;
108 }

// this run, indicates that the data block is a second indirect blocks, and a process similar to the indirect block. The following is the treatment of secondary indirect block. // block minus the

number of blocks contained in the indirect block (512).

109 block - = 512;


// If a new node is created and i is 0. A second indirect block field, you need to apply a disk block for storing a second indirect block // block information, and this secondary fill actual disk

block number indirect blocks field. Thereafter, the i-node set have been modified preparation and modification time.

110 if (create &&! inode-> i_zone [8])


111 if (inode-> i_zone [8] = new_block (Inode-> i_dev)) {
112 inode-> i_dirt = 1;
113 inode-> i_ctime = CURRENT_TIME ;
114 }
// At this time, if the second node i indirect block field is 0, the application indicates that the disk block fails, returns 0 exit.

115 if (! inode-> i_zone [8])


116 return 0;

--354--
9.6 inode.c program

// read an indirect block of the second block.

117 if (! (bh = bread (Inode-> i_dev, inode-> i_zone [8])))


118 return 0;
// get a first block of the secondary indirect block (block / 512) in the logical block number entry.

119 i = ((unsigned short *) bh-> b_data) [block >> 9];


// If the indirect block is created and the secondary of a first block (block / 512) a logical block number entry is 0, then, need to apply a magnetic disk // block (logical block) as an indirect

block of the two secondary level block, and so that a second indirect block item block (block / 512) equal to the number of two block // block. Then a second set of indirect block has been

modified block flag. And releases an indirect block of the second block.

120 if (create &&! i)


121 if (i = new_block (Inode-> i_dev)) {
122 ((Unsigned short *) (bh-> b_data)) [block >> 9] = i;
123 bh-> b_dirt = 1;
124 }
125 brelse (Bh);
// two indirect block, if the secondary block number is 0, that the applicant failed disk block, returns 0 exit.

126 if (! i)
127 return 0;
// read two blocks of the second indirect block.

128 if (! (bh = bread (Inode-> i_dev, i)))


129 return 0;
// take the logical block number of the block of the first two items in the block. (The upper block 511 in order to define a value not exceeding 511)

130 i = ((unsigned short *) bh-> b_data) [block & 511];


// If the logical block number is created and two block item block is 0, then, the application a disk block (logical block), the block data is stored as a final // information.

And let the two block item block is equal to the new logical block number (i). // set two then the block mark has been modified.

131 if (create &&! i)


132 if (i = new_block (Inode-> i_dev)) {
133 ((Unsigned short *) (bh-> b_data)) [block & 511] = i;
134 bh-> b_dirt = 1;
135 }
// the last two blocks of the secondary release indirect blocks, returns to block number of the logical blocks corresponding to the new block on disk application.

136 brelse (Bh);


137 return i;
138 }
139
//// data block corresponding to the logical block number block in the i-node information acquisition apparatus according to the file.

140 int bmap (Struct m_inode * Inode, int block)


141 {
142 return _bmap (Inode, block, 0);
143 }
144
//// create the data block corresponding to the logical block in the block device and returns the device corresponding to the logical block numbers.

145 int create_block (Struct m_inode * Inode, int block)


146 {
147 return _bmap (Inode, block, 1);
148 }
149
//// i release a node (written back device).
150 void iput (Struct m_inode * Inode)
151 {
152 if (! inode)
153 return;
154 wait_on_inode (Inode); // wait for the inode unlocked (if the case is locked).

--355--
9.6 inode.c program

155 if (! inode-> i_count)


156 panic ( ' iput: trying to free free inode ");
// If pipeline i-node, then wait for the pipeline process wakes up, citations minus 1, if there is a reference is returned. Otherwise // pipeline release the memory

occupied by the page, and reset the node's reference count, the modified logo and pipeline signs and returns. // For pipe node, inode-> i_size kept the physical

memory page address. See get_pipe_inode (), 228,234 lines.

157 if (inode-> i_pipe) {


158 wake_up (& Inode-> i_wait);
159 if (--inode-> i_count)
160 return;
161 free_page (Inode-> i_size);
162 inode-> i_count = 0;
163 inode-> i_dirt = 0;
164 inode-> i_pipe = 0;
165 return;
166 }
// If the node corresponding to the device number i = 0, the node decrements this count reference 1, returns.

167 if (! inode-> i_dev) {


168 inode-> i_count--;
169 return;
170 }
// If the i-node block device file, in which case the logical block device number field is 0, the device is refreshed. And wait for the i-node unlocked.

171 if ( S_ISBLK (Inode-> i_mode)) {


172 sync_dev (Inode-> i_zone [0]);
173 wait_on_inode (Inode);
174 }
175 repeat:
// If the count is greater than a reference node I is decremented.

176 if (inode-> i_count> 1) {


177 inode-> i_count--;
178 return;
179 }
// If the number of links of the node i is 0, releasing all logical blocks of the node i, and releases the node i.

180 if (! inode-> i_nlinks) {


181 truncate (Inode);
182 free_inode (Inode);
183 return;
184 }
// If the node i has been amended, it updates the i-node, and wait for the i-node unlocked.

185 if (inode-> i_dirt) {


186 write_inode (Inode); / * We can sleep - so do again * /
187 wait_on_inode (Inode);
188 goto repeat;
189 }
// i node the reference count is decremented by one.

190 inode-> i_count--;


191 return;
192 }
193
//// Get a free node i from the i-node table entry (inode_table) in. // Find the node i to count the reference count
of 0, and written late cleared, it returns a pointer.
194 struct m_inode * get_empty_inode (Void)
195 {
196 struct m_inode * Inode;

--356--
9.6 inode.c program

197 static struct m_inode * Last_inode = inode_table ; // last_inode first point i-node table.
198 int i;
199
200 do {// scan
i-node table.
201 inode = NULL ;
202 for (i = NR_INODE ; I; i--) {
// If after last_inode already pointing to the last one i-node table, then allowed to re-point the beginning of the i-node table.

203 if (++ last_inode> = inode_table + NR_INODE )


204 last_inode = inode_table ;
// If the count i is the node pointed last_inode is 0, then the node i may find free entry. Let inode points to the i // node. If the i-node has been
modified flag and the lock flag are 0, then we can use the i-node, then exit the loop.
205 if (! last_inode-> i_count) {
206 inode = last_inode;
207 if (! inode-> i_dirt &&! inode-> i_lock)
208 break;
209 }
210 }
// If no idle i-node (inode = NULL), then the entire i-node table printed out for debugging and crash.
211 if (! inode) {
212 for (i = 0; i < NR_INODE ; I ++)
213 printk ( "% 04x:% 6d \ t ", inode_table [I] .i_dev,
214 inode_table [I] .i_num);
215 panic ( ' No free inodes in mem ");
216 }
// wait for the i-node unlocked (if they are locked words).
217 wait_on_inode (Inode);
// If the node i has been modified flag is set, then the i-node refresh, and wait for the i-node unlocked.
218 while (inode-> i_dirt) {
219 write_inode (Inode);
220 wait_on_inode (Inode);
221 }
222 } While (inode-> i_count); // if the node i has been occupied by another, then node i find free again. // found free i-node entries. The items of
the node i is cleared, and the reference flag is set to 1, the i-node pointer is returned.
223 memset (Inode, 0, sizeof (* inode));
224 inode-> i_count = 1;
225 return inode;
226 }
227
//// acquisition pipeline node. It returns a pointer to the node i (if NULL is a failure). // first scan i-node table, find a free i-node item, and then get a free memory for pipeline

use. // The resulting reference count of node i is set to 2 (readers and writers), the type of pipe conduit initialization header and trailer, opposite the i-node representation.

228 struct m_inode * get_pipe_inode (Void)


229 {
230 struct m_inode * Inode;
231232
if (! (inode = get_empty_inode ())) // If no idle node i NULL is returned.
233 return NULL ;
234 if (! (inode-> i_size = get_free_page ())) {I_size // node to the field buffer.
235 inode-> i_count = 0; // If there is no free memory,
236 return NULL ; // release the i-node, and returns NULL.
237 }
238 inode-> i_count = 2; / * Sum of readers / writers * / / * Read / write both total * /

--357--
9.6 inode.c program

239 PIPE_HEAD (* Inode) = PIPE_TAIL (* Inode) = 0; // reset the pipe head and tail pointer.
240 inode-> i_pipe = 1; // set the node as a symbol of pipeline use.

241 return inode; // returns the i-node pointer.

242 }
243
//// specified node number i is read from the device. // nr - i
node number.
244 struct m_inode * iget (Int dev, int nr)
245 {
246 struct m_inode * Inode, * empty;
247
248 if (! dev)
249 panic ( ' iget with dev == 0 ");
// i take an idle node i from node table.
250 empty = get_empty_inode ();
// i-node table scan. I find the specified node number. And increments the node number of citations.

251 inode = inode_table ;


252 while (inode < NR_INODE + inode_table ) {
// If the node device number i is not equal to the current scan device specified number or node number is not equal to the specified node number, scanning continues.

253 if (inode-> i_dev! = dev || inode-> i_num! = nr) {


254 inode ++;
255 continue;
256 }
// find the specified device number and i-node node number, wait for the node unlock (if the case is locked).

257 wait_on_inode (Inode);


// node is waiting for the unlocking stage, node table may change, so the judge again, if a change occurs, again to re-scan the entire // i-node table.

258 if (inode-> i_dev! = dev || inode-> i_num! = nr) {


259 inode = inode_table ;
260 continue;
261 }
The node i // reference count is incremented.

262 inode-> i_count ++;


263 if (inode-> i_mount) {
264 int i;
265
// If the mounting point i is a node other file systems, the super block table mounted in the superblock this search node i. // If not found, an error message is displayed,

and the release of the free node function start getting returns the i-node pointer.

266 for (i = 0; i < NR_SUPER ; I ++)


267 if ( super_block [I] .s_imount == inode)
268 break;
269 if (i> = NR_SUPER ) {
270 printk ( ' Mounted inode has not got sb \ n ");
271 if (empty)
272 iput (Empty);
273 return inode;
274 }
// the i-node disk write. From this superblock mounted on the i-node number of the file system to take equipment, and to make an i-node number. // then re-scan the entire i-node

table, taking the root file system is mounted.

275 iput (Inode);


276 dev = super_block [I] .s_dev;
277 nr = ROOT_INO ;
278 inode = inode_table ;

--358--
9.6 inode.c program

279 continue;
280 }
// i have found the appropriate node, give up provisional application of the free node, the node returns i found.

281 if (empty)
282 iput (Empty);
283 return inode;
284 }
// if i do not find the specified node in the i-node table, the use of free applications in front of the establishment of the i-node node in the i-node table. // i and the node information

read from the device. Returned to the node i.

285 if (! empty)
286 return ( NULL );
287 inode = empty;
288 inode-> i_dev = dev;
289 inode-> i_num = nr;
290 read_inode (Inode);
291 return inode;
292 }
293
//// i read information specified node from the device into memory (buffer).
294 static void read_inode (Struct m_inode * Inode)
295 {
296 struct super_block * Sb;
297 struct buffer_head * Bh;
298 int block;
299
// first lock the i-node, the node is located superblock device.
300 lock_inode (Inode);
301 if (! (sb = get_super (Inode-> i_dev)))
302 panic ( ' trying to read inode without dev ");
// = number of the logical block (boot block superblock +) of the node i + i-node is located bitmap + the number of blocks occupied by a logic block bitmap occupied @ + (i-node number -1) /

each comprising i-nodes.

303 block = 2 + sb-> s_imap_blocks + sb-> s_zmap_blocks +


304 (Inode-> i_num-1) / INODES_PER_BLOCK ;
// read logic block where the node i from the device, and the i-node information pointing to the corresponding inode pointer.

305 if (! (bh = bread (Inode-> i_dev, block)))


306 panic ( ' unable to read i-node block ");
307 * (Struct d_inode *) Inode =
308 ((Struct d_inode *) Bh-> b_data)
309 [(Inode-> i_num-1)% INODES_PER_BLOCK ];
// final release read buffer and unlock the i-node.
310 brelse (Bh);
311 unlock_inode (Inode);
312 }
313
//// i-node information is written in the specified apparatus (the buffer corresponding to the write buffer block, will be written to the disc when the refresh buffer).

314 static void write_inode (Struct m_inode * Inode)


315 {
316 struct super_block * Sb;
317 struct buffer_head * Bh;
318 int block;
319
// First, lock the i-node, if the node i have not been modified or device number of the i-node is equal to zero, then unlock the i-node, // and exit.

--359--
9.7 super.c program

320 lock_inode (Inode);


321 if (! inode-> i_dirt ||! inode-> i_dev) {
322 unlock_inode (Inode);
323 return;
324 }
// Get the super block of the node i.
325 if (! (sb = get_super (Inode-> i_dev)))
326 panic ( ' trying to write inode without device ");
// = number of the logical block (boot block superblock +) of the node i + i-node is located bitmap + the number of blocks occupied by a logic block bitmap occupied @ + (i-node number -1) /

each comprising i-nodes.

327 block = 2 + sb-> s_imap_blocks + sb-> s_zmap_blocks +


328 (Inode-> i_num-1) / INODES_PER_BLOCK ;
// read logic block where the node i from the device.
329 if (! (bh = bread (Inode-> i_dev, block)))
330 panic ( ' unable to read i-node block ");
// Copy the i-node information item to the logical block to be i node.
331 ((Struct d_inode *) Bh-> b_data)
332 [(Inode-> i_num-1)% INODES_PER_BLOCK ] =
333 * (Struct d_inode *) Inode;
// set buffer has been modified logo, while the i-node modification flag is set to zero. Then release the buffer containing the node i, and unlock the node i.

334 bh-> b_dirt = 1;


335 inode-> i_dirt = 0;
336 brelse (Bh);
337 unlock_inode (Inode);
338 }
339

9.6.3 Other Information

no ☺ .

9.7 super.c program

9.7.1 Functional Description

This document describes the function of the superblock file system operations, the low-level function functions belonging to the file system, the file name and directory

manipulation functions for the upper layer use. There are get_super () , put_super () with read_super () . Moreover 2 A related file system load / unload system calls sys_umount () with sys_mount

() As well as the root file system load function mount_root () . And some other auxiliary functions buffer.c A similar role in helper functions.

Super block is stored in the main information about the entire file system structure information which refer to "general functional description" in FIG. 9.x .

get_super () Function is used under the conditions specified device, search superblock superblock corresponding memory array, and returns the corresponding pointer

superblock. Therefore, when the function is called, the corresponding file system must already be loaded ( mount ), Or at least the super block has been occupied by a super block

array, otherwise returns NULL .

put_super () SuperBlock for releasing the specified device. It corresponds to the super block of the file system i Bitmap node and the logical block bitmap buffer blocks

occupied freed. Calling umount () This function will be called when unloading a file system or replace the disk.

read_super () For the file system superblock specified device read into the buffer, and registers the super block array, but also the file system i Bitmap node and the logical

block is read into memory bitmap array corresponding to the superblock structure. Finally, and returns the pointer to the superblock structure.

sys_umount () Unloading system calls for a specific device file name of the file system, sys_mount () It is used to a directory

--360--
9.7 super.c program

Load a file system name.


Program last function mount_root () Root file system is used to install the system, and will be invoked during system initialization. The specific operation flow chart 9-18 Fig.

Disk i-node structure must be 32 bytes


Set the root i-node number of citations is 4, and

the current i-node as a process working directory


The document table 64 is initialized and the root directory of 1.

If the root file system is a floppy disk, you will be

prompted to insert the root disk and press the Enter key The statistics logic block bitmap and displays the

idle disk blocks

Initialization superblock array (8 total)

The i-node bit map nodes i and statistical idle

display
And reading the superblock structure information

on the root node i root device

return

Map 9-18 mount_root () Function Function

This function is used to install the system in addition to the root file system, they also function as initializing the kernel file system. It superblock memory array is

initialized, the file descriptor array table also file_table [] It is initialized, and the root file system and the number of free disk blocks Idle i Nodes were counted and displayed.

mount_root () Function is executed in the system initialization procedure main.c In the process 0 Created the first sub-process (process 1 ) After the call, and the system

where it is called only once. The specific location is in the initialization function calls init () of setup () Function. setup ()

Function is located in / kernel / blk_drv / hd.c The first 71 Line begins.

9.7.2 Code comments

program 9-5 linux / fs / super.c

1/*
2 * Linux / fs / super.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * Super.c contains code to handle the super-block tables.


9*/
10 #include <linux / config.h> // kernel configuration file header. Define the keyboard language and hard disk type (HD_TYPE) option.

11 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

12 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

13 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

1415 #include <errno.h>


// error number header files. The system comprises various error number. (Linus imported from the minix).

16 #include <sys / stat.h> // File Status header file. Containing configuration file or system state stat {} and constants. mount_root

--361--
9.7 super.c program

1718 int sync_dev (Int dev);


// perform synchronization operations on the cache and data equipment specified device. (Fs / buffer.c, 59)

19 void wait_for_keypress (Void); // wait keystrokes. (Kernel / chr_drv / tty_io.c, 140)


2021 / * Set_bit uses setb, as gas does not recognize setc * /

/ * Set_bit () command using the setb, because gas does not recognize the assembler instruction setc * / //// specified value of the test bits at bit offset (0 or

1), and returns the bit value. (It should be named test_bit () more appropriate) // embedded assembler macros. Bitnr parameters are bit offset value, addr is

the address of the start bit test operation. //% 0 - ax (__ res),% 1 - 0,% 2 - bitnr,% 3 - addr

twenty two #define set_bit (Bitnr, addr) ({\


twenty three register int __res __asm ​__ ( " ax "); \
twenty four __asm ​__ ( " bt% 2,% 3; setb %% al ":" = a "(__ res): " a "( 0), " r "( bitnr), " m "(* ( addr))); \
25 __res;})
2627 struct super_block super_block [ NR_SUPER ]; // superblock structure array (total 8).

28 / * This is initialized in init / main.c * /


/ * ROOT_DEV has been initialized in init / main.c * /
29 int ROOT_DEV = 0;
30
//// locked superblock specified.
31 static void lock_super (Struct super_block * Sb)
32 {
33 cli (); // disable interrupts.

34 while (sb-> s_lock) // If the superblock has been locked, then wait for sleep.

35 sleep_on (& (Sb-> s_wait));


36 sb-> s_lock = 1; // to the super block lock (lock flag is set).
37 sti (); // open the interruption.

38 }
39
//// unlock the specified superblock. (If you use this name even more ulock_super appropriateness).

40 static void free_super (Struct super_block * Sb)


41 {
42 cli (); // disable interrupts.

43 sb-> s_lock = 0; // reset the lock flag.


44 wake_up (& (Sb-> s_wait)); // wake-up process is waiting for the superblock.

45 sti (); // open the interruption.

46 }
47
//// sleep waiting for superblock to unlock.

48 static void wait_on_super (Struct super_block * Sb)


49 {
50 cli (); // disable interrupts.

51 while (sb-> s_lock) // If the superblock is already locked, then wait for sleep.

52 sleep_on (& (Sb-> s_wait));


53 sti (); // open the interruption.

54 }
55
//// super block to take the specified device. Returns a pointer to the superblock structure.

56 struct super_block * get_super (Int dev)


57 {
58 struct super_block * S;
59
// If you do not specify a device, then returns a null pointer.

--362--
9.7 super.c program

60 if (! dev)
61 return NULL ;
// s pointing to the beginning of the super block array. Search the entire array of super blocks, looking for superblock specified device.

62 s = 0+ super_block ;
63 while (s < NR_SUPER + super_block )
// if the current search term is specified equipment superblock, first waiting for the superblock unlocked (if already locked by another process, then). // In the meantime, the

superblock may be used by other equipment, so this time to be determined once again whether or not the specified device superblock, superblock // if the pointer is returned.

Otherwise, re-search again for the super block array, so it s again point to the start of the superblock array //.

64 if (s-> s_dev == dev) {


65 wait_on_super (S);
66 if (s-> s_dev == dev)
67 return s;
68 s = 0+ super_block ;
// if the current search term is not, then check the next item. If the superblock specified is not found, a null pointer is returned.

69 } Else
70 s ++;
71 return NULL ;
72 }
73
//// release superblock specified device.

// release super block array entry equipment used (set s_dev = 0), and releasing the device node i and the logical block bitmap cache block bitmap // occupied. If a

corresponding file system superblock is the root file system, or it has been installed on the i-node // other file systems, the superblock can not be released.

74 void put_super (Int dev)


75 {
76 struct super_block * Sb;
77 struct m_inode * Inode;
78 int i;
79
// If the specified device is the root file system device, the warning message "to change the root system tray, ready to battle it life and death", and return.

80 if (dev == ROOT_DEV ) {
81 printk ( ' root diskette changed: prepare for armageddon \ n \ r ");
82 return;
83 }
// If you can not find the superblock specified equipment is returned.

84 if (! (sb = get_super (Dev)))


85 return;
// If the superblock indicates other file systems are mounted on this i-node file system, a warning message is displayed, return.

86 if (sb-> s_imount) {
87 printk ( ' Mounted disk changed - tssk, tssk \ n \ r ");
88 return;
89 }
// find the super block after the specified device, lock the first super block, and the device number field is set corresponding to the super block is 0, i.e., @ soon abandon the superblock.

90 lock_super (Sb);
91 sb-> s_dev = 0;
// then release the buffer block device node i and the logical block bitmap in the bitmap buffer occupied.

92 for (i = 0; i < I_MAP_SLOTS ; I ++)


93 brelse (Sb-> s_imap [i]);
94 for (i = 0; i < Z_MAP_SLOTS ; I ++)
95 brelse (Sb-> s_zmap [i]);
// finally unlock the super block and returns.

--363--
9.7 super.c program

96 free_super (Sb);
97 return;
98 }
99
//// superblock is read from the buffer to the device.

// If the superblock and device is already in the cache is valid, the process directly returns a pointer to the superblock.

100 static struct super_block * read_super (Int dev)


101 {
102 struct super_block * S;
103 struct buffer_head * Bh;
104 int i, block;
105
// If the device is not specified, then returns a null pointer.

106 if (! dev)
107 return NULL ;
// first check whether the apparatus can replace the disc (i.e. whether the device is a floppy disk), the disk replaced if the high speed cache block buffers of all the relevant failure //

devices are required for failure processing (release original loading the file system).

108 check_disk_change (Dev);


// If the superblock device has been in the cache, the directly returns a pointer to the superblock.

109 if (s = get_super (Dev))


110 return s;
// Otherwise, first find an empty entry in the super-block array (ie, items that s_dev = 0). If the array has been filled null pointer is returned.

111 for (s = 0+ super_block ;; s ++) {


112 if (s> = NR_SUPER + super_block )
113 return NULL ;
114 if (! s-> s_dev)
115 break;
116 }
// After the empty entry found superblock, the superblock is used to specify the equipment, part of the initialization of the memory item superblock.

117 s-> s_dev = dev;


118 s-> s_isup = NULL ;
119 s-> s_imount = NULL ;
120 s-> s_time = 0;
121 s-> s_rd_only = 0;
122 s-> s_dirt = 0;
// then lock the superblock, superblock and reads the device information from the buffer pointed to bh. If you read the superblock fails, // then release the selected item

above superblock array, and unlock the entry, exit returns a null pointer.

123 lock_super (S);


124 if (! (bh = bread (Dev, 1))) {
125 s-> s_dev = 0;
126 free_super (S);
127 return NULL ;
128 }
// Copy superblock information reading device on the corresponding entry to an array of super block structure. And release the stored information is read cache block.

129 * ((Struct d_super_block *) S) =


130 * ((Struct d_super_block *) Bh-> b_data);
131 brelse (Bh);
// If the file system superblock magic numbers paragraphs read wrong, the instructions on the device is not the correct file system, so // same as above, release the item

selected above superblock array, and unlock the item, exit returns a null pointer. // For the linux kernel version, only support minix file system version 1.0, whose magic

number is 0x137f.

132 if (s-> s_magic! = SUPER_MAGIC ) {


133 s-> s_dev = 0;
134 free_super (S);

--364--
9.7 super.c program

135 return NULL ;


136 }
// the next node i on the device starts reading the bitmap data and the logical block bitmap. First, initialize the memory space bitmap superblock structure.

137 for (i = 0; i < I_MAP_SLOTS ; I ++)


138 s-> s_imap [i] = NULL ;
139 for (i = 0; i < Z_MAP_SLOTS ; I ++)
140 s-> s_zmap [i] = NULL ;
// Node i then read the bitmap and the logical block bitmap information from the device and stored in the corresponding field in the superblock.

141 block = 2;
142 for (i = 0; i <s-> s_imap_blocks; i ++)
143 if (s-> s_imap [i] = bread (Dev, block))
144 block ++;
145 else
146 break;
147 for (i = 0; i <s-> s_zmap_blocks; i ++)
148 if (s-> s_zmap [i] = bread (Dev, block))
149 block ++;
150 else
151 break;
// If the bitmap is read is not equal to the number of logical blocks of the logical block number of the bit of FIG should occupy described bitmap information file system in question, the

superblock // initialization failed. It can only apply for the release of all the resources front, returns a null pointer and exit.

152 if (block! = 2 + s-> s_imap_blocks + s-> s_zmap_blocks) {// release bitmap node i and
the logical block bitmap occupied buffer cache.
153 for (i = 0; i < I_MAP_SLOTS ; I ++)
154 brelse (S-> s_imap [i]);
155 for (i = 0; i < Z_MAP_SLOTS ; I ++)
156 brelse (S-> s_zmap [i]);
// release the selected item above superblock array, and unlock the super block entry, exit returns a null pointer.

157 s-> s_dev = 0;


158 free_super (S);
159 return NULL ;
160 }
// Otherwise, every success. For idle function for the i-node is concerned, if all the i-node on the device have all been used, the function returns 0 // find value. Thus No.

0 i node is not used, so there will be the least significant bit in the bitmap is set to 1, to prevent the file system assigns numbers 0 i // node. Similarly, also the minimum

logical block bitmap bit set to 1.

161 s-> s_imap [0] -> b_data [0] | = 1;


162 s-> s_zmap [0] -> b_data [0] | = 1; // unlock the

superblock, superblock and returns the pointer.

163 free_super (S);


164 return s;
165 }
166
//// unmount the file system of the system calls. // parameter

dev_name is the device filename.

167 int sys_umount (Char * dev_name)


168 {
169 struct m_inode * Inode;
170 struct super_block * Sb;
171 int dev;
172
// first find the corresponding node i according to the device file name, and whichever device number.

173 if (! (inode = namei (Dev_name)))


174 return - ENOENT ;

--365--
9.7 super.c program

175 dev = inode-> i_zone [0];


// If not, block device file, node i is released just dev_i application, return an error code.
176 if (! S_ISBLK (Inode-> i_mode)) {
177 iput (Inode);
178 return - ENOTBLK ;
179 }
// release the i-node device file name.
180 iput (Inode);
// If the device is the root file system, you can not be uninstalled, return error number.

181 if (dev == ROOT_DEV )


182 return - EBUSY ;
// If a device fails to take the superblock, the device or the file system is not installed, an error code is returned.

183 if (! (sb = get_super (Dev)) ||! (Sb-> s_imount))


184 return - ENOENT ;
// If the node i is attached to the super block is not specified install set flag, a warning message is displayed.

185 if (! sb-> s_imount-> i_mount)


186 printk ( ' Mounted inode has i_mount = 0 \ n ");
// Find the i-node table to see if there are files on the process of using the device, if there are busy error code is returned.

187 for (inode = inode_table +0; inode < inode_table + NR_INODE ; Inode ++)
188 if (inode-> i_dev == dev && inode-> i_count)
189 return - EBUSY ;
// reset flag mounting node i is attached to the release of the node i.
190 sb-> s_imount-> i_mount = 0;
191 iput (Sb-> s_imount);
// set is mounted in the super block i node the field is empty, the node i and the release of the root file system device is mounted // set the root system superblock i-node pointer is

NULL.

192 sb-> s_imount = NULL ;


193 iput (Sb-> s_isup);
194 sb-> s_isup = NULL ;
// release the superblock and device occupied bitmap buffer block, and perform synchronization operations on the cache and data device to the device.

195 put_super (Dev);


196 sync_dev (Dev);
197 return 0;
198 }
199
//// installation file system calls.
// parameter dev_name is the device file name, dir_name is installed into a directory name, logo rw_flag be installed to read and write files. // place will be loaded must be a

directory name, and the i-node corresponding not occupied by other programs.

200 int sys_mount (Char * dev_name, char * dir_name, int rw_flag)


201 {
202 struct m_inode * Dev_i, * dir_i;
203 struct super_block * Sb;
204 int dev;
205
// first find the corresponding node i according to the device file name, and whichever device number. // For the

block special device file, the device number i i_zone node [0].

206 if (! (dev_i = namei (Dev_name)))


207 return - ENOENT ;
208 dev = dev_i-> i_zone [0];
// If the file is not a block device, then release the i-node dev_i just made, it returns an error code.

209 if (! S_ISBLK (Dev_i-> i_mode)) {


210 iput (Dev_i);
211 return - EPERM ;

--366--
9.7 super.c program

212 }
// release the device file i-node dev_i.
213 iput (Dev_i);
// find the i-node dir_i corresponding to the given directory file name.

214 if (! (dir_i = namei (Dir_name)))


215 return - ENOENT ;
// If the reference count is not node i is 1 (only reference herein), or a node number of the node i is the node number of the root file system // 1, the i-node is

released, return error code.

216 if (dir_i-> i_count! = 1 || dir_i-> i_num == ROOT_INO ) {


217 iput (Dir_i);
218 return - EBUSY ;
219 }
// If the node is not a document node directory, you can also release the i node, return an error code.

220 if (! S_ISDIR (Dir_i-> i_mode)) {


221 iput (Dir_i);
222 return - EPERM ;
223 }
// read the superblock file system is mounted, it is also released if the failure node i, returns an error code.

224 if (! (sb = read_super (Dev))) {


225 iput (Dir_i);
226 return - EBUSY ;
227 }
// If the file system is to be installed is already installed in other places, the i-node is released, return error code.

228 if (sb-> s_imount) {


229 iput (Dir_i);
230 return - EBUSY ;
231 }
// If the node i to be installed to the file system has been installed (installation flag has been set), the i-node is released, return error code.

232 if (dir_i-> i_mount) {


233 iput (Dir_i);
234 return - EPERM ;
235 }
// the file system is mounted superblock "is mounted to the i-node" field points to the node i is attached to the directory name.

236 sb-> s_imount = dir_i;


// set the node flag to install and the installation position of the node i has been modified flag. / * Note! There is no iput (dir_i) * /

237 dir_i-> i_mount = 1; / * This would operate within umount * /

238 dir_i-> i_dirt = 1; / * NOTE! We do not iput (dir_i) * /


239 return 0; / * We do that in umount * /
240 }
241
//// install the root file system.
// This function is turned on when initialization settings in the system (sys_setup ()) call. (Kernel / blk_drv / hd.c, 157)
242 void mount_root (Void)
243 {
244 int i, free ;
245 struct super_block * P;
246 struct m_inode * Mi;
247
// If the disk is not i-node structure 32 bytes, an error, crash. This determination is to modify the source code for preventing inconsistency when.

248 if (32! = sizeof (struct d_inode ))


249 panic ( ' bad i-node size ");
// initialization file table array (a total of 64, i.e., while the system 64 can only open the file), the file structure of all the reference count is set to 0 //. Why [??

initialization on here? Because the root file system is loaded here ☺]

--367--
9.7 super.c program

250 for (i = 0; i < NR_FILE ; I ++)


251 file_table [I] .f_count = 0;
// If the root file system where the device is a floppy disk, then it prompts "Insert root file system disk and press ENTER" button and wait.

252 if ( MAJOR ( ROOT_DEV ) == 2) {


253 printk ( ' Insert root floppy and press ENTER ");
254 wait_for_keypress ();
255 }
// initialize array superblock (total 8).
256 for (p = & super_block [0]; p <& super_block [ NR_SUPER ]; P ++) {
257 p-> s_dev = 0;
258 p-> s_lock = 0;
259 p-> s_wait = NULL ;
260 }
// If the superblock on the read root device fails, the information is displayed, and crashes.

261 if (! (p = read_super ( ROOT_DEV )))


262 panic ( ' Unable to mount root ");
// read the file system of the device from the root node i (1), if it fails an error message is displayed, the crash.

263 if (! (mi = iget ( ROOT_DEV , ROOT_INO )))


264 panic ( ' Unable to read root i-node ");
// increment the i-node number of citations 3 times. Since the upper and lower rows 266-268 also refers to the node i.

265 mi-> i_count + = 3; / * NOTE! It is logically used 4 times, not 1 * /


/ * Note! Logically, it has been cited four times, and not once * /
// set the super block is mounted and the file system is mounted to a node i of the i-node for node i.

266 p-> s_isup = p-> s_imount = mi;


// set the current working directory and the root directory of the current process node i. At this time, the current process is the No. 1 process.

267 current -> pwd = mi;


268 current -> root = mi;
// count the number of free blocks on the device. First, for i equal to the total number of the logical device indicated in the superblock.

269 free = 0;
270 i = p-> s_nzones;
// then the statistics of the number of free block bitmap according to the logical block corresponding bits of occupancy. Here SET_BIT macro function () // test bit only, and not set

bits. "I & 8191" for obtaining the offset value in the i-node number of the current block. "I >> 13" is divided by i // 8192, i.e. in addition to the number of bits contained in a disk block.

271 while (- i> = 0)


272 if (! set_bit (I & 8191, p-> s_zmap [i >> 13] -> b_data))
273 free ++;
Total number of free logical blocks on the device / logical block // display.

274 printk ( "% d /% d free blocks \ n \ r ", free , P-> s_nzones);


// i idle nodes on statistical device. First, for i equal to the total number of nodes i + 1'd device indicated superblock. Plus 1 is 0 // node also counted in the data.

275 free = 0;
276 i = p-> s_ninodes + 1;
// then calculated according to the nodes i i idle node bitmap corresponding bits of occupancy.

277 while (- i> = 0)


278 if (! set_bit (I & 8191, p-> s_imap [i >> 13] -> b_data))
279 free ++;
The total number of idle available on the device nodes i / i // node display.

280 printk ( "% d /% d free inodes \ n \ r ", free , P-> s_ninodes);


281 }
282

--368--
9.8 namei.c program

9.8 namei.c program

9.8.1 Functional Description

The file is linux 0.11 The longest kernel function, but only 700 Multi-line ☺ . This document is mainly achieved in accordance directory to find the corresponding name or file

name i Function Node, and establish and delete something about the directory, the directory entry to establish and delete operations and other functions and system calls. Due to

the previous program in several major functions have more detailed comments in English, and various functions and system function calls and clear, so not repeat them here.

9.8.2 Code comments

program 9-6 linux / fs / namei.c

1/*
2 * Linux / fs / namei.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * Some corrections by tytso.


9*/
/*
* tytso made some correction.
*/
1011 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

12 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

13 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

1415 #include <string.h>


// string header file. Mainly defines the built-in functions related to operation of the string.

16 #include <fcntl.h> // control file header. Operable control descriptor file and constants defined symbols.
17 #include <errno.h> // error number header files. The system comprises various error number. (Linus imported from the minix).

18 #include <const.h> // constant symbol header file. Currently only defines each flag i node i_mode field.
19 #include <sys / stat.h> // File Status header file. Containing configuration file or system state stat {} and constants.

20
// Access macro mode. x is a file access flags include / fcntl.h line 7 defined at the beginning. // The x value corresponding to the index (the value

represented rwx permissions: r, w, rw, wxrwxrwx) (values ​are octal).

twenty one #define ACC_MODE ( x ) ( "\ 004 \ 002 \ 006 \ 377 "[( x ) & O_ACCMODE ])

2223 / *

twenty four * Comment out this line if you want names> NAME_LEN chars to be
25 * Truncated. Else they will be disallowed.
26 * /
/*
* If you want the file name length> NAME_LEN characters are truncated, the following definitions will be commented out.

*/
27 / * #Define NO_TRUNCATE * /
28

--369--
9.8 namei.c program

29 #define MAY_EXEC 1 // executable (enter).


30 #define MAY_WRITE 2 // write.
31 #define MAY_READ 4 // read.
3233 / *

34 * permission ()
35 *
36 * Is used to check for read / write / execute permissions on a file.
37 * I do not know if we should look at just the euid or both euid and
38 * Uid, but that should be easily changed.
39 * /
/*
* permission ()
* This function is used to detect read a file / write / execute permissions. I do not know if just check euid, or
* You need to check both euid and uid, but it is easy to modify.

*/
//// detect file access permissions.
// Parameters: inode - i node corresponding to the file; mask - the mask access attributes. // returns: access

permission to return 1, otherwise it returns 0.

40 static int permission (Struct m_inode * Inode, int mask)


41 {
42 int mode = inode-> i_mode; // File Access Properties

4344 / * Special case: not even root can read / write a deleted file * /

/ * Special case: even by the superuser (root) can not read / write a file has been removed * / // if the node i has a corresponding

device, but the number of connections of the node i is equal to 0, it returns.

45 if (inode-> i_dev &&! inode-> i_nlinks)


46 return 0;
// Otherwise, if the effective user id user id process (euid) and i-node is the same, then take the user access to the host file.

47 else if ( current -> euid == inode-> i_uid)


48 mode >> = 6;
// Otherwise, if the effective group id group id of the process (egid) and i-node are the same, take group access rights of users.

49 else if ( current -> egid == inode-> i_gid)


50 mode >> = 3;
// If the above is taken in the same access to the mask, or a super-user, the process returns 1, and 0 otherwise.

51 if (((mode & mask & 0007) == mask) || suser ())


52 return 1;
53 return 0;
54 }
5556 / *

57 * Ok, we can not use strncmp, as the name is not in our data space.
58 * Thus we'll have to use match. No big problem. Match also makes
59 * Some sanity tests.
60 *
61 * NOTE! Unlike strncmp, match returns 1 for success, 0 for failure.
62 * /
/*
* ok, we can not use strncmp string comparison function, because the name is not in our data space (not kernel space).
* So we can only use the match (). Not a big problem. match () also deal with some complete test.
*
* note! The difference is that with strncmp match () returns 1 if successful, 0 is returned on failure.

*/

--370--
9.8 namei.c program

//// specified length string comparison functions.

// Parameters: len - the length of the string comparison; name - the name of the file pointer; de - directory entry structure. // Returns: 1 return

the same, different returns 0.

63 static int match (Int len, const char * name, struct dir_entry * De)
64 {
65 register int same __asm ​__ ( " ax ");
66
// null pointer if the directory entry, the directory entry or node i is equal to 0, or to compare the string is longer than the length of the file name, 0 is returned.

67 if (! de ||! de-> inode || len> NAME_LEN )


68 return 0;
// If you want to compare the length len is less than NAME_LEN, but the catalog entry file names longer than len, 0 is returned.

69 if (len < NAME_LEN && de-> name [len])


70 return 0;
// The following statements embedded assembly, a string comparison operation is performed in the user data space (fs).

//% 0 - eax (comparison same);% 1 - eax (eax initial value 0);% 2 - esi (name pointer);% 3 - edi (name of the directory entry pointer); //% 4 - ecx ( Comparative byte

length value len).

71 __asm ​__ ( " cld \ n \ t " // clear direction bit.

72 "Fs; repe; cmpsb \ n \ t" // user space execution cycle comparison [esi ++] and [edi ++] operation,

73 "Setz %% al" // If the comparison result as (z = 0) is set al = 1 (same = eax).


74 : "= a "( same)
75 : "" (0) " S "(( long) name), " D "(( long) de-> name), " c "( len)
76 : " cx "," di "," si ");
77 return same; // returns the result of the comparison.

78 }
7980 / *

81 * find_entry ()
82 *
83 * Finds an entry in the specified directory with the wanted name. It
84 * Returns the cache buffer in which the entry was found, and the entry
85 * Itself (as a parameter - res_dir). It does NOT read the inode of the
86 * Entry - you'll have to do that yourself if you want to.
87 *
88 * This also takes care of the few special cases due to '..'- traversal
89 * Over a pseudo-root and a mount point.
90 * /
/*
* find_entry ()
* Looking for a directory entry with a name that matches the specified directory. Returns a directory entry contains a high-speed find

* Buffers and directory entry itself (as a parameter - res_dir). Read directory entry is not i-node - as
* If required need their own operations.

*
* '..' directory entries, also during operation of several special cases were treated - such as a pseudo-root to traverse

* And mounting points.

*/
//// find the directory entry specifies the directory and file name.

// Parameters: dir - i node pointer of the directory; name - the name of the file; namelen - File name length; // Return: high speed buffer

pointer; res_dir - directory entry structure pointer returned;

91 static struct buffer_head * find_entry (Struct m_inode ** dir,


92 const char * name, int namelen, struct dir_entry ** res_dir)
93 {
94 int entries;
95 int block, i;

--371--
9.8 namei.c program

96 struct buffer_head * Bh;


97 struct dir_entry * De;
98 struct super_block * Sb;
99
// If the definition of NO_TRUNCATE, then if the file names longer than the maximum length NAME_LEN, is returned.

100 #ifdef NO_TRUNCATE


101 if (namelen> NAME_LEN )
102 return NULL ;
// If not defined NO_TRUNCATE, then if the file names longer than the maximum length NAME_LEN, it is truncated.

103 #else
104 if (namelen> NAME_LEN )
105 namelen = NAME_LEN ;
106 #endif
The number of directory entries entries entries // calculate this catalog. Back blanking directory entry structure pointer.

107 entries = (* dir) -> i_size / (sizeof (struct dir_entry ));


108 * res_dir = NULL ;
// If the file name length is equal to 0, it returns NULL, exit.
109 if (! namelen)
110 return NULL ;
111 / * Check for '..', as we might have to do some "magic" for it * /
/ * Check the directory entry ".. ', may require special handling because of its * /

112 if (namelen == 2 && get_fs_byte (Name) == '.' && get_fs_byte (Name + 1) == '.') {
113 / * '..' in a pseudo-root results in a faked '.' (Just change namelen) * /
/ * Pseudo-roots '..' as a fake. '' (Just change the name length) * / // if the root node pointer of the current process that is

specified directory, the file name changed to '.'

114 if ((* dir) == current -> root)


115 namelen = 1;
// Otherwise, if the directory i-node number is equal to ROOT_INO (1), it indicates that the root file system. The file system superblock.

116 else if ((* dir) -> i_num == ROOT_INO ) {


117 / * '..' over a mount-point results in 'dir' being exchanged for the mounted
118 directory-inode. NOTE! We set mounted, so that we can iput the new dir * /
/ * On a mounting point '..' will result in the exchange directory i-node to install the file system directory.

note! Since the flag is set mounted, so we can take out the new directory * /
119 sb = get_super ((* Dir) -> i_dev);
// If the node i is attached to the present, the first release of the original node i, then node i to be processed is mounted. Let i // * dir point which is

mounted to a node; i references the node plus one.

120 if (sb-> s_imount) {


121 iput (* Dir);
122 (* Dir) = sb-> s_imount;
123 (* Dir) -> i_count ++;
124 }
125 }
126 }
// If the first direct disk block number i of the node pointed to 0, the process returns NULL, exit.

127 if ((block = (* dir) -!> i_zone [0]))


128 return NULL ;
// read the directory entry specified data block from the host device node, if unsuccessful, it returns NULL, exit.

129 if (! (bh = bread ((* Dir) -> i_dev, block)))


130 return NULL ;
// search directory entry matches the specified file name in the directory entry data block, let de point to data blocks, and the number of directory entry in the directory at no more than

// under the conditions of circulation perform a search.

--372--
9.8 namei.c program

131 i = 0;
132 de = (struct dir_entry *) Bh-> b_data;
133 while (i <entries) {
// If the current directory entry data blocks have been searched, yet find the matching directory entry, then release the current directory entry data block.

134 if ((char *) de> = BLOCK_SIZE + Bh-> b_data) {


135 brelse (Bh);
136 bh = NULL ;
// read the data block in the next directory entry. If this is empty, as long as no complete search for all directory entries in the directory, skip this block, // continue reading the next directory

entry data block. If the block is not empty, let de directory entry points to the data block, to continue the search.

137 if (! (block = bmap (* Dir, i / DIR_ENTRIES_PER_BLOCK )) ||


138 ! (Bh = bread ((* Dir) -> i_dev, block))) {
139 i + = DIR_ENTRIES_PER_BLOCK ;
140 continue;
141 }
142 de = (struct dir_entry *) Bh-> b_data;
143 }
// If a match is found, then the directory entry, the directory entry directory entry structure pointer and the data block pointer returned exit.

144 if ( match (Namelen, name, de)) {


145 * res_dir = de;
146 return bh;
147 }
// otherwise continue a directory entry in the directory entry data blocks relatively.

148 de ++;
149 i ++;
150 }
// If all catalog items are specified directory has not been searched to find the corresponding directory entry, directory entry data block is released, returns NULL.

151 brelse (Bh);


152 return NULL ;
153 }
154 155 /
*
156 * add_entry ()
157 *
158 * Adds a file entry to the specified directory, using the same
159 * Semantics as find_entry (). It returns NULL if it failed.
160 *
161 * NOTE !! The inode part of 'de' is left at 0 - which means you
162 * May not sleep between calling this and putting something into
163 * The entry, as someone else might have used it while you slept.
164 * /
/*
* add_entry ()
* Use the find_entry () the same way, to the specified directory to add a file directory entry.

* If it fails it returns NULL.


*
* note! ! 'De' (designated directory entry structure pointer) i-node portion is set to 0 - which means

* In calling the function and can not be added to the directory entry information between sleep, since sleep so if other

* People (process) may have been used for the directory entry.

*/
//// add directory entry for the specified directory and file name.

// Parameters: dir - i node specified directory; name - the name of the file; namelen - File name length; // Return: high speed buffer

pointer; res_dir - directory entry structure pointer returned;

165 static struct buffer_head * add_entry (Struct m_inode * Dir,

--373--
9.8 namei.c program

166 const char * name, int namelen, struct dir_entry ** res_dir)


167 {
168 int block, i;
169 struct buffer_head * Bh;
170 struct dir_entry * De;
171
172 * res_dir = NULL ;
// If the definition of NO_TRUNCATE, then if the file names longer than the maximum length NAME_LEN, is returned.

173 #ifdef NO_TRUNCATE


174 if (namelen> NAME_LEN )
175 return NULL ;
// If not defined NO_TRUNCATE, then if the file names longer than the maximum length NAME_LEN, it is truncated.

176 #else
177 if (namelen> NAME_LEN )
178 namelen = NAME_LEN ;
179 #endif
// If the file name length is equal to 0, it returns NULL, exit.
180 if (! namelen)
181 return NULL ;
// If the first direct disk block number in the directory pointed to node i is 0, NULL is returned exit.

182 if (! (block = dir-> i_zone [0]))


183 return NULL ;
// If you read the disk block fails, NULL is returned and exit.
184 if (! (bh = bread (Dir-> i_dev, block)))
185 return NULL ;
// data block in the directory entry directory entry last cycle to find unused. Let de-structured pointer points to the directory entry of the cache data block // at the beginning, i.e. the first

directory entry.

186 i = 0;
187 de = (struct dir_entry *) Bh-> b_data;
188 while (1) {
// If the current directory entry discrimination beyond the current data block, the data block is released, re-apply for a disk block block. // If the application fails, it

returns NULL, exit.

189 if ((char *) de> = BLOCK_SIZE + Bh-> b_data) {


190 brelse (Bh);
191 bh = NULL ;
192 block = create_block (Dir, i / DIR_ENTRIES_PER_BLOCK );
193 if (! block)
194 return NULL ;
// If the read pointer is returned empty disk block, the block is skipped to continue.

195 if (! (bh = bread (Dir-> i_dev, block))) {


196 i + = DIR_ENTRIES_PER_BLOCK ;
197 continue;
198 }
// Otherwise, let the directory entry structure pointer de aspirations of the block cache block beginning.

199 de = (struct dir_entry *) Bh-> b_data;


200 }
// If the directory entry number of the current operated by i * directory structure size has exceeded the size of the directory noted i_size, it indicates that the first i // directory entries not been

used, we can use it. So setting (node ​pointer i is set to the directory entry is empty) the directory entry. When the length value, and updates the directory // (plus a length of the directory entry, the

directory i-node set have been modified flags, and then update the changes to the directory

// between the current time.

201 if (i * sizeof (struct dir_entry )> = Dir-> i_size) {


202 de-> inode = 0;

--374--
9.8 namei.c program

203 dir-> i_size = (i + 1) * sizeof (struct dir_entry );


204 dir-> i_dirt = 1;
205 dir-> i_ctime = CURRENT_TIME ;
206 }
// if the i-node directory entry is empty, then find a directory entry has not been used. And updates the directory modification time to the current time. // copy and file name to the directory

entry of the file name field, sets the appropriate flag has been modified cache block from the user data area. // return the directory entry pointer and a pointer to the buffer cache and quit.

207 if (! de-> inode) {


208 dir-> i_mtime = CURRENT_TIME ;
209 for (i = 0; i < NAME_LEN ; I ++)
210 de-> name [i] = (i <namelen)? get_fs_byte (Name + i): 0;
211 bh-> b_dirt = 1;
212 * res_dir = de;
213 return bh;
214 }
// If the directory entry has been used, then continue to detect the next directory entry.

215 de ++;
216 i ++;
217 }
// unreachable here. Maybe Linus when writing code to make a copy of the above find_entry () code, and then modify the ☺ .
218 brelse (Bh);
219 return NULL ;
220 }
221 222 /
*
223 * get_dir ()
224 *
225 * Getdir traverses the pathname until it hits the topmost directory.
226 * It returns NULL on failure.
227 * /
/*
* get_dir ()
* The search function is based on the path name given until it reaches the top of the directory.

* If it fails it returns NULL.


*/
//// search directory specified path name. //
Parameters: pathname - pathname.
// Returns: i node pointer directory. Return NULL on failure.
228 static struct m_inode * get_dir (Const char * pathname)
229 {
230 char c;
231 const char * thisname;
232 struct m_inode * Inode;
233 struct buffer_head * Bh;
234 int namelen, inr, idev;
235 struct dir_entry * De;
236
// If the process is not set to the root node i, or the process referred to as the root node i 0, then the system errors, crashes.

237 if (! current -> root ||! current -> root-> i_count)


238 panic ( ' No root inode ");
// If the current working directory of the process pointer is empty, or the current directory i-node reference count is 0, the system also has a problem, crash.

239 if (! current -> pwd ||! current -> pwd-> i_count)


240 panic ( ' No cwd inode ");

--375--
9.8 namei.c program

// If the first character a user-specified path name is '/', then the path name is absolute pathname. I from the root node starts to operate.

241 if ((c = get_fs_byte (Pathname)) == '/') {


242 inode = current -> root;
243 pathname ++;
// Otherwise, if the first character is the other character, then it is given a relative path name. The current working directory of the process should be started. // get the i-node processes the

current working directory.

244 } Else if (c)


245 inode = current -> pwd;
// otherwise, it indicates the path name is empty, an error. Return NULL, exit.

246 else
247 return NULL ; / * Empty name is bad * / / * Empty pathname is wrong * /
// The reference count acquired node i is incremented by one.

248 inode-> i_count ++;


249 while (1) {
I // If the node is not a directory node, or no access permission to enter, then release the i node, return NULL, exit.
250 thisname = pathname;
251 if (! S_ISDIR (Inode-> i_mode) ||! permission (Inode, MAY_EXEC )) {
252 iput (Inode);
253 return NULL ;
254 }
// path name from the search start character is detected, until the end of the symbol characters are (NULL) or '/', the current process at this time is just namelen

// length of the directory names. If the last name is a directory, but then did not add '/', i will not return to the last node directory! // example: / var / log /
httpd, node i will only return log / directory.
255 for (namelen = 0; (c = get_fs_byte (Pathname ++)) && (c = '/');! Namelen ++)
256 / * Nothing * /;
// If the character is the end symbol NULL, the show has reached the specified directory, the i-node pointer is returned to exit.

257 if (! c)
258 return inode;
// call the function lookup directory entry specified directory and file names, looking for subdirectory entries in the current process directory. If none is found, then release the i // node, and

returns NULL, exit.

259 if (! (bh = find_entry (& Inode, thisname, namelen, & de))) {


260 iput (Inode);
261 return NULL ;
262 }
// i take inr node number and device number of the subdirectory idev item, and releases the cache block i of the node containing the directory entry.

263 inr = de-> inode;


264 idev = inode-> i_dev;
265 brelse (Bh);
266 iput (Inode);
i node information // inr take node number, if fails, it returns NULL, exit. Otherwise, proceed to the i-node subdirectory.
267 if (! (inode = iget (Idev, inr)))
268 return NULL ;
269 }
270 }
271 272 /
*
273 * dir_namei ()
274 *
275 * Dir_namei () returns the inode of the directory of the
276 * Specified name, and the name within that directory.
277 * /
/*

--376--
9.8 namei.c program

* dir_namei ()
* dir_namei () function returns the name of the directory i-node pointer, and the name at the top level directory.

*/
// Parameters: pathname - directory path name; namelen - path name length. // Returns: i pointer specifies the node name of the topmost

directory of a directory and a directory name and the topmost length.

278 static struct m_inode * dir_namei (Const char * pathname,


279 int * namelen, const char ** name)
280 {
281 char c;
282 const char * basename;
283 struct m_inode * Dir;
284
// get topmost directory of the specified path name of the i-node, if the error returns NULL, exit.

285 if (! (dir = get_dir (Pathname)))


286 return NULL ;
// path name search pathname detection, investigation and finally a '/' followed by the name of the string, its length is calculated, and returns the pointer to the node I // Top layer

directory.

287 basename = pathname;


288 while (c = get_fs_byte (Pathname ++))
289 if (c == '/')
290 basename = pathname;
291 * namelen = pathname-basename-1;
292 * name = basename;
293 return dir;
294 }
295 296 /
*
297 * namei ()
298 *
299 * Is used by most simple commands to get the inode of a specified name.
300 * Open, link etc use their own routines, but this is enough for things
301 * Like 'chmod' etc.
302 * /
/*
* namei ()
* This function is used to obtain a number of simple commands to specify the name of the i-node path. open, link, etc. is to use them

* Their respective functions, but as such a modified mode command 'chmod', etc., this function has been sufficient.

*/
//// i nodes take the path name specified. //

Parameters: pathname - pathname. // Returns: i

corresponding to the node.

303 struct m_inode * namei (Const char * pathname)


304 {
305 const char * basename;
306 int inr, dev, namelen;
307 struct m_inode * Dir;
308 struct buffer_head * Bh;
309 struct dir_entry * De;
310
// First find the specified path of the directory name and i-node topmost directory, if not, it returns NULL, exit.
311 if (! (dir = dir_namei (Pathname, & namelen, & basename)))
312 return NULL ;
// if the length of the topmost names of return is zero, it indicates that the path name to a directory named last item.

--377--
9.8 namei.c program

313 if (! namelen) / * Special case: '/ usr /' etc * /


314 return dir; / * Corresponds to the '/ usr /', etc. * /

// find the i-node to specify the filename directory entry in the return of top-level directory. Because if the last name is a directory, but then there is no // add '/', i will

not return to the last node directory! For example: / var / log / httpd, node i will only return log / directory. // So dir_namei () will not be a '/' last name as the end of a

file name to look at. It should therefore separately // this case use the search function FIND_ENTRY directory entry node i () for processing.

315 bh = find_entry (& Dir, basename, namelen, & de);


316 if (! bh) {
317 iput (Dir);
318 return NULL ;
319 }
// i-node number and device number of the directory of the directory entry is taken, and releases the buffer cache directory and i-node containing the directory entry.

320 inr = de-> inode;


321 dev = dir-> i_dev;
322 brelse (Bh);
323 iput (Dir);
// i take the section number corresponding to the node to modify its access time is the current time, and the flag is set has been modified. The i-node pointer and finally returns.

324 dir = iget (Dev, inr);


325 if (dir) {
326 dir-> i_atime = CURRENT_TIME ;
327 dir-> i_dirt = 1;
328 }
329 return dir;
330 }
331 332 /
*
333 * open_namei ()
334 *
335 * Namei for open - this is in fact almost the whole open-routine.
336 * /
/*
* open_namei ()
* open () namei function used - this is actually almost the complete program to open the file.
*/
//// File Open namei function.
// Parameters: pathname - the file pathname; flag - File Open logo; mode - File access permissions attributes; // Return: return 0 if successful, otherwise it returns

an error code; res_inode - i node pointer returned by the corresponding file path name of.

337 int open_namei (Const char * pathname, int flag, int mode,
338 struct m_inode ** res_inode)
339 {
340 const char * basename;
341 int inr, dev, namelen;
342 struct m_inode * Dir, * inode;
343 struct buffer_head * Bh;
344 struct dir_entry * De;
345
// If the file is read-only access permission mode flag (0), but the file was truncated 0 O_TRUNC flag is set, the flag will be changed to write only.

346 if ((flag & O_TRUNC ) &&! (Flag & O_ACCMODE ))


347 flag | = O_WRONLY ;
// use the process of file access permissions masks, masked corresponding bit of a given mode, and add common file flags.

348 mode & = 0777 & ~ current-> umask ;


349 mode | = I_REGULAR ;
// find the corresponding node i, and the top of the file name and the path name length.

--378--
9.8 namei.c program

350 if (! (dir = dir_namei (Pathname, & namelen, & basename)))


351 return - ENOENT ;
// If the topmost file name length is 0 (e.g., '/ usr /' pathname this case), then when the opening operation is not created, cut 0, // indicates open a directory

name, directory directly returned to the i node, and exit.

352 if (! namelen) { / * Special case: '/ usr /' etc * /


353 if (! (flag & ( O_ACCMODE | O_CREAT | O_TRUNC ))) {
354 * res_inode = dir;
355 return 0;
356 }
// otherwise release the i node, return an error code.

357 iput (Dir);


358 return - EISDIR ;
359 }
// get the high-speed buffer corresponding to the file name and the directory entry structure de directory entry is located in the corresponding directory node dir.

360 bh = find_entry (& Dir, basename, namelen, & de);


// if the cache pointer is NULL, then find that there is no directory entry corresponding to the file name, and therefore can only be created file operations.

361 if (! bh) {
// create the file if it is not, then release the i-node directory, returns an error number to exit.

362 if (! (flag & O_CREAT )) {


363 iput (Dir);
364 return - ENOENT ;
365 }
// If the user did not write powers the directory, then release the i-node directory, returns an error number to exit.

366 if (! permission (Dir, MAY_WRITE )) {


367 iput (Dir);
368 return - EACCES ;
369 }
I // apply a new node in the directory corresponding to the node device, if the failed node i is released directory, and returns the error code is no space.

370 inode = new_inode (Dir-> i_dev);


371 if (! inode) {
372 iput (Dir);
373 return - ENOSPC ;
374 }
// Otherwise, to use the new node i, its initial set: set the node id of the user; the corresponding node access mode; setting flag has been modified.

375 inode-> i_uid = current -> euid;


376 inode-> i_mode = mode;
377 inode-> i_dirt = 1;
// and then add a new directory entry in the specified directory dir.

378 bh = add_entry (Dir, basename, namelen, & de);


// If the high-speed buffer pointer returned should contain the new directory entry is NULL, it means adding a directory entry failed. // then the new reference node is

connected i count by 1; i node and release of the directory and i-node, return error code to exit.

379 if (! bh) {
380 inode-> i_nlinks--;
381 iput (Inode);
382 iput (Dir);
383 return - ENOSPC ;
384 }
// initial settings to the new directory entry: the i-node number is set as a number of new applications to node i; high-speed counter and flag buffer has been modified. // then release the

buffer cache, the release of the i-node directory. Returns the i-node pointer to the new directory entry and exit.

385 de-> inode = inode-> i_num;


386 bh-> b_dirt = 1;
387 brelse (Bh);
388 iput (Dir);

--379--
9.8 namei.c program

389 * res_inode = inode;


390 return 0;
391 }
// If the above takes the file name in the directory structure of the directory entry corresponding to the operation is successful (bh i.e. not NULL), i // node number and the device number in

which it is taken out of the directory entry, and releases the cache area and i node directory.

392 inr = de-> inode;


393 dev = dir-> i_dev;
394 brelse (Bh);
395 iput (Dir);
// If O_EXCL exclusive use flag is set, the file already exists error code, quit to return.
396 if (flag & O_EXCL )
397 return - EEXIST ;
// If operation takes the directory entry corresponding to the i-node fails, the access error code is returned, exit.

398 if (! (inode = iget (Dev, inr)))


399 return - EACCES ;
// If the node i node is a directory and the access mode is read-only or write-only, or no access permissions, then release the i // node, returns an error
code access and exit.
400 if (( S_ISDIR (Inode-> i_mode) && (flag & O_ACCMODE )) ||
401 ! permission (Inode, ACC_MODE (Flag))) {
402 iput (Inode);
403 return - EPERM ;
404 }
// update the i-node access time field to the current time.
405 inode-> i_atime = CURRENT_TIME ;
// If you set up 0 truncated flag, the file is truncated to the length of the i-node 0.

406 if (flag & O_TRUNC )


407 truncate (Inode);
// Returns a pointer to the last directory entry node i, and returns 0 (success).

408 * res_inode = inode;


409 return 0;
410 }
411
//// system calls - creates a special file or regular file nodes (node).
// create a name for the filename, specified by mode and dev file system nodes (regular file, device special file or named pipe). // Parameters: filename - the

pathname; mode - specifies the license and the type of node creation; dev - device number. // Returns: 0 for success, otherwise it returns an error code.

412 int sys_mknod (Const char * filename, int mode, int dev)
413 {
414 const char * basename;
415 int namelen;
416 struct m_inode * Dir, * inode;
417 struct buffer_head * Bh;
418 struct dir_entry * De;
419
// If it is not super-user, access permission error code is returned.

420 if (! suser ())


421 return - EPERM ;
// If you can not find the i-node corresponding to the path name of the directory, the error code is returned.

422 if (! (dir = dir_namei (Filename, & namelen, & basename)))


423 return - ENOENT ;
// If the topmost file name length is zero, then the final pathname given filename is not specified, the directory i-node is released, return error code // exit.

424 if (! namelen) {

--380--
9.8 namei.c program

425 iput (Dir);


426 return - ENOENT ;
427 }
// If you do not have permission to write in that directory, the directory i-node is released, returning an error code access permission to exit.

428 if (! permission (Dir, MAY_WRITE )) {


429 iput (Dir);
430 return - EPERM ;
431 }
// If the path name directory entry corresponding to the last file name already exists, the release of high-speed buffer that contains the directory entry, the release of the i-node directory //

returns an error code file already exists, quit.

432 bh = find_entry (& Dir, basename, namelen, & de);


433 if (bh) {
434 brelse (Bh);
435 iput (Dir);
436 return - EEXIST ;
437 }
// i apply for a new node, if unsuccessful, then release the i-node directory, no space to return an error code to exit.

438 inode = new_inode (Dir-> i_dev);


439 if (! inode) {
440 iput (Dir);
441 return - ENOSPC ;
442 }
// Set the attribute pattern of the node i. If you want to create a block device or file is a character file, so that a direct block pointer node i // 0 equals device number.

443 inode-> i_mode = mode;


444 if ( S_ISBLK (Mode) || S_ISCHR (Mode))
445 inode-> i_zone [0] = dev;
// set modification time of the i-node, the access time to the current time.

446 inode-> i_mtime = inode-> i_atime = CURRENT_TIME ;


447 inode-> i_dirt = 1;
// Add a new directory in a directory entry, if it fails (buffer cache directory entry that contains the pointer is NULL), node i is released // directory; i node the requested

connection reference count is reset, and release the i node. Returns an error code to exit.

448 bh = add_entry (Dir, basename, namelen, & de);


449 if (! bh) {
450 iput (Dir);
451 inode-> i_nlinks = 0;
452 iput (Inode);
453 return - ENOSPC ;
454 }
// make i-node field of the directory entry is equal to the new i-node number, set the high-speed buffer has been modified logo, and a new release directory i-node, release // buffer cache, and

returns 0 (success).

455 de-> inode = inode-> i_num;


456 bh-> b_dirt = 1;
457 iput (Dir);
458 iput (Inode);
459 brelse (Bh);
460 return 0;
461 }
462
//// system calls - to create the directory.
// Parameters: pathname - pathname; mode - use the directory property rights. // Returns: 0 for

success, otherwise it returns an error code.

463 int sys_mkdir (Const char * pathname, int mode)

--381--
9.8 namei.c program

464 {
465 const char * basename;
466 int namelen;
467 struct m_inode * Dir, * inode;
468 struct buffer_head * Bh, * dir_block;
469 struct dir_entry * De;
470
// If it is not super-user, access permission error code is returned.

471 if (! suser ())


472 return - EPERM ;
// If you can not find the i-node corresponding to the path name of the directory, the error code is returned.

473 if (! (dir = dir_namei (Pathname, & namelen, & basename)))


474 return - ENOENT ;
// If the topmost file name length is zero, then the final pathname given filename is not specified, the directory i-node is released, return error code // exit.

475 if (! namelen) {
476 iput (Dir);
477 return - ENOENT ;
478 }
// If you do not have permission to write in that directory, the directory i-node is released, returning an error code access permission to exit.

479 if (! permission (Dir, MAY_WRITE )) {


480 iput (Dir);
481 return - EPERM ;
482 }
// If the path name directory entry corresponding to the last file name already exists, the release of high-speed buffer that contains the directory entry, the release of the i-node directory //

returns an error code file already exists, quit.

483 bh = find_entry (& Dir, basename, namelen, & de);


484 if (bh) {
485 brelse (Bh);
486 iput (Dir);
487 return - EEXIST ;
488 }
// i apply for a new node, if unsuccessful, then release the i-node directory, no space to return an error code to exit.

489 inode = new_inode (Dir-> i_dev);


490 if (! inode) {
491 iput (Dir);
492 return - ENOSPC ;
493 }
// set the new file length i corresponding to the node 32 (the size of a directory entry), set the node has been modified modified time stamp, and the nodes and the access time //.

494 inode-> i_size = 32;


495 inode-> i_dirt = 1;
496 inode-> i_mtime = inode-> i_atime = CURRENT_TIME ;
// apply a disk block for node i, and let the first node is equal to a direct block pointer of the block number. If the application fails, then the release of @ directory corresponding to the node i;

i-node connection count reset a new application; i releasing the new node, return error code is no space to exit.

497 if (! (inode-> i_zone [0] = new_block (Inode-> i_dev))) {


498 iput (Dir);
499 inode-> i_nlinks--;
500 iput (Inode);
501 return - ENOSPC ;
502 }
// set the new i-node has been modified flag.

503 inode-> i_dirt = 1;

--382--
9.8 namei.c program

// read the disk block new application. If the error is released directory corresponding to the node i; release applications disk blocks; reset node i // new application connection count; i

releasing the new node, return error code is no space to exit.

504 if (! (dir_block = bread (Inode-> i_dev, inode-> i_zone [0]))) {


505 iput (Dir);
506 free_block (Inode-> i_dev, inode-> i_zone [0]);
507 inode-> i_nlinks--;
508 iput (Inode);
509 return - ERROR ;
510 }
// make de directory entry pointing to the data block, the directory entry counter i-node number field equal to the i-node number of the new application, the name field is equal to. "."

511 de = (struct dir_entry *) Dir_block-> b_data;


512 de-> inode = inode-> i_num;
513 strcpy (De-> name, ".");
// then under de entry point to a directory structure that is used to store the parent directory node number and the name "..."

514 de ++;
515 de-> inode = dir-> i_num;
516 strcpy (De-> name, "..");
517 inode-> i_nlinks = 2;
// then set the high-speed buffer has been modified mark and release the buffer.

518 dir_block-> b_dirt = 1;


519 brelse (Dir_block);
// initialization setting mode field of the new node i and node i has been set to the modify flag.

520 inode-> i_mode = I_DIRECTORY | (Mode & 0777 & ~ current-> umask );
521 inode-> i_dirt = 1;
// Add a new directory in a directory entry, if it fails (buffer cache directory entry that contains the pointer is NULL), node i is released // directory; i node the requested

connection reference count is reset, and release the i node. Returns an error code to exit.

522 bh = add_entry (Dir, basename, namelen, & de);


523 if (! bh) {
524 iput (Dir);
525 free_block (Inode-> i_dev, inode-> i_zone [0]);
526 inode-> i_nlinks = 0;
527 iput (Inode);
528 return - ENOSPC ;
529 }
// make i-node field of the directory entry is equal to the new i-node number, set the high-speed buffer has been modified logo, and a new release directory i-node, release // buffer cache, and

returns 0 (success).

530 de-> inode = inode-> i_num;


531 bh-> b_dirt = 1;
532 dir-> i_nlinks ++;
533 dir-> i_dirt = 1;
534 iput (Dir);
535 iput (Inode);
536 brelse (Bh);
537 return 0;
538 }
539 540 /
*
541 * Routine to check that the specified directory is empty (for rmdir)
542 * /
/*
* Used to check the specified directory is empty subroutine (for rmdir system calls).
*/
//// check whether the specified directory is empty.

--383--
9.8 namei.c program

// Parameters: inode - i node pointer in the specified directory. // returns:

1 - is empty; 0 - Do not empty.

543 static int empty_dir (Struct m_inode * Inode)


544 {
545 int nr, block;
546 int len;
547 struct buffer_head * Bh;
548 struct dir_entry * De;
549
// Calculates an existing directory number of a directory entry (should have at least two, i.e., ".", And ".." directory entries two files).

550 len = inode-> i_size / sizeof (struct dir_entry );


// if the number is less than 2 or directory entry in the directory i-node to the first block does not point to any direct disk block number, or the corresponding disk blocks // can not reproduce,

the warning message "on device dev directory wrong" return 0 (failure).

551 if (len <2 ||! inode-> i_zone [0] ||


552 ! (Bh = bread (Inode-> i_dev, inode-> i_zone [0]))) {
553 printk ( ' warning - bad directory on dev% 04x \ n ", inode-> i_dev);
554 return 0;
555 }
// make de point to read the disk containing the data block buffer cache items recorded in the first term.

556 de = (struct dir_entry *) Bh-> b_data;


// If the i-node number field value of a directory entry node number i is not equal to the directory entry or the second directory i-node number field // zero, two or directory entry

field name is not equal to "." and "..", a warning message is displayed error "on the device dev directory wrong" // and returns 0.

557 if i_num || (de [0] .inode! = inode->! de [1] .inode ||


558 strcmp ( ".", De [0] .name) || strcmp ( "..", de [1] .name)) {
559 printk ( ' warning - bad directory on dev% 04x \ n ", inode-> i_dev);
560 return 0;
561 }
// make nr equal to the directory entry number; de directory entries pointing to third.

562 nr = 2;
563 de + = 2;
// loop detects all directory entries (len-2 th) in the directory, i-node to see if the directory entry number field is not 0 (is used).

564 while (nr <len) {


// If the disk blocks in the block directory entry has been completed is detected, then the disk buffer cache block is released, the disk reading a block containing // directory entry. If the

corresponding block is not used (or already do, such as files have been deleted, etc.), then continue to read the next one, if not read, then the // error, return 0. Otherwise, let de directory

entry points to the first read-out block.

565 if ((void *) de> = (void *) (bh-> b_data + BLOCK_SIZE )) {


566 brelse (Bh);
567 block = bmap (Inode, nr / DIR_ENTRIES_PER_BLOCK );
568 if (! block) {
569 nr + = DIR_ENTRIES_PER_BLOCK ;
570 continue;
571 }
572 if (! (bh = bread (Inode-> i_dev, block)))
573 return 0;
574 de = (struct dir_entry *) Bh-> b_data;
575 }
// If the i-node number field of the directory entry is not equal to 0, then the directory is being used before the project, the high-speed buffer is released, returns 0 // exit.

576 if (de-> inode) {


577 brelse (Bh);
578 return 0;
579 }

--384--
9.8 namei.c program

// Otherwise, if the query has not finished all the directory entry in the directory, continue testing.

580 de ++;
581 nr ++;
582 }
// here described is not found in the directory of the directory entry is used (of course, except for the first two), the buffer is released, a return.

583 brelse (Bh);


584 return 1;
585 }
586
//// system calls - delete the directory specified name. // Parameters: name -

the directory name (path name). // Returns: 0 for success, otherwise it

returns an error number.

587 int sys_rmdir (Const char * name)


588 {
589 const char * basename;
590 int namelen;
591 struct m_inode * Dir, * inode;
592 struct buffer_head * Bh;
593 struct dir_entry * De;
594
// If it is not super-user, access permission error code is returned.

595 if (! suser ())


596 return - EPERM ;
// If you can not find the i-node corresponding to the path name of the directory, the error code is returned.

597 if (! (dir = dir_namei (Name, & namelen, & basename)))


598 return - ENOENT ;
// If the topmost file name length is zero, then the final pathname given filename is not specified, the directory i-node is released, return error code // exit.

599 if (! namelen) {
600 iput (Dir);
601 return - ENOENT ;
602 }
// If you do not have permission to write in that directory, the directory i-node is released, returning an error code access permission to exit.

603 if (! permission (Dir, MAY_WRITE )) {


604 iput (Dir);
605 return - EPERM ;
606 }
// If the path name directory entry corresponding to the last file name does not exist, the release of high-speed buffer that contains the directory entry, the release of the i-node directory

// returns an error code file already exists, quit. Otherwise, dir is the directory that contains the name to be deleted directory i-node, de // directory entry is to be deleted directory

structure.

607 bh = find_entry (& Dir, basename, namelen, & de);


608 if (! bh) {
609 iput (Dir);
610 return - ENOENT ;
611 }
// i take the specified node of the directory entry. If the error is released i-node directory, and the release of high-speed buffer containing directory entries, returns // error number.

612 if (! (inode = iget (Dir-> i_dev, de-> inode))) {


613 iput (Dir);
614 brelse (Bh);
615 return - EPERM ;
616 }
// If the directory has limited the effective user id delete flag and the process is not equal to the user id i node, then do not have permission to delete

--385--
9.8 namei.c program

// In addition to the directory, then release the i-node that contains the directory you want to delete the directory name of the directory you want to delete and the i-node, high-speed buffer is

released, return // return an error code.

617 if ((dir-> i_mode & S_ISVTX ) && current -> euid &&
618 inode-> i_uid! = current -> euid) {
619 iput (Dir);
620 iput (Inode);
621 brelse (Bh);
622 return - EPERM ;
623 }
// If the device number i of the node to be deleted is not equal to the directory entry contains the device number of the directory entry of the directory or the directory is deleted // connection

reference count is greater than 1 (expressed symbolic link, etc.), can not be delete the directory, then release contains the name of the directory you want to delete a directory node // i want to

delete the directory and the i-node, high-speed buffer is released, it returns an error code.

624 if (inode-> i_dev! = dir-> i_dev || inode-> i_count> 1) {


625 iput (Dir);
626 iput (Inode);
627 brelse (Bh);
628 return - EPERM ;
629 }
// If the node number to be deleted directory i-node is equal to the directory entry to be deleted directory that contains the node number i, then try to delete. "" // directory. Then release the

i-node contains the directory you want to delete the directory name of the directory you want to delete and the i-node, the release of high-speed buffer // return an error code.

630 if (inode == dir) { / * We may not delete ".", But "../dir" is ok * /


631 iput (Inode); / * We can not be deleted ".", But you can delete "../dir" * /
632 iput (Dir);
633 brelse (Bh);
634 return - EPERM ;
635 }
// property to be deleted directory i-node indicates that this is not a directory, then release the i-node that contains the directory you want to delete a directory name that you want to delete

the directory and // i-node, high-speed buffer is released, returns an error code.

636 if (! S_ISDIR (Inode-> i_mode)) {


637 iput (Inode);
638 iput (Dir);
639 brelse (Bh);
640 return - ENOTDIR ;
641 }
// If this needs to be deleted directory is not empty, then release to remove a directory that contains a directory name and i-node that you want to delete the directory i-node, high-speed

buffer // release, returns an error code.

642 if (! empty_dir (Inode)) {


643 iput (Inode);
644 iput (Dir);
645 brelse (Bh);
646 return - ENOTEMPTY ;
647 }
// If the connection is to delete the directory number of the i-node need not equal 2, a warning message is displayed.

648 if (inode-> i_nlinks! = 2)


649 printk ( ' empty directory has nlink! = 2 (% d) ", inode-> i_nlinks);
// set that needs to be deleted directory entry directory i-node number field is 0, indicating that the directory entry is no longer used, and the directory entry contains a set of high-speed // buffer

has been modified mark and release the buffer.

650 de-> inode = 0;


651 bh-> b_dirt = 1;
652 brelse (Bh);
// set number of connections is deleted directory node i is 0, and set the i-node has been modified flag.

653 inode-> i_nlinks = 0;

--386--
9.8 namei.c program

654 inode-> i_dirt = 1;


// delete the directory will contain a directory name of the referenced node i count by 1, which changes the modification time and modification time to the current time, and the node is set //

modify flag.

655 dir-> i_nlinks--;


656 dir-> i_ctime = dir-> i_mtime = CURRENT_TIME ;
657 dir-> i_dirt = 1;
// delete directory contains the final release of the i-node directory name and the directory you want to delete the i-node, returns 0 (success).

658 iput (Dir);


659 iput (Inode);
660 return 0;
661 }
662
//// system calls - delete the file name and may also remove its associated files.
// delete a name from the file system. If a file is the last connection, and the process is not open the file, the file // will be deleted, and release the space
occupied by the device. // Parameters: name - file name.

// Returns: 0 for success, otherwise it returns an error number.

663 int sys_unlink (Const char * name)


664 {
665 const char * basename;
666 int namelen;
667 struct m_inode * Dir, * inode;
668 struct buffer_head * Bh;
669 struct dir_entry * De;
670
// If you can not find the i-node corresponding to the path name of the directory, the error code is returned.

671 if (! (dir = dir_namei (Name, & namelen, & basename)))


672 return - ENOENT ;
// If the topmost file name length is zero, then the final pathname given filename is not specified, the directory i-node is released, return error code // exit.

673 if (! namelen) {
674 iput (Dir);
675 return - ENOENT ;
676 }
// If you do not have permission to write in that directory, the directory i-node is released, returning an error code access permission to exit.

677 if (! permission (Dir, MAY_WRITE )) {


678 iput (Dir);
679 return - EPERM ;
680 }
// If the path name directory entry corresponding to the last file name does not exist, the release of high-speed buffer that contains the directory entry, the release of the i-node directory

// returns an error code file already exists, quit. Otherwise, dir is the directory that contains the name to be deleted directory i-node, de // directory entry is to be deleted directory

structure.

681 bh = find_entry (& Dir, basename, namelen, & de);


682 if (! bh) {
683 iput (Dir);
684 return - ENOENT ;
685 }
// i take the specified node of the directory entry. If the error is released i-node directory, and the release of high-speed buffer containing directory entries, returns // error number.

686 if (! (inode = iget (Dir-> i_dev, de-> inode))) {


687 iput (Dir);
688 brelse (Bh);
689 return - ENOENT ;

--387--
9.8 namei.c program

690 }
// If the directory has restricted deletion flag and the user is not the superuser and the effective user id of the process is not equal to the deleted file // user id of the i-node, and the effective user

id of the process does not mean i node directory user id, you do not have permission to delete the file // name. Then release the i-node directory and the file name of the i-node directory entry,

the release of the buffer that contains the directory entries, returns an error number.

691 if ((dir-> i_mode & S_ISVTX ) &&! suser () &&


692 current -> euid = inode-> i_uid &&!
693 current -> euid = dir-> i_uid) {!
694 iput (Dir);
695 iput (Inode);
696 brelse (Bh);
697 return - EPERM ;
698 }
// If the specified file is a directory, you can not delete, release the i-node directory and the file name of the i-node directory entry, release // buffer that contains the directory entries,

returns an error number.

699 if ( S_ISDIR (Inode-> i_mode)) {


700 iput (Inode);
701 iput (Dir);
702 brelse (Bh);
703 return - EPERM ;
704 }
// If the i-node number of connections is already zero, a warning message is displayed, as a correction.

705 if (! inode-> i_nlinks) {


706 printk ( ' Deleting nonexistent file (% 04x:% d),% d \ n ",
707 inode-> i_dev, inode-> i_num, inode-> i_nlinks);
708 inode-> i_nlinks = 1;
709 }
// filename directory entry in the i-node number field is set to 0, indicating that the release of the directory entry, and to set the buffer containing the directory entry modified flag //

releasing the buffer cache.

710 de-> inode = 0;


711 bh-> b_dirt = 1;
712 brelse (Bh);
// the number of connections of the node i is decremented by 1, modified flag set, updating change time to the current time. The final release of directory and i-node point i // Festival, returns 0

(success).

713 inode-> i_nlinks--;


714 inode-> i_dirt = 1;
715 inode-> i_ctime = CURRENT_TIME ;
716 iput (Inode);
717 iput (Dir);
718 return 0;
719 }
720
//// system call function - to create a file name for the file.
// Create a new connection to an existing file (also known as hard-wired - hard link). // Parameters: oldname - original

path name; newname - new path name. // Returns: Returns 0 if successful, otherwise it returns an error number.

721 int sys_link (Const char * oldname, const char * newname)


722 {
723 struct dir_entry * De;
724 struct m_inode * Oldinode, * dir;
725 struct buffer_head * Bh;
726 const char * basename;
727 int namelen;
728

--388--
9.8 namei.c program

// i take oldinode node corresponding to the original file path name. If 0, then the error, returns an error number.

729 oldinode = namei (Oldname);


730 if (! oldinode)
731 return - ENOENT ;
// If the original path is a directory name corresponding to the name, the i-node is released, returns an error number.

732 if ( S_ISDIR (Oldinode-> i_mode)) {


733 iput (Oldinode);
734 return - EPERM ;
735 }
// Find the most top-level directory node i new path name, and returns the last name of the file and its length. i-node if the directory is not found, then release the i-node // original path

name, returns an error number.

736 dir = dir_namei (Newname, & namelen, & basename);


737 if (! dir) {
738 iput (Oldinode);
739 return - EACCES ;
740 }
// If the file name does not include the new path name, the path name of the original release of the i-node i node and the new path name of the directory, returns an error number.

741 if (! namelen) {
742 iput (Oldinode);
743 iput (Dir);
744 return - EPERM ;
745 }
// If the number of the new device pathname of the directory path name and device number is not the same as the original, you can not establish a connection, then release the i-node i

node name of the new path // directory path and original name, returns an error number.

746 if (dir-> i_dev! = oldinode-> i_dev) {


747 iput (Dir);
748 iput (Oldinode);
749 return - EXDEV ;
750 }
// If the user does not have write permissions in the new directory, you can not establish a connection, then release the i-node i node of the new pathname of the directory path and original

name // returns the error number.

751 if (! permission (Dir, MAY_WRITE )) {


752 iput (Dir);
753 iput (Oldinode);
754 return - EACCES ;
755 }
// check whether the new path name already exists, if there is, it can not establish a connection, then release that contains the directory entry // existing high-speed buffer, the release of the

new i-node path name of the directory path name and the original i-node , returns an error number.

756 bh = find_entry (& Dir, basename, namelen, & de);


757 if (bh) {
758 brelse (Bh);
759 iput (Dir);
760 iput (Oldinode);
761 return - EEXIST ;
762 }
// add a new directory entry in the directory. If it fails to release the i-node of the directory path and original name of the i-node, it returns an error number.

763 bh = add_entry (Dir, basename, namelen, & de);


764 if (! bh) {
765 iput (Dir);
766 iput (Oldinode);
767 return - ENOSPC ;
768 }
Otherwise, set i // initial node number of the directory entry is equal to the original path name i-node number, and added a new set comprising the buffer cache directory entry

--389--
9.9 file_table.c program

// modified logo, release the buffer, the release of the i-node directory.

769 de-> inode = oldinode-> i_num;


770 bh-> b_dirt = 1;
771 brelse (Bh);
772 iput (Dir);
// original node count by one application to modify its change time to the current time, and i-node set have been modified flags, and finally releasing the original node i // path name,

and returns 0 (success).

773 oldinode-> i_nlinks ++;


774 oldinode-> i_ctime = CURRENT_TIME ;
775 oldinode-> i_dirt = 1;
776 iput (Oldinode);
777 return 0;
778 }
779

9.9 file_table.c program

9.9.1 Functional Description

The program currently is empty, only defines the file table array.

9.9.2 Code comments

program 9-7 linux / fs / file_table.c

1/*
2 * Linux / fs / file_table.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <linux / fs.h>
// file system header files. Table structure definition file (file, buffer_head, m_inode, etc.).
89 struct file file_table [ NR_FILE ]; // file table array (64).

10

9.10 block_dev.c program

From here 4 Programs: block_dev.c , char_dev.c , pipe.c with file_dev.c Are for subsequent proceedings read_write.c

Services. read_write.c Program achieved a major system calls write () with read () . This 4 Programs can be seen as a system call and block devices, character devices, pipes "device"

and file system "device " The interface driver. The relationship between them can be used in FIG. 9-19 Representation. System calls write () or read () Based on the provided parameter

file descriptor attributes, it is determined what type of file, and then calls the appropriate interface program read / write function, respectively, which will then execute the

corresponding function drivers.

--390--
9.10 block_dev.c program

write () System calls read () read_write.c

Access to formal documents


file_write (), file_read ()

File access pipeline pipe_read


file_dev.c
(), pipe_write () block device to access

files block_write (), block_read ()


pipe.c

Access character device file rw_char


(). The main equipment operable tty_write (), block_dev.c
tty_read () and
rw_memory () function and the like. char_dev.c

Map 9-19 Interface functions with all types of file systems and file system calls

9.10.1 Functional Description

block_dev.c Program file device belonging to the block type of program data access operations. The file includes block_read () with block_write () Two block devices read

and write functions. These two functions are for system calls read () with write () It calls, where there is no other references.

Since the block is read with each disk device tray units of blocks (in the same buffer buffer block length), so the function block_write ()

First, the parameter file pointer pos Location mapping into data blocks and block offset value, and then use the function block reads bread () Or pre-reading function block breada () The

file pointer location data block read into a buffer block buffer, and then need to write the data according to the block length chars Copy the user data in the data from the buffer to

the beginning of the current buffer offset location in the block. If there is need to write data, then the next block is read into the buffer in the buffer block, and copy the user data to

the buffer block, the write data in the second time and thereafter, the offset offset Are 0 . Referring to FIG. 9-20 Fig.

N-th block N + 1 th block Block of the n + 2

offset pos chars chars1 chars2

count

Map 9-20 Read and write data block schematic diagram of a hand position

User buffer is assigned by the system user program at the start of execution, or dynamically during execution of the application. Linear virtual address of the user by the

buffer, before calling this function, the system will map the virtual address to a linear memory area corresponding main memory page.

function block_read () Mode of operation and block_write () The same, just copy the data from the buffer to the place specified by the user.

--391--
9.10 block_dev.c program

9.10.2 Code comments

program 9-8 linux / fs / block_dev.c

1/*
2 * Linux / fs / block_dev.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <errno.h>
// error number header files. The system comprises various error number. (Linus imported from the minix).

89 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

10 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

11 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

12 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

13
//// block write function - byte data specified length is written from a given offset to the specified device. // parameters: dev - device number; pos - the

device file offset pointer; buf - the user address space buffer address; //

count - the number of bytes to be transferred.

// For the kernel, a write operation is to write data to a high-speed buffer, when data is written to the device is ultimately determined by the cache management program // and processed.

Further, because the device is read in units of blocks, so that writing starting position for the data block is not in the start // at the start of the block requires the entire first byte read is located,

and the need to write from the write fill that the beginning of the block, then the entire block of data // complete write disk (i.e., referred to cache a program processing).

14 int block_write (Int dev, long * pos , Char * buf , Int count )
15 {
// pos converted from block start address to a block number of the block read. And determine the need to read the first byte offset position offset in the block.

16 int block = * pos >> BLOCK_SIZE_BITS ;


17 int offset = * pos & ( BLOCK_SIZE -1);
18 int chars;
19 int written = 0;
20 struct buffer_head * Bh;
twenty one register char * p;
twenty two

// count for the number of bytes to be written, do the following cycle until all write.
twenty three while ( count > 0) {
The number of bytes in the block can be written // calculated. If the number of bytes to be written less than a fill, you can simply write count bytes.

twenty four chars = BLOCK_SIZE - offset;


25 if (chars> count )
26 chars = count ;
// If exactly one write data directly apply a cache block, or need to be modified to read the data block, and // the two pre-read data, then the block number is

incremented by one.

27 if (chars == BLOCK_SIZE )
28 bh = getblk (Dev, block);
29 else
30 bh = breada (Dev, block, block + 1, block + 2, -1);
31 block ++;
// If buffer block operation fails, it returns the number of bytes have been written, if not write any byte error number (negative number) is returned.

32 if (! bh)
33 return written written:? - EIO ;
// p points to read data block start writing position. If the last written data is less than one, the block starts from the need to fill in (modified) // bytes required, so there

needs to set to zero offset.

--392--
9.10 block_dev.c program

34 p = offset + bh-> b_data;


35 offset = 0;
// The file pointer advances have been offset number of bytes written. Has accumulated write bytes chars. Transferring the count value by subtracting the number of bytes have been transferred.

36 * pos + = Chars;
37 written + = chars;
38 count - = chars;
// Copy chars bytes from the buffer to the user buffer area pointed to by p start writing.
39 while (chars -> 0)
40 * (P ++) = get_fs_byte ( buf ++);
// set the flag buffer block has been modified, and releases the buffer (i.e. the buffer reference count is decremented by 1).

41 bh-> b_dirt = 1;
42 brelse (Bh);
43 }
44 return written; // returns the number of bytes that have been written, the normal exit.

45 }
46
//// data block read function - device read from the specified location and the specified number of bytes into the cache.

47 int block_read (Int dev, unsigned long * pos , Char * buf , Int count )
48 {
// pos converted from block start address to a block number of the block read. And determine the need to read the first byte offset position offset in the block.

49 int block = * pos >> BLOCK_SIZE_BITS ;


50 int offset = * pos & ( BLOCK_SIZE -1);
51 int chars;
52 int read = 0;
53 struct buffer_head * Bh;
54 register char * p;
55
// for the number of bytes to be read into the count, the following cycle until all read.
56 while ( count > 0) {
The number of bytes in the block needs to read // calculations. If the number of bytes to read dissatisfied one, just read count bytes.

57 chars = BLOCK_SIZE -offset;


58 if (chars> count )
59 chars = count ;
// read the required data block, and the two pre-read data if read error, it returns the number of bytes read, without any // read byte, an error number is returned. The block

number is then incremented by one.

60 if (! (bh = breada (Dev, block, block + 1, block + 2, -1)))


61 return read ? read : - EIO ;
62 block ++;
// start position p at the device needs to be read from the read block. If the data to be read is less than the last one, // need to start reading from block bytes required,

so there need to be offset to zero.

63 p = offset + bh-> b_data;


64 offset = 0;
// file offset pointer advances to the read bytes chars. Accumulating the number of bytes read. Transferring the count value by subtracting the number of bytes have been transferred.

65 * pos + = Chars;
66 read + = Chars;
67 count - = chars;
// start position is copied from buffer area pointed to by p chars bytes of data to the user buffer, and releases the buffer cache.

68 while (chars -> 0)


69 put_fs_byte (* (P ++), buf ++);
70 brelse (Bh);
71 }
72 return read ; // returns the number of bytes read, normal exit.

73 }

--393--
9.11 file_dev.c program

74

9.11 file_dev.c program

9.11.1 Functional Description

The file includes file_read () with file_write () Two functions. Also calls for the system to function read () with write () It calls, where there is no other references. And on a file block_dev.c

Similarly, the file is used to access the file data. But the function of this program is carried out by specifying the file pathname manner. Function parameters is given in the

document i Node and file structure information, by i Node information corresponding to the acquired device numbers from file Structure, we can get read and write files in the

current cursor position. And the function on a file is directly read and write the parameters specified in the device number and location of the file, a block device is designed for file

operations, e.g.

/ Dev / fd0 Device files.

9.11.2 Code comments

program 9-9 linux / fs / file_dev.c

1/*
2 * Linux / fs / file_dev.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <errno.h>
// error number header files. The system comprises various error number. (Linus from the introduction of minix)

8 #include <fcntl.h> // control file header. Operable control descriptor file and constants defined symbols.
910 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

11 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

12 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

1314 #define MIN (A, b) (((a) <(b))? (A) :( b))


// get a, b is the minimum value.

15 #define MAX (A, b) (((a)> (b))? (A) :( b)) // get a, b is the maximum value.

16
//// file read function - The i-node and file structure, the data reading device.

// node may know that the device number i, a filp file structure may know the current position of the read and write pointers. buf // specified position in the user-mode buffer, count the

number of bytes to be read. The return value is the number of bytes, or an error number (less than 0) actually read.

17 int file_read (Struct m_inode * Inode, struct file * Filp, char * buf , Int count )
18 {
19 int left, chars, nr;
20 struct buffer_head * Bh;
twenty one

// If the byte count to be read is less than zero, then returns.


twenty two if ((left = count ) <= 0)
twenty three return 0;
// If the number of bytes to read is also not equal to 0, the following cycle until all read.
twenty four while (left) {
// The i-node table and file structure information, fetch the current data block read and write files on the device at a position corresponding to the logical block number nr. Nr 0 // If not, node i

from the specified device to read the logical block, the read operation fails if the loop is exited. If nr is 0, indicating specified

--394--
9.11 file_dev.c program

// data block does not exist, block buffer pointer is set to NULL.

25 if (nr = bmap (Inode, (filp-> f_pos) / BLOCK_SIZE )) {


26 if (! (bh = bread (Inode-> i_dev, nr)))
27 break;
28 } Else
29 bh = NULL ;
// file read and write pointer offset value calculated in the data block is nr, the number of bytes read block (BLOCK_SIZE-nr), and then left to compare the number of bytes needed

// read, wherein the smaller value is the number of bytes required to read chars. If (BLOCK_SIZE-nr) // This large then the data block is the last one to be read, otherwise needed

to read a block of data.

30 nr = filp-> f_pos% BLOCK_SIZE ;


31 chars = MIN ( BLOCK_SIZE -nr, left);
// pointer to adjust the read and write files. The number of bytes chars advancing the read pointer. Subtracting the corresponding byte count remaining chars.

32 filp-> f_pos + = chars;


33 left - = chars;
// If the data read from the device, the pointing position will be p read block buffer to start reading, and copying bytes chars // buffer buf to the user.
Otherwise the user to fill the buffer chars zero-valued bytes.
34 if (bh) {
35 char * p = nr + bh-> b_data;
36 while (chars -> 0)
37 put_fs_byte (* (P ++), buf ++);
38 brelse (Bh);
39 } Else {
40 while (chars -> 0)
41 put_fs_byte (0, buf ++);
42 }
43 }
// modify the access time of the i-node for the current time. Returns the number of bytes read, when the number of bytes read is 0, the error number is returned.

44 inode-> i_atime = CURRENT_TIME ;


45 return ( count -left)? ( count -left): - ERROR ;
46 }
47
//// file write function - The i-node information and file structure, the user data into the specified device. // node may know that the device number i, a filp file structure may know the

current position of the read and write pointers. buf // specified position in the user-mode buffer, count the number of bytes to be written. The return value is the number of bytes, or an

error number (less than 0) actually written.

48 int file_write (Struct m_inode * Inode, struct file * Filp, char * buf , Int count )
49 {
50 off_t pos ;
51 int block, c;
52 struct buffer_head * Bh;
53 char * p;
54 int i = 0;
5556 / *

57 * Ok, append may not work when many processes are writing at the same time
58 * But so what. That way leads to madness anyway.
59 * /
/*
* ok, when many processes simultaneously write, append operation may not work, but so what. Either way will do so
* Resulting in a mass of confusion.

*/
// If you are adding data, the file is read and write pointers To move a file after the tail. Otherwise it will be written in the file read and write pointer.

60 if (filp-> f_flags & O_APPEND )


61 pos = Inode-> i_size;

--395--
9.11 file_dev.c program

62 else
63 pos = Filp-> f_pos;
Ruoyi i // number of bytes written to be written is smaller than the number of bytes for the count, the following cycle.

64 while (i < count ) {


// Create a data block number (pos / BLOCK_SIZE) corresponding to logical blocks on the device, and returns the logical block number on the device. // If the logical block number = 0,

the creation fails, exit the loop.

65 if (! (block = create_block (Inode, pos / BLOCK_SIZE )))


66 break;
@ The corresponding data blocks in the logical block number reading apparatus, if the error loop is exited.

67 if (! (bh = bread (Inode-> i_dev, block)))


68 break;
// offset value determined file read and write pointers in the data block c, p at the start position of the read block buffer read. // set the buffer has been modified flag.

69 c = pos % BLOCK_SIZE ;
70 p = c + bh-> b_data;
71 bh-> b_dirt = 1;
// read from the start position to the end of the block co-writable c = (BLOCK_SIZE-c) bytes. If c is larger than the number of bytes // (count-i) needs to write the

remaining, the re-writing only the c = (count-i) to.

72 c = BLOCK_SIZE -c;
73 if (c> count -i) c = count -i;
// number of bytes in the file read and write pointer advances to be written. If the current file pointer position value read exceeds the size of the file, then the node i // modify the

file size field and i-node set have been modified flag.

74 pos + = C;
75 if ( pos > Inode-> i_size) {
76 inode-> i_size = pos ;
77 inode-> i_dirt = 1;
78 }
// number of bytes written byte count c accumulated in the writing. C copy bytes to a location in the buffer cache p // points to the start of the user from the buffer

buf. Then release the buffer.

79 i + = c;
80 while (c -> 0)
81 * (P ++) = get_fs_byte ( buf ++);
82 brelse (Bh);
83 }
// Change the file modification time to the current time.

84 inode-> i_mtime = CURRENT_TIME ;


// If this operation is not added to the end of the file data, file read and write pointers adjusted to put the current write position, and change the node i // modify time to the current time.

85 if (! (filp-> f_flags & O_APPEND )) {


86 filp-> f_pos = pos ;
87 inode-> i_ctime = CURRENT_TIME ;
88 }
// returns the number of bytes written, if the number of bytes written is 0, the error number of -1 is returned.

89 return (i i:? -1);


90 }
91

--396--
9.12 pipe.c program

9.12 pipe.c program

9.12.1 Functional Description

Pipeline operation is the most basic way of inter-process communication. This program includes a function of reading and writing files conduit read_pipe () with write_pipe () ,

While achieving a piping system calls sys_pipe () . These two functions are also system calls read () with write () The realization of low-level function, it is only in

read_write.c Use.
At initialization pipes, pipe i Node i_size Field is set to point to the pipeline buffer pointer, the head pointer stored in the data pipeline i_zone [0] Field, and the tail pointer

stored in the data pipeline i_zone [1] Field. For read operations the pipeline, the data is read out from the tail pipe, and the pipe advances the tail pointer bytes are read a plurality

of positions; for the write operation to the pipeline, the data is written to the head pipe, the head pipe and write byte pointer forward several positions. See illustration below conduit 9-21

Fig.

Pipeline buffer length (PAGE_SIZE)

Data pipe length (PIPE_SIZE)


Buffer Pointer
(The i_size)
Tail pointer tail Head pointer head
(i_zone [1]) (i_zone [0])

Map 9-21 Pipeline buffer schematic operation

read_pipe () For data read pipeline. If there is no data in the pipeline, the pipeline will wake up the process of writing, while he goes to sleep. If the read data, the head

pointer correspondingly adjusting pipe, and transmit the data to the user buffer. When all the data in the pipe are removed, they must wake up waiting for a write pipeline process,

and returns the number of data bytes read. When the writing process has exited the pipeline pipeline operations, functions immediately withdraw and return the number of bytes

read.

write_pipe () The read operation of the function and the function is similar to the pipe. System calls sys_pipe () For creating unnamed pipe. It first acquires the file system

table two entries, then also find two descriptor table entry in the file descriptor table is not used in the current process, to save the corresponding file structure pointer. Then

apply a system idle i Node, while obtaining a pipe used buffer block. Then the corresponding file structure is initialized, the file structure is set to a read-only mode, the other

set to a write-only mode. Finally, the two file descriptors to the user.

9.12.2 Code comments

program 9-10 linux / fs / pipe.c

1/*
2 * Linux / fs / pipe.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <signal.h>
// signal header files. Defined symbolic constant signal, the signal structure and the operation function prototype signal.

--397--
9.12 pipe.c program

89 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

10 #include <linux / mm.h> / * For get_free_page * / / * use them get_free_page * /


// memory management header files. It contains the defined page size and page number of the release function prototypes.

11 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

12
//// conduit read function.
// parameters are inode corresponding to the i-node conduit, buf is the buffer pointer data, count the number of bytes read.

13 int read_pipe (Struct m_inode * Inode, char * buf , Int count )


14 {
15 int chars, size, read = 0;
16
Byte count is greater than the read count // Ruoyu 0, the loop performs the following operations.

17 while ( count > 0) {


// If there is no current pipeline data (size = 0), the process waits for the node is awakened, if those who did not write the pipeline, it returns the number of bytes read // exit.

Otherwise, in the i-node sleep, waiting for information.

18 while (! (size = PIPE_SIZE (* Inode))) {


19 wake_up (& Inode-> i_wait);
20 if (inode-> i_count! = 2) / * are there any writers? * /
twenty one return read ;
twenty two sleep_on (& Inode-> i_wait);
twenty three }
// get the tail pipe end of the bytes into the buffer chars. If the count is greater than the number of bytes to be read further, so that it is equal to the count. // If chars than the length of the

current size of data contained in the pipe, so that it is equal to the size.

twenty four chars = PAGE_SIZE - PIPE_TAIL (* Inode);


25 if (chars> count )
26 chars = count ;
27 if (chars> size)
28 chars = size;
// read byte count by subtracting the number of bytes read chars, and accumulating the number of bytes read.

29 count - = chars;
30 read + = Chars;
// size so point to the tail pipe, the pipe to adjust the current tail pointer (forward chars bytes).

31 size = PIPE_TAIL (* Inode);


32 PIPE_TAIL (* Inode) + = chars;
33 PIPE_TAIL (* Inode) & = ( PAGE_SIZE -1);
// copy the data to the user in the pipeline buffer. For node i pipe, which pipe is i_size field block pointer buffer.
34 while (chars -> 0)
35 put_fs_byte (((Char *) inode-> i_size) [size ++], buf ++);
36 }
// wait for the wake-up process piping i node, and returns the number of bytes read.

37 wake_up (& Inode-> i_wait);


38 return read ;
39 }
40
//// pipe write operations function.

// parameters are inode corresponding to the i-node conduit, buf is the buffer pointer data, count is the number of bytes written to the pipe.

41 int write_pipe (Struct m_inode * Inode, char * buf , Int count )


42 {
43 int chars, size, written = 0;
44
If the count value of the byte count // written also greater than 0, the following cycle.

--398--
9.12 pipe.c program

45 while ( count > 0) {


// If the current pipeline is not already full (size = 0), then wait for the process node wakes up, if you have not read those pipes, the // send SIGPIPE signal to the process, and returns the

number of bytes that have been written and drop out. When the address byte 0, -1 is returned. // otherwise sleep on the i-node, waiting for the pipeline to make room.

46 while (! (size = ( PAGE_SIZE -1)- PIPE_SIZE (* Inode))) {


47 wake_up (& Inode-> i_wait);
48 if (inode-> i_count! = 2) {/ * no readers * /
49 current -> signal | = (1 << ( SIGPIPE -1));
50 ? Return written written: -1;
51 }
52 sleep_on (& Inode-> i_wait);
53 }
// get the pipe to the head end of the buffer space bytes chars. If it is larger than the count of bytes still to be written, so that it is equal to the // count. If chars conduit is greater

than the current free space in the length size, so that it is equal to the size.

54 chars = PAGE_SIZE - PIPE_HEAD (* Inode);


55 if (chars> count )
56 chars = count ;
57 if (chars> size)
58 chars = size;
// write byte count minus the number of bytes that can be written chars, and has accumulated the number of bytes to write written.

59 count - = chars;
60 written + = chars;
// size so point data of the head pipe, the head pipe data pointer adjustment current (forward chars bytes).

61 size = PIPE_HEAD (* Inode);


62 PIPE_HEAD (* Inode) + = chars;
63 PIPE_HEAD (* Inode) & = ( PAGE_SIZE -1);
// Copy chars bytes from the buffer to a user pipeline. For node i pipe which is a pipe i_size field block pointer buffer.
64 while (chars -> 0)
65 ((Char *) inode-> i_size) [size ++] = get_fs_byte ( buf ++);
66 }
// wake-up process to wait for the i node, return the number of bytes written to the exit.

67 wake_up (& Inode-> i_wait);


68 return written;
69 }
70
//// create a pipe system calls.
// creates a handle to the file (Descriptor) in the array referred to in fildes. This points to a file handle pipe i node. fildes [0] // for reading the data
pipeline, fildes [1] for writing data to the pipeline. Return 0 // success, -1 on error.

71 int sys_pipe (Unsigned long * fildes)


72 {
73 struct m_inode * Inode;
74 struct file * F [2];
75 int fd [2];
76 int i, j;
77
// taken from the system file table two free entry (item reference count field is zero), and are set to a reference count.

78 j = 0;
79 for (i = 0; j <2 && i < NR_FILE ; I ++)
80 if (! file_table [I] .f_count)
81 (F [j ++] = i + file_table ) -> f_count ++;
// If there is only one free item, then release the (reference count is reset).

82 if (j == 1)

--399--
9.13 char_dev.c program

83 f [0] -> f_count = 0;


// If the two free entry is not found, it returns -1.
84 if (j <2)
85 return -1;
// for two entries made in the above file structure, each assigned a file handle, process and file structure pointer pointing to the two // file structure.

86 j = 0;
87 for (i = 0; j <2 && i < NR_OPEN ; I ++)
88 if (! current -> filp [i]) {
89 current -> filp [fd [j] = i] = f [j];
90 j ++;
91 }
// If there is only one free file handle, the handle is released.
92 if (j == 1)
93 current -> filp [fd [0]] = NULL ;
// If the handle is not find two free, releasing two file structures above item acquired (reference count is reset), and returns -1.
94 if (j <2) {
95 f [0] -> f_count = f [1] -> f_count = 0;
96 return -1;
97 }
// Application conduit node i, and allocates a buffer (a memory) for the pipeline. If unsuccessful, the file handle corresponding release two piece structure and file // item, and returns

-1.

98 if (! (inode = get_pipe_inode ())) {


99 current -> filp [fd [0]] =
100 current -> filp [fd [1]] = NULL ;
101 f [0] -> f_count = f [1] -> f_count = 0;
102 return -1;
103 }
// Initialize two file structures, i refer to the same node, read and write pointers are set to zero. The first mode is a file structure of the file is set to read, // The first two file mode is set to

write the file structure.

104 f [0] -> f_inode = f [1] -> f_inode = inode;


105 f [0] -> f_pos = f [1] -> f_pos = 0;
106 f [0] -> f_mode = 1; / * Read * /
107 f [1] -> f_mode = 2; / * Write * /
// Copy the file handle array array corresponding to the user and returns 0 exit.
108 put_fs_long (Fd [0], 0 + fildes);
109 put_fs_long (Fd [1], 1 + fildes);
110 return 0;
111 }
112

9.13 char_dev.c program

9.13.1 Functional Description

char_dev.c File includes character device file access functions. There are rw_ttyx () , rw_tty () , rw_memory () with rw_char () . There is also a read-write device function pointer

table. Item numbers in the table represent the major number.

rw_ttyx () Serial read and write functions is a terminal device, which is a major number 4 . By calling tty The driver implements the serial read and write operations of the

terminal.

--400--
9.13 char_dev.c program

rw_tty () Console terminal is read and write functions, major number 5 . The principle and rw_ttyx () The same, but the process can console for operating restrictions.

rw_memory () File is a memory device read and write functions, major number 1 . Achieved byte operations for image memory. but linux 0.11

Version of the kernel minor number 0 , 1 , 2 The operation has not been achieved. until 0.96 Version began to implement minor number 1 with 2 Read and write operations.

rw_char () It is a character read-write device interface function operation. Other characters device operating device characters corresponding character reader apparatus by

the function pointer table function. Operating functions of the file system open () , read () So it was operated by all its character device file.

9.13.2 Code comments

program 9-11 linux / fs / char_dev.c

1/*
2 * Linux / fs / char_dev.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <errno.h>
// error number header files. The system comprises various error number. (Linus imported from the minix).

8 #include <sys / types.h> // type of header files. System defines the basic data types.

910 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

11 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

1213 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

14 #include <asm / io.h> // io header files. Defined hardware port I / O macro assembler statements.

1516 extern int tty_read (Unsigned minor, char * buf , Int count );
// read terminal.
17 extern int tty_write (Unsigned minor, char * buf , Int count ); // write terminal.
18
// Define the function pointer type character reader apparatus.

19 typedef (* crw_ptr ) (Int rw, unsigned minor, char * buf , Int count , off_t * pos );
20
//// serial terminal to read and write functions.

// Parameters: rw - read and write commands; minor - the terminal sub-device number; buf - buffer; cout - the number of bytes read; //

pos - the current pointer read and write operations, for operating the terminal, the pointer is useless. //

Returns: the number of bytes actually read.

twenty one static int rw_ttyx (Int rw, unsigned minor, char * buf , Int count , off_t * pos )
twenty two {

twenty three return ((rw == READ )? tty_read (Minor, buf , count ):


twenty four tty_write (Minor, buf , count ));
25 }
26
//// terminal functions read and write operations.

// Ibid rw_ttyx (), only increased detect whether there is control terminal of the process.

27 static int rw_tty (Int rw, unsigned minor, char * buf , Int count , off_t * pos )
28 {
// If the process does not correspond to the control terminal, an error number is returned.

29 if ( current -> tty <0)


30 return - EPERM ;
// Otherwise, the function calls to read and write terminal rw_ttyx (), and returns the actual number of bytes read.

--401--
9.13 char_dev.c program

31 return rw_ttyx (Rw, current -> tty, buf , count , pos );


32 }
33
//// memory read and write data. Unrealized.

34 static int rw_ram (Int rw, char * buf , Int count , off_t * pos )
35 {
36 return - EIO ;
37 }
38
//// memory data read and write functions. Unrealized.

39 static int rw_mem (Int rw, char * buf , Int count , off_t * pos )
40 {
41 return - EIO ;
42 }
43
//// kernel data area read and write functions. Unrealized.

44 static int rw_kmem (Int rw, char * buf , Int count , off_t * pos )
45 {
46 return - EIO ;
47 }
48
// function port read and write operations.

// Parameters: rw - read and write commands; buf - buffer; cout - the number of bytes read; pos - port address. // Returns: the number of bytes

actually read.

49 static int rw_port (Int rw, char * buf , Int count , off_t * pos )
50 {
51 int i = * pos ;
52
// number of bytes read for the request address and the port is less than 64K, the loop is executed a single byte write operations.

53 while ( count -> 0 && i <65536) {


// If the read command, read from the port i is a byte and put it in the user's buffer.
54 if (rw == READ )
55 put_fs_byte ( inb (I), buf ++);
// If the write command from the user to take a byte of data in the buffer to the output port i.

56 else
57 outb ( get_fs_byte ( buf ++), i);
// forward a port. [??]
58 i ++;
59 }
// calculate the number of bytes read / write, and read and write pointers corresponding adjustment.

60 i - = * pos ;
61 * pos + = I;
// returns the number of bytes read / written.

62 return i;
63 }
64
//// memory read and write functions.

65 static int rw_memory (Int rw, unsigned minor, char * buf , Int count , off_t * pos )
66 {
// The sub-device number of memory devices, each memory read and write calls different functions.

67 switch (minor) {
68 case 0:
69 return rw_ram (Rw, buf , count , pos );

--402--
9.14 read_write.c program

70 case 1:
71 return rw_mem (Rw, buf , count , pos );
72 case 2:
73 return rw_kmem (Rw, buf , count , pos );
74 case 3:
75 return (rw == READ ?) 0: count ; / * Rw_null * /
76 case 4:
77 return rw_port (Rw, buf , count , pos );
78 default:
79 return - EIO ;
80 }
81 }
82
// define several types of equipment systems.

83 #define NRDEVS ((Sizeof ( crw_table )) / (Sizeof ( crw_ptr )))


84
// function pointer table character reader apparatus.

85 static crw_ptr crw_table [] = {


86 NULL , / * Nodev * / / * No device (null device) * /
87 rw_memory , / * / Dev / mem etc * / / * / Dev / mem, etc. * /
88 NULL , / * / Dev / fd * / / * / Dev / fd Floppy * /
89 NULL , / * / Dev / hd * / / * / Dev / hd hard disk * /
90 rw_ttyx , / * / Dev / ttyx * / / * / Dev / ttyx serial terminal * /
91 rw_tty , / * / Dev / tty * / / * / Dev / tty terminal * /
92 NULL , / * / Dev / lp * / / * / Dev / lp * Printers /
93 NULL }; / * Unnamed pipes * / / * Not Named Pipes * /

94
//// character device read and write functions.

// Parameters: rw - read and write commands; dev - device number; buf - buffer; count - the number of bytes read; pos - read and write pointers. // Return: The actual read /

write bytes.

95 int rw_char (Int rw, int dev, char * buf , Int count , off_t * pos )
96 {
97 crw_ptr call_addr;
98
// If the device number exceeds the number of system device, an error code is returned.

99 if ( MAJOR (Dev)> = NRDEVS )


100 return - ENODEV ;
// If the device is not corresponding to the read / write function, an error code is returned.

101 if (! (call_addr = crw_table [ MAJOR (Dev)]))


102 return - ENODEV ;
// call the function corresponding to the apparatus read and write operations, and returns the actual number of bytes read / written.

103 return call_addr (rw, MINOR (Dev), buf , count , pos );


104 }
105

9.14 read_write.c program

9.14.1 Functional Description

This file implements the file operating system call read () , write () with lseek () . read () with write () According to the different file types,

--403--
9.14 read_write.c program

Respectively call the front 4 Corresponding file read and write functions implemented. Therefore, this document is in front of 4 Files in function of the upper interface. lseek ()

For setting the file read and write pointers.

read () System call first to determine the effectiveness of the parameters, then according to the file i Determining the type of node information file. If the caller pipe file pipe.c

The read function; if the character device file, the call char_dev.c middle rw_char () Character read function; if the file is a block device, is executed block_dev.c Program block

reading the device, and returns the number of bytes read; if it is a directory file or a regular file in general, is called file_dev.c The document read function file_read () . write () Implementation

and system calls read () similar.

lseek () The system will call configuration file handle corresponding to the file in the current read and write pointers to be modified. For the read and write pointers can not

move files and file duct, it will give an error number, and return immediately.

9.14.2 Code comments

program 9-12 linux / fs / read_write.c

1/*
2 * Linux / fs / read_write.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <sys / stat.h>
// File Status header file. Containing configuration file or system state stat {} and constants.

8 #include <errno.h> // error number header files. The system comprises various error number. (Linus imported from the minix).

9 #include <sys / types.h> // type of header files. System defines the basic data types.

1011 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

12 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

13 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

14
// character device read and write functions.

15 extern int rw_char (Int rw, int dev, char * buf , Int count , off_t * pos ); // read pipeline operation function.

16 extern int read_pipe (Struct m_inode * Inode, char * buf , Int count ); // write pipeline operation function.

17 extern int write_pipe (Struct m_inode * Inode, char * buf , Int count ); // read function block device.

18 extern int block_read (Int dev, off_t * pos , Char * buf , Int count ); // write function block device.

19 extern int block_write (Int dev, off_t * pos , Char * buf , Int count ); // read file manipulation functions.

20 extern int file_read (Struct m_inode * Inode, struct file * Filp,


twenty one char * buf , Int count );
// write file manipulation functions.

twenty two extern int file_write (Struct m_inode * Inode, struct file * Filp,
twenty three char * buf , Int count );
twenty four

//// relocatable file read and write system calls the function pointer.

// Parameter fd is the file handle, offset is the new offset value file read and write pointers, Origin offset is the starting position, is SEEK_SET // (0, from the beginning of the file), SEEK_CUR

(1, from the current read and write position), SEEK_END (, from the end of the file), one of the three 2.

25 int sys_lseek (Unsigned int fd, off_t offset, int origin )


26 {
27 struct file * file ;
28 int tmp;
29

--404--
9.14 read_write.c program

// open file handle if the program value is greater than a maximum number of files NR_OPEN (20), or a pointer to the file structure of the handle is null, or the node I // file structure

corresponding to the field is empty, a specified device or file pointer is not positioned, error code is returned and exit.

30 if (fd> = NR_OPEN ||! ( file = current -> filp [fd]) || (! file -> f_inode)
31 ||! IS_SEEKABLE ( MAJOR ( file -> f_inode-> i_dev)))
32 return - EBADF ;
// If the file corresponding to the i-node is a pipe node, an error code is returned, exit. Head and tail pointers are not free to move pipe!

33 if ( file -> f_inode-> i_pipe)


34 return - ESPIPE ;
// The positioning flag set, read and write pointers are relocated file.
35 switch ( origin ) {
// origin = SEEK_SET, required to set the start of the file as the file read and write pointers origin. If the offset value is less than zero, the error codes returned // return an error. Otherwise,

set the file read and write pointers equal offset.

36 case 0:
37 if (offset <0) return - EINVAL ;
38 file -> f_pos = offset;
39 break;
// origin = SEEK_CUR, requires a file as read and write pointers at the current read and write pointers relocated origin. If the offset is added to the current pointer value is less than 0 // file,

an error code is returned to exit. Or adding the offset value to the current read and write pointers.

40 case 1:
41 if ( file -> f_pos + offset <0) return - EINVAL ;
42 file -> f_pos + = offset;
43 break;
// origin = SEEK_END, requirements as to the origin end of the file relocation read and write pointers. At this time, if the file size plus the offset value is less than zero, an error code is returned

// exit. Otherwise relocation write pointer value plus an offset file length.

44 case 2:
45 if ((tmp = file -> f_inode-> i_size + offset) <0)
46 return - EINVAL ;
47 file -> f_pos = tmp;
48 break;
// origin setting error, return an error code to exit.
49 default:
50 return - EINVAL ;
51 }
52 return file -> f_pos; // returns after relocation file read and write pointer value.

53 }
54
//// read the file system calls.
// parameter is the file handle fd, buf is the buffer, count is the number of bytes to be read.

55 int sys_read (Unsigned int fd, char * buf , Int count )


56 {
57 struct file * file ;
58 struct m_inode * Inode;
59
// open file handle if the program value is greater than a maximum number of files NR_OPEN, or need to be read byte count is less than 0, the handle // or file structure pointer is NULL,

then return an error code and exits.

60 if (fd> = NR_OPEN || count <0 ||! ( file = current -> filp [fd]))
61 return - EINVAL ;
For count // number of bytes read is equal to 0, 0 is returned, exit

62 if (! count )
63 return 0;
// Verify storage buffer memory limitations of the data.

64 verify_area ( buf , count );


// i take the corresponding file node. If the pipeline file, and the file is read pipeline mode, then read the pipeline operation, if successful return

--405--
9.14 read_write.c program

// number of bytes read, otherwise it returns an error code to exit.

65 inode = file -> f_inode;


66 if (inode-> i_pipe)
67 return ( file -> f_mode & 1)? read_pipe (Inode, buf , count ): - EIO ;
// If the file is a character, then read a character device operation, returns the number of characters read.

68 if ( S_ISCHR (Inode-> i_mode))


69 return rw_char ( READ , Inode-> i_zone [0], buf , count , & file -> f_pos);
// If the file is a block device, the read operation is executed block device, and returns the number of bytes read.

70 if ( S_ISBLK (Inode-> i_mode))


71 return block_read (Inode-> i_zone [0], & file -> f_pos, buf , count );
// If the file is a directory file or a regular, first verify the validity of the read count and the number of adjustment (plus the number of bytes read if the file // read pointer value is greater

than the current file size, the read reset length number of bytes of the file - the current write pointer value, reads // if equal to 0, 0 is returned to exit), then performs a file read operation

returns the number of bytes read and exit.

72 if ( S_ISDIR (Inode-> i_mode) || S_ISREG (Inode-> i_mode)) {


73 if ( count + file -> f_pos> inode-> i_size)
74 count = Inode-> i_size - file -> f_pos;
75 if ( count <= 0)
76 return 0;
77 return file_read (Inode, file , buf , count );
78 }
// Otherwise print file attribute node and returns an error code to exit.

79 printk ( "( Read) inode-> i_mode =% 06o \ n \ r ", inode-> i_mode);


80 return - EINVAL ;
81 }
8283 int sys_write (Unsigned int fd, char * buf , Int count )

84 {
85 struct file * file ;
86 struct m_inode * Inode;
87
// If the program to open the file handle is greater than a maximum number of files NR_OPEN, or the need to write a file structure pointer byte count is less than 0, // or the handle is

empty, it returns an error code and exits.

88 if (fd> = NR_OPEN || count <0 ||! ( file = current -> filp [fd]))
89 return - EINVAL ;
For count // number of bytes read is equal to 0, 0 is returned, exit

90 if (! count )
91 return 0;
// i take the corresponding file node. If the pipeline file, and the file is written pipeline mode, the write pipeline operation, if successful // number of bytes written is returned, otherwise it

returns an error code to exit.

92 inode = file -> f_inode;


93 if (inode-> i_pipe)
94 return ( file -> f_mode & 2)? write_pipe (Inode, buf , count ): - EIO ;
// If the file is a character, you write a character device operation, returns the number of characters written, quit.

95 if ( S_ISCHR (Inode-> i_mode))


96 return rw_char ( WRITE , Inode-> i_zone [0], buf , count , & file -> f_pos);
// If the file is a block device, then the block device write operation, and returns the number of bytes written, quit.

97 if ( S_ISBLK (Inode-> i_mode))


98 return block_write (Inode-> i_zone [0], & file -> f_pos, buf , count );
// If regular files, perform file write operations, and returns the number of bytes written, quit.

99 if ( S_ISREG (Inode-> i_mode))


100 return file_write (Inode, file , buf , count );
// Otherwise, display the file mode corresponding node, it returns an error code to exit.

101 printk ( "( Write) inode-> i_mode =% 06o \ n \ r ", inode-> i_mode);

--406--
9.15 truncate.c program

102 return - EINVAL ;


103 }
104

9.15 truncate.c program

9.15.1 Functional Description

This procedure for releasing the specified i All nodes on the logical blocks occupied by the device, including direct blocks, indirect blocks, and a secondary indirect blocks.

Whereby a file node corresponding to the file length of cut 0 And the release of the device footprint. i Node block and schematic diagram of Figure direct indirect blocks 9-22 Fig.

node
[5] i zone
Other fields[6] i Once indirect block
zone [4] i zone
[2] i zone [3] i
zone [1] i zone
i zone [0] i

Direct block number

A second number of i zone [7] i


An indirect block of Two secondary
zone [8]
indirect block indirect block number
the second block blocks indirect blocks

Map 9-22 Inode ( i Nodes) logical connection block

9.15.2 Code comments

program 9-13 linux / fs / truncate.c

1/*
2 * Linux / fs / truncate.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

89 #include <sys / stat.h>


// File Status header file. Containing configuration file or system state stat {} and constants.

10
//// released once indirect block.

--407--
9.15 truncate.c program

11 static void free_ind (Int dev, int block)


12 {
13 struct buffer_head * Bh;
14 unsigned short * p;
15 int i;
16
// If the logical block number is 0, it returns.

17 if (! block)
18 return;
// read once indirect block, and that the use of the release on all logic blocks, and then releasing the first buffer indirect block.

19 if (bh = bread (Dev, block)) {


20 p = (unsigned short *) bh-> b_data; // points to the data buffer.
twenty one for (i = 0; i <512; i ++, p ++) // 512 may have a block number on each logical block.

twenty two if (* p)
twenty three free_block (Dev, * p); // release a specified logical block.
twenty four brelse (Bh); // release the buffer.
25 }
// indirect block on a release device.
26 free_block (Dev, block);
27 }
28
//// release second indirect block.

29 static void free_dind (Int dev, int block)


30 {
31 struct buffer_head * Bh;
32 unsigned short * p;
33 int i;
34
// If the logical block number is 0, it returns.

35 if (! block)
36 return;
// read an indirect block of the second block, and that the use of releasing all logical blocks thereon, then release the buffer of the one block.

37 if (bh = bread (Dev, block)) {


38 p = (unsigned short *) bh-> b_data; // points to the data buffer.
39 for (i = 0; i <512; i ++, p ++) 512 can be connected to two blocks on each logical block of //.

40 if (* p)
41 free_ind (Dev, * p); // indirect block the release of all time.

42 brelse (Bh); // release the buffer.


43 }
// Finally, indirect block on the secondary device is released.

44 free_block (Dev, block);


45 }
46
//// node truncated to a length corresponding to the file 0, and delivery device footprint.

47 void truncate (Struct m_inode * Inode)


48 {
49 int i;
50
// If it is not a regular file is a directory or file, is returned.
51 if (! ( S_ISREG (Inode-> i_mode) || S_ISDIR (Inode-> i_mode)))
52 return;
// i node 7 releases direct logical blocks, the logical blocks and seven full-zero entries.

53 for (i = 0; i <7; i ++)

- 408 -
9.16 open.c program

54 if (inode-> i_zone [i]) { // If the block number is not 0, it is released.

55 free_block (Inode-> i_dev, inode-> i_zone [i]);


56 inode-> i_zone [i] = 0;
57 }
58 free_ind (Inode-> i_dev, inode-> i_zone [7]); // release the first indirect block.

59 free_dind (Inode-> i_dev, inode-> i_zone [8]); // release second indirect block.

60 inode-> i_zone [7] = inode-> i_zone [8] = 0; // 7,8 logical block entry zero.
61 inode-> i_size = 0; // File size zero.
62 inode-> i_dirt = 1; // set the node has been modified flag.

63 inode-> i_mtime = inode-> i_ctime = CURRENT_TIME ; // reset node and file modification time to the current time.
64 }
6566

9.16 open.c program

9.16.1 Functional Description

This document implements a number of documents related to the operation of the system call. There are file was created, opened and closed, modify modified file access

permissions of the file's owner and attributes, file modification time operating system and file system root Changes and so on.

9.16.2 Code comments

program 9-14 linux / fs / open.c

1/*
2 * Linux / fs / open.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <string.h>
// string header file. Mainly defines the built-in functions related to operation of the string.

8 #include <errno.h> // error number header files. The system comprises various error number. (Linus imported from the minix).

9 #include <fcntl.h> // control file header. Operable control descriptor file and constants defined symbols.
10 #include <sys / types.h> // type of header files. System defines the basic data types.

11 #include <utime.h> // user time header. It defines the access and modification time structure and utime () prototype.

12 #include <sys / stat.h> // File Status header file. Containing configuration file or system state stat {} and constants.

1314 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

15 #include <linux / tty.h> // tty header file, which defines tty_io, aspects of the serial communication parameters constant.

16 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

17 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

18
// get file system information system calls.
19 int sys_ustat (Int dev, struct ustat * Ubuf)
20 {
twenty one return - ENOSYS ;
twenty two }

--409--
9.16 open.c program

twenty three

//// settings file access and modification times.

// filename parameter is the file name, times are access and modification time structure pointer.

// If times pointer is not NULL, the access time to information provided utimbuf structure file access and modification times. // times if the pointer is NULL, then take the time

to set the current system access and modification times domain specified file.

twenty four int sys_utime (Char * filename, struct utimbuf * times )


25 {
26 struct m_inode * Inode;
27 long actime, modtime;
28
// find the i-node corresponding to the file name, if not found, an error code is returned.

29 if (! (inode = namei (Filename)))


30 return - ENOENT ;
// If the access and modification times data structure pointer is not NULL, the time value read from the configuration set by the user.

31 if ( times ) {
32 actime = get_fs_long ((Unsigned long *) & times -> actime);
33 modtime = get_fs_long ((Unsigned long *) & times -> modtime);
// Otherwise, set the access and modification times to the current time.

34 } Else
35 actime = modtime = CURRENT_TIME ;
I // Modify node access time field and the modification time field.

36 inode-> i_atime = actime;


37 inode-> i_mtime = modtime; // set flag has been modified i-node,

the node is released, and returns 0.

38 inode-> i_dirt = 1;
39 iput (Inode);
40 return 0;
41 }
4243 / *

44 * XXX should we use the real or effective uid? BSD uses the real uid,
45 * So as to make this call useful to setuid programs.
46 * /
/*
* File Properties XXX, we use the real user id or the effective user id? BSD systems use a real user id,
* So the call can be used for setuid programs. (Note: POSIX standards recommend the use of real user ID)

*/
//// check access to the file.
// filename is the name of the parameter, mode is a mask, a R_OK (4), W_OK (2), X_OK (1) and F_OK (0) components. // If the request is allowed access,

then returns 0, otherwise it returns an error code.

47 int sys_access (Const char * filename, int mode)


48 {
49 struct m_inode * Inode;
50 int res, i_mode;
51
// mask 3 composed of a low, so all the high bit clear.
52 mode & = 0007;
// If the file name corresponding to the i-node does not exist, an error code is returned.

53 if (! (inode = namei (Filename)))


54 return - EACCES ;
// get file attribute code, and releases the node i.
55 i_mode = res = inode-> i_mode & 0777;
56 iput (Inode);

--410--
9.16 open.c program

// If the current process is the host of the file, then take the file host of the property.

57 if ( current -> uid == inode-> i_uid)


58 res >> = 6;
// Otherwise, if the current process is to belong to a group of the file, take the file group properties.

59 else if ( current -> gid == inode-> i_gid)


60 res >> = 6;
// If the file attributes have attribute bits queries, access permissions, return 0.

61 if ((res & 0007 & mode) == mode)


62 return 0;
63 /*
64 * XXX we are doing this test last because we really should be
65 * swapping the effective with the real user id (temporarily),
66 * and then calling suser () routine. If we do call the
67 * suser () routine, it needs to be called last.
68 */
/*
* XXX we finally do the following test, because we actually need to exchange and effective user id

* Real user id (temporarily), then call suser () function. If we really want to call
* suser () function, you need to finally being called.

*/
// If the current user id 0 (root) and execute mask bit is a 0 or a file can be accessed by anyone, 0 is returned.
69 if ((! current -> uid) &&
70 (! (Mode & 1) || (i_mode & 0111)))
71 return 0;
// otherwise it returns an error code.

72 return - EACCES ;
73 }
74
//// change the current working directory system calls. // filename parameter is

the name of the directory. // operational success, returns 0, otherwise it returns

an error code.

75 int sys_chdir (Const char * filename)


76 {
77 struct m_inode * Inode;
78
// If the file name corresponding to the i-node does not exist, an error code is returned.

79 if (! (inode = namei (Filename)))


80 return - ENOENT ;
// If the node i i node is not a directory, then release the node, it returns an error code.

81 if (! S_ISDIR (Inode-> i_mode)) {


82 iput (Inode);
83 return - ENOTDIR ;
84 }
// release the current working directory of the process of the original i-node, and point to the new home of the working directory i-node. Return 0.

85 iput ( current -> pwd);


86 current -> pwd = inode;
87 return (0);
88 }
89
//// change the root system calls. // The specified path name to the root directory

'/'. // returns 0 if the operation was successful, otherwise it returns an error code.

90 int sys_chroot (Const char * filename)

--411--
9.16 open.c program

91 {
92 struct m_inode * Inode;
93
// If the file name corresponding to the i-node does not exist, an error code is returned.

94 if (! (inode = namei (Filename)))


95 return - ENOENT ;
// If the node i i node is not a directory, then release the node, it returns an error code.

96 if (! S_ISDIR (Inode-> i_mode)) {


97 iput (Inode);
98 return - ENOTDIR ;
99 }
// release the root directory of the current process node i, and reset the specified directory name is here i node, return 0.

100 iput ( current -> root);


101 current -> root = inode;
102 return (0);
103 }
104
//// modify file system attributes calls the function.

// filename parameter is the file name, mode is the new file attributes. // returns 0 if the operation is

successful, otherwise it returns an error code.

105 int sys_chmod (Const char * filename, int mode)


106 {
107 struct m_inode * Inode;
108
// If the file name corresponding to the i-node does not exist, an error code is returned.

109 if (! (inode = namei (Filename)))


110 return - ENOENT ;
// If the effective user id of the current process is not equal to the user id file i node, and the current process is not the super user, then release the // file i node, return an

error code.

111 if (( current -> euid = inode-> i_uid) &&!! suser ()) {


112 iput (Inode);
113 return - EACCES ;
114 }
// reset the file attributes i node and the home node i has been modified flag. Releasing the node i, 0 is returned.

115 inode-> i_mode = (mode & 07777) | (inode-> i_mode & ~ 07777);
116 inode-> i_dirt = 1;
117 iput (Inode);
118 return 0;
119 }
120
//// modify the host file system calls.
// filename parameter is the file name, uid is the user identifier (user id), gid is the group id. // returns 0 if the operation is

successful, otherwise it returns an error code.

121 int sys_chown (Const char * filename, int uid, int gid)
122 {
123 struct m_inode * Inode;
124
// If the file name corresponding to the i-node does not exist, an error code is returned.

125 if (! (inode = namei (Filename)))


126 return - ENOENT ;
// If the current process is not the super user, then release the i node, return an error code.

127 if (! suser ()) {


128 iput (Inode);

--412--
9.16 open.c program

129 return - EACCES ;


130 }
// Set the file corresponding to the user id and group id node i and node i has been modified flag set, releasing the node i, 0 is returned.

131 inode-> i_uid = uid;


132 inode-> i_gid = gid;
133 inode-> i_dirt = 1;
134 iput (Inode);
135 return 0;
136 }
137
//// open (or create) the file system calls.
// filename parameter is the file name, flag is the flag to open the file: read-only O_RDONLY, write-only or read-write O_WRONLY O_RDWR, // and a combination

O_CREAT, O_EXCL, O_APPEND and some other flags, if this function creates a new file, the mode // attribute specifies the license for the use of the file, these attributes

have S_IRWXU (host file has read, write, and execute permissions), S_IRUSR // (user has read file permissions), S_IRWXG (group members have read, write, and

execute rights) and so on. For newly created files, // these attributes apply only to future access to the file, create a read-only file open call will also return a read-write file

handle. // If the operation is successful file handle (file descriptor) is returned, otherwise it returns an error code. (See sys / stat.h, fcntl.h)

138 int sys_open (Const char * filename, int flag, int mode)
139 {
140 struct m_inode * Inode;
141 struct file * F;
142 int i, fd;
143
// Set the mode mode set by the user with the process of phase mask, resulting in file mode permission.

144 mode & = 0777 & ~ current-> umask ;


// search process configuration file structure pointer array, look for a free item, if the item has no free, error code is returned.

145 for (fd = 0; fd < NR_OPEN ; Fd ++)


146 if (! current -> filp [fd])
147 break;
148 if (fd> = NR_OPEN )
149 return - EINVAL ;
Close file handle bitmap // set when executed, resets the corresponding bits.

150 current -> close_on_exec & = ~ (1 << fd);


Let f // point to the file list at the beginning of the array. Search free files in item (item handler reference count of 0), if the file table has no free // structure entry, an error

code is returned.

151 f = 0 + file_table ;
152 for (i = 0; i < NR_FILE ; I ++, f ++)
153 (! F-> f_count) if break;
154 if (i> = NR_FILE )
155 return - EINVAL ;
// make the corresponding file handle to process file structure pointer to search the file structure, and to make the handle reference count is incremented by one.

156 ( current -> filp [fd] = f) -> f_count ++;


// call the function performs opening operation, if the return value is less than 0, then the error is released just apply to file structure, return error code.

157 if ((i = open_namei (Filename, flag, mode, & inode)) <0) {


158 current -> filp [fd] = NULL ;
159 f-> f_count = 0;
160 return i;
161 }
162 / * Ttys are somewhat special (ttyxx major == 4, tty major == 5) * /
/ * Ttys some special (the form ttyxx main number == 4, tty main number == 5) * /

// If the file is a character device, so if the device number is 4, then the number of the current process to set tty for the child device number i node. // set the current parent process and process

group ID tty tty corresponding entries equal to the process of the parent process group number.

163 if ( S_ISCHR (Inode-> i_mode))

--413--
9.16 open.c program

164 if ( MAJOR (Inode-> i_zone [0]) == 4) {


165 if ( current -> leader && current -> tty <0) {
166 current -> tty = MINOR (Inode-> i_zone [0]);
167 tty_table [ current -> tty] .pgrp = current -> pgrp;
168 }
// Otherwise, if the character device file number is 5, then, if the current process is not tty, then the error, the release of the i-node // and file structure to the application, returns an error

code.

169 } Else if ( MAJOR (Inode-> i_zone [0]) == 5)


170 if ( current -> tty <0) {
171 iput (Inode);
172 current -> filp [fd] = NULL ;
173 f-> f_count = 0;
174 return - EPERM ;
175 }
176 / * Likewise with block-devices: check for floppy_change * /
/ * Block device files for the same: to check if the disc is replaced * /
// If you open a block device file, check whether the disc replacement, if replacement is required for high-speed buffer // buffer block should all the equipment.

177 if ( S_ISBLK (Inode-> i_mode))


178 check_disk_change (Inode-> i_zone [0]);
// initialization file structure. Flag set file structure and properties, the reference count is set to the handle 1, a field node i, // file read and write pointers are initialized to zero. Returns the

file handle.

179 f-> f_mode = inode-> i_mode;


180 f-> f_flags = flag;
181 f-> f_count = 1;
182 f-> f_inode = inode;
183 f-> f_pos = 0;
184 return (fd);
185 }
186
//// create a file system calls.
// pathname argument is the pathname of the same mode as above SYS_OPEN () function. // successful file handle is

returned, otherwise returns an error code.

187 int sys_creat (Const char * pathname, int mode)


188 {
189 return sys_open (Pathname, O_CREAT | O_TRUNC , Mode);
190 }
191
// close the file system calls. // fd
argument is the file handle.
// returns 0 if successful, otherwise it returns an error code.

192 int sys_close (Unsigned int fd)


193 {
194 struct file * Filp;
195
// If the file handle number is greater than the program files can be opened at the same time, the error code is returned.

196 if (fd> = NR_OPEN )


197 return - EINVAL ;
// reset execution process closes the file handle to the bitmap corresponds bit.

198 current -> close_on_exec & = ~ (1 << fd);


// If the file handle corresponding to the file structure pointer is NULL, an error code is returned.

199 if (! (filp = current -> filp [fd]))


200 return - EINVAL ;

--414--
9.17 exec.c program

// pointer to the file structure of the file handle is set to NULL.

201 current -> filp [fd] = NULL ;


// If before closing the file handle corresponding to the file structure has a reference count is 0, then the kernel errors, crashes.

202 if (filp-> f_count == 0)


203 panic ( ' Close: file count is 0 ");
// Otherwise, the corresponding file handle structure reference count by 1, if not 0, then return 0 (success). Ruoyi equal to 0, indicating that the file has no handles //

reference, release the file node i, 0 is returned.

204 if (--filp-> f_count)


205 return (0);
206 iput (Filp-> f_inode);
207 return (0);
208 }
209

9.17 exec.c program

9.17.1 Functional Description

This source and binary executable files to achieve shell Load and execute the script file. One of the major function is a function

do_execve () It is a system interrupt call ( int 0x80) Function No. __ NR_execve () Call C Handler is exec () The main function of the realization function clusters. Its main functions

are:

• Perform initialization parameters and environmental parameters space of the page - Set initial spatial start pointer; page pointer array is initialized space ( NULl) ;

According to the execution of the execution object file Natori i Node; calculating the number of number of parameters and environment variables; check the file types,

execute permission;

• The header data structure execution start of the file, wherein the information to be processed - According to the executable file i Node reads the file header information;

if Shell Script (the first line to #! Start), the analysis Shell Program name and its parameters, and execute the file as an argument to the execution of the execution Shell

Program; execution is executable in accordance with the magic number and segment length information to determine the file;

• Calls on the current process carried out before running the new initialization file - Point to the new executable file i Node; the reset signal handler; head configuration

information is provided in accordance with local descriptor segment base address and length; and environmental parameters set page pointer; modification process

performed for each content field;

• Uehara call stack replacement execve () The return address for the new executive to run the program address, run the newly loaded program.

execve () Function may have a large number of common parameters and operations, and environmental parameters of the space environment space MAX_ARG_PAGES Pages,

with a total length of up to 128kB byte. Store data in a manner similar to the space stack operation, i.e., from the assumed 128kB Reverse stored starting at the end of the space or

environment variable parameter string. In the initial, program defines a pointer to the end space ( 128kB-4 Byte) at the inner space of the offset value p , With the increase of the

offset value data is stored and retracted, FIG. 9-23 As can be seen, p Clearly pointed out how much free space in the current environment space still remaining parameters. In the

analysis functions copy_string () When, this can refer to FIG.

--415--
9.17 exec.c program

Environmental parameter space (there are a total of MAX_ARG_PAGES page, 128kb)

Data storage direction


0

page pointer array

012
Unallocated page Assigned page
Current offset value p The initial offset value p

.
.

Map 9-23 Arguments and environment variables string space

create_tables () Function for a given value in accordance with the current stack pointer p Numerical variables and parameters argc And the number of environment variables

envc Creating the environment variable pointer table and parameter in the new program stack, and the return stack pointer value at this time sp . After the stack pointer is created in

the form of a table shown below 9-24 Fig.

NULL Original sp (parameter p)

Big envc + 1

NULL

changes in address
argc + 1

envp
argv
Small argc
sp (return value)

Map 9-24 The new program stack pointer indicates the intention

9.17.2 Code comments

program 9-15 linux / fs / exec.c

1/*
2 * Linux / fs / exec.c
3*
4 * (C) 1991 Linus Torvalds
5*/
6

--416--
9.17 exec.c program

7/*
8 * # -! Checking implemented by tytso.
9*/
/*
* # ! Program starts detection in part by tytso implemented.
*/
1011 / *

12 * Demand-loading implemented 01.12.91 - no need to read anything but


13 * The header into memory. The inode of the executable is put into
14 * "Current-> executable", and page faults do the actual loading. Clean.
15 *
16 * Once more I can proudly say that linux stood up to being changed: it
17 * Was less than 2 hours work to get demand-loading completely implemented.
18 * /
/*
* When the demand load is achieved in 1991.12.1 - just execute the file header part read into memory without

* The entire execution files are loaded into memory. i node executable file is placed in the current process executable field

* ( "Current-> executable"), and page exceptions actual loading operation and cleanup executable file.
*
* Once again, I can proudly say, linux can withstand modification: in less than two hours of work time to complete

* We realized the need to load handling.

*/
1920 #include <errno.h>
// error number header files. The system comprises various error number. (Linus imported from the minix).

twenty one #include <string.h> // string header file. Mainly defines the built-in functions related to operation of the string.

twenty two #include <sys / stat.h> // File Status header file. Containing configuration file or system state stat {} and constants.

twenty three #include <a.out.h> // a.out header files. It defines the a.out executable file format and some macros.

2425 #include <linux / fs.h>


// file system header files. Table structure definition file (file, buffer_head, m_inode, etc.).
26 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

27 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

28 #include <linux / mm.h> // memory management header files. It contains the defined page size and page number of the release function prototypes.

29 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

3031 extern int sys_exit (Int exit_code); // program exits a system call.

32 extern int sys_close (Int fd); // close the file system calls.
3334 / *

35 * MAX_ARG_PAGES defines the number of pages allocated for arguments


36 * And envelope for the new program. 32 should suffice, this gives
37 * A maximum env + arg of 128kB!
38 * /
/*
* MAX_ARG_PAGES defines a new program memory allocated to the maximum number of pages of arguments and environment variables.

* Memory 32 should be sufficient, which makes the environment parameters (env + arg) combined to achieve the total space 128kB!

*/
39 #define MAX_ARG_PAGES 32
4041 / *

42 * Create_tables () parses the env- and arg-strings in new user


43 * Memory and creates the pointer tables from them, and puts their

--417--
9.17 exec.c program

44 * Addresses on the "stack", returning the new stack pointer value.


45 * /
/*
* create_tables () function parses the string in the environment variables and parameters of the new user memory, whereby

* Create a pointer table, and put their addresses on the "stack", and then returns a pointer to the value of the new stack.

*/
//// create environment variables and parameters pointer table in the new user stack.

// Parameters: p - the data segment as a starting point offset pointer parameters and environmental information; argc - the number of arguments; envc - number of environmental

variables. // returns: the stack pointer.

46 static unsigned long * create_tables (Char * p, int argc, int envc)


47 {
48 unsigned long * argv * envp ;
49 unsigned long * sp;
50
// stack pointer is 4 bytes (Section 1) addressed as a boundary, so there is an integral multiple of 4 so that the sp.

51 sp = (unsigned long *) (0xfffffffc & (unsigned long) p); // sp moved downwardly, the number of vacant space occupied by the environmental

parameters and environmental parameters so that the pointer points to where envp.

52 sp - = envc + 1;
53 envp = Sp;
// sp downward movement, the number of empty command line parameter space occupied by the pointer, and a pointer to the argv so there. // pointer plus

below 1, sp width incremented pointer byte value.

54 sp - = argc + 1;
55 argv = Sp;
// pointer envp environmental parameters and command-line parameters and the number of command line arguments a pointer onto the stack.

56 put_fs_long ((Unsigned long) envp , - sp);


57 put_fs_long ((Unsigned long) argv , - sp);
58 put_fs_long ((Unsigned long) argc, - sp);
// pointer to the command line parameters into the appropriate place vacated foregoing, the last place a NULL pointer.

59 while (argc -> 0) {


60 put_fs_long ((Unsigned long) p, argv ++);
61 while ( get_fs_byte (P ++)) / * nothing * /; // forward pointer p 4 bytes.
62 }
63 put_fs_long (0, argv );
// pointer into the environment variable corresponding to each of the previously vacated places, and finally placing a NULL pointer.

64 while (envc -> 0) {


65 put_fs_long ((Unsigned long) p, envp ++);
66 while ( get_fs_byte (P ++)) / * nothing * /;
67 }
68 put_fs_long (0, envp );
69 return sp; // returns the current structure of the new stack pointer.

70 }
7172 / *

73 * Count () counts the number of arguments / envelopes


74 * /
/*
* The number of function calculation command line parameters / environment variables count ().

*/
//// count the number of parameters.

// Parameters: argv - parameter array of pointers, a pointer to the last entry is NULL. // Returns: the number of

arguments.

75 static int count (Char ** argv )


76 {

--418--
9.17 exec.c program

77 int i = 0;
78 char ** tmp;
7980
if (tmp = argv )
81 while ( get_fs_long ((Unsigned long *) (tmp ++)))
82 i ++;
8384
return i;
85 }
8687 / *

88 * 'Copy_string ()' copies argument / envelope strings from user


89 * Memory to free pages in kernel mem. These are in a format ready
90 * To be put directly into the top of new user memory.
91 *
92 * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
93 * Whether the string and the string array are from user or kernel segments:
94 *
95 * From_kmem argv * argv **
96 * 0 user space user space
97 * 1 kernel space user space
98 * 2 kernel space kernel space
99 *
100 * We do this by playing games with the fs segment register. Since it
101 * It is expensive to load a segment register, we try to avoid calling
102 * Set_fs () unless we absolutely have to.
103 * /
/*
* 'Copy_string ()' function copies a string from the user memory space to kernel parameters and environment free pages in memory.

* These have been directly into the new user memory format.
*
* On day 1991.12.24 modified by TYT (Tytso), it increased from_kmem parameter, which indicates the character string or

* Segment string array derived from the user or kernel section.

*
* from_kmem argv * argv **
* 0 User-space user space
* 1 Kernel space user space
* 2 Kernel space kernel space
*
* We are through the clever handling fs segment register operations. Due to load a segment register too costly, so
* We try to avoid calling set_fs (), unless it is necessary.
*/
//// copying a specified number of the parameter string to the parameter space and the environment.

// parameters: argc - The number of parameters to be added; argv - parameter array of pointers; page - page space environment parameters and an array of pointers. //

p - offset pointer in the parameter table space, always points to the head of the string copied; from_kmem - source string flag. // in do_execve () function, p is

initialized to point to a last long word parameter table, the parameter string (128kB) space // stack operation is reverse to replicate stored, so p pointer will always point

parameters the head of the string. // Returns: the parameter space environment and the current head pointer.

104 static unsigned long copy_strings (Int argc, char ** argv , Unsigned long * page,
105 unsigned long p, int from_kmem)
106 {
107 char * tmp, * pag;
108 int len, offset = 0;

--419--
9.17 exec.c program

109 unsigned long old_fs, new_fs;


110111
if (! p)
112 return 0; / * Bullet-proofing * / / * Verify offset pointer * /
// ds register values ​to take new_fs, and to keep the original register values ​fs old_fs.

113 new_fs = get_ds ();


114 old_fs = get_fs ();
// If the strings and string arrays from the kernel space is set fs segment register points to the kernel data segment (ds).

115 if (from_kmem == 2)
116 set_fs (New_fs);
// loop processing of each parameter is copied from the last parameter starts reverse, copied to the specified offset address.

117 while (argc--> 0) {


// user space if the character string in the string array in the kernel space, segment registers fs is set to the kernel data segment (ds).

118 if (from_kmem == 1)
119 set_fs (New_fs);
// start from the last parameter reverse operation, a fetch fs argument pointer to the last segment tmp, if it is empty, then an error crash.

120 if (! (tmp = (char *) get_fs_long (((Unsigned long *) argv ) + Argc)))


121 panic ( ' argc is wrong ");
// user space if the character string in the string array in the kernel space, the original value is restored fs segment register.

122 if (from_kmem == 1)
123 set_fs (Old_fs);
// Calculation of the argument string length len, tmp and end points of the argument string.

124 len = 0; / * Remember zero-padding * /


125 do { / * We know that the end of the string is NULL bytes * /

126 len ++;


127 } While ( get_fs_byte (Tmp ++));
// If this time exceeds the string length parameter and a further environment space remaining free length of the recovery period fs register 0 and returns.

128 if (p-len <0) { / * This should not happen - 128kB * /


129 set_fs (Old_fs); / * will not happen - because there's space 128kB * /
130 return 0;
131 }
// fs replication section currently assigned parameter string, the string is copied from the tail began to reverse.

132 while (len) {


133 - - p; --len; --tmp;
// function when beginning execution, the offset variable offset is initialized to zero, so when the offset-1 <0, is described first copy the string, so that it is equal to p // pointer

offset value within the page, and applied free pages.

134 if (--offset <0) {


135 offset = p% PAGE_SIZE ;
// If the strings and string arrays in the kernel space, the original value is restored fs segment register.

136 if (from_kmem == 2)
137 set_fs (Old_fs);
// If the current offset value string space where p page pointer array entry page [p / PAGE_SIZE] == 0, indicates that the corresponding page does not exist, // need to request a new free

memory pages, the page pointer is filled pointer array, and also to enable the new page pag point, if the application is not idle // page 0 is returned.

138 if (! (pag = (char *) page [p / PAGE_SIZE ]) &&


139 ! (Pag = (char *) page [p / PAGE_SIZE ] =
140 (Unsigned long *) get_free_page ()))
141 return 0;
// If the strings and string arrays from the kernel space is set fs segment register points to the kernel data segment (ds).

142 if (from_kmem == 2)
143 set_fs (New_fs);
144
145 }

--420--
9.17 exec.c program

// copy argument string into a byte at a pag + offset from the segments fs.

146 * (Pag + offset) = get_fs_byte (Tmp);


147 }
148 }
// If the strings and string arrays in the kernel space, the original value is restored fs segment register.

149 if (from_kmem == 2)
150 set_fs (Old_fs);
// Finally, return parameter head space and the environment offset parameter information has been copied.

151 return p;
152 }
153
//// modify the local descriptor table descriptor segment base address and length limit, and the spatial parameters and environment data page is placed in the end section. //

Parameters: text_size - code segment executable file header length value field gives the a_text; //

page - page space environment parameters and an array of pointers. //

Return: data length segment limit value (64MB).

154 static unsigned long change_ldt (Unsigned long text_size, unsigned long * page)
155 {
156 unsigned long code_limit, data_limit, code_base, data_base;
157 int i;
158
// The execution file header a_text value to calculate the length of a page code segment boundary indefinite length. And set the data length of 64MB.

159 code_limit = text_size + PAGE_SIZE -1;


160 code_limit & = 0xFFFFF000;
161 data_limit = 0x4000000;
// get the current local process code segment descriptor table in the code base, the same code base and the data segment base.

162 code_base = get_base ( current -> ldt [1]);


163 data_base = code_base;
// reset the local segment table base address and the code and data segment descriptors of indefinite length.

164 set_base ( current -> ldt [1], code_base);


165 set_limit ( current -> ldt [1], code_limit);
166 set_base ( current -> ldt [2], data_base);
167 set_limit ( current -> ldt [2], data_limit);
168 / * Make sure fs points to the NEW data segment * /
/ * Make sure fs segment register data already point to a new segment * /

// fs segment register into the local descriptor table data selectors (0x17).
169 __asm ​__ ( " pushl $ 0x17 \ n \ tpop %% fs ": :);
// parameters and environment space has been stored in the page data (there are a total of MAX_ARG_PAGES pages, 128kB) // end of the data segment into a linear

address. Calling function put_page () operating (mm / memory.c, 197).

170 data_base + = data_limit;


171 for (i = MAX_ARG_PAGES -1; i> = 0; i--) {
172 data_base - = PAGE_SIZE ;
173 if (page [i]) // If the page exists,
174 put_page (Page [i], data_base); // placed on the page.
175 }
176 return data_limit; // return the last data segment length limit (64MB).

177 }
178 179 /
*
180 * 'Do_execve ()' executes a new program.
181 * /
/*
* 'Do_execve ()' function executes a new program.
*/

--421--
9.17 exec.c program

//// execve () system call interrupt function. Load and execute child process (other programs). // This function

interrupt system calls (int 0x80) function function number __NR_execve call.

// Parameters: eip - program code pointer points to the stack at eip calling system interrupts, see kernel / system_call.s // program instructions beginning portion;

tmp - the interrupt return address when calling _sys_execve system useless; / /

filename - the file name of the execution of the program; argv - command line argument pointer array; envp - environment variable array of pointers. // Returns: If the call

succeeds, not returned; otherwise setting error number and returns -1.

182 int do_execve (Unsigned long * eip, long tmp, char * filename,
183 char ** argv , Char ** envp )
184 {
185 struct m_inode * Inode; I // node pointer memory structure variables.

186 struct buffer_head * Bh; // cache header pointer.


187 struct exec ex; // perform file header data structure variables.

188 unsigned long page [ MAX_ARG_PAGES ]; // pointer to an array of environmental parameters and page string space.

189 int i, argc, envc;


190 int e_uid, e_gid; // valid user id and effective group id.
191 int retval; // return value.
192 int sh_bang = 0; // control whether to execute scripting code.
// string parameters and environmental space offset pointer is initialized to point to the last word at the space length.

193 unsigned long p = PAGE_SIZE * MAX_ARG_PAGES -4;


194
// eip [1] is the original code segment register CS, wherein the selectors are not core segment selector, i.e. the kernel can call this function.

195 if ((0xffff & eip [1])! = 0x000f)


196 panic ( ' execve called from supervisor mode ");
// page pointer array initialization string space and environmental parameters (Table).

197 for (i = 0; i < MAX_ARG_PAGES ; I ++) / * Clear page-table * /


198 page [i] = 0;
// i take the node number corresponding to the executable file.

199 if (! (inode = namei (Filename))) / * Get executables inode * /


200 return - ENOENT ;
// count the number of parameters and the number of environment variables.

201 argc = count ( argv );


202 envc = count ( envp );
203
// perform file must be a regular file. If the file is a conventional error return code is set, jump to exec_error2 (line 347).
204 restart_interp:
205 if (! S_ISREG (Inode-> i_mode)) {/ * must be regular file * /
206 retval = - EACCES ;
207 goto exec_error2;
208 }
// This check is performed to perform the file permissions. According to its properties (corresponding to node i uid and gid), to see if the right to perform the present process it.

209 i = inode-> i_mode; // get the file attributes field values.

Effective user ID (euid) // If the user ID mark (set-user-id) set file, then the implementation process back on // set to file a user ID, otherwise it is set to
euid the current process. Here the value temporarily stored in e_uid variable. Effective group ID (egid) // If you set group ID flag (set-group-id) set file,
then the implementation process is set to the group ID // files. Otherwise it is set to egid the current process.

210 e_uid = (i & S_ISUID ?) Inode-> i_uid: current -> euid;


211 e_gid = (i & S_ISGID ?) Inode-> i_gid: current -> egid;
// If the file belonging to the user running the process, put the right word file attributes 6, the minimum is three host file access permission flags. // Otherwise, if the user files and running

processes belong to the same group, the word three is the lowest property group of users of file access permission flags. // otherwise the word three is the lowest property rights of other users

to access the file.

212 if ( current -> euid == inode-> i_uid)


213 i >> = 6;
214 else if ( current -> egid == inode-> i_gid)

--422--
9.17 exec.c program

215 i >> = 3;
// If the user does not perform the above rights and other users do not have any authority, and not the superuser, it indicates that the file is not // be executed. Thus not

performed, an error code is set, to the process jumps to exec_error2.

216 if (! (i & 1) &&


217 ! ((Inode-> i_mode & 0111) && suser ())) {
218 retval = - ENOEXEC ;
219 goto exec_error2;
220 }
// read execution file of data to a cache area, if the error is an error code is set, to the process jumps to exec_error2.
221 if (! (bh = bread (Inode-> i_dev, inode-> i_zone [0]))) {
222 retval = - EACCES ;
223 goto exec_error2;
224 }
// Next, the data structure of the executable file header is processed, points performed ex let the data structure of the head portion.

225 ex = * ((struct exec *) Bh-> b_data); / * Read exec-header * / / * Performing the read head portion * /

// If the two-byte executable file to the beginning of the '#!', And sh_bang flag is not set, then execute the script file processing.

226 if ((bh-> b_data [0] == '#') && (bh-> b_data [1] == '!') && (! sh_bang)) {
227 /*
228 * This section does the #! Interpretation.
229 * Sorta complicated, but hopefully it will work. -TYT
230 */
/*
* This part of the processing and interpretation of the '#!', Some complicated, but want to work. -TYT

*/
231232
char buf [1023], * cp, * interp, * i_name, * i_arg;
233 unsigned long old_fs;
234
// copy the program execution head his characters '#!' Behind the string to buf, which contains a script handler name.

235 strncpy ( buf , Bh-> b_data + 2, 1022);


// release the cache block and the node i performs file.

236 brelse (Bh);


237 iput (Inode);
// get the first line, and remove the start of spaces, tabs.
238 buf [1022] = '\ 0 ';
239 if (cp = strchr ( buf '\ n ')) {
240 * Cp = '\ 0 ';
241 for (cp = buf ; (* Cp == ' ') || (* cp ==' \ t '); cp ++);
242 }
// If the line is not something else, go wrong. Error code is set, the jump to exec_error1.
243 if (! cp || * cp == '\ 0 ') {
244 retval = - ENOEXEC ; / * No interpreter name found * /
245 goto exec_error1;
246 }
// otherwise have been the beginning of the script is interpreted single line of the program name.

247 interp = i_name = cp;


// The following analysis of the line. First, take the first string, it should be the name of the script interpreter, iname point to that name.

248 i_arg = 0;
249 for (; * cp && (* cp = '! ') && (* cp! =' \ t '); cp ++) {
250 if (* cp == '/')
251 i_name = cp + 1;
252 }
// If there are characters in the file name, then it should be the parameter string, so i_arg points to the string.

--423--
9.17 exec.c program

253 if (* cp) {
254 * Cp ++ = '\ 0 ';
255 i_arg = cp;
256 }
257 /*
258 * OK, we've parsed out the interpreter name and
259 * (Optional) argument.
260 */
/*
* OK, we have an interpreter parses the file name and (optional) parameter.
*/
// If sh_bang flag is not set, it is set, and replication environment variables and parameters specified number string to the parameter string and the environment space.

261 if (sh_bang ++ == 0) {
262 p = copy_strings (Envc, envp , Page, p, 0);
263 p = copy_strings (--Argc, argv +1, page, p, 0);
264 }
265 /*
266 * Splice in (1) the interpreter's name for argv [0]
267 * (2) (optional) argument to interpreter
268 * (3) filename of shell script
269 *
270 * This is done in reverse order, because of how the
271 * user environment and arguments are stored.
272 */
/*
* Splice (1) argv [0] in place of the name of interpreter
* (2) (optional) parameters interpreter
* Name (3) of the script
*
* This is reverse processed, due to the way users store environment and parameters caused.
*/
// copy the script file name to the arguments and environment space.

273 p = copy_strings (1, & filename, page, p, 1);


// Copy parameters to explain the program parameters and environment space.

274 argc ++;


275 if (i_arg) {
276 p = copy_strings (1, & i_arg, page, p, 2);
277 argc ++;
278 }
// copy the file name to explain the arguments and environment space. If an error, an error code is set, jump to exec_error1.

279 p = copy_strings (1, & i_name, page, p, 2);


280 argc ++;
281 if (! p) {
282 retval = - ENOMEM ;
283 goto exec_error1;
284 }
285 /*
286 * OK, now restart the process with the interpreter's inode.
287 */
/*
* OK, now using an interpreter i-node restart process.
*/
// fs retain the original segment register (pointing to the original user data section), which is now set to the kernel data segment.

--424--
9.17 exec.c program

288 old_fs = get_fs ();


289 set_fs ( get_ds ());
// i take the node interpreter, and jump to the restart_interp reprocessing.
290 if (! (inode = namei (Interp))) {/ * get executables inode * /
291 set_fs (Old_fs);
292 retval = - ENOENT ;
293 goto exec_error1;
294 }
295 set_fs (Old_fs);
296 goto restart_interp;
297 }
// release the buffer.
298 brelse (Bh);
// following the implementation of header information for processing.

// the following situations, the program will not be executed: if the executable file is not an executable file desired page (ZMAGIC), or portion of code relocations a_trsize // length is not equal to

0, or data relocation information length is not equal to 0, or code segments + + heap data segment length than 50MB, // indicates that the i-node or performs symbol table file is smaller than the

sum of the length of the length of the head portion, and executive code segment data segment + +.

299 if ( N_MAGIC (Ex)! = ZMAGIC || ex.a_trsize || ex.a_drsize ||


300 ex.a_text + ex.a_data + ex.a_bss> 0x3000000 ||
301 inode-> i_size <ex.a_text + ex.a_data + ex.a_syms + N_TXTOFF (Ex)) {
302 retval = - ENOEXEC ;
303 goto exec_error2;
304 }
// If the execution file execution section header length is not equal to the size of a memory block (1024 bytes), can not be executed. Turn exec_error2.

305 if ( N_TXTOFF (Ex)! = BLOCK_SIZE ) {


306 printk ( "% s:! N_TXTOFF = BLOCK_SIZE See a.out.h. ",. filename);
307 retval = - ENOEXEC ;
308 goto exec_error2;
309 }
// If sh_bang flag is not set, then string replication environment variables and parameters to specify the number of parameters and the environment space. // If sh_bang flag has been set, it

indicates that the script will run the program, then the environment variable page has been copied, no need to copy.

310 if (! sh_bang) {
311 p = copy_strings (Envc, envp , Page, p, 0);
312 p = copy_strings (Argc, argv , Page, p, 0);
// if p = 0, it means that the environment variable and parameter space page has been filled, to fit the. Go to the error handling.

313 if (! p) {
314 retval = - ENOMEM ;
315 goto exec_error2;
316 }
317 }
318 / * OK, This is the point of no return * /
/ * OK, let's start there would be no return to the place * /

// If the original program is a program execution, then the release of its i-node, and let the process executable program i field points to the new node.

319 if ( current -> executable)


320 iput ( current -> executable);
321 current -> executable = inode;
// reset all clear signal handler. SIG_IGN handle but can not be reset, and therefore between 322 and 323 need to add a line // if statement: if (!
Current-> sa [I] .sa_handler = SIG_IGN). This is a bug in the source code.
322 for (i = 0; i <32; i ++)
323 current -> sigaction [I] .sa_handler = NULL ;
// Close (close_on_exec) The file handle bitmap flag is executed, the specified closing open files, and reset the flag.
324 for (i = 0; i < NR_OPEN ; I ++)
325 if (( current -> close_on_exec >> i) & 1)

--425--
9.17 exec.c program

326 sys_close (I);


327 current -> close_on_exec = 0;
// the specified base address and length limit, release the original process code and data segments corresponding to the specified memory page table and a page table memory block

itself.

// execute the program at this time is not occupied any page of the main memory area. When executed, would cause the program to perform memory management page fault processing and its

application // memory page, and the program is read into memory.

328 free_page_tables ( get_base ( current -> ldt [1]), get_limit (0x0F));


329 free_page_tables ( get_base ( current -> ldt [2]), get_limit (0x17));
// If the "last task using the coprocessor" points to the current process, it is blank, and reset using the flag coprocessor.
330 if ( last_task_used_math == current )
331 last_task_used_math = NULL ;
332 current -> used_math = 0;
// The local table a_text modified descriptor segment base address and length limit, and the spatial parameters and environment data page is placed in the end section. // After the

implementation of the following statements, P at this time is at the beginning of the data segment as the origin offset value, and the parameter is pointing to the beginning of the data

environment space, i.e. converted into the // stack pointers.

333 p + = change_ldt (Ex.a_text, page) - MAX_ARG_PAGES * PAGE_SIZE ; // create_tables () parameters and environment variables

to create a new user stack pointer table and returns the stack pointer.

334 p = (unsigned long) create_tables ((Char *) p, argc, envc);


// modify the current process new information in the fields for the execution of the program. So that the end of process code segment value field end_code = a_text; // make the process a data

segment tail field end_data = a_data + a_text; end of the field so that the process stack brk = a_text + a_data + a_bss.

335 current -> brk = Ex.a_bss +


336 ( current -> end_data = ex.a_data +
337 ( current -> end_code = ex.a_text));
// set the field for the start of the process stack page stack pointer is located, and reset the effective user id and effective group id.

338 current -> start_stack = p & 0xfffff000;


339 current -> euid = e_uid;
340 current -> egid = e_gid;
// initialize a bss segment data, all zeros.
341 i = ex.a_text + ex.a_data;
342 while (i & 0xfff)
343 put_fs_byte (0, (char *) (i ++));
// call the original interrupt system program code on the stack pointer to point to the entry point of the replacement new execution of the program, the stack pointer and the stack pointer is

replaced // new execution of the program. Return instruction will pop the stack data and causes the CPU to perform a new executive program, it will not return to the program // call the original

system interrupts go.

344 eip [0] = ex.a_entry; / * Eip, magic happens :-) * / / * eip, magic worked * /
345 eip [3] = p; / * Stack pointer * / / * Esp, stack pointer * /
346 return 0;
347 exec_error2:
348 iput (Inode);
349 exec_error1:
350 for (i = 0; i < MAX_ARG_PAGES ; I ++)
351 free_page (Page [i]);
352 return (retval);
353 }
354

9.17.3 Other Information

9.17.3.1 a.out Executable file format

Linux Kernel 0.11 Supports only a.out (Assembley & link editor output) Executable file format, although this format is now gradually do, and use more feature complete ELF

( Executable and Link Format ) Format, but because of its simplicity, as a material just getting started learning more applicable. The following comprehensive introduction a.out format.

--426--
9.17 exec.c program

In the header file < a.out.h> It affirmed the three data structures as well as some of the macro function. These machine code files describe the data structures (binary)

executable on the system.

An executable file can have a total of seven sections (Section VII) components. In order, these portions are: an end effector

portion ( exec header)

Execute the file header section. This portion contains a number of parameters, these parameters are used to load the kernel executable file into memory and executed,

and the linker ( ld) Using these parameters will be some combination of binary object files into an executable file. This is the only part of the necessary.

Code segment portion ( text segment)

Containing program execution is loaded into memory so that the instruction code and associated data. It can be loaded as read-only. Data

segment portion ( data segment)

This portion contains data already initialized, it is always loaded into the read-write memory. Relocations

section ( text relocations)

This portion contains the linker used for recording data. The code segment for the positioning of the pointer or address in the binary object file combination. Data relocation

section ( data relocations)

The effect is similar relocations section, but is a relocatable data segment pointers. Symbol table section ( simbol

table)

This part also contains the data for recording linker used for cross-reference to named variables and functions (symbol) between the binary object file.

String table section ( string table)

This portion contains the symbol corresponding to the name string. Each binaries are to perform a data structure ( exec structure )Start. The form of the data

structure as follows:

struct exec {
unsigned long a_midmag; unsigned
long a_text; unsigned long a_data;
unsigned long a_bss; unsigned long
a_syms; unsigned long a_entry;
unsigned long a_trsize; unsigned long
a_drsize;};

Function of each field is as follows:

a_midmag - The field containing the N_GETFLAG () , N_GETMID with N_GETMAGIC () Sub-section accessible by the link is loaded at runtime into the process address

space. Macros N_GETMID () Machine for returning an identifier ( machine-id) , Indicating a binary file that will run on any machine. N_GETMAGIC () Macro specified magic number,

which uniquely determines the difference between the binaries loaded with other documents. Field must contain one of the following values:

OMAGIC - It represents code and data segments and head immediately after the execution is stored in a row. The kernel code and data segments are loaded into

read-write memory.

NMAGIC - with OMAGIC Like, code and data segments and head immediately after the execution is stored in a row. However, the kernel code is loaded into a read

only memory section and load data into the code segment begins next writable memory boundaries.

ZMAGIC - Kernel loads separate page from the binary executable file if necessary. Performs a header, the code and data segments are processed blocks into a

plurality of page sizes linker. Kernel code loaded when the page is read-only, and the page data segment is writable.

a_text - The length field contains the value of the code segment, the number of bytes.

a_data - This field contains the length of the data section, the number of bytes.

--427--
9.17 exec.c program

a_bss - contain' bss Segments' length, with a core which is provided after the initial data segment break ( brk ). When the kernel loader, this memory can be written after the

data segment is showing, and, if initially all zeros.

a_syms - The symbol table contains the byte length of the value part.

a_entry - After the core containing the executable file is loaded into memory, the memory address of the start of program execution.

a_trsize - This field contains the code relocation table size, the number of bytes.

a_drsize - This field contains the data relocation table size, the number of bytes. in a.out.h Header file defines several macros use exec Conformance testing structure or

the positioning of each execution file portion (section) the position of the offset value. These macros are:

N_BADMAG (exec) in case a_magic Field can not be identified, a nonzero value is returned.

N_TXTOFF (exec) Starting position code segment byte offset value.

N_DATOFF (exec) Start position of the data segment byte offset value.

N_DRELOFF (exec) Data re-start position of the byte offset location table.

N_TRELOFF (exec) Starting position of the code byte relocation table offset.

N_SYMOFF (exec) Start position of the symbol table byte offset value.

N_STROFF (exec) Starting position of the string table byte offset value. Relocation records having a standard format, which

relocation information ( relocation_info) To describe the structure:

struct relocation_info {
int r_address;
unsigned int r_symbolnum: 24, r_pcrel: 1,
r_length: 2, r_extern: 1,
r_baserel: 1, r_jmptable: 1,
r_relative: 1, r_copy: 1;

};

Meaning of each field in the structure is as follows:

r_address - This field contains the byte offset pointer link required program processing (editing) of. Relocations offset value from the beginning of the code segment is

counted, the value of the offset data relocation is calculated from the beginning of the data segment. The linker will have been stored in the offset value using the relocation

records the calculated new value is added.

r_symbolnum - This field contains a sequence number value in the symbol table (not a byte offset) symbol structure. After the linker is calculated absolute

address of the symbol, it is added to the address pointer being relocated. (in case r_extern Bits is 0 The situation is different, see below. )

r_pcrel - If this bit is set, the linker will think is updating a pointer that use pc Relative addressing mode, machine code instruction section belongs. When

using this program is run relocated pointer that addresses are implicitly added to the pointer.

r_length - The pointer field contains the length of the 2 The power value: 0 Show 1 Bytes long, 1 Show 2 Bytes long, 2 Show 4 Bytes long.

r_extern - If the bit is set, indicating that the relocation requires an external reference; in this case must use a symbolic link to update the corresponding address pointer.

When this bit is 0 , Then relocation is "local"; the Linker pointer is updated to reflect changes in the respective segment load address, rather than reflecting a change in symbol

values ​(unless simultaneously provided r_baserel , See below). under these circumstances, r_symbolnum

Contents of the field is a n_type Value (see below); such field tells the linker is repositioned pointer to that segment.

r_baserel - If this bit is set, then r_symbolnum Field specifies a symbol to be relocated to Global Offset Table ( Global Offset Table) One offset value. At

runtime, the global offset table is set to the offset address of a symbol.

r_jmptable - If the bit is set, then r_symbolnum Field specifies a symbol to be relocated to the procedure linkage table ( Procedure

--428--
9.17 exec.c program

Linkage Table) One offset value.


r_relative - If the bit is set, then the relocation to the target file will be the image file of its components at runtime loaded address associated. Such relocation

occurs only in the shared object files.

r_copy - If the bit is set, the relocation record specifies a symbol, the symbol of the content is copied to r_address designated place. The copy operation is

shared by the target modules in a suitable data items completed runtime linker.

The symbol name is mapped to an address (or, more colloquially string is mapped to a value). Because the linker to adjust the name address, a symbol must be used to

indicate its address until you have been given an absolute address value. Symbol is the name of a variable length symbol table and a fixed-length string table records the

composition. Symbol table is nlist An array of structures, as shown below:

struct nlist {
union {
char * N_name;
long
n_strx;
} N_un;
unsigned char n_type;
char n_other;
short n_desc;
unsigned long n_value;
};

The meaning of each field is:

n_un.n_strx - This name has signed byte offset in the string table. When the program uses nlist () Accessing a function symbol table, this field is replaced n_un.n_name

Field, which is a pointer to the memory string.

n_type - Used to link the program to determine how to update the value of the symbol. Using a bit mask ( bitmasks) can n_type Field is divided into three

sub-fields, for N_EXT Type of sign bit, the program will link them as "external" symbol, and other binary object files to allow references to them. N_TYPE The

mask bits for the linker of interest:

N_UNDF - Undefined symbol. Linker must locate external symbols having the same name in the other binary object file to determine the absolute value

of the symbol data. Under special circumstances, if n_type Field is nonzero and no binary file defines this symbol, the linker in BSS The symbol resolution

is in a segment address, a length equal to retain n_value

Byte. If more than one binary symbol is not defined in the object file and the binary value of the target files are inconsistent its length, the linker will

select all files in the target binary maximum length.

N_ABS - An absolute symbol. Linker does not update an absolute symbol.

N_TEXT - A code symbols. The value of this symbol is the code address, the linker when combining binary object file updates its value.

N_DATA - A data symbol; and N_TEXT Similarly, the data for the address. An offset value corresponding to the code and data symbols but the value is not the address

file; offset to find the file, it is necessary to determine the relevant portion of the load start address and subtracting it, and then add the offset portion.

N_BSS - One BSS Symbols; data symbols and code or the like, but without a corresponding shift in the binary object file.

N_FN - A file name of the symbol. When you merge binary object files, the linker will insert the symbol in binary notation before. Name of the symbol is to give the

filename linker, and its value is a binary file in the first code segment address. Symbols do not need to file name, but very useful for the transfer procedure when

linking and loading.

N_STAB - Mask transfer procedure for selecting the symbol (e.g. gdb) Bit of interest; its value stab () Explained.

n_other - According to the field n_type Determining a segment, independent information about the symbols provide symbol relocation operation. Currently, n_other

Lowest field 4 Bits comprising one of two values: AUX_FUNC with AUX_OBJECT (For definition, see < link.h> ). AUX_FUNC

The symbol associated with the function call, AUX_OBJECT The symbols associated with the data, whether they are located in the data segment is a code segment. This field is

used to link the main program ld To create a dynamic executable.

--429--
9.18 stat.c program

n_desc - Transfer procedure reserved for use; linker does not process it. The debugger different fields for a different purpose.

n_value - Containing the value of the symbol. For the code, data, and BSS Symbol, which is an address; for other symbols (e.g. symbols transfer procedure), the value may

be arbitrary.

String table is of length u_int32_t Followed by a null The end of the symbol strings. The length of the table is representative of the size, in bytes, so 32 Its minimum position

on the machine (or the first 1 Offset of the string) always 4 .

9.18 stat.c program

9.18.1 Functional Description

The program implements the system call takes the file status information stat () with fstat () , And the information is stored in the file structure of the buffer status of the user.

stat () Natori is the use of file information, fstat () Using a file handle (descriptor) to extract information.

9.18.2 Code comments

program 9-16 linux / fs / stat.c

1/*
2 * Linux / fs / stat.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <errno.h>
// error number header files. The system comprises various error number. (Linus imported from the minix).

8 #include <sys / stat.h> // File Status header file. Containing configuration file or system state stat {} and constants.

910 #include <linux / fs.h>


// file system header files. Table structure definition file (file, buffer_head, m_inode, etc.).
11 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

12 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

13 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

14
//// Copy the file status information.

// parameters are inode file corresponding to the node i, statbuf stat file status is structured pointer, for storing the acquired state information.

15 static void cp_stat (Struct m_inode * Inode, struct stat * Statbuf)


16 {
17 struct stat tmp;
18 int i;
19
// first verifies (or distribution) of the data storage memory.

20 verify_area (Statbuf, sizeof (* statbuf)); // temporary then copy the

information on the corresponding node.

twenty one tmp.st_dev = inode-> i_dev; // device number file is located.

twenty two tmp.st_ino = inode-> i_num; // file i node number.


twenty three tmp.st_mode = inode-> i_mode; // file attributes.
twenty four tmp.st_nlink = inode-> i_nlinks; Number of connections // file.

25 tmp.st_uid = inode-> i_uid; User id // file.

--430--
9.19 fcntl.c program

26 tmp.st_gid = inode-> i_gid; Group id // files.


27 tmp.st_rdev = inode-> i_zone [0]; // device number (if the file is a special character file or file blocks).
28 tmp.st_size = inode-> i_size; // file size (in bytes) (if the file is a regular file).
29 tmp.st_atime = inode-> i_atime; // last access time.
30 tmp.st_mtime = inode-> i_mtime; // Last Modified.
31 tmp.st_ctime = inode-> i_ctime; // node last modified time.
// Finally, copy the status information to the user buffer.
32 for (i = 0; i <sizeof (tmp); i ++)
33 put_fs_byte (((Char *) & tmp) [i], & ((char *) statbuf) [i]);
34 }
35
//// file status system call function - get file status information based on the file name. // filename parameter is specified file name,

statbuf is a pointer to the buffer to store state information. // returns 0 if the error an error code is returned.

36 int sys_stat (Char * filename, struct stat * Statbuf)


37 {
38 struct m_inode * Inode;
39
// First, find the i-node corresponding to the file name, error if the error code is returned.

40 if (! (inode = namei (Filename)))


41 return - ENOENT ;
I // Copy file status information to the user on the node buffer, and releases the node i.
42 cp_stat (Inode, statbuf);
43 iput (Inode);
44 return 0;
45 }
46
//// file status system call - get file status information based on the file handle. // fd parameter is the handle of the specified file

(descriptor), statbuf the buffer pointer is stored status information. // returns 0 if the error an error code is returned.

47 int sys_fstat (Unsigned int fd, struct stat * Statbuf)


48 {
49 struct file * F;
50 struct m_inode * Inode;
51
// If the file handle is greater than the number of files a program opens up NR_OPEN, or a pointer to the file structure of the handle is null, or the node I // file structure corresponding

to the field is empty, an error, returns an error code and exits.

52 if (fd> = NR_OPEN ||! (F = current -> filp [fd]) || (inode = f-> f_inode))!
53 return - EBADF ;
// Copy the file i-node status information to the user buffer.
54 cp_stat (Inode, statbuf);
55 return 0;
56 }
57

9.19 fcntl.c program

9.19.1 Functional Description

From the beginning of this section a number of documents annotated, all belonging to the upper handlers directories and files operations.

--431--
9.19 fcntl.c program

This document fcntl.c Achieve the document control system call fcntl () And two file handles (descriptor) replication system call dup () with dup2 () .

dup2 () Specify the value of the new handle, and dup () Current minimum value of unused handle is returned. Handle copy operation is mainly used in the standard input file I / O

redirection and operational aspects of the pipeline.

9.19.2 Code comments

program 9-17 linux / fs / fcntl.c

1/*
2 * Linux / fs / fcntl.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <string.h>
// string header file. Mainly defines the built-in functions related to operation of the string.

8 #include <errno.h> // error number header files. The system comprises various error number. (Linus imported from the minix).

9 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,
// Some parameters related descriptors set and get embedded assembly function macro statement.

10 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

11 #include <asm / segment.h> // operation section header. For embedded segment register defines the operation assembly function.

1213 #include <fcntl.h>


// control file header. Operable control descriptor file and constants defined symbols.
14 #include <sys / stat.h> // File Status header file. Containing configuration file or system state stat {} and constants.

1516 extern int sys_close (Int fd);


// close the file system calls. (Fs / open.c, 192)
17
//// copy file handle (descriptors).
// fd argument is you want to copy a file handle, arg specifies the minimum number of new file handles. // returns the new file

handle or an error code.

18 static int dupfd (Unsigned int fd, unsigned int arg)


19 {
// If the file handle is greater than the number of files a program opens up NR_OPEN, or file structure of the handle does not exist, an error, an error code and returns // exit.

20 if (fd> = NR_OPEN ||! current -> filp [fd])


twenty one return - EBADF ;
// If the new handle value specified arg is greater than the maximum number of open files, an error, an error return code and exits.

twenty two if (arg> = NR_OPEN )


twenty three return - EINVAL ;
// find the item index number greater than or equal arg but not yet used in the array of pointers to the file structure of the current process.

twenty four while (arg < NR_OPEN )


25 if ( current -> filp [arg])
26 arg ++;
27 else
28 break;
// If the new handle value found arg is greater than the maximum number of open files, an error, an error return code and exits.

29 if (arg> = NR_OPEN )
30 return - EMFILE ;
// Close the figure flag bit is reset when the handle is executed. I.e. running exec () is not closed when the handle class functions.

31 current -> close_on_exec & = ~ (1 << arg);


// enabling the pointer is equal to the original file structure pointer handle fd of the file reference count is incremented.

32 ( current -> filp [arg] = current -> filp [fd]) -> f_count ++;
33 return arg; // returns the new file handle.

--432--
9.19 fcntl.c program

34 }
35
//// Copy the file handle system calls.
// copy specified file handle oldfd, the new handle value equal to newfd. If newfd is already open, close it first.
36 int sys_dup2 (Unsigned int oldfd, unsigned int newfd)
37 {
38 sys_close (Newfd); // If the handle newfd is already open, close it first.
39 return dupfd (Oldfd, newfd); // copy and return the new handle.

40 }
41
//// Copy the file handle system calls.
// copy specified file handle oldfd, the value of the new handle is currently the smallest unused handle.

42 int sys_dup (Unsigned int fildes)


43 {
44 return dupfd (Fildes, 0);
45 }
46
//// file control system call functions.
// fd argument is the file handle, cmd is the operation command (see include / fcntl.h, 23-30 lines).

47 int sys_fcntl (Unsigned int fd, unsigned int cmd, unsigned long arg)
48 {
49 struct file * Filp;
50
// If the file handle to open the process up to a value greater than the number of files NR_OPEN, or file structure pointer of the handle is empty, an error // return an error code and exit.

51 if (fd> = NR_OPEN ||! (Filp = current -> filp [fd]))


52 return - EBADF ;
// separately according to different command cmd.

53 switch (cmd) {
54 case F_DUPFD : // copy the file handle.
55 return dupfd (Fd, arg);
56 case F_GETFD : // get close flag to perform file handles.
57 return ( current -> close_on_exec >> fd) & 1;
58 case F_SETFD : Close flag // set handle execution. Bit 0 is set arg is set, otherwise closed.
59 if (arg & 1)
60 current -> close_on_exec | = (1 << fd);
61 else
62 current -> close_on_exec & = ~ (1 << fd);
63 return 0;
64 case F_GETFL : // get file status flags and access modes.
65 return filp-> f_flags;
66 case F_SETFL : // set file status and access mode (set according to arg added, non-blocking flag).

67 filp-> f_flags & = ~ ( O_APPEND | O_NONBLOCK );


68 filp-> f_flags | = arg & ( O_APPEND | O_NONBLOCK );
69 return 0;
70 case F_GETLK : case F_SETLK : case F_SETLKW : // not implemented.

71 return -1;
72 default:
73 return -1;
74 }
75 }
76

--433--
9.20 ioctl.c program

9.20 ioctl.c program

9.20.1 Functional Description

ioctl.c File implements the input / output control system call ioctl () . The main call tty_ioctl () Function of the terminal I / O Control.

9.20.2 Code comments

program 9-18 linux / fs / ioctl.c

1/*
2 * Linux / fs / ioctl.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #include <string.h>
// string header file. Mainly defines the built-in functions related to operation of the string.

8 #include <errno.h> // error number header files. The system comprises various error number. (Linus imported from the minix).

9 #include <sys / stat.h> // File Status header file. Containing configuration file or system state stat {} and constants.

1011 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

1213 extern int tty_ioctl (Int dev, int cmd, int arg); // terminal ioctl (chr_drv / tty_ioctl.c, 115).

14
// definition of the input and output control (the ioctl) function pointer.

15 typedef int (* ioctl_ptr ) (Int dev, int cmd, int arg);


16
// define several types of equipment systems.

17 #define NRDEVS ((Sizeof ( ioctl_table )) / (Sizeof ( ioctl_ptr )))


18
// ioctl operation function pointer table.

19 static ioctl_ptr ioctl_table [] = {


20 NULL , / * Nodev * /
twenty one NULL , / * / Dev / mem * /
twenty two NULL , / * / Dev / fd * /
twenty three NULL , / * / Dev / hd * /
twenty four tty_ioctl , / * / Dev / ttyx * /
25 tty_ioctl , / * / Dev / tty * /
26 NULL , / * / Dev / lp * /
27 NULL }; / * Named pipes * /
2829

//// system calls - input and output control functions.


// Parameters: fd - a file descriptor; cmd - command code; arg - argument. // Returns: 0 for

success, otherwise it returns an error code.

30 int sys_ioctl (Unsigned int fd, unsigned int cmd, unsigned long arg)
31 {
32 struct file * Filp;
33 int dev, mode;
34
// If the file descriptor exceeds the number of files can be opened, or to a file structure descriptor pointer is empty, an error code is returned, exit.

--434--
9.20 ioctl.c program

35 if (fd> = NR_OPEN ||! (Filp = current -> filp [fd]))


36 return - EBADF ;
// get the corresponding file attribute. If the file is not a character file, not a block device file, an error code is returned to exit.

37 mode = filp-> f_inode-> i_mode;


38 if (! S_ISCHR (Mode) &&! S_ISBLK (Mode))
39 return - EINVAL ;
// get node device number i from the character or block file. If the device number is greater than the number of existing equipment system, an error number is returned.

40 dev = filp-> f_inode-> i_zone [0];


41 if ( MAJOR (Dev)> = NRDEVS )
42 return - ENODEV ;
// If the device is not in the ioctl function corresponding to the function table pointer, then an error code is returned.

43 if (! ioctl_table [ MAJOR (Dev)])


44 return - ENOTTY ;
// otherwise return the actual ioctl function return code, success, returns 0, otherwise it returns an error code.

45 return ioctl_table [ MAJOR (Dev)] (dev, cmd, arg);


46 }
47

--435--
10.1 Overview

The first 10 Chapter Memory Management ( mm)

10.1 Outline

in Intel 80x86 Architecture, Linux Kernel memory manager uses paging management. Using the page directory and page table structure of the other processing core part of

the code the application and release operations to memory. Memory management is a memory page as a unit, and a memory page is the address of a continuous 4K Bytes of

physical memory. By page directory entries and page table entries, you can use addressing and managing the specified page. in Linux 0.11 Memory management directory, there

are three documents, such as a list 10-1 As shown in:

List 10-1 Memory Management subdirectory File List

Name Size Last Modified Time (GMT) Description

Makefile 813 bytes 1991-12-02 03:21:45 m

memory.c 11223 bytes 1991-12-03 00:48:01 m


page.s 508 bytes 1991-10-02 14:16:30 m

among them, page.s Relatively short document, containing only the abnormal memory page of interrupt processing ( int 14 ). The main achievement of the processing of the

missing pages and page write-protected. memory.c It is the core memory page file management, memory for initialization, page directory and page table management and other

core part of the application process for memory.

10.2 Overall Functional Description

in Intel 80X86 CPU The program uses the address in the addressing sequence is composed of segment and offset values. This address is not directly used to address the

physical memory address, and therefore referred to as virtual addresses. In order to address the physical memory, a need for an address translation mechanism to map or transform

the virtual address to physical memory, the other one of the main function is the main function of this address conversion memory management mechanism (memory management

is seeking memory site protection mechanisms. due to space limitations, not discussed in this chapter). Virtual segment address management mechanism is first converted into a

form of intermediate address -CPU 32 Bit linear address and then use this paging management system maps linear addresses to physical addresses.

In order to clarify Linux Kernel memory management mode of operation, we need to understand how memory paging management, understand the mechanism of

addressing. Object of the paging supervisor is to map pages of physical memory to a linear address. When analyzing memory management procedures in this chapter, a clear

distinction needs to clear a given address is linear address or actual physical memory address.

10.2.1 Memory paging management system

in Intel 80x86 Systems, paging management table is performed by two memory page directory table and page table thereof. See Fig. 10-1

Fig.
Where the structure of the page table and page directory table is the same, the same entry structure. Each entry (referred to as the page directory entry) (page directory

table 4 Byte) is used to address a page table, and each page table entry ( 4 Byte) specifies a physical memory pages. Therefore, if you specify a page directory entry and a page

table entry, we can uniquely determine the corresponding physical memory pages. Page directory table occupied by a memory, so most

--437--
Overall 10.2 Functional Description

More than can be addressed 1024 A page table. Each page table while it occupies a memory, a page table can therefore address up to 1024 Physical memory pages. In this way 80386

All page table, a page table of contents can be addressed were addressed 1024 X 1024 X 4096 = 4G Memory space. in Linux 0.11 Kernel, all processes using a page table of

contents, and each process has its own page table.

For the rest of the application process or kernel is concerned, the use of memory when applying linear address. Next we asked: "So, a linear address how to use these

tables to map to a physical address on it?." To use the paging mechanism, a 32 Bit linear address is divided into three sections, each directory entry is used to specify a page, a

page table entry and a corresponding physical memory page address offset, which can be addressed to a linear address indirectly specified physical memory location. See Fig. 10-2 Fig.

a page table entry page table entry page table entry page
The table
main memory area of ​physical memory

table entry of

entry page
1024 Memory
a page table
Page
table entry of
Memory page

entry page
memory page

page table memory page

entry in the memory page

Page table memory page

memory page

memory page
Page directory table
memory page
directory entry directory entry entry page entry page table entry page table entry
page table memory page
directory page
entry page entry in the
memory page
1024 Page directory Page table
memory page

memory page memory page

Map 10-1 Page directory table and page table structure diagram

131 222 1211 0

Linear Address: page directory entry page table entry page offset value

Page directory table Page table Page frame

Page table entry

Page directory entry Physical address

CR3

Map 10-2 A schematic view of linear address conversion

Bit linear address 31-22 Altogether 10 Bits are used to determine the directory entry in the page directory, bit 21-12 Addressing page directory entry for the specified page

table page table entry, the last 12 Offset address bits of a physical memory page table entry exactly as specified in.

--438--
Overall 10.2 Functional Description

In the memory management functions, a large amount of calculation using the actual transformation from the linear address to physical address. For a given process, a

linear address through FIG. 10-2 Address conversion relationship shown, we can easily find the page directory entry corresponding to the linear address. If the directory entry is

valid (being used), then the directory entry specified in the page frame address of the page table base address in physical memory, then the combined linear page table entry

pointer address, if the page table entry is valid, the page table entry in the designated page frame address, we can determine the address specified ultimate linear address

corresponding to the actual physical memory pages. Conversely, if the physical memory page address to be used in a known, find the corresponding linear address is required for

all of the entire page directory table and page table search. If the physical memory pages are shared, we may find more corresponding linear address. Map 10-3 The method of

using the image shows a given linear addresses are mapped to physical memory pages. For the first process (task 0 ), Which is in the page table after table of contents page, a

total of 4 page. For the application process, its memory page table is used when the process of creating an application to the memory management procedures, and therefore is in

the main memory area.

Physical Memory
16M

The corresponding memory address

table corresponding memory page

32-bit linear address

The primary bank

Directory entry page table entry page offset value

2
Process's page

head.s code page directory table A memory

Map 10-3 Linear address corresponding to the physical address

A system can exist simultaneously multiple page directory table, but at some point there is only one page table of contents is available. The current page directory table is CPU

Register CR3 To determine which stores the physical memory address of the current page directory table. But in the book in question Linux The kernel using only one page

directory table.

In Fig. 10.1 We see that each page table entry corresponding to the physical memory pages 4G Within the address range is random and is determined by the page table

entry in page frame address of the content, that is, setting the page table entry is determined by the memory management program. Each entry in the page frame address, access

flag, dirty (has rewritten) flag and the flags and the like exist. Structure entry can be found in FIG. 10-4 Fig.

31 12 11 0

U/ R/
Page frame address bits 31..12 (PAGE Available
P
FRAME ADDRESS) (AVAIL) 0 0 DA 0 0
S W

Map 10-4 Page directory and page table entry structure

--439--
Overall 10.2 Functional Description

Among them, the page frame address ( PAGE FRAME ADDRESS) It specifies a physical memory starting address. Because the memory pages are located 4K

On the border, so its low 12 Bit is always 0 Therefore low entry 12 Bits may be used for it. In a table of contents page, the page frame address entry is the starting address of a

page table; in a second stage page table, the page frame address of the page table entry contains the physical memory page address desired memory operations.

Bitmap exists ( PRESENT - P ) To determine whether a page table entry can be used to address the conversion process. P = 1 It indicates that the item is available. When a

directory entry or a second entry level P = 0 , Then the entry is invalid, address translation can not be used. At this time, all other bits of the entry are available to the program;

processor, these bits are not tested.

when CPU When trying to use a page table entry for address translation, if any at this time a page table entry P = 0 , The processor will send abnormal signals page. At this

page fault exception handler can put the requested page into physical memory, and the instruction that caused the exception will be re-executed.

I visited ( Accessed - A ) And modified ( Dirty - D ) Bit is used to provide information about the pages used. In addition to the modified bits of the page directory entries, these

bits are set by hardware, but not reset.

Before a memory read or write operation, CPU The provision of the relevant bits accessed directories and secondary page table entry. Before a write to an address covered

by the page table entry two, the processor will set the two page table entry modified bit, and the page directory entry is modified bit unused. When the demand for more memory

than the actual amount of physical memory, the memory manager can use these bits to determine which page can be removed from memory to make room. The memory manager

also oversees the testing and resetting these bits.

Read / Write bit ( Read / Write - R / W ) And user / super user bits ( User / Supervisor - U / S ) Not used for address translation, but page-level mechanism to protect, by CPU In

the same time during the address translation operation.

10.2.2 Linux In physical memory management and allocation

With these concepts, we can explain Linux A method of memory management. But also you need to know Linux 0.11 Using kernel memory space. for Linux

0.11 Core, which supports up to default 16M Physical memory. In having a 16MB Memory

80x86 Computer system, Linux Physical memory occupied by the kernel part of the foremost section, FIG. end Mark the end position of the kernel module. Followed by a high-speed

buffer memory address as its highest 4M . High-speed buffer memory and is displayed ROM BIOS Divided into two sections. The remaining portion of memory called a main memory

area. Main memory area is allocated by the program management of this chapter. If the system still exist RAM When the virtual disk, the primary bank should deduct the preceding

virtual disk memory space occupied. When you need to use the primary bank would need to apply to the memory management procedures in this chapter, the application of the

basic units of memory pages. Function of each part of the entire physical memory is a schematic view of FIG. 10-5 Fig.

Kernel Module Cache Virtual disk The primary bank

end 0 640K 1M 4M 4.5M 16M

Memory and BIOS ROM

Map 10-5 A schematic view of a main memory area

In the boot chapter, we already know, Linux The page directory and page tables are in the program head.s Set. head.s Program at the physical address 0 Department store

a page table of contents, followed by a 4 A page table. This 4 Page table will be used for mission 0 Other derivative process will apply for memory pages in the main memory area

to store their page tables. Chapter two is the program used to operate on these tables, thereby achieving

--440--
Overall 10.2 Functional Description

Memory allocation using now the main memory area.

In order to save the physical memory, the call fork () When generating a new process, a new process with the original process will share the same memory area. Only

when one of the write process, the system will allocate memory for additional pages. This is the concept of copy-on-write.

page.s A program for realizing abnormal page interrupt processing ( int 14 ). The interrupt handler calls were interrupted due to the missing pages and page write-protected

due memory.c middle do_no_page () with do_wp_page () Function for processing. do_no_page () Page will need to take the device to the block from the memory at a specified

location. In the case of shared memory pages, do_wp_page () Will be written copy of the page ( copy on write , Copy-on-write), which also canceled the sharing of the page.

10.2.3 Linux Linear kernel address space allocation

When the code reading this chapter, we also need to understand the distribution of a process executing program code and data in a virtual linear address space, see the

chart below 10-6 Fig.

start_code Length brk


Environmental parameter block

Code data bss parameter

nr * 64M (Nr + 1) * 64M


Length end_code

Stack Pointer
Length end_data
* Where nr is task number

Map 10-6 Process linear address space distribution

Each process in the linear address are from nr * 64M The address of the start position ( nr Is task number), occupied by the linear address space is

64M . Wherein the ambient parameter data block up to the last section 128K Which left initial stack pointer. In the process of creation bss The first section of the page is initialized to

all zeros.

10.2.4 Copy on write ( copy on write )mechanism

When the process A Use of system calls fock Create a child process B When, as a child process B In fact, it is the parent process A A copy of the parent process and therefore

will have the same physical page. That in order to achieve the goal to save memory and speed the creation of, fork () Function will let the child process B Read-only shared parent A Physical

page. At the same time the parent process A Physical access to these pages are also set to read-only. See memory.c Program copy_page_tables () function. As a result, when the

parent process A Or the child process B Either a write operation, the implementation of these will have to share the physical page of page faults abnormal ( page_fault int14) Interrupted,

this time CPU Exception handling function execution system provided do_wp_page () To try to resolve this anomaly.

do_wp_page () This will result in a write abort to cancel the shared physical page (using un_wp_page () Function), a new copy of the physical page write process, the

parent process A And child processes B Each piece of content has the same physical page. But then it really made the copy operation (only one physical copy this page). And the

piece will be performed physical page write operation can be marked write access. Finally, return from the exception handler, CPU It will just lead to re-execute the write operation

instruction exception, so the process can continue execution.

Therefore, for the write process in its own virtual address range, it will be used above the passive copy-write operation, namely: write -> Page aborted -> Write-protection

exception processing -> Re-write operation is performed. As for the system kernel, when a write operation is performed in the virtual address range for a process, for example, the

process of calling a system call, the system call will copy the data to process the buffer area, it will take the initiative to call to memory page validation function write_verify () To

determine whether there has been a shared page exists, if so, to copy a page write operation.

--441--
10.3 Makefile file

10.3 Makefile file

10.3.1 Functional Description

This document is mm Directory management program to compile profiles, total make Program.

10.3.2 Code comments

program 10-1 linux / mm / Makefile

1 CC = Gcc # GNU C language compiler.


2 CFLAGS = -O -Wall -fstrength-reduce -fcombine-regs -fomit-frame-pointer \
3 - finline-functions -nostdinc -I ../ include
# C compiler options. -Wall display all warnings; -O optimization option, to optimize code size and execution time;
# - fstrength-reduce execution code optimization cycle, excluding iteration variable; -fomit-frame-pointer will be omitted to save unnecessary

# The frame pointers; -fcombine-regs merge register, reduce the use of register class; -finline-functions all Jane
# Short single function calling program code embedded; -nostdinc -I ../ include not using the default path comprises a file, and
# Here the use of the specified directory (../include).
4 AS = Gas # GNU assembler.
5 AR = Gar # GNU binary file processing program for creating, modifying and extracting files from the archive.
6 LD = Gld # The GNU linker.
7 CPP = Gcc -E -nostdinc -I ../ include
# C pre-processing options. -E C only run pre-treatment, pre-treatment and the results for all of the specified program is output to the standard output C

# The apparatus or a specified output file; -nostdinc -I ../ include op.


8
# The following rule indicates that make use of the following command will compile all .c files generated .s Assembler. The rule of command

# Refers gcc CFLAGS using the specified options compiled C code is compiled without stops (-S), thereby generating
# C each corresponding to the input file assembler code file. Assembler default file name is generated by the original file name C
# Remove .c and .s suffix plus. -o represented followed by the name of the output file. Of which $ *. S (or $ @ ) is automatic target variable,

# $ <Represents the first prerequisite here that is qualified * .c files.


9 .co:
10 $ (CC) $ (CFLAGS) \
11 - c -o $ *. o $ <
# The following rule means that all .s assembler .o files compiled into object files. Line 22 is a command to achieve the specific operation.

12 .so:
13 $ (AS) -o $ *. O $ <
14 .cs: # Similar to the above, * c file -. * .S assembler files. Not connect.
15 $ (CC) $ (CFLAGS) \
16 - S -o $ *. S $ <
1718 OBJS
= Memory.o page.o # Define the target file variable OBJS.
1920 all: mm.o

2122 mm.o: $ (OBJS)


# Use the following prerequisites have after OBJS command to connect to the target mm.o

twenty three $ (LD) -r -o mm.o $ (OBJS)


twenty four

# The following rules for the cleanup. When performing 'make clean', will execute commands on the 26-27 line, remove all compiled
# Connection file generated. 'Rm' command is to delete the file, meaning -f option is to ignore the file does not exist, and does not delete the information.

25 clean:

--442--
10.4 memory.c program

26 rm -f core * .o * .a tmp_make
27 for i in * .c; do rm -f `basename $$ i .c`.s; done
28
# Here was the objective or rules for checking dependencies between files. Methods as below:

# Sed string editing program for the Makefile (where that is their own) for processing, the output is deleted Makefile
# File '### Dependencies' all rows behind the row (row 35 starting from below), and generates tmp_make
# Temporary files (for 30 lines). Gcc then performs a preprocessing operation on each file in the C mm / directory.
# - M flag tells the preprocessor output description of the rules relating to each target file, and make compliance with these rules syntax.

# For each source file, the output of preprocessor make a rule, the result is a certain form of the corresponding source file
# File name plus its dependencies - lists all the header files included in the source file. The pretreatment results are added to the temporary

# Tmp_make file, and then copy the temporary file into a new file Makefile.

29 dep:
30 sed '/ \ # \ # \ # Dependencies / q' <Makefile> tmp_make
31 (For i in * .c; do $ (CPP) -M $$ i; done) >> tmp_make
32 cp tmp_make Makefile
3334 ### Dependencies:

35 memory.o: memory.c ../include/signal.h ../include/sys/types.h \


36 . . /include/asm/system.h ../include/linux/sched.h ../include/linux/head.h \
37 . . /include/linux/fs.h ../include/linux/mm.h ../include/linux/kernel.h

10.4 memory.c program

10.4.1 Functional Description

This program paged memory management. To achieve the main memory area and dynamically allocated memory recovery operation. For the physical memory

management kernel uses an array of bytes ( mem_map [] ) To represent the state of the main memory area of ​all physical memory page. Each byte describes the occupancy state of

a physical memory page. Where the value indicates the number of occupied, 0 It indicates that the corresponding physical memory is idle. When applying a physical memory, will

increase the value of the corresponding byte 1 . For management process virtual linear address of the kernel uses page directory table and page table structure to manage the

processor. The mapping relationship between the physical memory pages and the process linear address is handled by modifying the contents page directory and page table

entries. Next, several major functions provided to the procedure described in detail.

get_free_page () with free_page () These two functions are used to manage the physical memory in the main memory area of ​occupancy and vacancy, regardless of the

linear address of each process.

get_free_page () Function is used to apply a free memory page in the main memory area, and returns to the start address of the physical memory page. First, it scans the

memory array of FIG byte page mem_map [] , Is looking for value 0 Byte entries (corresponding to the free page). If there is no return 0 End, represents the physical memory is used

up. If the value is found 0 Byte, it is set 1 And converted to the corresponding free page start address. Then make clear operation of the memory page. Finally, return to the starting

address of the free physical memory pages.

free_page () For releasing a physical memory at the specified address. It first determines whether the memory address specified by < 1M , If it returns, because 1M Within

the kernel is specific; if the specified physical memory address is greater than or equal to the actual top-end memory address, an error message is displayed; then converted from

page number specified by the memory address: ( addr - 1M) / 4K ; Then determines the corresponding page number mem_map [] Whether byte entries 0 , If not for the 0 , It

decreases 1 Return; otherwise cleared the byte entries, and shows " Trying to release a free page " Error message.

free_page_tables () with copy_page_tables () These two functions places a physical memory page table corresponding to the block ( 4M ) Units, linear release or copies the

specified address and length (number of page table) corresponding to the physical memory page block. Not only for the items corresponding to the page directory and page table

management in linear address modification, but also take up or release operation for each page table page table entries corresponding to all pages of physical memory.

free_page_tables () And for releasing the linear address to specify the length (the number of page table) corresponding to the physical memory pages. It first determines

whether the designated address is in linear 4M On the boundary, if not, an error message and freezes the display; then determines whether the specified address value = 0 ,if,

--443--
10.4 memory.c program

Error message is displayed " Trying to free up space occupied by the core and buffer " And crash; number of directory entries in the page directory table occupied then calculates size

, I.e. the number of page table and calculates the corresponding directory entry starting number; then occupied start from a corresponding home directory entries, all released size Directory

entries; simultaneous release of all page table entries and the corresponding physical memory page corresponding to the page directory entry of the table referred to; the last page

is refreshed transformation cache.

copy_page_tables () For copying the specified linear address and length (number of page tables) corresponding to the memory page directory and page table entries so as

to be copied to the corresponding page directory and page tables are shared original area of ​physical memory used. This function first verify that the specified source and

destination address of the linear address are linear 4Mb The memory boundary address, otherwise an error message is displayed, and crash; start page is then converted to the

corresponding linear address specified by the directory entry ( from_dir, to_dir ); And calculates the required memory area occupied by copying the number of tables (i.e., a page

directory entry number) page; and then begins the original directory entry page table entry to the new directory entry and free the page table entry, respectively. Page directory

table is only one, and the new process's page table need to apply to hold free memory pages; thereafter then the original and the new page directory and page table entry are set

to read-only page. When a page write operation on the use of aborted calls, copy on write operation. Finally, the shared physical memory pages corresponding to the byte array in

FIG. mem_map [] The flag increase 1 operating.

put_page () For mapping a physical memory page to the specified address at the specified linear. It first determines the validity of the specified memory page address, to be

in 1M And the most upper memory address outside the system, or warning; then calculates the designated directory entry corresponding to the linear address of the page directory

table; at this time if the directory entry is valid ( P = 1 ), Whichever corresponds to the address of the page table; otherwise apply to the free page using the page table, and sets the

corresponding page table page table entry attributes. Finally, still returns the specified physical memory page address.

do_wp_page () Page is aborted process (in mm / page.s Page implemented) called in write-protect handlers. It is first determined whether the address code region in the

process, if the program is terminated (code can not be altered); and copy operations when the page write ( Copy on Write ).

do_no_page () Page is invoked during aborted page fault handler. It first determines whether the specified offset with respect to the length of the linear address base address

value of the process in a process space. If it is greater than the length of the code plus data, or just beginning the process of creation, then immediately apply a physical memory,

and mapped into the process linear address, and then return; then try for page sharing operation, if successful, return immediately; otherwise apply for a a page memory and reads

the information from the device; if the page information is added, to specify a linear address + 1 Page length exceeds the length of the process code plus data, it would be over in

part cleared. The page is then mapped into the linear address specified.

get_empty_page () For obtaining a free physical memory and mapped to the specified linear address. Mainly used get_free_page ()

with put_page () Function to achieve this functionality.

10.4.2 Code comments

program 10-2 linux / mm / memory.c

1/*
2 * Linux / mm / memory.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * Demand-loading started 01.12.91 - seems it is high on the list of


9 * Things wanted, and it should be easy to implement -. Linus
10 * /
/*
* Load demand is beginning from 01.12.91 written - in the programming table seems to be the most important program,

* And should be easily prepared - linus


*/
1112 / *

13 * Ok, demand-loading was easy, shared pages a little bit tricker. Shared

--444--
10.4 memory.c program

14 * Pages started 02.12.91, seems to work -. Linus.


15 *
16 * Tested sharing by executing about 30 / bin / sh: under the old kernel it
17 * Would have taken more than the 6M I have free, but it worked well as
18 * Far as I could see.
19 *
20 * Also corrected some "invalidate ()" s - I was not doing enough of them.
twenty one * /

/*
* OK, demand load is relatively easy to write, and share the page it takes a little skill. Share page program is
* 02.12.91 start writing, it seems to work - Linus.
*
* By performing about 30 / bin / sh shared test operations: the old core needs to occupy more than among
* 6M memory, and now it does not. Now it seems to work very well.
*
* To "invalidate ()" functions have been corrected - I have done enough in this regard.

*/
2223 #include <signal.h>
// signal header files. Defined symbolic constant signal, the signal structure and the operation function prototype signal.

2425 #include <asm / system.h>


// system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

2627 #include <linux / sched.h> // scheduler header file, which defines the structure of the task_struct task, task 0 of the initial data,

// Some parameters related descriptors set and get embedded assembly function macro statement.

28 #include <linux / head.h> // head header file defines a simple structure segment descriptors, and several selectors constants.

29 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

3031 volatile void do_exit (Long code); // process handler exits, in kernel / exit.c, 102 rows.

32
//// display ran out of memory error message and exit.

33 static inline volatile void oom (Void)


34 {
35 printk ( ' out of memory \ n \ r ");
36 do_exit ( SIGSEGV ); // do_exit () exit code should be used, where a signal value SIGSEGV (11)
37 } // error code meaning is the same value "Resource temporarily unavailable", just synonymous.

38
// refresh the page cache conversion macro function.

@ In order to improve the efficiency of address conversion, CPU the most recently used page table data stored in the chip in the cache. After the modified page table // information, we

need to flush the buffer. The method used here to reload the page directory base register cr3 to refresh. // The following eax = 0, is the base address of the page directory.

39 #define invalidate () \
40 __asm ​__ ( " movl %% eax, %% cr3 "::" a "( 0))
4142 / * These are not to be changed without changing head.s etc * /

/ * Define the following needs to be changed if you need to change with head.s and other documents relevant information * / // linux 0.11 kernel by default supports a

maximum memory capacity of 16M, these definitions can be modified to fit more memory.

43 #define LOW_MEM 0x100000 // low-end memory (1MB).


44 #define PAGING_MEMORY (15 * 1024 * 1024) // paged memory 15MB. Primary bank up to 15M.
45 #define PAGING_PAGES ( PAGING_MEMORY >> 12) // physical memory pages after pages.

46 #define MAP_NR (Addr) (((addr) - LOW_MEM ) >> 12) // Specify the memory address mapping for the page number.

47 #define USED 100 // flags page is occupied, you see line 405.
48
// CODE_SPACE (addr) ((((addr) + 0xfff) & ~ 0xfff) <current-> start_code + current-> end_code).

--445--
10.4 memory.c program

// This macro is used to determine whether a given address is located in the code segment of the current process, see line 252.

49 #define CODE_SPACE (Addr) ((((addr) +4095) & ~ 4095) <\


50 current -> start_code + current -> end_code)
5152 static long HIGH_MEMORY = 0;
// global variables, the most high-end store the actual physical memory address.

53
// copy a memory (4K bytes).
54 #define copy_page (From, to) \
55 __asm ​__ ( " cld; rep; movsl "::" S "( from), " D "( to), " c "( 1024): " cx "," di "," si ")
56
// memory map bytes (1 byte represents a memory), each page corresponding byte flag for the current page is referenced (occupied) times.

57 static unsigned char mem_map [ PAGING_PAGES ] = {0};


5859 / *

60 * Get physical address of first (actually last :-) free page, and mark it
61 * Used. If no free pages left, return 0.
62 * /
/*
* Gets the first (in fact, is the last one :-) free pages, and marked as used. If there are no free pages,
* Return 0.
*/
//// take the free pages. If you have no memory available, and 0 is returned.

// Input:% 1 (ax = 0) - 0;% 2 (LOW_MEM);% 3 (cx = PAGING PAGES);% 4 (edi = mem_map + PAGING_PAGES-1). // Output: Returns% 0 (ax = starting
address of the page).
@ 4% above the actual point to register the mem_map [] byte memory the last byte of FIG. This function starts scanning from the forward end of FIG byte // flags of all pages

(total number of pages of PAGING_PAGES), if the free page (memory image of byte 0) page address is returned. // Note! This function simply pointed out that in a free page of

the main memory area, but is not mapped to the linear address of a process to go. // back put_page () function is used for mapping.

63 unsigned long get_free_page (Void)


64 {
65 register unsigned long __res asm ( " ax ");
6667 __asm ​__ ( " std; repne; scasb \ n \ t "
// bit direction, the al (0) is compared with each page corresponding to (DI) content,

68 "Jne 1f \ n \ t" // If no byte is equal to 0, then the skip end (return 0).
69 "Movb $ 1,1 (%% edi) \ n \ t // position corresponding to the memory image of a page.

70 "Sall $ 12, %% ecx \ n \ t" // number of pages * 4K = opposite page start address.

71 "Addl% 2, %% ecx \ n \ t" // coupled with low memory address, that get the actual physical page start address.

72 "Movl %% ecx, %% edx \ n \ t" // start address of the actual page edx register.
73 "Movl $ 1024, %% ecx \ n \ t" // set the count value of the register ecx 1024.

74 "Leal 4092 (%% edx), %% edi \ n \ t" // The EDI 4092 + edx position (the end of the page).
75 "Rep; stosl \ n \ t" // edi within the meaning of the memory is cleared (in the opposite direction, the page is about to be cleared).

76 "Movl %% edx, %% eax \ n" // start address of the page eax (return value).
77 "1:"
78 : "= a "(__ res)
79 : "" (0) " i "( LOW_MEM ) " c "( PAGING_PAGES ),
80 "D" ( mem_map + PAGING_PAGES -1)
81 : " di "," cx "," dx ");
82 return __res; // return to idle page address (if no idle also returns 0).
83 }
8485 / *

86 * Free a page of memory at physical address 'addr'. Used by


87 * 'Free_page_tables ()'

--446--
10.4 memory.c program

88 * /
/*
* Release physical address 'addr' a beginning of memory. A function 'free_page_tables ()'.
*/
//// release a physical page of memory address addr began.

// 1MB of memory space for the kernel and buffer, not as a memory allocation page.
89 void free_page (Unsigned long addr)
90 {
91 if (addr < LOW_MEM ) Return; // If addr physical address of the memory is less than the lower end (1MB), is returned.

92 if (addr> = HIGH_MEMORY ) // If the physical address addr> = most high-end memory, the error message is displayed.

93 panic ( ' trying to free nonexistent page ");


94 addr - = LOW_MEM ; // minus the physical address of the memory location of low-end, divided by 4KB, have page numbers.

95 addr >> = 12;


96 if ( mem_map [Addr] -) return; // if the corresponding memory page mapping byte is not equal to 0, 1 minus returns.

97 mem_map [Addr] = 0; // otherwise set corresponding to the page mapping byte is 0, and displays an error message, crash.

98 panic ( ' trying to free free page ");


99 }
100 101 /
*
102 * This function frees a continuos block of page tables, as needed
103 * By 'exit ()'. As does copy_page_tables (), this handles only 4Mb blocks.
104 * /
/*
* The following function releases contiguous block of memory page table, 'exit ()' This function is required. And copy_page_tables ()

* Similarly, the processing function is only 4Mb of memory blocks.

*/
//// linear address and the specified constraint length (number of page table), release the corresponding memory page of the memory block specified table entry idle juxtaposition. //

page directory physical address 0 is located at the beginning of 1024, accounting for 4K bytes. Each directory entry to specify a page table. // page table starting at physical address

0x1000 (immediately directory space), each page table have 1024, also accounted for a 4K memory. // each page table entry corresponding to a physical memory (4K). And the size of

the page table entry directory entry are four bytes. // Parameters: from - the starting base address; size - length of release.

105 int free_page_tables (Unsigned long from, unsigned long size)


106 {
107 unsigned long * pg_table;
108 unsigned long * dir, nr;
109
110 if (from & 0x3fffff) // To address the need to free the memory block 4M boundary.

111 panic ( ' free_page_tables called with wrong alignment ");


112 if (! from) // error, try to release the core and buffer space occupied.

113 panic ( ' Trying to free up swapper memory space ");


// Calculate the percentage page directory number (4M binary integer multiple) entry, i.e., the number of page table occupied.

114 size = (size + 0x3fffff) >> 22;


// calculate the following sentence starting directory entry. The directory entry number = from >> 22, because each occupies 4 bytes, and since the beginning of the page directory

physical address @ 0, so the actual directory entry pointer of the directory entry number << = 2, i.e. (from >> 20). And the 0xffc ensure effective // ​directory entry pointer range.

115 dir = (unsigned long *) ((from >> 20) & 0xffc); / * _ pg_dir = 0 * /
116 for (; size -> 0; dir ++) { // size needs to be released now is the number of directory entries memory.

117 if (! (1 & * dir)) // if the directory entry is invalid (P bit = 0), then continue.

118 continue; Bit 0 (P bits) // directory entry indicates that the corresponding page table exists.

119 pg_table = (unsigned long *) (0xfffff000 & * dir); // get directory entry in the page table address.
120 for (nr = 0; nr <1024; nr ++) {// each page table entry 1024 pages.
121 if (1 & * pg_table) // If the active page table entries (P bit = 1), then release the corresponding memory pages.

122 free_page (0xfffff000 & * pg_table);

--447--
10.4 memory.c program

123 * pg_table = 0; // clear the contents of the page table entry.

124 pg_table ++; // points to a page table next.


125 }
126 free_page (0xfffff000 & * dir); // release the memory occupied by the page table page. However, due to page table

// physical address within 1M, so the sentence does nothing.

127 * dir = 0; // clear the directory entry corresponding page table.

128 }
129 invalidate (); // refresh the page transform cache.

130 return 0;
131 }
132 133 /
*
134 * Well, here is one of the most complicated functions in mm. It
135 * Copies a range of linerar addresses by copying only the pages.
136 * Let's hope this is bug-free, 'cause this one I do not want to debug :-)
137 *
138 * Note We do not copy just any chunks of memory -! Addresses have to
139 * Be divisible by 4Mb (one page-directory entry), as this makes the
140 * Function easier. It's used only by fork anyway.
141 *
142 * NOTE 2 !! When from == 0 we are copying kernel space for the first
143 * Fork (). Then we DONT want to copy a full page-directory entry, as
144 * That would lead to some serious memory waste - we just copy the
145 * First 160 pages -. 640kB Even that is more than we need, but it
146 * Does not take any more memory - we do not copy-on-write in the low
147 * 1 Mb-range, so the pages can be shared with the kernel. Thus the
148 * Special case for nr = xxxx.
149 * /
/*
* Well, here is one of the most complicated mm memory management program. It is only by replicating memory pages

* Copying the contents to a range of linear addresses. I hope that the code does not error, because I do not want

* Then this piece of code debugging ☺ .

*
* note! We are not only copy any of the memory block - a block of memory address needs to be a multiple of 4Mb (just

* Page directory entry corresponding to a memory size), because this treatment can function very simple. one way or another,

* It is only fork () using (fork.c line 56).


*
* Note 2! ! When from == 0, is the call to copy the kernel space for the first time fork (). At this point we

* Do not want to copy the entire page directory entry corresponding to memory, because doing so would lead to serious waste of memory - we

* Only copy the first page 160 - correspond 640kB. Even copy these pages has exceeded our needs,
* But it will not take up more memory - the copy operation is in the low range of 1Mb of memory we do not write, so

* These pages can be shared with the kernel. So this is a special case of nr = xxxx (nr number of pages in the program middle finger).

*/
//// copy specified linear address and length (number of page table) corresponding to the memory page directory and a page table entry, so that the copied page directory and page

table corresponding to the original //// physical memory area is shared.

// copy the memory corresponding to the specified address and length of the page directory entries and page table entries. To apply for a new page to hold the page table, the original memory

area is shared; // After two processes shared memory area, a write operation, was assigned to perform the process until there is a new memory page (copy-on-write mechanism).

150 int copy_page_tables (Unsigned long from, unsigned long to, long size)
151 {
152 unsigned long * from_page_table;
153 unsigned long * to_page_table;
154 unsigned long this_page;
155 unsigned long * from_dir, * to_dir;

--448--
10.4 memory.c program

156 unsigned long nr;


157
// source and destination addresses need to be on the boundary address memory of 4Mb. Otherwise error, crash.

158 if ((from & 0x3fffff) || (to & 0x3fffff))


159 panic ( ' copy_page_tables called with wrong alignment ");
// get directory entry pointer source address and destination address (from_dir and to_dir). See note on 115's.

160 from_dir = (unsigned long *) ((from >> 20) & 0xffc); / * _ pg_dir = 0 * /
161 to_dir = (unsigned long *) ((to >> 20) & 0xffc); // count the number of blocks of memory occupied

by the page table to be copied (i.e. the number of directory entries).

162 size = ((unsigned) (size + 0x3fffff)) >> 22; // start of each page table
below occupied by sequentially copy operation.
163 for (; size -> 0; from_dir ++, to_dir ++) {// if the entry specifies the destination
directory page table exists (P = 1), is an error, crash.
164 if (1 & * to_dir)
165 panic ( ' copy_page_tables: already exist ");
// If the source directory entry is not used, then do not copy the corresponding page table, skip.

166 if (! (1 & * from_dir))


167 continue;
// get the current address from_page_table source directory entry in the page table.

168 from_page_table = (unsigned long *) (0xfffff000 & * from_dir);


// for the purpose of taking a free memory page table, if the return is 0 description did not apply to free memory pages. Return Value = -1, exit.

169 if (! (to_page_table = (unsigned long *) get_free_page ()))


170 return -1; / * Out of memory, see freeing * /
// set the destination directory entries. 7 is flag information indicating (Usr, R / W, Present).

171 * to_dir = ((unsigned long) to_page_table) | 7;


// page table for the current process, setting the number of pages to be copied. If you are in kernel space, you only need to copy the head 160 (640KB), // otherwise need to

copy all 1024 pages a page table.

172 nr = (from == 0) 0xA0: 1024;?


// For the current page table and began copying a specified number nr memory pages.

173 for (; nr--> 0; from_page_table ++, to_page_table ++) {


174 this_page = * from_page_table; // get the source page table entry content.

175 if (! (1 & this_page)) // If the current source page is not used, then do not copy.

176 continue;
// reset the page table entry R / W flag (set to 0). (If the U / S bit is 0, the R / W has no effect. If the U / S is 1, the R / W is 0, then it can only read page // run code

in the user layer. If the U / S and R / W are set, then there is written permission.)

177 this_page & = ~ 2;


178 * to_page_table = this_page; // copy to the destination page table entry in the page table.
// If the address indicated in the page table entries than 1MB page, you need to set the mem_map memory page mapping array [], // then calculate a page number and using it as

an index page map array entry corresponding increase in the number of references. For located below 1MB pages, the page description // kernel, there is no need for the mem_map

[] is set. Because mem_map [] only for managing the main memory area of ​a page using // situation. Thus, for the core moves on to task 0 and calls fork () Create Task 1 (for running

the init ()), since at this time

// copy the pages are also still in the kernel code region, the following statement will not execute the judgment. Only when calling fork () // the code of the parent process in the main

memory area (page position is greater than 1MB) will be performed. This situation needs to appear in a process called execve (), // load and execute the new code.

179 if (this_page> LOW_MEM ) {


// The following sentence is to make the meaning of the source page table entry also referred to as read-only memory pages. Because now there are two processes share

memory zone. // If one needs to write to memory, you can write pages by abnormal protection process for the write process operation // allocate a new free page, that operate

copy-on-write.

180 * from_page_table = this_page; // make the source page table entry are also read-only.
181 this_page - = LOW_MEM ;
182 this_page >> = 12;
183 mem_map [This_page] ++;

--449--
10.4 memory.c program

184 }
185 }
186 }
187 invalidate (); // refresh the page transform cache.

188 return 0;
189 }
190 191 /
*
192 * This function puts a page in memory at the wanted address.
193 * It returns the physical address of the page gotten, 0 if
194 * Out of memory (either when trying to access page-table or
195 * Page.)
196 * /
/*
* The following function will place a page memory at the specified address. It returns the physical address of the page, if

* Not enough memory (when accessing the page table or page), 0 is returned.

*/
//// mapped to a physical memory page address to the specified linear.

// main job is to set the information specified page in the page directory and page tables. If successful, the page address is returned. // function in C do_no_page missing page abnormalities ()

will call this function. For abnormalities caused by missing pages, missing pages due to any reason and // page table modification, CPU does not need to refresh the page transformation buffer

(or called Translation Lookaside Buffer, TLB), // even if the page table entry sign P It is modified from 0 to 1. Because invalid page item will not be buffered, so when modifying an invalid page

table entries do not need to refresh //. In this was manifested as without calling Invalidate () function.

197 unsigned long put_page (Unsigned long page, unsigned long address)
198 {
199 unsigned long tmp, * page_table;
200 201 / * NOTE !!! This uses the fact that _pg_dir = 0 * /

/ * Note !!! This uses page directory base _pg_dir = 0 (zero) * /


202
// If the page location of the application is less than LOW_MEM (1Mb) or beyond the actual system memory containing the high-end HIGH_MEMORY, a warning is issued.

203 if (page < LOW_MEM || page> = HIGH_MEMORY )


204 printk ( ' Trying to put page% p at% p \ n ", page, address);
// If the page is not set in the application page of the memory map in FIG bytes, a warning message is displayed.

205 if ( mem_map [(Page- LOW_MEM ) >> 12]! = 1)


206 printk ( ' mem_map disagrees with% p at% p \ n ", page, address);
// Calculation directory entry corresponding to the address pointer specifies the page in the directory table.

207 page_table = (unsigned long *) ((address >> 20) & 0xffc);


// If the directory entry valid (P = 1) (ie, the designated page table in memory), then obtain the address from which page_table designated page table.

208 if ((* page_table) & 1)


209 page_table = (unsigned long *) (0xfffff000 & * page_table);
210 else {
// Otherwise, the page table page to a requested idle use, and a respective flag is set in the corresponding directory entry 7 (User, U / S, R / W). Then // address

page_table page table.

211 if (! (tmp = get_free_page ()))


212 return 0;
213 * page_table = tmp | 7;
214 page_table = (unsigned long *) tmp;
215 }
// Set the page table entry contents of the physical memory pages specified address in the page table. Each page table can have a total of 1024 (0x3ff).

216 page_table [(address >> 12) & 0x3ff] = page | 7;


217 / * No need for invalidate * /
/ * Do not need to refresh the page cache conversion * /

--450--
10.4 memory.c program

218 return page; // return page address.


219 }
220
//// cancel write protect page function. Page abort the process for write-protection exception processing (copy-on-write). // input parameters for the page table

entry pointer.

// [un_wp_page mean cancellation of the page write protection: Un-Write Protected. ]


221 void un_wp_page (Unsigned long * table_entry)
222 {
223 unsigned long old_page, new_page;
224
225 old_page = 0xfffff000 & * table_entry; // get the specified page table entry physical page location (address). // If the memory address is greater than

the low end of the original page LOW_MEM (1Mb), and a value of 1 byte in the page map of FIG array (only referenced // 1, the page is not shared), then the

page in the page entry set R / W flag (write), and refresh the page cache // transform, and then returns.

226 if (old_page> = LOW_MEM && mem_map [ MAP_NR (Old_page)] == 1) {


227 * table_entry | = 2;
228 invalidate ();
229 return;
230 }
// Otherwise, the main area of ​application for an idle memory pages.

231 if (! (new_page = get_free_page ()))


232 oom (); // Out of Memory. Insufficient memory processing.

// If the page is larger than the original low-end memory (it means mem_map []> 1, the page is shared), then the original page page mapping // array value is decremented by one. Then

assign the contents of the page table entry is updated to the new page, and can read and write flag is set (U / S, R / W, P). // refresh the page transform cache. Finally, copy the original

page contents to a new page.

233 if (old_page> = LOW_MEM )


234 mem_map [ MAP_NR (Old_page)] -;
235 * table_entry = new_page | 7;
236 invalidate ();
237 copy_page (Old_page, new_page);
238 }
239 240 /
*
241 * This routine handles present pages, when users try to write
242 * To a shared page. It is done by copying the page to a new address
243 * And decrementing the shared-page counter for the old page.
244 *
245 * If it's in code space we exit with a segment error.
246 * /
/*
* The function handles existing memory pages (copy-on-write) when the user tries to write on a shared page
* It is by copying the page to a new address and decrements the count value of the original page Share page implementation.

*
* If it's in the code space, we will exit with an error message segment.

*/
//// page exception interrupt handler calls the C function. Write a shared page handler. It is called page.s program. Error_code // parameter is generated

automatically by the CPU, address is a linear address of a page. // write when sharing page, the page to be copied (copy-on-write).

247 void do_wp_page (Unsigned long error_code, unsigned long address)


248 {
249 #if 0
250 / * We can not do this yet: the estdio library writes to code space * /
251 / * Stupid, stupid. I really want the libc.a from GNU * /

--451--
10.4 memory.c program

/ * We can not do this: because estdio library performs write operations in the code space * / / * really stupid. I

really want to get libc.a library from the GNU. * /

252 if ( CODE_SPACE (Address)) // if the address is in the code space, execution of the program is terminated.

253 do_exit ( SIGSEGV );


254 #endif
// Handle cancel the page protection. Parameter specifies the page in the page table entry pointer of the page table, it is calculated: // ((address >> 10)

& 0xffc): Calculates the offset address in the page address of the page table; // (0xfffff000 & * ((address >> 20) & 0xffc)): take the address value in the

directory entry of the page table, where // ((address >> 20) & 0xffc) calculates the directory entry pointer of the page on which the page table; // two

together i.e., obtain the specified address corresponding to the page table entry pointer of the page. Here to make copies of pages that are shared.

255 un_wp_page ((Unsigned long *)


256 (((Address >> 10) & 0xffc) + (0xfffff000 &
257 * ((Unsigned long *) ((address >> 20) & 0xffc)))));
258 259 }

260
//// write verification page.

// If the page is not writable, the copy page. It is called in line 34 fork.c.
261 void write_verify (Unsigned long address)
262 {
263 unsigned long page;
264
// whether the specified address corresponding to the page directory entry of the page table exists (P), if present (P = 0) is returned.

265 if (! ((page = * ((unsigned long *) ((address >> 20) & 0xffc))) & 1))
266 return;
// page table fetch address, the address specified by the page's page table entry in the page offset table to obtain the corresponding page table entry pointer of the physical page.

267 page & = 0xfffff000;


268 page + = ((address >> 10) & 0xffc);
// If the page is not writable (flag R / W is not set), the shared inspection and copying pages operations (copy-on-write) execution.

269 if ((3 & * (unsigned long *) page) == 1) / * non-writeable, present * /


270 un_wp_page ((Unsigned long *) page);
271 return;
272 }
273
//// get a free memory and mapped to the specified linear address.

// and get_free_page () different. get_free_page () only apply for one page of physical memory main memory area. // function which is not only to get a

physical memory pages, further calls put_page (), map the physical page to the specified linear address // place.

274 void get_empty_page (Unsigned long address)


275 {
276 unsigned long tmp;
277
// If you can not get a free page, or page can not be placed into the specified address is not enough memory message is displayed. 279 // line comment on the

English meaning is: Even if you perform get_free_page () returns 0 does not matter, because put_page () // in this case also apply for free physical page again,

see line 210.

278 if (! (tmp = get_free_page ()) ||! put_page (Tmp, address)) {


279 free_page (Tmp); / * 0 is ok - ignored * /
280 oom ();
281 }
282 }
283 284 /
*
285 * Try_to_share () checks the page at address "address" in the task "p",

--452--
10.4 memory.c program

286 * To see if it exists, and if it is clean. If so, share it with the current
287 * Task.
288 *
289 * NOTE! This assumes we have checked that p! = Current, and that they
290 * Share the same executable.
291 * /
/*
* try_to_share () in the task "p" in the address of the page to check "address" at, see page exists, it is clean.
* If it is clean, then it shared with the current task.
*
* note! Here we have assumed that p! = Current task, and they share the same execution.
*/
//// attempt at a specified address on page sharing process operation.

// also verify whether the specified address has applied for a page, if it is an error, crash. // returns 1-
success, 0 failed.
292 static int try_to_share (Unsigned long address, struct task_struct * P)
293 {
294 unsigned long from;
295 unsigned long to;
296 unsigned long from_page;
297 unsigned long to_page;
298 unsigned long phys_addr;
299
// seek page directory entry specified memory address.

300 from_page = to_page = ((address >> 20) & 0xffc); // calculate the page directory entry of

the code starting address of the corresponding p.

301 from_page + = ((p-> start_code >> 20) & 0xffc); // calculate the current process page

directory entry corresponding to the start address of the code.

302 to_page + = (( current -> start_code >> 20) & 0xffc);


303 / * Is there a page-directory at from? * /
/ * Whether there are pages directories from office? * / //

*** p-process pages operation.

// fetch page directory entries. If the directory entry is invalid (P = 0), it is returned. Otherwise, take the directory entry corresponding page table address from.

304 from = * (unsigned long *) from_page;


305 if (! (from & 1))
306 return 0;
307 from & = 0xfffff000;
// pointer value calculation page table entry corresponding to the address, and remove the contents of the page table entry phys_addr.

308 from_page = from + ((address >> 10) & 0xffc);


309 phys_addr = * (unsigned long *) from_page;
310 / * Is the page clean and present? * /
/ * And a clean page exist? * /
// 0x41 the corresponding page table entry Dirty and Present flag. If the page is not clean or invalid is returned.

311 if ((phys_addr & 0x41)! = 0x01)


312 return 0;
// address-phys_addr page. If the page address does not exist or is less than the low-end memory (1M) returns exit.

313 phys_addr & = 0xfffff000;


314 if (phys_addr> = HIGH_MEMORY || phys_addr < LOW_MEM )
315 return 0;
// *** page for the current process to operate.

// fetch page catalog items to. If the directory entry is invalid (P = 0), then take free pages, and the directory entry update to_page referred to.

316 to = * (unsigned long *) to_page;


317 if (! (to & 1))

--453--
10.4 memory.c program

318 if (to = get_free_page ())


319 * (Unsigned long *) to_page = to | 7;
320 else
321 oom ();
// get the corresponding page table address to, page table entry address to_page. If the corresponding page already exists, an error, crash.

322 & = 0xfffff000 to;


323 to_page = to + ((address >> 10) & 0xffc);
324 if (1 & * (unsigned long *) to_page)
325 panic ( ' try_to_share: to_page already exists ");
326 / * Share them: write-protect * /
/ * Sharing deal with them: Write protection * /

// set the p-process the page write protection flag (setting R / W = 0 read-only). And the corresponding page table entry in the current process point to it.

327 * (Unsigned long *) from_page & = ~ 2;


328 * (Unsigned long *) to_page = * (unsigned long *) from_page; // Transform page cache
refresh.
329 invalidate ();
// Calculation operated page number of the page, and the page for the corresponding reference map is incremented by one item in the array.

330 phys_addr - = LOW_MEM ;


331 phys_addr >> = 12;
332 mem_map [Phys_addr] ++;
333 return 1;
334 }
335 336 /
*
337 * Share_page () tries to find a process that could share a page with
338 * The current one. Address is the address of the wanted page relative
339 * To the current data space.
340 *
341 * We first check if it is at all feasible by checking executable-> i_count.
342 * It should be> 1 if there are other tasks sharing this inode.
343 * /
/*
* share_page () tries to find a process that can share the page with the current process. Parameter address is
* A page address of the current data space shared expectations.

*
* First, we verify the feasibility by detecting executable-> i_count. If there are other tasks shared
* The inode, it should be greater than 1.

*/
//// Share page. See if you can share a page in the page fault processing. // returns

1 - Successful, 0 - failed.

344 static int share_page (Unsigned long address)


345 {
346 struct task_struct ** p;
347
// If it is not executable, it is returned. excutable the implementation process of the i-node memory structure.

348 if (! current -> executable)


349 return 0;
// If you can only perform a single (executable-> i_count = 1), also quit.
350 if ( current -> executable-> i_count <2)
351 return 0;
// search task array all tasks. Looking processes can share the page with the current process, and try to share the page specified address.

352 for (p = & LAST_TASK ; P> & FIRST_TASK ; --P) {


353 if (! * p) // If the task entry is free, then keep looking.

--454--
10.4 memory.c program

354 continue;
355 if ( current == * p) // If the current task is, but also continue to look for.

356 continue;
357 if ((* p) -> executable =! current -> executable) // If the executable range, continues.
358 continue;
359 if ( try_to_share (Address, * p)) // try to share a page.
360 return 1;
361 }
362 return 0;
363 }
364
//// page exception interrupt handling function calls. Handle exceptions missing pages. It is called page.s program. Error_code // parameter is

generated automatically by the CPU, address is a linear address of a page.

365 void do_no_page (Unsigned long error_code, unsigned long address)


366 {
367 int nr [4];
368 unsigned long tmp;
369 unsigned long page;
370 int block, i;
371
372 address & = 0xfffff000; // page address.
// first calculate the linear address specified in the process space with respect to the length of the offset base address value of the process.

373 tmp = address - current -> start_code;


// If the executable space, or beyond the current process specified address + data length codes, an application of the physical memory and mapped // linear mapped to the specified

address. i-node structure is executable process. Value of 0 indicates that the beginning of the process is provided, // required memory; the specified address is outside the linear length

code plus data indicating the new application process memory space, but also needs to be given. // therefore a direct call get_empty_page () function, an application memory and mapped

to the specified physical address can be linear. // start_code is a process code segment address, end_data is code plus data length. For Linux kernel, its code segment and data segment

is a start // is the same base address.

374 if (! current -> executable || tmp> = current -> end_data) {


375 get_empty_page (Address);
376 return;
377 }
// If the attempt to share the success of the page, then exit.

378 if ( share_page (Tmp))


379 return;
// get free pages, if memory is not enough, not enough memory is displayed, terminate the process.

380 if (! (page = get_free_page ()))


381 oom ();
382 / * Remember that 1 block is used for header * /
/ * Remember (program) to use a head block * /
// first block of data items to calculate the missing page is located. BLOCK_SIZE = 1024 bytes, a data block requires 4 memory.

383 block = 1 + tmp / BLOCK_SIZE ;


// The i-node information, access to data blocks corresponding to the logical block number on the device.

384 for (i = 0; i <4; block ++, i ++)


385 nr [i] = bmap ( current -> executable, block);
// read data (four logical blocks) to the page at the specified physical address of a page on the device.

386 bread_page (Page, current -> executable-> i_dev, nr);


// in an increase of a memory, the memory portion of the page may exceed the process end_data position. The following is a part of the cycle i.e. the physical page // beyond clearing

processing is performed.

387 i = tmp + 4096 - current -> end_data;


388 tmp = page + 4096;
389 while (i--> 0) {

--455--
10.4 memory.c program

390 tmp--;
391 * (Char *) tmp = 0;
392 }
// if the physical page is mapped to the linear address specified operation is successful, it returns. Otherwise, the release of memory pages, display memory is not enough.

393 if ( put_page (Page, address))


394 return;
395 free_page (Page);
396 oom ();
397 }
398
//// physical memory initialization.

// Parameters: start_mem - physical memory can be used as the starting position of the paging process (RAMDISK memory space occupied has been removed, etc.). //

end_mem - The actual maximum physical memory address.

// In this version of the Linux kernel, can use up to 16Mb of RAM, 16Mb of memory will not be greater than to consider, not abandoned. // 0 - 1Mb of memory

space for the kernel system (in fact, 0-640Kb).

399 void mem_init (Long start_mem, long end_mem)


400 {
401 int i;
402
403 HIGH_MEMORY = End_mem; // set the most high-end memory.

404 for (i = 0; i < PAGING_PAGES ; I ++) // First of all pages set as occupied (USED = 100) states,
405 mem_map [I] = USED ; // upcoming full-page mapping array set to USED.

406 i = MAP_NR (Start_mem); // then calculated using the number of the start page of memory.

407 end_mem - = start_mem; // recalculation pageable memory block size processed.

408 end_mem >> = 12; // to calculate the number of pages that can be used for paging processing.

409 while (end_mem -> 0) // Finally, the available pages corresponding page mapping array is cleared.

410 mem_map [I ++] = 0;


411 }
412
// Calculate the number of free memory pages and display.

413 void calc_mem (Void)


414 {
415 int i, j, k, free = 0;
416 long * pg_tbl;
417
// scan memory pages mapped array mem_map [], the number of pages and get idle display.

418 for (i = 0; i < PAGING_PAGES ; I ++)


419 if (! mem_map [I]) free ++;
420 printk ( "% d pages free (of% d) \ n \ r ", free , PAGING_PAGES );
// scan all pages directory entries (except 0,1 item), if the page directory entry is valid, statistically valid number of pages in the corresponding page table, and displays.

421 for (i = 2; i <1024; i ++) {


422 if (1 & pg_dir [I]) {
423 pg_tbl = (long *) (0xfffff000 & pg_dir [I]);
424 for (j = k = 0; j <1024; j ++)
425 if (pg_tbl [j] & 1)
426 k ++;
427 printk ( ' Pg-dir [% d] uses% d pages \ n ", i, k);
428 }
429 }
430 }
431

--456--
10.5 page.s program

10.5 page.s program

10.5.1 Functional Description

The file includes page exception interrupt handler (interrupt 14 ), Mainly deal with two cases. First, because of the lack of Page abort caused by calling do_no_page

(error_code, address) To deal with; the second is the page write page protection caused by abnormal, this time calling page write-protected handlers do_wp_page (error_code,

address) For processing. Wherein the error code ( error_code) By CPU Automatically generated and pushed onto the stack, the linear address access time of abnormality from the

control register CR2 Acquired. CR2 It is designed to store the linear address of the page fault.

10.5.2 Code comments

program 10-3 linux / mm / page.s

1/*
2 * Linux / mm / page.s
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * Page.s contains the low-level page-exception code.


9 * The real work is done in mm.c
10 * / / *

* page.s underlying page that contains exception-handling code. The actual work is done in the memory.c.

*/
1112 .globl _page_fault

1314 _page_fault:

15 xchgl% eax, (% esp) # Remove the error code to eax.

16 pushl% ecx
17 pushl% edx
18 push% ds
19 push% es
20 push% fs
twenty one movl $ 0x10,% edx # Set the kernel data segment selector.

twenty two mov% dx,% ds


twenty three mov% dx,% es
twenty four mov% dx,% fs
25 movl% cr2,% edx # Taken page due to abnormal linear address

26 pushl% edx # The linear address onto the stack and error codes as arguments to the call.
27 pushl% eax
28 testl $ 1,% eax # Test flag P, if not missing pages caused abnormal jump.
29 jne 1f
30 call _do_no_page # Call the page fault handler (mm / memory.c, 365 lines).
31 jmp 2f
32 1: call _do_wp_page # Call the write-protect handler (mm / memory.c, 247 lines).
33 2: addl $ 8,% esp # Discarding two pressure parameters onto the stack.

--457--
10.5 page.s program

34 pop% fs
35 pop% es
36 pop% ds
37 popl% edx
38 popl% ecx
39 popl% eax
40 iret

10.5.3 Other Information

10.5.3.1 Page exception handling

When the processor is detected during the following two conditions translate the linear address to a physical address, the page fault exception occurs, the interrupt

14 . o when CPU Found that the presence of the corresponding page directory entry or page table entry bits ( Present ) Flag 0 .

o The current process does not have access to the specified page. For interrupt exception handling page, CPU It provides two pieces of

information used to diagnose and recover from abnormal operation page.

(1) On the error code on the stack. The error code indicates the anomaly is caused because the page does not exist or access rights violated due;

When an exception occurs CPU The current privilege layer; and a read or write operation. An error code format 32 Bit long word. But only the final 3 A bit. Illustrate

the cause when an exception occurs: Bit 2 (U / S) - 0 That the implementation in Supervisor mode, 1 It represents execution in user mode; bit 1 (W / R) - 0 It

indicates a read operation, 1 It indicates a write operation; bit 0 (P)

- page-level
0 She represents
protection.
the page does not exist, 1 She represents the

(2) CR2 ( Control register 2) . CPU The cause abnormal for accessing stored in linear address CR2 in. Exception handler can

Use this address to locate the corresponding page directory and page table entries. If allowed to occur during another page in the page exception handler execution

exception, the handler should be CR2 Pushed onto the stack.

--458--
11.1 Overview

The first 11 Chapter headers ( include)

11.1 Outline

Before using the function, you should first declare the function. For ease of use, the usual practice is the same type of function or data structures and constants stated

in a header file ( header file )in. Header file may also include any relevant macro and type definitions ( macros ). Is used in the preprocessing of instructions in the source code

file "# include "To quote the relevant header files.

In a typical application source code, header and library files in the development environment are inextricably close contact with each function in the library need to be

declared in the header file. Header files application development environment (typically placed in the system / usr / include / Directory) can be seen as they provide library (for

example, libc.a A part of the function), or is an explanation of the interface library functions stated. After the compiler converts the source code into object modules, the linker ( linker )

Program will target all of the modules together, including any library files used in the module. Thereby forming an executable program.

For standard C Library in terms of its basic header files have 15 A. Each header file shows a particular type of functionality or structure definition described, e.g. I / O Manipulation

functions, processing functions and other characters. Detailed description of the standard library can be referred to Plauger Edited " The Standard C Library "This book.

For kernel source code described in this book, involving the headers can be seen as a summary description of the kernel library and services provided, and related

procedures kernel-specific header files. In the header file describes all the data structures used by the kernel, initialization data, constants, and macros defined, also include a

small amount of program code.

11.2 include / File directory

Kernel header files used are stored in include / Under contents. Files in that directory to see the list 11.1 Fig. It should be clear: For ease of use and compatibility, Linus Naming

standard when preparing the kernel header files used C Similar naming library header files, header files and even many names, some of which are content with the standard C Library

header files is basically the same, but the kernel headers is still the kernel source code for the kernel or with a program dedicated closely linked. in a Linux System, header files,

they co-exist with the standard library. The usual practice is to place these header files in the standard library header files in the directory under the subdirectory to let the program

requires kernel data structures or constant use.

In addition, because of copyright issues, Linus Trying to realign some of the header files to replace with a standard copyright restrictions C Library header files. Thus these

header files kernel source code header files and development environment where there is some overlap. in Linux System, the list 11-1

middle asm / , linux / with sys / Kernel header files in three subdirectories usually need to be copied to the standard C Library header files directory (/ usr / include ), Whereas some

other documents if there is no conflict with the standard library header files can be placed directly into the standard library header files directory, or change into three subdirectories

in here.

asm / The main directory for storing header files declare functions or data structures closely related to computer architecture. linux / Directory is Linux Some kernel header

files used by the program. and sys / The store directory 5 A resource associated with the kernel headers.

Linux 0.11 A total of kernel version 32 Header file (*. h) ,among them asm / Subdirectory contains 4 A, linux / Subdirectory contains 10 A,

sys / Subdirectory contains 5 A. From the beginning of the next section, we first describe include / Directory 13 Header file, followed by the documentation for each subdirectory.

Description order to sort by file name.

--459--
11.3 a.out.h file

List 11-1 linux / include / File directory

name size Last Modified Time (GMT) Explanation

asm / 1991-09-17 13:08:31

linux / 1991-11-02 13:35:49

sys / 1991-09-17 15:06:07

a.out.h 6047 bytes 1991-09-17 15:10:49 m

const.h 321 bytes 1991-09-17 15:12:39 m

ctype.h 1049 bytes 1991-11-07 17:30:47 m

errno.h 1268 bytes 1991-09-17 15:04:15 m

fcntl.h 1374 bytes 1991-09-17 15:12:39 m

signal.h 1762 bytes 1991-09-22 19:58:04 m

stdarg.h 780 bytes 1991-09-17 15:02:23 m

stddef.h 286 bytes 1991-09-17 15:02:17 m

string.h 7881 bytes 1991-09-17 15:04:09 m

termios.h 5325 bytes 1991-11-25 20:02:08 m

time.h 734 bytes 1991-09-17 15:02:02 m

unistd.h 6410 bytes 1991-11-25 20:18:55 m

utime.h 225 bytes 1991-09-17 15:03:38 m

11.3 a.out.h file

11.3.1 Functional Description

a.out.h File is not part of the standard C Libraries, kernel-specific header files. But because there is no conflict with the name of the standard library header files, so

Linux The system typically can be placed / usr / include / Directory, for the program to involve the use of relevant content. The header file defines the main binaries a.out (Assembley

out) Format. Wherein the data structure comprises three functions and macros.

From Linux 0.9x Version of the kernel start (from 0.96 Start), the system uses a direct GNU Header files a.out.h . Thus causing the Linux

0.9x Under the program can not be compiled Linux 0.1x Running on the system. Analyze the following two a.out The difference at the header files, and explains how to make 0.9x Execute

files can also be in 0.1x Under Run.

This document and GNU of a.out.h The main difference is that the file exec The first field of the structure a_magic . GNU The file name field is a_info And the field is

divided into the 3 Subdomains: Flag field ( Flags ), Machine type field ( Machine Type ) And the magic number field ( Magic Number ). Also defines a machine type

corresponding macro field N_MACHTYPE with N_FLAGS . See Fig. 11-1 Fig.

--460--
11.3 a.out.h file

a_info exec structure field, 4 bytes

Flags (00)
Machine Type (100 ie 0x64)
Magic Number (0413 namely 0x10b)

Map 11-1 Executable file header structure exec The first field a_magic ( a_info )

in Linux 0.9x System, for the use of a static library executable file attached, the value in the parentheses in FIG each domain annotations is the default value of this field.

This binary executable file at the beginning of 4 Bytes are:

0x0b, 0x01, 0x64, 0x00

Here the header file defines only the magic number field. Thus, in Linux 0.1x A system a.out Binary executable file format started 4 Bytes are:

0x0b, 0x01, 0x00, 0x00

As can be seen, the use of GNU of a.out Executable file format and Linux 0.1x Difference compiled executable file on the system only in the field of machine type.

Therefore, we can Linux 0.9x Up a.out Machine type field format executable file (first 3 Bytes) cleared, let it run in 0.1x System. As long as the portable executable file system calls

are already in 0.1x The system can be implemented. At the beginning of the formation Linux 0.1x When many of the root file system commands, the author adopted this approach.

GNU of a.out.h Header files and here a.out.h Header files is no different in other respects. In addition, the reference list of

BSD system a.out.h Description of the file.

11.3.2 Code comments

program 11-1 linux / include / a.out.h

1 #ifndef _A_OUT_H 2 #define _A_OUT_H 3 4 #define


__GNU_EXEC_MACROS__ 5

// perform file header structure.

// ============================= // unsigned
long a_magic // perform file magic number. Use N_MAGIC and other macro access.

// unsigned a_text // the code length, the number of bytes.

// unsigned a_data // Data length, the number of bytes.

// unsigned a_bss // length uninitialized data area in the file, the number of bytes.

// unsigned a_syms // the length of the symbol table file, the number of bytes.

// unsigned a_entry // execution start address.

// unsigned a_trsize // the code length of relocation information, the number of bytes.

// unsigned a_drsize // Data length relocation information, the number of bytes.

// -----------------------------
6 struct exec {

--461--
11.3 a.out.h file

7 unsigned long a_magic; / * Use macros N_MAGIC, etc for access * /


8 unsigned a_text; / * Length of text, in bytes * /
9 unsigned a_data; / * Length of data, in bytes * /
10 unsigned a_bss; / * Length of uninitialized data area for file, in bytes * /
11 unsigned a_syms; / * Length of symbol table data in file, in bytes * /
12 unsigned a_entry; / * Start address * /
13 unsigned a_trsize; / * Length of relocation info for text, in bytes * /
14 unsigned a_drsize; / * Length of relocation info for data, in bytes * /
15 };
16
// for magic number structure taken execution.

17 #ifndef N_MAGIC 18 #define N_MAGIC ( exec ) (( exec ) .A_magic)

19 #endif
2021 #ifndef OMAGIC 22 / * Code indicating object file or impure executable. * /

/ * Indicates the target file or impure executable code * /


twenty three #define OMAGIC 0407

// the history, the earliest in the PDP-11 computer, the magic number (magic number) is the octal number 0407. It is located at the beginning of the program execution head structure. // PDP-11

was originally a jump instruction, then jump to the code that represents the beginning of the word 7. In this way, the loader (loader) on

// can jump after the executable file into memory instructions directly to the beginning of the run. Now there is no program uses this approach, but this

// octal number to identify it as a file type of sign (magic number) retained. OMAGIC can be thought of Old Magic meaning.
twenty four / * Code indicating pure executable. * /
/ * Code specified as pure executable file * / // New Magic, after 1975 started. It relates to virtual memory mechanism.

25 #define NMAGIC 0410


26 / * Code indicating demand-paged executable. * /
/ * Specified as demand paging process executable file * / // its head structure occupies a (4K).
27 #define ZMAGIC 0413
28 #endif / * not OMAGIC * /
29 // There is also a QMAGIC, in order to save disk space, the head structure execution file on the disc and compact code storage.

// can not be identified if the magic number, returns true.

30 #ifndef N_BADMAG 31 #define N_BADMAG


(x) \
32 ( N_MAGIC ( x )! = OMAGIC && N_MAGIC ( x )! = NMAGIC \
33 && N_MAGIC ( x )! = ZMAGIC )
34 #endif
3536 #define _N_BADMAG ( x )
\
37 ( N_MAGIC ( x )! = OMAGIC && N_MAGIC ( x )! = NMAGIC \
38 && N_MAGIC ( x )! = ZMAGIC )
39
// offset in the first program memory.
40 #define _N_HDROFF ( x ) ( SEGMENT_SIZE - sizeof (struct exec ))
41
// Code start offset value.
42 #ifndef N_TXTOFF 43 #define N_TXTOFF
(x)\
44 ( N_MAGIC ( x ) == ZMAGIC ? _N_HDROFF (( x )) + Sizeof (struct exec ): Sizeof (struct exec ))
45 #endif
46

--462--
11.3 a.out.h file

// start offset value data.


47 #ifndef N_DATOFF 48 #define N_DATOFF ( x ) ( N_TXTOFF ( x ) + ( x ) .A_text)

49 #endif
50
// offset codes relocation information.

51 #ifndef N_TRELOFF 52 #define N_TRELOFF ( x ) ( N_DATOFF ( x ) + ( x ) .A_data)

53 #endif
54
// offset data relocation information.
55 #ifndef N_DRELOFF 56 #define N_DRELOFF ( x ) ( N_TRELOFF ( x ) + ( x ) .A_trsize)

57 #endif
58
// offset value symbol table.

59 #ifndef N_SYMOFF 60 #define N_SYMOFF ( x ) ( N_DRELOFF ( x ) + ( x ) .A_drsize)

61 #endif
62
// offset value character string information.

63 #ifndef N_STROFF 64 #define N_STROFF ( x ) ( N_SYMOFF ( x ) + ( x ) .A_syms)

65 #endif
6667 / * Address of text segment in memory after it is loaded. * /

/ * Code segment is loaded into memory address * /

68 #ifndef N_TXTADDR 69 #define N_TXTADDR


(x)0
70 #endif
7172 / * Address of data segment in memory after it is loaded.

73 Note that it is up to you to define SEGMENT_SIZE


74 on machines not listed here. * /
/ * Segment data is loaded into the address in memory.

Note that for the following machine name is not listed, you need to define the corresponding

SEGMENT_SIZE * /

75 #if defined (vax) || defined (hp300) || defined (pyr)


76 #define SEGMENT_SIZE PAGE_SIZE 77 #endif

78 #ifdef hp300
79 #define PAGE_SIZE 4096
80 #endif
81 #ifdef sony
82 #define SEGMENT_SIZE 0x2000
83 #endif / * Sony. * /
84 #ifdef is68k
85 #define SEGMENT_SIZE 0x20000
86 #endif
87 #if defined (m68k) && defined (PORTAR)
88 #define PAGE_SIZE 0x400
89 #define SEGMENT_SIZE PAGE_SIZE 90 #endif

--463--
11.3 a.out.h file

9192 #define PAGE_SIZE 4096

93 #define SEGMENT_SIZE 1024


94
// size of segment boundary.

95 #define _N_SEGMENT_ROUND ( x ) ((( x ) + SEGMENT_SIZE --1) & ~ ( SEGMENT_SIZE - 1))


96
// Code section end address.

97 #define _N_TXTENDADDR ( x ) ( N_TXTADDR ( x ) + ( x ) .A_text)


98
// start address data.
99 #ifndef N_DATADDR 100 #define N_DATADDR
(x)\
101 ( N_MAGIC ( x ) == OMAGIC ? ( _N_TXTENDADDR ( x )) \
102 : ( _N_SEGMENT_ROUND ( _N_TXTENDADDR ( x ))))
103 #endif
104105 / * Address of bss segment in memory after it is loaded. * /

/ * Bss segment loaded into memory after the address * /

106 #ifndef N_BSSADDR 107 #define N_BSSADDR ( x ) ( N_DATADDR ( x ) + ( x )


.A_data)
108 #endif
109
// nlist structure. Symbol table record structure.

110 #ifndef N_NLIST_DECLARED


111 struct nlist {
112 union {
113 char * n_name;
114 struct nlist * N_next;
115 long n_strx;
116 } N_un;
117 unsigned char n_type; // This byte is divided into 3 fields, a mask lines 146-154 corresponding field.

118 char n_other;


119 short n_desc;
120 unsigned long n_value;
121 };
122 #endif
123
Variable offset value // exec structure defined below.

124 #ifndef N_UNDF 125 #define N_UNDF


0
126 #endif
127 #ifndef N_ABS 128 #define N_ABS
2
129 #endif
130 #ifndef N_TEXT 131 #define N_TEXT
4
132 #endif
133 #ifndef N_DATA 134 #define N_DATA
6
135 #endif
136 #ifndef N_BSS 137 #define N_BSS
8

--464--
11.3 a.out.h file

138 #endif
139 #ifndef N_COMM 140 #define N_COMM
18
141 #endif
142 #ifndef N_FN 143 #define N_FN
15
144 #endif
145
// The following three constants defined nlist structure mask n_type variables (eight process representation).

146 #ifndef N_EXT 147 #define N_EXT


1
148 #endif
149 #ifndef N_TYPE 150 #define N_TYPE
036
151 #endif
152 #ifndef N_STAB 153 #define N_STAB
0340
154 #endif
155 156 / * The following type indicates the definition of a symbol as being

157 an indirect reference to another symbol. The other symbol


158 appears as an undefined reference, immediately following this symbol.
159
160 Indirection is asymmetrical. The other symbol's value will be used
161 to satisfy requests for the indirect symbol, but not vice versa.
162 If the other symbol does not have a definition, libraries will
163 be searched to find a definition. * /
/ * The following indicates the type of symbols defined as an indirect reference to another symbol. Immediately other the symbol

* The symbol is presented as undefined references.

*
* Indirect asymmetric. Values ​of other symbols will be used to satisfy the request indirect symbols, but not vice versa.

* If no other symbol is not defined, the library will be searched to find a definition * /

164 #define N_INDR 0xa


165 166 / * The following symbols refer to set elements.

167 All the N_SET [ATDB] symbols with the same name form one set.
168 Space is allocated for the set in the text section, and each set
169 element's value is stored into one word of the space.
170 The first word of the space is the length of the set (number of elements).
171
172 The address of the set is made into an N_SETV symbol
173 whose name is the same as the name of the set.
174 This symbol acts like a N_DATA global symbol
175 in that it can satisfy undefined external references. * /
/ * The following symbols related to the set of elements. All symbols have the same name N_SET [ATDB] of

Forming a set. In the code section it has been assigned to a collection space, and the set value of each element is stored in a space character (word) a. A

first set of word length there space (the number of sets of elements).

It is put into a set of addresses N_SETV symbol set with the same name as its name. In meeting the external reference

undefined, the symbol acts as a global symbol N_DATA. * /

176 177 / * These appear as input to LD, in a .o file. * /

/ * The following symbols are used as linker LD input in the target file. * /

--465--
11.3 a.out.h file

178 #define N_SETA 0x14 / * Absolute set element symbol * /


/ * Absolute collection element symbol * /

179 #define N_SETT 0x16 / * Text set element symbol * /


/ * Set of code symbols of elements * /

180 #define N_SETD 0x18 / * Data set element symbol * /


/ * Set of data symbols of elements * /

181 #define N_SETB 0x1A / * Bss set element symbol * /


/ * Set Bss element symbols * /

182 183 / * This is output from LD. * /

/ * Here is the output of the LD. * /

184 #define N_SETV 0x1C / * Pointer to set vector in data area. * /


/ * Set point vector data region. * /
185 186 #ifndef N_RELOCATION_INFO_DECLARED

187 188 / * This structure describes a single relocation to be performed.

189 The text-relocation section of the file is a vector of these structures,


190 all of which apply to the text section.
191 Likewise, the data-relocation section applies to the data section. * /
/ * The following describes the structure of a relocation operation performed.

The relocation code file is a vector part of these structures, all of which are suitable for the code portion. Similarly, the data

relocation applied to the data portion. * /

192
// relocation information structure.

193 struct relocation_info 194 {

195 / * Address (within segment) to be relocated. * /


/ * Required addresses (within the segment) relocation. * /

196 int r_address;


197 / * The meaning of r_symbolnum depends on r_extern. * /
/ * R_symbolnum meaning r_extern related. * /
198 unsigned int r_symbolnum: 24;
199 / * Nonzero means value is a pc-relative offset
200 and it should be relocated for changes in its own address
201 as well as for changes in the symbol or section specified. * /
/ * Means that the value is non-zero offset value related to a pc, which in its own address space

And changing the sign or the specified section, to be relocated * /

202 unsigned int r_pcrel: 1;


203 / * Length (as exponent of 2) of the field to be relocated.
204 Thus, a value of 2 indicates 1 << 2 bytes. * /
/ * Required field length to be relocated (a power of 2).
Thus, if the value is represented by 2 bytes 2 << 1. * /

205 unsigned int r_length: 2;


206 / * 1 => relocate with value of symbol.
207 r_symbolnum is the index of the symbol
208 in file's the symbol table.
209 0 => relocate with the address of a segment.
210 r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
211 (The N_EXT bit may be set also, but signifies nothing). * /
/ * 1 => the value of the symbol relocation.

r_symbolnum symbol table index file is signed. 0 =>


addresses to be relocated.

--466--
11.3 a.out.h file

r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS (N_EXT bits


can also be set, but meaningless). * /
212 unsigned int r_extern: 1;
213 / * Four bits that are not used, but when writing an object file
214 it is desirable to clear them. * /
/ * No use of four bits, but when writing an object file
Best to reset them out. * /
215 unsigned int r_pad: 4;
216 };
217 #endif / * no N_RELOCATION_INFO_DECLARED. * /
218219220 #endif / * __ A_OUT_GNU_H__ * /

221

11.3.3 Other Information

11.3.3.1 a.out Executable file format

Linux Kernel 0.11 Supports only a.out (Assembley out) Executable file format, although this format is now gradually do, and use more feature complete ELF ( Executable

and Link Format ) Format, but because of its simplicity, as a material just getting started learning more applicable. The following comprehensive introduction a.out format.

In the header file < a.out.h> It affirmed the three data structures as well as some of the macro function. These machine code files describe the data structures (binary)

executable on the system.

An executable file can have a total of seven sections (Section VII) components. In order, these portions are: an end effector portion ( exec header) . Execute the file header

section. This portion contains a number of parameters, these parameters are used to load the kernel executable file into memory and executed, and the linker ( ld) Using these

parameters will be some combination of binary object files into an executable file. This is the only part of the necessary.

Code segment portion ( text segment) . Containing program execution is loaded into memory so that the instruction code and associated data. It can be loaded as read-only.

Data segment portion ( data segment) . This portion contains data already initialized, it is always loaded into the read-write memory. Relocations section ( text relocations) .

This portion contains the linker used for recording data. The code segment for the positioning of the pointer or address in the binary object file combination.

Data relocation section ( data relocations) . The effect is similar relocations section, but is a relocatable data segment pointers.

Symbol table section ( simbol table) . This part also contains the data for recording linker used for cross-reference to named variables and functions (symbol)

between the binary object file.

String table section ( string table) . This portion contains the symbol corresponding to the name string. Each binaries are to perform a data structure ( exec

structure )Start. The form of the data structure as follows:

struct exec {
unsigned long a_midmag; // a_magic or a_info
unsigned long a_text; unsigned long
a_data; unsigned long a_bss; unsigned
long a_syms; unsigned long a_entry;
unsigned long a_trsize; unsigned long
a_drsize;};

--467--
11.3 a.out.h file

Function of each field is as follows:

a_midmag The field containing the N_GETFLAG () , N_GETMID with N_GETMAGIC () Sub-section accessible by the link is loaded at runtime into the process address space.

Macros N_GETMID () Machine for returning an identifier ( machine-id) , Indicating a binary file that will run on any machine. N_GETMAGIC () Macro specified magic number, which

uniquely determines the difference between the binaries loaded with other documents. Field must contain one of the following values:

OMAGIC It represents code and data segments and head immediately after the execution is stored in a row. The kernel code and data segments are loaded into

read-write memory.

NMAGIC with OMAGIC Like, code and data segments and head immediately after the execution is stored in a row. However, the kernel code is loaded into a read

only memory section and load data into the code segment begins next writable memory boundaries.

ZMAGIC Kernel loads separate page from the binary executable file if necessary. Performs a header, the code and data segments are processed blocks into a

plurality of page sizes linker. Kernel code loaded when the page is read-only, and the page data segment is writable.

a_text The length field contains the value of the code segment, the number of bytes.

a_data This field contains the length of the data section, the number of bytes.

a_bss contain' bss Segments' length, with a core which is provided after the initial data segment break ( brk ). Kernel loading process

Timing, this can be written in the memory after the data segments exhibit, and initially all zero.

a_syms The symbol table contains the byte length of the value part.

a_entry After the core containing the executable file is loaded into memory, the memory address of the start of program execution.

a_trsize This field contains the code relocation table size, the number of bytes.

a_drsize This field contains the data relocation table size, the number of bytes.

in a.out.h Header file defines several macros use exec Conformance testing structure or the positioning of each execution file portion (section) the position of the offset

value. These macros are:

N_BADMAG (exec) in case a_magic Field can not be identified, a nonzero value is returned.

N_TXTOFF (exec) Starting position code segment byte offset value.

N_DATOFF (exec) Start position of the data segment byte offset value.

N_DRELOFF (exec) Data re-start position of the byte offset location table.

N_TRELOFF (exec) Starting position of the code byte relocation table offset.

N_SYMOFF (exec) Start position of the symbol table byte offset value.

N_STROFF (exec) Starting position of the string table byte offset value.

Relocation records having a standard format, which relocation information ( relocation_info) To describe the structure:

struct relocation_info {
int r_address;
unsigned int r_symbolnum: 24, r_pcrel: 1,
r_length: 2, r_extern: 1,
r_baserel: 1, r_jmptable: 1,
r_relative: 1, r_copy: 1;

};

Meaning of each field in the structure is as follows:

--468--
11.3 a.out.h file

r_address This field contains the byte offset pointer link required program processing (editing) of. Relocations offset value is

Counted from the beginning of the code segment, the data offset value is calculated from the relocation at the beginning of the data segment. The linker will have been stored in

the offset value using the relocation records the calculated new value is added.

r_symbolnum This field contains a sequence number value in the symbol table (not a byte offset) symbol structure. After the linker is calculated absolute address

of the symbol, it is added to the address pointer being relocated. (in case r_extern Bits is 0 The situation is different, see below. )

r_pcrel If this bit is set, the linker will think is updating a pointer that use pc Addressing related parties

Type, belonging to the machine code instruction section. When using this program is run relocated pointer that addresses are implicitly added to the pointer.

r_length The pointer field contains the length of the 2 The power value: 0 Show 1 Bytes long, 1 Show 2 Bytes long, 2 Show 4 byte

long.
r_extern If the bit is set, indicating that the relocation requires an external reference; in this case must use a symbolic link address

To update the corresponding pointer. When this bit is 0 , Then relocation is "local"; the Linker pointer is updated to reflect changes in the respective segment load address, rather

than reflecting a change in symbol values ​(unless simultaneously provided r_baserel , See below). under these circumstances, r_symbolnum

Contents of the field is a n_type Value (see below); such field tells the linker is repositioned pointer to that segment.

r_baserel If this bit is set, then r_symbolnum Field specifies a symbol to be relocated to Global Offset Table ( Global

Offset Table) One offset value. At runtime, the global offset table is set to the offset address of a symbol.

r_jmptable If the bit is set, then r_symbolnum Field specifies a symbol to be relocated to the procedure linkage table ( Procedure

Linkage Table) One offset value.


r_relative If the bit is set, then the relocation to the target file will be the image file of its components at runtime loaded address associated. Such relocation

occurs only in the shared object files.

r_copy If the bit is set, the relocation record specifies a symbol, the symbol of the content is copied to r_address

designated place. The copy operation is shared by the target modules in a suitable data items completed runtime linker.

The symbol name is mapped to an address (or, more colloquially string is mapped to a value). Because the linker to adjust the name address, a symbol must be used to

indicate its address until you have been given an absolute address value. Symbol is the name of a variable length symbol table and a fixed-length string table records the

composition. Symbol table is nlist An array of structures, as shown below:

struct nlist {
union {
char * N_name;
long
n_strx;
} N_un;
unsigned char n_type;
char n_other;
short n_desc;
unsigned long n_value;
};

The meaning of each field is:

n_un.n_strx This name has signed byte offset in the string table. When the program uses nlist () Accessing a function symbol table, this field is replaced n_un.n_name

Field, which is a pointer to the memory string.

n_type Used to link the program to determine how to update the value of the symbol. Using a bit mask ( bitmasks) can n_type Field into

Three sub-fields, for N_EXT Type of sign bit, the program will link them as "external" symbol, and other binary object files to allow references

to them. N_TYPE The mask bits for the linker of interest:

N_UNDF Undefined symbol. Linker must locate external symbols having the same name in the other binary object file to determine the absolute value

of the symbol data. Under special circumstances, if n_type Field is non-zero, and no two

--469--
11.4 const.h file

Binary file defines this symbol, the linker in BSS The symbol resolution is in a segment address, a length equal to retain

n_value Byte. If more than one binary symbol is not defined in the object file and the binary value of the target files are inconsistent its length, the

linker will select all files in the target binary maximum length.

N_ABS An absolute symbol. Linker does not update an absolute symbol.

N_TEXT A code symbols. The value of this symbol is the code address, the linker when combining binary object file updates its value.

N_DATA A data symbol; and N_TEXT Similarly, the data for the address. An offset value corresponding to the code and data symbols but the value is not the

address file; offset to find the file, it is necessary to determine the relevant portion of the load start address and subtracting it, and then add the offset portion.

N_BSS One BSS Symbols; data symbols and code or the like, but without a corresponding shift in the binary object file.

N_FN A file name of the symbol. When you merge binary object files, the linker will insert the symbol in binary notation before. Name of the symbol is to give the

filename linker, and its value is a binary file in the first code segment address. Symbols do not need to file name, but very useful for the transfer procedure when

linking and loading.

N_STAB Mask transfer procedure for selecting the symbol (e.g. gdb) Bit of interest; its value stab () Explained.

n_other According to the field n_type Determining a segment, independent information about the symbols provide symbol relocation operation. Currently,

n_other Lowest field 4 Bits comprising one of two values: AUX_FUNC with AUX_OBJECT (For definition, see < link.h> ).

AUX_FUNC The symbol associated with the function call, AUX_OBJECT The symbols associated with the data, whether they are located in the data segment is a code segment.

This field is used to link the main program ld To create a dynamic executable.

n_desc Transfer procedure reserved for use; linker does not process it. The different fields as different debugger

the use of.

n_value Containing the value of the symbol. For the code, data, and BSS Symbol, which is an address; for other symbols (e.g., modulation

Programming symbol), the value may be arbitrary.

String table is of length u_int32_t Followed by a null The end of the symbol strings. The length of the table is representative of the size, in bytes, so 32 Its minimum position

on the machine (or the first 1 Offset of the string) always 4 .

11.4 const.h file

11.4.1 Functional Description

The document defines the i File attributes and types of nodes i_mode Some fields are used Flag constant symbols.

11.4.2 Code comments

program 11-2 linux / include / const.h

1 #ifndef _CONST_H 2 #define _CONST_H 3 4 #define


BUFFER_END 0x200000

// define the buffer memory using terminal (do not use the constant code).

5
Each flag // i i_mode node data structure fields.
6 #define I_TYPE 0170000 I // specified node type.
7 #define I_DIRECTORY 0040000 // is a directory file.
8 #define I_REGULAR 0100000 // regular file, not the file or directory special file.
9 #define I_BLOCK_SPECIAL 0060000 // block device special file.
10 #define I_CHAR_SPECIAL 0020000 // character device special file.

11 #define I_NAMED_PIPE 0010000 // named pipes.

--470--
11.5 ctype.h file

12 #define I_SET_UID_BIT 0004000 // set the effective user id type at execution time.

13 #define I_SET_GID_BIT 0002000 // Set id type active set when executed.


1415 #endif

16

11.5 ctype.h file

11.5.1 Functional Description

The document is the first document on character testing and treatment, as well as standard C One library header files. Which defines some judgment about the character

type and converting macros. For example, whether a character c Is a numeric character ( isdigit (c) ) Or a space ( isspace (c) ). Using an array (table) in the process (the lib / ctype.c ),

The definition of the array ASCII All of the properties and character code table. When using a macro, the character is as a table (__ ctype) Index, acquiring a byte from the table, then

the relevant bit can be obtained.

11.5.2 Code comments

program 11-3 linux / include / ctype.h

1 #ifndef _CTYPE_H 2 #define


_CTYPE_H 3 4 #define _U

0x01 / * Upper * / // This bit is used uppercase [AZ].


5 #define _L 0x02 / * Lower * / // This bit is used lowercase characters [az].

6 #define _D 0x04 / * Digit * / // The digital bit [0-9].


7 #define _C 0x08 / * Cntrl * / // This bit is used for control characters.

8 #define _P 0x10 / * Punct * / // This bit is used for punctuation characters.

9 #define _S 0x20 / * White space (space / lf / tab) * / // For whitespace characters such as spaces, \ t, \ n and so on.

10 #define _X 0x40 / * Hex digit * / // This bit is used for hexadecimal number.

11 #define _SP 0x80 / * Hard space (0x20) * / // This bit is used for a space character (0x20).

1213 extern unsigned char _ctype [];


// array of character characteristic (Table), defined above corresponding to each character attributes.

14 extern char _ctmp ; // a temporary character variable (in lib / ctype.c defined).
15
// Here are some determined character type macro.

16 #define isalnum (C) (( _ctype +1) [c] & ( _U | _L | _D )) // character or numeric [AZ], [az] or [0-9].
17 #define isalpha (C) (( _ctype +1) [c] & ( _U | _L )) // character.
18 #define iscntrl (C) (( _ctype +1) [c] & ( _C )) // is a control character.

19 #define isdigit (C) (( _ctype +1) [c] & ( _D )) // numbers.


20 #define isgraph (C) (( _ctype +1) [c] & ( _P | _U | _L | _D )) // is a graphical character.

twenty one #define islower (C) (( _ctype +1) [c] & ( _L )) // lowercase characters.

twenty two #define isprint (C) (( _ctype +1) [c] & ( _P | _U | _L | _D | _SP )) // is printable characters.
twenty three #define ispunct (C) (( _ctype +1) [c] & ( _P )) // punctuation.
twenty four #define isspace (C) (( _ctype +1) [c] & ( _S )) // blank characters such as spaces, \ f, \ n, \ r, \ t, \ v.

25 #define isupper (C) (( _ctype +1) [c] & ( _U )) // uppercase characters.

26 #define isxdigit (C) (( _ctype +1) [c] & ( _D | _X )) // hexadecimal digits.


2728 #define isascii (C) (((unsigned) c) <= 0x7f)
// ASCII characters.
29 #define toascii (C) (((unsigned) c) & 0x7f) // converted to ASCII characters.

--471--
11.6 errno.h file

// definition of two or more, the use of macro arguments prefix (unsigned), should be added to the c-bracket, i.e. expressed as (c). // Because c may be a complex

expression in the program. For example, if the parameter is a + b, if brackets, then the macro definition @ becomes: (unsigned) a + b. This is obviously wrong. Brackets

can be added correctly represented as (unsigned) (a + b).

3031 #define tolower (C) ( _ctmp = C, isupper ( _ctmp )? _ctmp - ( ' A '-' a '): _ctmp ) // into corresponding lowercase.

32 #define toupper (C) ( _ctmp = C, islower ( _ctmp )? _ctmp - ( ' a '-' A '): _ctmp ) // converted to the corresponding uppercase characters.

33 The reason more than two macro definitions // used a temporary variable _ctmp is: In macro definitions, macro parameters can only be used once.

But for multithreading // this is not safe, because two or more threads might use this public temporary variables at the same time. // therefore start from Linux 2.2.x

version changed to use two functions to replace both the macro definition.

34 #endif
35

11.6 errno.h file

11.6.1 Functional Description

In the standard system, or C There is a language called errno Variables regarding C Standards need for this variable, C Organization for Standardization ( X3J11 ) Caused a

lot of controversy. But the debate is not removed result errno Instead create a name " errno.h " Header files. Because standardization organizations want each library function or data

objects are required to declare in a corresponding standard header file.

The main reason is: For each kernel system call, if the return value is the result of the value of the specified system call, then it is difficult to report error conditions. If so

that each function returns a true / false indication of value, and the results returned values ​separately, you can not easily get the result value of the system call. One solution is to

be a combination of these two ways: For a certain system calls, you can specify a differentiated and effective results range error return value. For example, the pointer may be

employed null Value for the pid You can return - 1 value. In many other cases, as long as the value does not conflict with the findings can be adopted - 1 To represent the error

value. But the standard C Library function return values ​only inform whether an error occurred, the type of error must also learn from other places, so using a errno This variable.

For standard C Library design mechanism compatible, Linux Kernel library files also adopted this approach. Therefore borrowed Standard C This header file. Relevant examples

can be found in lib / open.c Program and unistd.h The system calls the macro definition. In some cases, although the program from returning - 1 Know the value of a mistake, but

would like to know the specific error number, you can read errno The value to determine the last error error number.

Although this document only defines Linux Some of the system error code (error number) of the constant symbols, and Linus Compatibility also want to consider a

program with defined symbols POSIX Like standard. But do not underestimate this simple code, the file is SCO

The company blamed Linux Operating system infringe on the copyright of one of the documents listed. To investigate this question of infringement, the 2003 year 12 month,

10 More current Linux The kernel of the top developers on the Internet to discuss countermeasures. These include Linus , Alan Cox , HJLu , Mitchell Blank Jr . Since the current kernel

version ( 2.4.x )middle errno.h Files from 0.96c Version of the kernel unchanged in the beginning, they have been "tracking" to the old version of the kernel code. At last Linus It found

that the file is from HJLu Was maintained Libc 2.x Library using a program automatically generated, some of which include SCO Copyrighted UNIX old version( V6 , V7 Etc.) the same

variable name.

11.6.2 Code comments

program 11-4 linux / include / errno.h

1 #ifndef _ERRNO_H 2 #define


_ERRNO_H 3 4 / *

5 * Ok, as I had not got any other source of information about


6 * Possible error numbers, I was forced to use the same numbers

--472--
11.6 errno.h file

7 * As minix.
8 * Hopefully these are posix or something. I would not know (and posix
9 * Is not telling me - they want $$$ for their f *** ing standard).
10 *
11 * We do not use the _SIGN cludge of minix, so kernel returns must
12 * See to the sign by themselves.
13 *
14 * NOTE! Remember to change strerror () if you change this file!
15 * /
/*
* ok, because I did not get any information about the other wrong number, I can only use the minix system
* The same error number.

* Hope these are POSIX-compliant or to a certain extent is this, I do not know (and POSIX
* He did not tell me - to get their asshole standards need to pay).
*
* We did not use the minix _SIGN cluster like that, so the return value of the kernel must identify themselves sign.

*
* note! If you change the file, you have to remember to modify strerror () function.
*/
16
// system calls and library function returns a lot of special value to indicate the operation failed or wrong. This value is typically chosen @ -1 or other specific value to represent. But

this return value only error occurred. If you need to know the type of error, we need to see // variable representing the number of system error errno. The variable that is declared in

errno.h file. When the program started at the beginning of the variable value is initialized to 0 //.

17 extern int errno ;


18
// When an error, the system call will be placed in errno error number (a negative value), and returns -1. So if you need to know the specific program // wrong number, you need to see

the value of errno.

19 #define ERROR 99 // General error.


20 #define EPERM 1 // operating without a license.

twenty one #define ENOENT 2 // file or directory does not exist.

twenty two #define ESRCH 3 // specified process does not exist.

twenty three #define EINTR 4 // interrupt function calls.


twenty four #define EIO 5 // Input / output error.
25 #define ENXIO 6 // specified device or address does not exist.

26 #define E2BIG 7 // parameter list is too long.

27 #define ENOEXEC 8 // execute the program format error.

28 #define EBADF 9 // file handle (a descriptor) error.


29 #define ECHILD 10 // child process does not exist.

30 #define EAGAIN 11 // Resource temporarily unavailable.

31 #define ENOMEM 12 // Not enough storage.

32 #define EACCES 13 // no permission.


33 #define EFAULT 14 // wrong address.

34 #define ENOTBLK 15 // not a block device file.


35 #define EBUSY 16 // resource is busy.

36 #define EEXIST 17 // File already exists.


37 #define EXDEV 18 // illegal connections.

38 #define ENODEV 19 // device does not exist.

39 #define ENOTDIR 20 // is not a directory file.


40 #define EISDIR twenty one // is a directory file.
41 #define EINVAL twenty two // Invalid argument.

42 #define ENFILE twenty three // open file system too.


43 #define EMFILE twenty four // open file too much.

--473--
11.7 fcntl.h file

44 #define ENOTTY 25 // IO inappropriate control operation (no tty terminal).


45 #define ETXTBSY 26 // No longer use.
46 #define EFBIG 27 // file size too big.
47 #define ENOSPC 28 // Device is full (the device has no space).
48 #define ESPIPE 29 // invalid file pointer relocation.
49 #define EROFS 30 // read-only file system.
50 #define EMLINK 31 // too many connections.

51 #define EPIPE 32 // wrong pipe.


52 #define EDOM 33 // domain (domain) error.
53 #define ERANGE 34 // result is too large.

54 #define EDEADLK 35 // avoid resource deadlock.

55 #define ENAMETOOLONG 36 // file name is too long.

56 #define ENOLCK 37 // no fix is ​available.


57 #define ENOSYS 38 // function not implemented.

58 #define ENOTEMPTY 39 // directory is not empty.

5960 #endif

61

11.7 fcntl.h file

11.7.1 Functional Description

Document Control Options header file. The main definition of the function fcntl () with open () Used in some of the options.

11.7.2 Code comments

program 11-5 linux / include / fcntl.h

1 #ifndef _FCNTL_H 2 #define _FCNTL_H 3


4 #include <sys / types.h>

// type of header files. System defines the basic data types.

56 / * Open / fcntl - NOCTTY, NDELAY is not implemented yet * /

/ * Open / fcntl - NOCTTY and NDELAY not yet achieved * /


7 #define O_ACCMODE 00003 // File Access mode mask.
// Open the file open () and file control fcntl () function uses the file access mode. At the same time you can only use one of the three.

8 #define O_RDONLY 00 // Open the file in read-only mode.

9 #define O_WRONLY 01 // open the file for writing only.


10 #define O_RDWR 02 // open the file in read-write mode.

// Here is the file creation flags to open (). Access can be used with the above embodiment mode with "bits or apos.

11 #define O_CREAT 00100 / * Not fcntl * / // If the file does not exist is created.
12 #define O_EXCL 00200 / * Not fcntl * / // Exclusive use of file flags.
13 #define O_NOCTTY 00400 / * Not fcntl * / // The control terminal is not allocated.

14 #define O_TRUNC 01000 / * Not fcntl * / // If the file already exists and is write operation, the length of the cut to zero.

15 #define O_APPEND 02000 // add to open the file pointer is set to the file.
16 #define O_NONBLOCK 04000 / * Not fcntl * / // Non-blocking open and manipulate files.
17 #define O_NDELAY O_NONBLOCK // non-blocking open and manipulate files.

--474--
11.7 fcntl.h file

1819 / * Defines for fcntl-commands. Note that currently

20 * Locking is not supported, and other things are not really


twenty one * Tested.

twenty two * /

/ * The following defines the fcntl commands. Note that currently support the lock command has not, while the other

* Command actually has not been tested.

*/
// command file handle (descriptor) function operation the fcntl () a.

twenty three #define F_DUPFD 0 / * Dup * / // handle copy file handle to a minimum value.
twenty four #define F_GETFD 1 / * Get f_flags * / // Take the file handle flags.
25 #define F_SETFD 2 / * Set f_flags * / // Setting File Handles flag.
26 #define F_GETFL 3 / * More flags (cloexec) * / // Take the file status flags and access modes.
27 #define F_SETFL 4 // set the file status flags and access modes.

// Here is the file locking command. the fcntl () lock the third parameter is a pointer to a pointer to the flock structure.

28 #define F_GETLK 5 / * Not implemented * / // Return prevention locked flock structure.


29 #define F_SETLK 6 // set (F_RDLCK or F_WRLCK) or clear (F_UNLCK) locked.
30 #define F_SETLKW 7 // wait to set or clear lock.
3132 / * For F_ [GET | SET] FL * /

/ * For F_GETFL or the F_SETFL * /


// close the file handle when executing exec () cluster functions. (Closed execution - Close On EXECution)

33 #define FD_CLOEXEC 1 / * Actually anything with low bit set goes * /


/ * Actually * can be as long as low as 1 /

3435 / * Ok, these are locking features, and are not implemented at any

36 * Level. POSIX wants them.


37 * /
/ * OK, the following is the type of lock, any function are not yet implemented. These types of POSIX standards.

*/
38 #define F_RDLCK 0 // read or shared file locking.
39 #define F_WRLCK 1 // exclusive or write file locking.

40 #define F_UNLCK 2 // unlock the file.


4142 / * Once again - not implemented, but ... * /

/ * The same - not yet realized, but ... * /


// file locking operations data structure. Describes the type (L_Type) under the influence of file segments, start offset (l_whence), // relative offset (l_start),

length of the lock (l_len) and lock embodiment of the process id.

43 struct flock {
44 short l_type; // lock type (F_RDLCK, F_WRLCK, F_UNLCK).
45 short l_whence; // start offset (SEEK_SET, SEEK_CUR or SEEK_END).
46 off_t l_start; // blocked at the start of the lock. Relative offset (number of bytes).

47 off_t l_len; // blocked Locked size; if it is 0, compared to the end of the file.

48 pid_t l_pid; // locked process id.


49 };
50
// The following function prototypes use the flag or command. // Create a new

file or overwriting a file that already exists.

// filename parameter is the name of the file to be created, mode is a property created file (see include / sys / stat.h).
51 extern int creat (Const char * filename, mode_t mode);
// handle file operations, will affect the file open.
// parameter fildes is a file handle, cmd is the command operation, see the above line 23-30.

52 extern int fcntl (Int fildes, int cmd, ...);

--475--
11.8 signal.h file

// open a file. Establish a link between the file and the file handle.

// filename parameter is the name of the file to be opened, flags is a combination of the above 7-17 mark on the line.

53 extern int open (Const char * filename, int flags, ...);


5455 #endif

56

11.8 signal.h file

11.8.1 Functional Description

Signal provides a method for processing asynchronous events. Signal is also known as a soft interrupt. By sending a signal to a process that we can control the state of

the process (pause, continue or terminate). This document defines all the signal names and functions of the basic operations used in the kernel. The most important function is to

change the function of a specified signal processing method signal () with sigaction () .

As can be seen from this document, Linux The kernel implements POSIX.1 All required 20 Signals. So we can say that Linux

In the beginning of the design has been fully taken into account the compatibility with the standard. See specific function implementation program kernel / signal.c .

11.8.2 File Comments

program 11-6 linux / include / signal.h

1 #ifndef _SIGNAL_H 2 #define _SIGNAL_H


3 4 #include <sys / types.h>

// type of header files. System defines the basic data types.

56 typedef int sig_atomic_t ;


// defines the signal type atomic operation.

7 typedef unsigned int sigset_t ; / * 32 bits * / // Defined set of signal types.


89 #define _NSIG
32 // definition of signal type --32 species.

10 #define NSIG _NSIG // NSIG = _NSIG


11
// These are the signals Linux 0.11 kernel definition. 20 which includes all the required signals POSIX.1.
12 #define SIGHUP 1 // Hang Up -- Off control terminal or process.

13 #define SIGINT 2 // Interrupt - - interrupts from the keyboard.

14 #define SIGQUIT 3 // Quit - - Exit from the keyboard.


15 #define SIGILL 4 // Illeagle - - illegal instruction.

16 #define SIGTRAP 5 // Trap - - trace breakpoints.

17 #define SIGABRT 6 // Abort - - abnormal termination.

18 #define SIGIOT 6 // IO Trap - - Ibid.


19 #define SIGUNUSED 7 // Unused - - did not use.
20 #define SIGFPE 8 // FPE - - the coprocessor error.
twenty one #define SIGKILL 9 // Kill - - Forced process terminates.

twenty two #define SIGUSR1 10 // User1 -- User signal 1, the process can be used.

twenty three #define SIGSEGV 11 // Segment Violation - invalid memory references.


twenty four #define SIGUSR2 12 // User2 -- User signal 2, the process can be used.

25 #define SIGPIPE 13 // Pipe -- Pipe write error-free readers.

26 #define SIGALRM 14 // Alarm - - Real-time alarm timer.


27 #define SIGTERM 15 // Terminate - - process terminates.

28 #define SIGSTKFLT 16 // Stack Fault - Error Stack (coprocessor).

--476--
11.8 signal.h file

29 #define SIGCHLD 17 // Child -- Child process to stop or terminate.

30 #define SIGCONT 18 // Continue -- Recovery process continues.

31 #define SIGSTOP 19 // Stop - - stop the process of execution.

32 #define SIGTSTP 20 // TTY Stop -- tty issued to stop the process, can be ignored.

33 #define SIGTTIN twenty one // TTY In -- Background process request input.

34 #define SIGTTOU twenty two // TTY Out -- Background process request output.

3536 / * Ok, I have not implemented sigactions, but trying to keep headers POSIX * /

/ * OK, I have not implemented the preparation sigactions, but still want to honor the header file POSIX standard * /

37 #define SA_NOCLDSTOP 1 // When the child process is stopped, not for SIGCHLD process.

38 #define SA_NOMASK 0x40000000 // no longer receive the blocking signal in the specified signal processing (signal handler) in the.

39 #define SA_ONESHOT 0x80000000 // signal handler once been called to revert to the default handler.
40
// The following constants are used sigprocmask (how,) - changing the current blocking signals (mask). Used to change the behavior of the function.

41 #define SIG_BLOCK 0 / * For blocking signals * /


// add concentrated in blocking a given set of signals.

42 #define SIG_UNBLOCK 1 / * For unblocking signals * /


// Deletes a specified set of signals from the blocking signal.

43 #define SIG_SETMASK 2 / * For setting the signal mask * /


// Set the current blocking signal (mask signal).

44
// The following symbols are two constants function pointers point to no return value, and has an int integer parameter. Both address pointer value is a function of the value //

Logically actually not the case. The following can be used as a function of the second signal parameter. To tell the kernel, // let the kernel handle the signal processing of the

signal or ignored. Use See kernel / signal.c procedures, line 94-96.

45 #define SIG_DFL ((Void (*) (int)) 0) / * Default signal handling * /


// default signal handler (signal handler).
46 #define SIG_IGN ((Void (*) (int)) 1) / * Ignore signal * /
// ignore the signal handler.
47
// The following are sigaction data structures.

// sa_handler is a signal corresponding to the specified action to be taken. Can SIG_DFL above, or to ignore this signal SIG_IGN, // it may be a pointer to a

function of the signal processing.

// sa_mask given mask on the signal, when the signal blocking program execution processing of these signals. // sa_flags specified set of signal change signal processing

procedure. It is composed of flag lines 37-39 of definition. // sa_restorer function pointer is restored, the library Libc provided, for cleaning the user mode stack. See kernel

/ signal.c // In addition, the trigger signal causes the signal processing will also be blocked, unless the SA_NOMASK flag.

48 struct sigaction {
49 void (* sa_handler) (int);
50 sigset_t sa_mask;
51 int sa_flags;
52 void (* sa_restorer) (void);
53 };
54
// The following signal function is used to install a new signal processing (signal handler) is a signal _sig, similar sigaction (). // This function contains two parameters: _sig

need to capture the specified signal; _func function pointer having a free parameter and return value. // the return value of the function also having a parameter int (last (int))

function pointers and no return value, which is the original handler processes the signal @.

55 void (* signal (int _sig, void (* _func) (int))) (int);


// The following two functions are used to transmit signals. kill () for transmitting any signal (kernel / exit.c, 60 lines) to any process or group of processes. // raise () to send a

signal to the current process itself. Its function is equivalent to kill (getpid (), sig).

56 int raise (Int sig);


57 int kill ( pid_t pid, int sig);
// process the task structure in addition to a 32-bit signal represents a field current signal to be processed in order to process than bits, there is a

--477--
11.9 stdarg.h file

// for shielding a process similar to the bit indicates the current blocking signal sets (set mask signal) is blocked field, it is 32, @ which each bit representing a corresponding

blocking signal. Set shielded signal modification process can block or release signal blocking specify. The following five // ​function is used to operate the process of masking

signal set, though simple is simple to implement, but this version of the kernel has not been achieved. // sigaddset () and sigdelset () signal set signal for add, delete modified.

sigaddset () // for pointing signal to mask the specified concentration increased signal signo. sigdelset and vice versa.

// sigemptyset () and sigfillset () sets the mask signal for the initialization process. Each set of program signals before use, require the use of one of these two

functions // mask signal set is initialized. sigemptyset () for emptying the shield all signals, i.e. the signal in response to all //. sigfillset () to signal all signals into

focus, i.e., block all signals. Of course, SIGINT and SIGSTOP are // not shield the screen.

// sigismember () is used to specify the test signal is a focus signal (1 - Yes, 0 - not, -1 - Error).
58 int sigaddset ( sigset_t * Mask, int signo);
59 int sigdelset ( sigset_t * Mask, int signo);
60 int sigemptyset ( sigset_t * Mask);
61 int sigfillset ( sigset_t * Mask);
62 int sigismember ( sigset_t * Mask, int signo); / * 1 - is, 0 - not, -1 error * /
// set the signal to be tested to see whether there is a pending signal. Return process in the set of signals currently being blocked in the set.

63 int sigpending ( sigset_t * Set);


// The following function is used to change the process currently set is blocked signal (mask signal). If oldset is not NULL, // returns the process by which the current signal mask set. If

set pointer is not NULL, then modify the process according to the mask signal set how (41-43 lines) indicated.

64 int sigprocmask (Int how, sigset_t * Set, sigset_t * Oldset);


// temporary replacement of a process with the following functions sigmask mask signal, then pauses the process until it receives a signal. // if a capture signal and a return signal from

the handler, the function also returns, and the signal will return to the value of the mask before the call is made.

65 int sigsuspend ( sigset_t * Sigmask);


// sigaction () when it receives a specified course of action taken for the signal to change. See the description of the kernel / signal.c program.

66 int sigaction (Int sig, struct sigaction * Act, struct sigaction * Oldact);
6768 #endif / * _ SIGNAL_H * /

69

11.9 stdarg.h file

11.9.1 Functional Description

C One of the biggest features of the language is to allow the programmer number of custom variable parameter function. To access these parameters variable argument

list, you need to use stdarg.h File macro. stdarg.h Header files C According to Organization for Standardization BSD systematic varargs.h File revisions.

stdarg.h Is the standard header file parameters. It defines a variable argument list as macros. Mainly explained - types ( va_list) And three macros

(Va_start, va_arg with va_end) For vsprintf , vprintf , vfprintf function. When reading the file, you need to understand the use of variable argument function, see kernel /

vsprintf.c After the description of the list.

11.9.2 Code comments

program 11-7 linux / include / stdarg.h

1 #ifndef _STDARG_H 2 #define _STDARG_H 3 4 typedef char * va_list ; // va_list defined type is a
character pointer.

56 / * Amount of space required in an argument list for an arg of type TYPE.

7 TYPE may alternatively be an expression whose type is used. * /

--478--
11.10 stddef.h file

/ * Here are the type of space arg list of parameters required by the TYPE.
TYPE can also be an expression of the type of use * /

8
// length in bytes of the following sentence defines the rounded value of type TYPE. Int length is a multiple of (4).

9 #define __va_rounded_size ( TYPE ) \


10 (((Sizeof ( TYPE ) + Sizeof (int) - 1) / sizeof (int)) * sizeof (int))
11
// The following function (implemented macro) points to the first AP variable parameter passed to the function of the parameter table. // before

the first call to va_arg or va_end, you must first call the function.

// __builtin_saveregs on line 17 () is defined in the library program libgcc2.c gcc, for saving registers. // it // gcc manual instructions
can be found in the section "Target Description Macros" in the "Implementing the Varargs Macros" section.

12 #ifndef __sparc__
13 #define va_start (AP, LASTARG) \
14 (AP = ((char *) & (LASTARG) + __va_rounded_size (LASTARG)))
15 #else
16 #define va_start (AP, LASTARG) \
17 (__Builtin_saveregs (), \
18 AP = ((char *) & (LASTARG) + __va_rounded_size (LASTARG)))
19 #endif
20
// The following macro function is called for a complete return to normal. va_end can modify the AP that it can not be used before recall

// va_start. va_end must read all of the parameters after the va_arg is invoked.

twenty one void va_end ( va_list ); / * Defined in gnulib * / / * Gnulib defined in * /


twenty two #define va_end (AP)

twenty three

// The following macro expansion for the expression and to have the same value type is passed to the next parameter. // For the default value,

va_arg can use characters, unsigned char, and the floating-point type.

// use the va_arg first time, it returns the first argument of the table, each subsequent calls will return the following table // a parameter. This is the first

visit AP, and then increase it by pointing to the next item to achieve. // va_arg use TYPE to complete the access and positioning the next, each called

once va_arg, it will modify the AP to indicate that the next parameter table //.

twenty four #define va_arg (AP, TYPE ) \


25 (AP + = __va_rounded_size ( TYPE ), \
26 * (( TYPE *) (AP - __va_rounded_size ( TYPE ))))
2728 #endif / * _ STDARG_H * /

29

11.10 stddef.h file

11.10.1 Functional Description

stddef.h There is also the name of the header file C Organization for Standardization ( X3J11 ) Is created, meaning standard ( std )definition( def) . Mainly used to store some of

the "standard definition." Another confusing contents of the header file is stdlib.h , But also by the standards organization established. stdlib.h

Mainly used to declare some of the various other functions not related to the type of header files. But the contents of two headers which often can be confusing which affirms that

header file in.

Some members of the standardization organization believe in those who can not fully support the standard C Independent environmental library, C Language should also

be a useful programming language. For a standalone environment, C Standard required to provide C All the properties of language, and for the standard C Library, this

--479--
11.11 string.h file

Kind of realized only provide support 4 Header file functions: float.h , limits.h , stdarg.h with stddef.h . This requires clear stddef.h

What content should contain files, header files and the other three for substantially more specific aspects:

float.h Floating point representation described characteristics;

limits.h Describes a characteristic Integer;

stdarg.h Macros are provided for access variable argument lists definitions. And any other type of stand-alone environment or macro definition used should be placed stddef.h

File. But members of the organization later relaxed these restrictions, leading to some definitions appear in multiple header files. For example, a macro definition NULL Also appeared

in other 4 Header file. Therefore, in order to prevent conflict, stddef.h In the definition file NULL Before first use undef Instruction cancel the original definition (first 14 Row).

Types and macros defined in this document, there is one thing in common: These definitions have tried to be included in the C The characteristics of the language, but later

due to various compilers have their own ways to define these information, it is difficult to write code that can replace all of these definitions come, so give up.

in Linux 0.11 Kernel rarely used files.

11.10.2 Code comments

program 11-8 linux / include / stddef.h

1 #ifndef _STDDEF_H 2 #define _STDDEF_H


3 4 #ifndef _PTRDIFF_T 5 #define _PTRDIFF_T
6 typedef long ptrdiff_t ;

// pointer type two subtraction results.


7 #endif
89 #ifndef _SIZE_T 10 #define _SIZE_T 11 typedef
unsigned long size_t ;

// return type of sizeof.


12 #endif
1314 #undef NULL 15 #define NULL ((Void *) 0)

// null pointer.
1617 #define offsetof ( TYPE , MEMBER) (( size_t ) & (( TYPE *) 0) -> MEMBER) // offset in the member types.

1819 #endif

20

11.11 string.h file

11.11.1 Functional Description

The header file defines all the string manipulation functions in the form of built-in functions, in order to improve execution speed using inline assembler. In the standard C The

library also provides a header file of the same name, but the function is realized in the standard C Library, and the file contains only the statement of the correlation function.

--480--
11.11 string.h file

11.11.2 Code comments

program 11-9 linux / include / string.h

1 #ifndef _STRING_H_ 2 #define _STRING_H_


3 4 #ifndef NULL 5 #define NULL ((Void *) 0)

6 #endif
78 #ifndef _SIZE_T 9 #define _SIZE_T 10 typedef
unsigned int size_t ;

11 #endif
1213 extern char * strerror (Int errno );

1415 / *

16 * This string-include defines all string functions as inline


17 * Functions. Use gcc. It also assumes ds = es = data space, this should be
18 * Normal. Most of the string-functions are rather heavily hand-optimized,
19 * See especially strtok, strstr, str [c] spn. They should work, but are not
20 * Very easy to understand. Everything is done entirely within the register
twenty one * Set, making the functions fast and clean. String instructions have been
twenty two * Used through-out, making for "slightly" unclear code :-)
twenty three *

twenty four * (C) 1991 Linus Torvalds


25 * /
/*
* This header file defines all the string string manipulation functions in the form of built-in functions. When using gcc, while

* Assumed ds = es = data space, this should be routine. The vast majority string functions are carried out by a large number of manual

* Optimization, in particular function strtok, strstr, str [c] spn. They should be able to work, but it is not that
* It is easy to understand. All operations are basically used to complete the set of registers, i.e., the function which makes fast or neat.

* All places are used in string instructions, which in turn makes the code "a little" hard to understand ☺

*
* (C) 1991 Linus Torvalds
*/
26
//// a string (the src) copied to another string (dest), until it encounters a NULL character after stopping. // Parameters: dest
- pointer to a string object, src - pointer to the source string. //% 0 - esi (src),% 1 - edi (dest).

27 extern inline char * strcpy (Char * dest, const char * src)


28 {
29 __asm ​__ ( " cld \ n " // clear direction bit.

30 "1: \ tlodsb \ n \ t" // load DS: [esi] 1 byte at al, and updates esi.
31 "Stosb \ n \ t" // memory byte al ES: [edi], and updates edi.
32 "Testb %% al, %% al \ n \ t" // memory byte is just 0?
33 "Jne 1b" // instead of the backward jump to label 1, otherwise ends.

34 :: " S "( src), " D "( dest): " si "," di "," ax ");
35 return dest; // return destination string pointer.

36 }
37

--481--
11.11 string.h file

//// copy count bytes of the source string to the destination string.

// If the source is less than the string length count bytes to additional null characters (NULL) to the destination string. // Parameters:

dest - pointer to a string object, src - source string pointer, count - the number of bytes copied. //% 0 - esi (src),% 1 - edi (dest),% 2 -

ecx (count).

38 extern inline char * strncpy (Char * dest, const char * src, int count )
39 {
40 __asm ​__ ( " cld \ n " // clear direction bit.

41 "1: \ tdecl% 2 \ n \ t" // register ecx - (count--).


42 "Js 2f \ n \ t" // if count <0 ahead to jump to the label 2, the end.
43 "Lodsb \ n \ t" // get ds: [esi] 1 byte at al, and esi ++.
44 "Stosb \ n \ t" // store the byte es: [edi], and edi ++.
45 "Testb %% al, %% al \ n \ t" // This byte is 0?
46 "Jne 1b \ n \ t" // not, forward jump to number 1 continue to copy.
47 "Rep \ n \ t" // Otherwise, the remaining number of null characters stored in the object stream.

48 "Stosb \ n"
49 "2:"
50 :: " S "( src), " D "( dest), " c "( count ): " si "," di "," ax "," cx ");
51 return dest; // return destination string pointer.

52 }
53
//// source string copied to the end of the destination string. // Parameters: dest - pointer to a string
object, src - pointer to the source string. //% 0 - esi (src),% 1 - edi (dest),% 2 - eax (0),% 3 - ecx
(-1).
54 extern inline char * strcat (Char * dest, const char * src)
55 {
56 __asm ​__ ( " cld \ n \ t " // clear direction bit.

57 "Repne \ n \ t" // al comparison and es: [edi] bytes, and the update edi ++,

58 "Scasb \ n \ t" // string until the object is found in byte 0, byte 1 at this time point is after edi.

59 "Decl% 1 \ n" // make es: [edi] point to a value of 0 bytes.

60 "1: \ tlodsb \ n \ t" // source string of bytes taken ds: [esi] al, and esi ++.
61 "Stosb \ n \ t" // the bytes to save es: [edi], and edi ++.
62 "Testb %% al, %% al \ n \ t" // This byte is 0?
63 "Jne 1b" // not, then jumps back to 1 to continue at the label copy, otherwise ends.

64 :: " S "( src), " D "( dest), " a "( 0), " c "( 0xffffffff): " si "," di "," ax "," cx ");
65 return dest; // return destination string pointer.

66 }
67
//// copy count bytes of the source string to the end of the destination string, and finally adding a null character. // Parameters:
dest - destination string, src - the source string, count - the number of bytes to be copied. //% 0 - esi (src),% 1 - edi (dest),% 2 -
eax (0),% 3 - ecx (-1),% 4 - (count).
68 extern inline char * strncat (Char * dest, const char * src, int count )
69 {
70 __asm ​__ ( " cld \ n \ t " // clear direction bit.

71 "Repne \ n \ t" // al comparison and es: [edi] byte, edi ++.


72 "Scasb \ n \ t" // value of 0 bytes until it finds the end of the string object.

73 "Decl% 1 \ n \ t" 0 // edi points to the byte value.


74 "Movl% 4,% 3 \ n" // To copy the number of bytes ecx.

75 "1: \ tdecl% 3 \ n \ t" // ecx - (counting from 0).


76 "Js 2f \ n \ t" // ecx <0?, It is the forward jump to the label 2.
77 "Lodsb \ n \ t" // Otherwise take ds: Byte al [esi] at, esi ++.
78 "Stosb \ n \ t" // store to es: [edi] office, edi ++.
79 "Testb %% al, %% al \ n \ t" // The byte value 0?
80 "Jne 1b \ n" // instead of the backward jump to number 1, continue to replicate.

--482--
11.11 string.h file

81 "2: \ txorl% 2,% 2 \ n \ t" // The al cleared.


82 "Stosb" // to deposit es: [edi] at.
83 :: " S "( src), " D "( dest), " a "( 0), " c "( 0xffffffff), " g "( count )
84 : " si "," di "," ax "," cx ");
85 return dest; // return destination string pointer.

86 }
87
//// comparing a string to another string. // Parameters: cs - string
1, ct - 2 string.
//% 0 - eax (__ res) returns the value,% 1 - edi (cs) string pointer 1,% 2 - esi (ct) 2 string pointer. // Returns: 1 if the string> string 2,
1 is returned; string string 2 = 1, 0 is returned; string 1 <string 2, -1 is returned.
88 extern inline int strcmp (Const char * cs, const char * ct)
89 {
90 register int __res __asm ​__ ( " ax "); // __res a register variable (eax).
91 __asm ​__ ( " cld \ n " // clear direction bit.

92 "1: \ tlodsb \ n \ t" // ds 2 takes a string of bytes: [esi] al, and esi ++.
93 "Scasb \ n \ t" // al string of bytes es 1: [edi] compared, and edi ++.
94 "Jne 2f \ n \ t" // If not equal, then jump to the label 2 forward.
95 "Testb %% al, %% al \ n \ t" // The byte value is 0 bytes it (end of the string)?
96 "Jne 1b \ n \ t" // not, then jump back to number 1, the comparison continues.

97 "Xorl %% eax, %% eax \ n \ t" // Yes, the return value is cleared eax,

98 "Jmp 3f \ n" // forward jump to number 3, the end.


99 "2: \ tmovl $ 1, %% eax \ n \ t" // eax in the set.
100 "Jl 3f \ n \ t" // If the foregoing comparison character string 2 <1 character string, the positive return at the end.

101 "Negl %% eax \ n" // otherwise eax = -eax, returns a negative value, end.

102 "3:"
103 : "= a "(__ res): " D "( cs), " S "( ct): " si "," di ");
104 return __res; // returns the result of the comparison.

105 }
106
//// string 1 is compared with the first count characters of the string 2. // Parameters: cs - string 1, ct - 2, count

the string - the number of characters to compare.

//% 0 - eax (__ res) returns the value,% 1 - edi (cs) string pointer 1,% 2 - esi (ct) string pointer 2,% 3 - ecx (count). // Returns: 1 if the string> string 2, 1
is returned; string string 2 = 1, 0 is returned; string 1 <string 2, -1 is returned.
107 extern inline int strncmp (Const char * cs, const char * ct, int count )
108 {
109 register int __res __asm ​__ ( " ax "); // __res a register variable (eax).
110 __asm ​__ ( " cld \ n " // clear direction bit.

111 "1: \ tdecl% 3 \ n \ t" // count--.


112 "Js 2f \ n \ t" // If count <0, the reference numeral 2 to jump forward.

113 "Lodsb \ n \ t" // get a string of characters ds 2: [esi] al, and esi ++.
114 "Scasb \ n \ t" // character string and comparing al es 1 is: [edi], and edi ++.
115 "Jne 3f \ n \ t" // If not equal, then jump forward to numeral 3.
116 "Testb %% al, %% al \ n \ t" // The characters are NULL characters?

117 "Jne 1b \ n" // not, then jump back to number 1, the comparison continues.

118 "2: \ txorl %% eax, %% eax \ n \ t" // is NULL character, eax cleared (return value).
119 "Jmp 4f \ n" 4 // jump to the label forward end.
120 "3: \ tmovl $ 1, %% eax \ n \ t" // eax in the set.
121 "Jl 4f \ n \ t" // If the previous comparison character string 2 <2 character string, returns an end.

122 "Negl %% eax \ n" // otherwise eax = -eax, returns a negative value, end.

123 "4:"
124 : "= a "(__ res): " D "( cs), " S "( ct), " c "( count ): " si "," di "," cx ");
125 return __res; // returns the result of the comparison.

--483--
11.11 string.h file

126 }
127
//// first match for the characters in the string. // Parameters: s -
the string, c - To find the characters.
//% 0 - eax (__ res),% 1 - esi (string pointer s),% 2 - eax (character c).
// Returns: pointer to string matching character first appears once. If the characters match is not found, a null pointer is returned.

128 extern inline char * strchr (Const char * s, char c)


129 {
130 register char * __res __asm ​__ ( " ax "); // __ res is the register variable (eax).
131 __asm ​__ ( " cld \ n \ t " // clear direction bit.

132 "Movb %% al, %% ah \ n" // will want to compare the characters move ah.

133 "1: \ tlodsb \ n \ t" // get the character string ds: [esi] al, and esi ++.
134 "Cmpb %% ah, %% al \ n \ t" // al character string is compared with the specified character ah.

135 "Je 2f \ n \ t" // If equal, the forward jump to numeral 2.


136 "Testb %% al, %% al \ n \ t" // al characters are NULL characters? (End of the string?)
137 "Jne 1b \ n \ t" // If not, then jump back to number 1, the comparison continues.

138 "Movl $ 1,% 1 \ n" // yes, then the match is not found character, esi set.
139 "2: \ tmovl% 1,% 0 \ n \ t" After // points to match a character byte pointer value is placed into the eax

140 "Decl% 0" // the pointer to point adjusted to match the character.

141 : "= a "(__ res): " S "( s), "" (c): " si ");
142 return __res; // Return pointer.
143 }
144
//// looking for a place specified character string last occurrence. (Reverse search string) // Parameters: s - the
string, c - To find the characters.
//% 0 - edx (__ res),% 1 - edx (0),% 2 - esi (string pointer s),% 3 - eax (character c). // Returns: pointer to string matching character last
appeared. If the characters match is not found, a null pointer is returned.
145 extern inline char * strrchr (Const char * s, char c)
146 {
147 register char * __res __asm ​__ ( " dx "); // __ res is the register variable (edx).
148 __asm ​__ ( " cld \ n \ t " // clear direction bit.

149 "Movb %% al, %% ah \ n" // will want to look for the character to move ah.

150 "1: \ tlodsb \ n \ t" // get the character string ds: [esi] al, and esi ++.
151 "Cmpb %% ah, %% al \ n \ t" // string of characters with a specified character ah al compare.

152 "Jne 2f \ n \ t" // If not equal, the forward jump to numeral 2.


153 "Movl %% esi,% 0 \ n \ t" // Save the pointer to the character in edx.

154 "Decl% 0 \ n" // pointer back one, pointing to the string matches the character.

155 "2: \ ttestb %% al, %% al \ n \ t" // comparison character is 0 right (to the end of the string)?

156 "Jne 1b" // instead of the backward jump to number 1, the comparison continues.

157 : "= d "(__ res): "" (0), " S "( s), " a "( c): " ax "," si ");
158 return __res; // Return pointer.
159 }
160
//// Looking first character string in a sequence, any sequence of characters in the character string are included in 2. // Parameters: cs
- 1 string pointer, ct - 2 string pointer.
//% 0 - esi (__ res),% 1 - eax (0),% 2 - ecx (-1),% 3 - esi (a string pointer cs),% 4 - (2 string pointer ct). // Returns a string length value comprise any
sequence of characters in the first character string 2.
161 extern inline int strspn (Const char * cs, const char * ct)
162 {
163 register char * __res __asm ​__ ( " si "); // __ res is the register variable (esi).
164 __asm ​__ ( " cld \ n \ t " // clear direction bit.

165 "Movl% 4, %% edi \ n \ t" // first string length 2 is calculated. 2 edi pointer into the string.

166 "Repne \ n \ t" // Comparative al (0) 2 and the string of characters (es: [edi]), and edi ++.

--484--
11.11 string.h file

167 "Scasb \ n \ t" // if not equal, the comparison continues (ecx gradually decreasing).

168 "Notl %% ecx \ n \ t" // ecx in each negated.


169 "Decl %% ecx \ n \ t" // ecx--, string length to obtain a value of 2.

170 "Movl %% ecx, %% edx \ n" // the length value into the string 2 is temporarily in edx.

171 "1: \ tlodsb \ n \ t" Character string 1 // Take ds: [esi] al, and esi ++.
172 "Testb %% al, %% al \ n \ t" // The character is equal to zero the value of it (end of string 1)?

173 "Je 2f \ n \ t" // If so, forward jump to the label 2.


174 "Movl% 4, %% edi \ n \ t" // pointer to take into two series of edi.
175 "Movl %% edx, %% ecx \ n \ t" // string length value of 2 and then placed in ecx.

176 "Repne \ n \ t" @ 2 Comparative al character string and es: [edi], and edi ++.
177 "Scasb \ n \ t" // if not equal comparison continues.

178 "Je 1b \ n" // If they are equal, then the backward jump to a label.

179 "2: \ tdecl% 0" // esi--, points to the last 2 contained in the character string.

180 : "= S "(__ res): " a "( 0), " c "( 0xffffffff), "" (cs), " g "( ct)
181 : " ax "," cx "," dx "," di ");
182 return __res-cs; // returns the length of the character sequences.

183 }
184
//// find the first sequence of characters in a string 1 2 does not contain any character string. //
Parameters: cs - 1 string pointer, ct - 2 string pointer.
//% 0 - esi (__ res),% 1 - eax (0),% 2 - ecx (-1),% 3 - esi (a string pointer cs),% 4 - (2 string pointer ct). // Returns a string length value does not contain any
sequence of characters the first two characters in the string.
185 extern inline int strcspn (Const char * cs, const char * ct)
186 {
187 register char * __res __asm ​__ ( " si "); // __ res is the register variable (esi).
188 __asm ​__ ( " cld \ n \ t " // clear direction bit.

189 "Movl% 4, %% edi \ n \ t" // first string length 2 is calculated. 2 edi pointer into the string.

190 "Repne \ n \ t" // Comparative al (0) 2 and the string of characters (es: [edi]), and edi ++.

191 "Scasb \ n \ t" // if not equal, the comparison continues (ecx gradually decreasing).

192 "Notl %% ecx \ n \ t" // ecx in each negated.


193 "Decl %% ecx \ n \ t" // ecx--, string length to obtain a value of 2.

194 "Movl %% ecx, %% edx \ n" // the length value into the string 2 is temporarily in edx.

195 "1: \ tlodsb \ n \ t" Character string 1 // Take ds: [esi] al, and esi ++.
196 "Testb %% al, %% al \ n \ t" // The character is equal to zero the value of it (end of string 1)?

197 "Je 2f \ n \ t" // If so, forward jump to the label 2.


198 "Movl% 4, %% edi \ n \ t" // pointer to take into two series of edi.
199 "Movl %% edx, %% ecx \ n \ t" // string length value of 2 and then placed in ecx.

200 "Repne \ n \ t" @ 2 Comparative al character string and es: [edi], and edi ++.
201 "Scasb \ n \ t" // if not equal comparison continues.

202 "Jne 1b \ n" // If not equal, then the backward jump to a label.
203 "2: \ tdecl% 0" // esi--, points to the last 2 contained in the character string.

204 : "= S "(__ res): " a "( 0), " c "( 0xffffffff), "" (cs), " g "( ct)
205 : " ax "," cx "," dx "," di ");
206 return __res-cs; // returns the length of the character sequences.

207 }
208
//// find any characters included in the first string 2 in string 1. // Parameters: cs -
pointer to a string of 1, ct - 2 pointer to a string.
//% 0 -esi (__ res),% 1 -eax (0),% 2 -ecx (0xffffffff),% 3 -esi (a string pointer cs),% 4 - (2 string pointer ct). // Returns a string pointer 2 contains
the string of characters.
209 extern inline char * strpbrk (Const char * cs, const char * ct)
210 {
211 register char * __res __asm ​__ ( " si "); // __ res is the register variable (esi).

--485--
11.11 string.h file

212 __asm ​__ ( " cld \ n \ t " // clear direction bit.

213 "Movl% 4, %% edi \ n \ t" // first string length 2 is calculated. 2 edi pointer into the string.

214 "Repne \ n \ t" // Comparative al (0) 2 and the string of characters (es: [edi]), and edi ++.

215 "Scasb \ n \ t" // if not equal, the comparison continues (ecx gradually decreasing).

216 "Notl %% ecx \ n \ t" // ecx in each negated.


217 "Decl %% ecx \ n \ t" // ecx--, string length to obtain a value of 2.

218 "Movl %% ecx, %% edx \ n" // the length value into the string 2 is temporarily in edx.

219 "1: \ tlodsb \ n \ t" Character string 1 // Take ds: [esi] al, and esi ++.
220 "Testb %% al, %% al \ n \ t" // The character is equal to zero the value of it (end of string 1)?

221 "Je 2f \ n \ t" // If so, forward jump to the label 2.


222 "Movl% 4, %% edi \ n \ t" // pointer to take into two series of edi.
223 "Movl %% edx, %% ecx \ n \ t" // string length value of 2 and then placed in ecx.

224 "Repne \ n \ t" @ 2 Comparative al character string and es: [edi], and edi ++.
225 "Scasb \ n \ t" // if not equal comparison continues.

226 "Jne 1b \ n \ t" // If not equal, then the backward jump to a label.
227 "Decl% 0 \ n \ t" // esi--, points contained in a 2-character string.
228 "Jmp 3f \ n" // forward jump to number 3.
229 "2: \ txorl% 0,% 0 \ n" // not found qualified, the return value is NULL.
230 "3:"
231 : "= S "(__ res): " a "( 0), " c "( 0xffffffff), "" (cs), " g "( ct)
232 : " ax "," cx "," dx "," di ");
233 return __res; // returns the pointer value.

234 }
235
//// find the first match the entire string string 2 in string 1. // Parameters: cs -
pointer to a string of 1, ct - 2 pointer to a string.
//% 0 -eax (__ res),% 1 -eax (0),% 2 -ecx (0xffffffff),% 3 -esi (a string pointer cs),% 4 - (2 string pointer ct). // Return: Returns a string in a string
matching string pointer 2.
236 extern inline char * strstr (Const char * cs, const char * ct)
237 {
238 register char * __res __asm ​__ ( " ax "); // __ res is the register variable (eax).
239 __asm ​__ ( " cld \ n \ t "\ // clear direction bit.

240 "Movl% 4, %% edi \ n \ t" // first string length 2 is calculated. 2 edi pointer into the string.

241 "Repne \ n \ t" // Comparative al (0) 2 and the string of characters (es: [edi]), and edi ++.

242 "Scasb \ n \ t" // if not equal, the comparison continues (ecx gradually decreasing).

243 "Notl %% ecx \ n \ t" // ecx in each negated.


244 "Decl %% ecx \ n \ t" / * NOTE! This also sets Z if searchstring = '' * /
/ * Note! If the search string is empty, the Z flag is set * / // 2 to obtain the string length value.

245 "Movl %% ecx, %% edx \ n" // the length value into the string 2 is temporarily in edx.

246 "1: \ tmovl% 4, %% edi \ n \ t" // pointer to take into two series of edi.
247 "Movl %% esi, %% eax \ n \ t" // pointer to the string 1 replication in eax.

248 "Movl %% edx, %% ecx \ n \ t" // string length value of 2 and then placed in ecx.

249 "Repe \ n \ t" // string comparison of 1 and 2 character string (ds: [esi], es: [edi]), esi ++, edi ++.

250 "Cmpsb \ n \ t" // if the corresponding equal character has been relatively down.

251 "Je 2f \ n \ t" / * Also works for empty string, see above * /
/ * Also valid for empty string, see above * / // if equal full, go to reference numeral 2.

252 "Xchgl %% eax, %% esi \ n \ t" // pointer to a string esi, a string pointer eax comparison result.
253 "Incl %% esi \ n \ t" // string of a pointer to the next character.

254 "Cmpb $ 0, -1 (%% eax) \ n \ t" 1 // string pointer (eax-1) referred to byte 0?
255 "Jne 1b \ n \ t" // not jump to the label 1, the sequence continues to start comparing the second letter of 1.

256 "Xorl %% eax, %% eax \ n \ t" // clear eax, indicating no match is found.

257 "2:"
258 : "= a "(__ res): "" (0), " c "( 0xffffffff), " S "( cs), " g "( ct)

--486--
11.11 string.h file

259 : " cx "," dx "," di "," si ");


260 return __res; // returns the result of the comparison.

261 }
262
//// string length is calculated. //
Parameters: s - string.
//% 0 - ecx (__ res),% 1 - edi (string pointer s),% 2 - eax (0),% 3 - ecx (0xffffffff). // Return: Returns the length of the string.

263 extern inline int strlen (Const char * s)


264 {
265 register int __res __asm ​__ ( " cx "); // __res a register variable (ecx).
266 __asm ​__ ( " cld \ n \ t " // clear direction bit.

267 "Repne \ n \ t" // al (0) and the string of characters es: [edi] comparison,

268 "Scasb \ n \ t" // If it has been more equal.


269 "Notl% 0 \ n \ t" // ecx negated.
270 "Decl% 0" // ecx--, to give to give the string length value.

271 : "= c "(__ res): " D "( s), " a "( 0), "" (0xffffffff): " di ");
272 return __res; // returns the string length value.

273 }
274 275 extern char * ___strtok ;
// temporary storage point for analysis of the following string pointer is 1 (s) of.

276
//// 2 using string character string is divided into a flag (tokern) sequence.
// The string 1 viewed as comprising a sequence of zero or more words (token), and separated by a delimiter character string of 2 or more characters. // When

the first call strtok (), returns a pointer to the string 1 of the first character of the first pointer token, and the token // return a null character to the delimiter.

Subsequent use null string as the caller 1, the string 1 will continue scanning in this way, until no // token so far. In various call processes, the division string 2

may be different. // Parameters: s - string to be processed 1, ct - each string 2 comprises a delimiter. @ Assembler output:% 0 - ebx (__ res),% 1 - esi (__ strtok);

@ Assembling the input:% 2 - ebx (__ strtok),% 3 - esi (pointer to a string of 1 s),% 4 - (2 string pointer ct). // Return: Returns a string
s in the first token, if the token is not found, a null pointer is returned. // string s subsequent call null pointer, the search for a next
token in the original string s.
277 extern inline char * strtok (Char * s, const char * ct)
278 {
279 register char * __res __asm ​__ ( " si ");
280 __asm ​__ ( " testl% 1,% 1 \ n \ t " // first test ESI (pointer to a string of 1 s) whether it is NULL.
281 "Jne 1f \ n \ t" // If not, the show is the first call of this function, jump label 1.
282 "Testl% 0,% 0 \ n \ t" // If it is NULL, it means that this is a follow-up call, test ebx (__ strtok).
283 "Je 8f \ n \ t" // If ebx pointer is NULL, the handle can not jump over.
284 "Movl% 0,% 1 \ n" // pointer to copy ebx esi.
285 "1: \ txorl% 0,% 0 \ n \ t" // clear ebx pointer.
286 "Movl $ -1, %% ecx \ n \ t" // set ecx = 0xffffffff.
287 "Xorl %% eax, %% eax \ n \ t" // clear eax.
288 "Cld \ n \ t" // clear direction bit.

289 "Movl% 4, %% edi \ n \ t" // length of the string below 2 requirements. edi points to string 2.

290 "Repne \ n \ t" The // al (0) and es: [edi] Comparative, and edi ++.
291 "Scasb \ n \ t" // null characters until you find the end of string 2, or count ecx == 0.
292 "Notl %% ecx \ n \ t" // will ecx negated,
293 "Decl %% ecx \ n \ t" // ecx--, to obtain the length of the string value of 2.

294 "Je 7f \ n \ t" / * Empty delimeter-string * /


/ * Empty string delimiter * / // 0 if the string length is 2, the reference numeral 7 rpm.

295 "Movl %% ecx, %% edx \ n" // The length of the string 2 temporarily stores edx.

296 "2: \ tlodsb \ n \ t" // get a string of characters ds 1: [esi] al, and esi ++.

--487--
11.11 string.h file

297 "Testb %% al, %% al \ n \ t" // The character is 0 the value of it (string 1 end)?

298 "Je 7f \ n \ t" // If so, jump label 7.


299 "Movl% 4, %% edi \ n \ t" // edi again point to string two.
300 "Movl %% edx, %% ecx \ n \ t" // take into string length counter value of 2 ecx.

301 "Repne \ n \ t" // comparing all characters in the character string in a string al. 2,

302 "Scasb \ n \ t" // determines whether the character is a delimiter.

303 "Je 2b \ n \ t" // If we can find the same character (delimiter) in the string 2, reference numeral 2 jump.

304 "Decl% 1 \ n \ t" // If not delimiter, a string pointer esi points to the character at that time.

305 "Cmpb $ 0, (% 1) \ n \ t" // The characters are NULL characters?

306 "Je 7f \ n \ t" // If so, then jump at the numeral 7.


307 "Movl% 1,% 0 \ n" Esi // pointer to the characters stored in ebx.
308 "3: \ tlodsb \ n \ t" // get next character string 1 ds: [esi] al, and esi ++.
309 "Testb %% al, %% al \ n \ t" // The characters are NULL characters?

310 "Je 5f \ n \ t" // If, represents the end of a string, a jump to the label 5.

311 "Movl% 4, %% edi \ n \ t" // edi again point to string two.


312 "Movl %% edx, %% ecx \ n \ t" 2 // string length counter value into ecx.
313 "Repne \ n \ t" // al in the comparison character string 1 and string 2 each character,

314 "Scasb \ n \ t" // test whether al character is a delimiter.

315 "Jne 3b \ n \ t" // If the jump label delimiter is 3, 1 is detected in the next character string.

316 "Decl% 1 \ n \ t" // If the delimiter, esi--, pointing to the delimiter character.
317 "Cmpb $ 0, (% 1) \ n \ t" // The delimiter is NULL characters?
318 "Je 5f \ n \ t" // If so, then jump to the label 5.
319 "Movb $ 0, (% 1) \ n \ t" // If not, then the delimiter character replaced with NULL.
320 "Incl% 1 \ n \ t" 1 // esi points to the next character string, the first string that is remaining.

321 "Jmp 6f \ n" // Jump label at 6.


322 "5: \ txorl% 1,% 1 \ n" // esi cleared.
323 "6: \ tcmpb $ 0, (% 0) \ n \ t" // ebx pointer to NULL characters?
324 "Jne 7f \ n \ t" // If not, then jump label 7.
325 "Xorl% 0,% 0 \ n" // If so, then let ebx = NULL.
326 "7: \ ttestl% 0,% 0 \ n \ t" // ebx pointer is NULL do?
327 "Jne 8f \ n \ t" // if not then jump 8, the end of the assembly code.

328 "Movl% 0,% 1 \ n" // will esi set to NULL.


329 "8:"
330 : "= b "(__ res), "= S "( ___strtok )
331 : "" ( ___strtok ) " 1" ( s), " g "( ct)
332 : " ax "," cx "," dx "," di ");
333 return __res; // returns a pointer to the new token.
334 }
335
//// memory block copy. Start Copy n bytes at the destination address from the source address dest at src. // Parameters:

dest - copy destination address, src - copy source address, n - the number of bytes copied. //% 0 - ecx (n),% 1 - esi

(src),% 2 - edi (dest).

336 extern inline void * memcpy (Void * dest, const void * src, int n)
337 {
338 __asm ​__ ( " cld \ n \ t " // clear direction bit.

339 "Rep \ n \ t" // Repeat copy ecx bytes,


340 "Movsb" // From the ds: [esi] to es: [edi], esi ++, edi ++.
341 :: " c "( n), " S "( src), " D "( dest)
342 : " cx "," si "," di ");
343 return dest; // return destination address.

344 }
345
//// memory block move. Copying the same block of memory, but considering the direction of movement.

--488--
11.11 string.h file

// Parameters: dest - copy destination address, src - copy source address, n - the number of bytes copied. // If
dest <src is:% 0 - ecx (n),% 1 - esi (src),% 2 - edi (dest). // Otherwise:% 0 - ecx (n),% 1 - esi (src + n-1),% 2 -
edi (dest + n-1). // this operation is to prevent overlapping coverage mistake when copying.

346 extern inline void * memmove (Void * dest, const void * src, int n)
347 {
348 if (dest <src)
349 __asm ​__ ( " cld \ n \ t " // clear direction bit.

350 "Rep \ n \ t" From @ ds: [esi] to es: [edi], and esi ++, edi ++,
351 "Movsb" // Repeat copy ecx bytes.
352 :: " c "( n), " S "( src), " D "( dest)
353 : " cx "," si "," di ");
354 else
355 __asm ​__ ( " std \ n \ t " // direction bit is set to start from the end of copying.

356 "Rep \ n \ t" From @ ds: [esi] to es: [edi], and esi -, edi--,
357 "Movsb" // copy ecx bytes.
358 :: " c "( n), " S "( src + n-1), " D "( dest + n-1)
359 : " cx "," si "," di ");
360 return dest;
361 }
362
//// comparison of two n bytes of memory (two strings), even if the case is not stopped NULL byte comparison. // Parameters: cs - 1 memory block address, ct - 2

memory block address, count - the number of bytes to be compared. //% 0 - eax (__ res),% 1 - eax (0),% 2 - edi (memory block 1),% 3 - esi (memory block 2),% 4 -

ecx (count). // Returns: If the block 1> 2 return to block 1; 1 block <block 2, returns -1; Block 2 Block 1 == 0 is returned.

363 extern inline int memcmp (Const void * cs, const void * ct, int count )
364 {
365 register int __res __asm ​__ ( " ax "); // __res is register variables.
366 __asm ​__ ( " cld \ n \ t " // clear direction bit.

367 "Repe \ n \ t" // if equal repetition,


368 "Cmpsb \ n \ t" // Compare ds: [esi] and es: content [edi], and esi ++, edi ++.
369 "Je 1f \ n \ t" // If the same, then jumps to a label, returns 0 (eax) value
370 "Movl $ 1, %% eax \ n \ t" // otherwise eax set,
371 "Jl 1f \ n \ t" // if the value of the contents of the memory block 2 <memory block 1, reference numeral 1 jump.

372 "Negl %% eax \ n" // otherwise eax = -eax.


373 "1:"
374 : "= a "(__ res): "" (0), " D "( cs), " S "( ct), " c "( count )
375 : " si "," di "," cx ");
376 return __res; // returns the result of the comparison.

377 }
378
//// Looking at memory blocks specified character (string) n byte size.
// Parameters: cs - Specifies the address of the memory block, c - the specified character, count - memory block length. //% 0 - edi (__ res),% 1 - eax

(character c),% 2 - edi (memory block address cs),% 3 - ecx (bytes count). // returns a pointer to the first character matched, if not found, NULL character is

returned.

379 extern inline void * memchr (Const void * cs, char c, int count )
380 {
381 register void * __res __asm ​__ ( " di "); // __ res is the register variable.
382 if (! count ) // If the memory block length == 0, the process returns NULL, not found.

383 return NULL ;


384 __asm ​__ ( " cld \ n \ t " // clear direction bit.

385 "Repne \ n \ t" // if not equal, repeat the following statement,


386 "Scasb \ n \ t" // al characters and es: [edi] character compared, and edi ++,

--489--
11.12 termios.h file

387 "Je 1f \ n \ t" // if equal forward jump to a label.


388 "Movl $ 1,% 0 \ n" // otherwise edi the set.
389 "1: \ tdecl% 0" // make edi points to find the character (or NULL).
390 : "= D "(__ res): " a "( c), " D "( cs), " c "( count )
391 : " cx ");
392 return __res; // returns the character pointer.

393 }
394
//// Fill with specified character memory block length.

// fill memory area pointed to by s with character c, co-fill count bytes. //% 0 - eax (character c),% 1 - edi
(memory addresses),% 2 - ecx (bytes count).
395 extern inline void * memset (Void * s, char c, int count )
396 {
397 __asm ​__ ( " cld \ n \ t " // clear direction bit.

398 "Rep \ n \ t" // ecx specified number of repetitions, execution

399 "Stosb" // characters into the al es: [edi], and edi ++.
400 :: " a "( c), " D "( s), " c "( count )
401 : " cx "," di ");
402 return s;
403 }
404 405 #endif

406

11.12 termios.h file

11.12.1 Functional Description

This file contains terminal I / O Interface definition. include termios Some data structures and function prototypes for the general terminal interface settings. These functions

are used to read or set the terminal attributes, line control, set the baud rate and read or read or set the front end of the terminal process group id . Although this is linux The early

header files, but it has been in full compliance with the current POSIX Standard, and made the appropriate extension.

Two terminal data structure defined in this document termio with termios Respectively in two categories UNIX Series (or carved Long), termio

It is in AT & T system V Defined, and termios Yes POSIX Standard specified. Two structure is basically the same, just termio Using the short integer type definition mode flag is set,

and termios With a length of custom mode flag set. Due to the current two structures are in use, so for compatibility, most systems are at the same time support them. In addition,

previously used a similar sgtty Structure, has the basic need.

11.12.2 Code comments

program 11-10 linux / include / termios.h

1 #ifndef _TERMIOS_H 2 #define _TERMIOS_H


3 4 #define TTY_BUF_SIZE 1024

// buffer length of tty.


56 / * 0x54 is just a magic number to make these relatively uniqe ( 'T') * /

/ * 0x54 just a magic number, the purpose is to make these unique constants ( 'T') * /

--490--
11.12 termios.h file

7
// tty device ioctl call command set. The ioctl command encoding in the low word. // the following name TC [*]

is the meaning tty control commands.

// get information of the corresponding terminal termios structure (see tcgetattr ()).

8 #define TCGETS 0x5401


// setting information corresponding terminal termios structure (see tcsetattr (), TCSANOW).

9 #define TCSETS 0x5402


// set the terminal termios before the information, it is necessary to wait for all the output queue processed data (depletion). In the case of modifying the parameters // will

affect the output, we need to use this form (see tcsetattr (), TCSADRAIN option).

10 #define TCSETSW 0x5403


// termios before setting information, it is necessary to wait for all the output data processed in the queue, and refresh (clear) input queue. // then set (see
tcsetattr (), TCSAFLUSH option).
11 #define TCSETSF 0x5404
// get information of the corresponding terminal termio structure (see tcgetattr ()).

12 #define TCGETA 0x5405


// setting information (see tcsetattr (), TCSANOW option) corresponding terminal termio structure.

13 #define TCSETA 0x5406


// termio terminal before the information is provided, it is necessary to wait for all the output queue processed data (depletion). In the case of modifying the parameters //

will affect the output, we need to use this form (see tcsetattr (), TCSADRAIN option).

14 #define TCSETAW 0x5407


// termio before setting information, it is necessary to wait for all the output data processed in the queue, and refresh (clear) input queue. // then set (see
tcsetattr (), TCSAFLUSH option).
15 #define TCSETAF 0x5408
// wait queue processed output (null), if the parameter value is 0, it sends a BREAK (see tcsendbreak (), tcdrain ()).
16 #define TCSBRK 0x5409
// start / stop control. If the parameter value is 0, the output is suspended; If 1, then reopen the suspended output; if is 2, then the Suspend

// input; if it is 3, then re-open pending input (see tcflow ()).


17 #define TCXONC 0x540A
// refresh output has been written but not yet sent or received but have not read data. If the parameter is 0, then refresh (clear) input queue; if it is 1, the refresh //

output queue; if is 2, the refresh input and output queues (see tcflush ()).

18 #define TCFLSH 0x540B


// The following name TIOC [*] tty the meaning of the input and output control command. // set the

terminal mode dedicated serial line.

19 #define TIOCEXCL 0x540C


// reset terminal dedicated serial line mode.

20 #define TIOCNXCL 0x540D


// set control tty terminal. (TIOCNOTTY - tty prohibition control terminal).
twenty one #define TIOCSCTTY 0x540E
// read the specified terminal device process group id (see tcgetpgrp ()).

twenty two #define TIOCGPGRP 0x540F


// set the designated terminal device process group id (see tcsetpgrp ()).

twenty three #define TIOCSPGRP 0x5410


// returns the number of characters has not been sent in the output queue.

twenty four #define TIOCOUTQ 0x5411


// analog input terminal. In the command pointer to a character as a parameter, and pretend to be the character typed on the terminal. // user must have superuser privileges or

have read permissions on the control terminal.

25 #define TIOCSTI 0x5412


// Window size information reading terminal device (see winsize structure).

26 #define TIOCGWINSZ 0x5413


// set the window size information terminal device (see winsize structure).

27 #define TIOCSWINSZ 0x5414


// returns the current state of the modem status bit flag set of control leads (see below lines 185-196).

--491--
11.12 termios.h file

28 #define TIOCMGET 0x5415


// set control leads single modem status state (true or false) (Individual control line Set).
29 #define TIOCMBIS 0x5416
// reset state control leads single modem state (Individual control line clear).
30 #define TIOCMBIC 0x5417
// set the state of the modem status leads. If a bit position of the bit, the modem corresponding to the asserted state leads.

31 #define TIOCMSET 0x5418


// read the software carrier detection flag (1 - Turn; 0 - off).
// for terminals or other devices locally connected, the software carrier flag is on, the line terminal using modem equipment or the // is closed. In order
to use these two ioctl call, tty line should be based on O_NDELAY way open, so open () // will not wait for the carrier.

32 #define TIOCGSOFTCAR 0x5419


// Set the software carrier detection flag (1 - Turn; 0 - off).
33 #define TIOCSSOFTCAR 0x541A
// Returns the number of characters in the queue has not been removed input.

34 #define TIOCINQ 0x541B


35
// size of the window (Window size) attribute structure. In a windowing environment it can be used to screen-based applications. // ioctls in

TIOCGWINSZ TIOCSWINSZ and can be used to set or read the information.

36 struct winsize {
37 unsigned short ws_row; The number of lines of characters // window.

38 unsigned short ws_col; The number of character columns // window.

39 unsigned short ws_xpixel; // window width, pixel value.


40 unsigned short ws_ypixel; // window height, pixel value.
41 };
42
// termio structure of AT & T System V.
43 #define NCC 8 // termio structure control the length of the array of characters.

44 struct termio {
45 unsigned short c_iflag; / * Input mode flags * / // input mode flag.
46 unsigned short c_oflag; / * Output mode flags * / // output mode flag.
47 unsigned short c_cflag; / * Control mode flags * / // control mode flag.
48 unsigned short c_lflag; / * Local mode flags * / // local mode flag.
49 unsigned char c_line; / * Line discipline * / // line discipline (rate).
50 unsigned char c_cc [ NCC ]; / * Control characters * / // control character array.

51 };
52
// termios structure of POSIX.
53 #define NCCS 17 // termios control structure length character array.
54 struct termios {
55 unsigned long c_iflag; / * Input mode flags * / // input mode flag.
56 unsigned long c_oflag; / * Output mode flags * / // output mode flag.
57 unsigned long c_cflag; / * Control mode flags * / // control mode flag.
58 unsigned long c_lflag; / * Local mode flags * / // local mode flag.
59 unsigned char c_line; / * Line discipline * / // line discipline (rate).
60 unsigned char c_cc [ NCCS ]; / * Control characters * / // control character array.

61 };
6263 / * C_cc characters * /
/ * C_cc array of characters * /
// The following is an index value corresponding to c_cc array of characters.

64 #define VINTR 0 // c_cc [VINTR] = INTR (^ C), \ 003, interrupt character.


65 #define VQUIT 1 // c_cc [VQUIT] = QUIT (^ \), \ 034, quit characters.
66 #define VERASE 2 // c_cc [VERASE] = ERASE (^ H), \ 177, clashes characters.

--492--
11.12 termios.h file

67 #define VKILL 3 // c_cc [VKILL] = KILL (^ U), \ 025, termination character.

68 #define VEOF 4 // c_cc [VEOF] = EOF (^ D), \ 004, end of file character.
69 #define VTIME 5 // c_cc [VTIME] = TIME (\ 0), \ 0, a timer value (see later description).
70 #define VMIN 6 // c_cc [VMIN] = MIN (\ 1), \ 1, the timer value.
71 #define VSWTC 7 // c_cc [VSWTC] = SWTC (\ 0), \ 0, switching characters.
72 #define VSTART 8 // c_cc [VSTART] = START (^ Q), \ 021, beginning characters.

73 #define VSTOP 9 // c_cc [VSTOP] = STOP (^ S), \ 023, stop character.


74 #define VSUSP 10 // c_cc [VSUSP] = SUSP (^ Z), \ 032, suspend character.
75 #define VEOL 11 // c_cc [VEOL] = EOL (\ 0), \ 0, end of line character.
76 #define VREPRINT 12 // c_cc [VREPRINT] = REPRINT (^ R), \ 022, re-display character.
77 #define VDISCARD 13 // c_cc [VDISCARD] = DISCARD (^ O), \ 017, the character is discarded.

78 #define VWERASE 14 // c_cc [VWERASE] = WERASE (^ W), \ 027, the word erase characters.
79 #define VLNEXT 15 // c_cc [VLNEXT] = LNEXT (^ V), \ 026, the next line of characters.

80 #define VEOL2 16 // c_cc [VEOL2] = EOL2 (\ 0), \ 0, end of line 2.


8182 / * C_iflag bits * /
/ * The c_iflag bits * /
// termios structure constant symbol input mode field c_iflag various flags.
83 #define IGNBRK 0000001 Ignore BREAK condition // input.
84 #define BRKINT 0000002 // SIGINT signal is generated when the BREAK.

85 #define IGNPAR 0000004 // ignore character parity error.


86 #define PARMRK 0000010 // Mark parity error.
87 #define INPCK 0000020 // allow input parity.
88 #define ISTRIP 0000040 // shielding character of the first eight.

89 #define INLCR 0000100 The newline is mapped to NL-CR // input carriage.


90 #define IGNCR 0000200 // Ignore carriage CR.
91 #define ICRNL 0000400 // when the input carriage return linefeed CR mapped to NL.

92 #define IUCLC 0001000 // when entering convert uppercase to lowercase characters.

93 #define IXON 0002000 // allowed to start / stop (XON / XOFF) control output.
94 #define IXANY 0004000 // allows any character to restart output.

95 #define IXOFF 0010000 // allowed to start / stop (XON / XOFF) control input.
96 #define IMAXBEL 0020000 // enter the ring when the queue is full.

9798 / * C_oflag bits * /


/ * The c_oflag bits * /
// termios structure constant output mode field symbol c_oflag various flags.
99 #define OPOST 0000001 // execute output processing.

100 #define OLCUC 0000002 // When the output lowercase characters to uppercase characters.

101 #define ONLCR 0000004 // the line breaks in the output is mapped to the transport NL - linefeed CR-NL.

102 #define OCRNL 0000010 // the output carriage return linefeed CR mapped to NL.

103 #define ONOCR 0000020 // not output the carriage CR 0.


104 #define ONLRET 0000040 // perform a carriage return line breaks NL function.

105 #define OFILL 0000100 // delay when using padding characters without time delay.

106 #define OFDEL 0000200 // fill character is ASCII code DEL. If not set, use ASCII NULL.
107 #define NLDLY 0000400 // Select Wrap delay.
108 #define NL0 0000000 // Wrap delay type 0.
109 #define NL1 0000400 // Wrap delay type 1.
110 #define CRDLY 0003000 // Choose Enter delay.
111 #define CR0 0000000 // Enter delay type 0.
112 #define CR1 0001000 // Enter delay type 1.
113 #define CR2 0002000 // Enter delay type 2.
114 #define CR3 0003000 // Enter delayed type 3.
115 #define TABDLY 0014000 // Select horizontal tab delay.
116 #define TAB0 0000000 // horizontal tab delay type 0.
117 #define TAB1 0004000 // horizontal tab delay type 1.

--493--
11.12 termios.h file

118 #define TAB2 0010000 // horizontal tab delay type 2.


119 #define TAB3 0014000 // horizontal tab delay type 3.
120 #define XTABS 0014000 // The TAB tabs into spaces, which value represents the number of spaces.

121 #define BSDLY 0020000 // Select the backspace delay.

122 #define BS0 0000000 // backspace delay type 0.


123 #define BS1 0020000 // backspace delay type 1.
124 #define VTDLY 0040000 // vertical tab delay.
125 #define VT0 0000000 0 // vertical tab delay type.
126 #define VT1 0040000 // vertical tab delay type 1.
127 #define FFDLY 0040000 // Select paging delay.
128 #define FF0 0000000 // paging delay type 0.
129 #define FF1 0040000 // paging delay type 1.
130 131 / * C_cflag bit meaning * /
/ * The meaning of the c_cflag bits * /
// termios structure constant control mode flag field c_cflag symbol mark (octal).
132 #define CBAUD 0000017 // mask bit transmission rate.
133 #define B0 0000000 / * Hang up * / / * Hangs up the line * /
134 #define B50 0000001 // 50 baud.
135 #define B75 0000002 // 75 baud.
136 #define B110 0000003 // 110 baud.
137 #define B134 0000004 // 134 baud.
138 #define B150 0000005 // 150 baud.
139 #define B200 0000006 // 200 baud.
140 #define B300 0000007 // 300 baud.
141 #define B600 0000010 // 600 baud.
142 #define B1200 0000011 // 1200 baud.
143 #define B1800 0000012 // 1800 baud.
144 #define B2400 0000013 // 2400 baud.
145 #define B4800 0000014 // 4800 baud.
146 #define B9600 0000015 // 9600.
147 #define B19200 0000016 // 19200.
148 #define B38400 0000017 // 38400 baud.
149 #define EXTA B19200 // extensions baud A.
150 #define EXTB B38400 // extensions baud B.

151 #define CSIZE 0000060 // mask bit width of the character.

152 #define CS5 0000000 // 5 bits per character.


153 #define CS6 0000020 // 6 bits per character.
154 #define CS7 0000040 // 7 bits per character.
155 #define CS8 0000060 // 8 bits per character.
156 #define CSTOPB 0000100 // Set two stop bits, rather than one.
157 #define CREAD 0000200 // allowed to receive.

158 #define CPARENB 0000400 // turn generates output parity, parity input.
159 #define CPARODD 0001000 // Input / Output parity is odd.
160 #define HUPCL 0002000 // hang up after the last process closes.

161 #define CLOCAL 0004000 // Ignore modem (Modem) control lines.


162 #define CIBAUD 03,600,000 / * Input baud rate (not used) * / / * The baud rate input (not used) * /
163 #define CRTSCTS 020 000 000 000 / * Flow control * / / * Flow Control * /
164 165 #define PARENB CPARENB
// turn generates output parity, parity input.
166 #define PARODD CPARODD // Input / Output parity is odd.
167 168 / * C_lflag bits * /
/ * The c_lflag bits * /

--494--
11.12 termios.h file

// constant symbol termios structure c_lflag the local mode flag field.
169 #define ISIG 0000001 // When the character is received INTR, QUIT, SUSP or DSUSP, generate respective signals.

170 #define ICANON 0000002 // open specification mode (cooked mode).

171 #define XCASE 0000004 // if set ICANON, the terminal is uppercase characters.
172 #define ECHO 0000010 // Echo input characters.
173 #define ECHOE 0000020 // if set ICANON, the ERASE / WERASE will erase the previous character / word.

174 #define ECHOK 0000040 // if set ICANON, the KILL character erases the current line.
175 #define ECHONL 0000100 // such as setting up ICANON, even if ECHO is not open also echo the NL character.

176 #define NOFLSH 0000200 // when generating SIGQUIT SIGINT signal and input output queue is not refreshed, when // SIGSUSP

signal generating refresh the input queue.

177 #define TOSTOP 0000400 // SIGTTOU signal is sent to the background process group, which // background process attempts to write their own

control terminal.

178 #define ECHOCTL 0001000 // If set ECHO, in addition to the ASCII TAB, NL, START and STOP control signals to be the // echo

pattern imaged ^ X, X is a control character value + 0x40.

179 #define ECHOPRT 0002000 // if set ICANON and IECHO, the characters will be displayed when erasing.

180 #define ECHOKE 0004000 // if set ICANON, the KILL is significant back by erasing all characters on the line.

181 #define FLUSHO 0010000 // output is refreshed. By typing the DISCARD character, the flag is reversed.

182 #define PENDIN 0040000 // When the next character is read, all the characters in the input queue is redisplayed.

183 #define IEXTEN 0100000 // open the input processing defined at implementation.

184 185 / * Modem lines * /


/ * Constant Modem line signal symbol * /

186 #define TIOCM_LE 0x001 // allow line (Line Enable).


187 #define TIOCM_DTR 0x002 // Data Terminal Ready (Data Terminal Ready).
188 #define TIOCM_RTS 0x004 // request (Request to Send).
189 #define TIOCM_ST 0x008 // send serial data (Serial Transfer). [??]
190 #define TIOCM_SR 0x010 // received serial data (Serial Receive). [??]
191 #define TIOCM_CTS 0x020 // Clear to Send (Clear To Send).
192 #define TIOCM_CAR 0x040 // Carrier Monitoring (Carrier Detect).
193 #define TIOCM_RNG 0x080 // Ring Indicator (Ring indicate).
194 #define TIOCM_DSR 0x100 // Data Set Ready (Data Set Ready).
195 #define TIOCM_CD TIOCM_CAR

196 #define TIOCM_RI TIOCM_RNG

197 198 / * Tcflow () and TCXONC use these * /


/ * The tcflow () and use these symbols TCXONC constants * /

199 #define TCOOFF 0 // suspend output.


200 #define TCOON 1 // restarting suspended output.

201 #define TCIOFF 2 // a STOP character transmission system, the device stops transmission of data to the system.

202 #define TCION 3 // transmission system a START character, the device starts data transmission to the system.

203 204 / * Tcflush () and TCFLSH use these * / / * drained tcflush () and constants TCFLSH use these symbols * /

205 #define TCIFLUSH 0 // clear the data received but not read.

206 #define TCOFLUSH 1 // clear the data has been written but not transmitted.

207 #define TCIOFLUSH 2 // clear the data received but not read. Clear data has been written but not transmitted.

208 209 / * Tcsetattr uses these * /


/ * The tcsetattr () uses these symbols constants * /

210 #define TCSANOW 0 // change immediately.


211 #define TCSADRAIN 1 // change all written output occurs after the transfer.
212 #define TCSAFLUSH 2 // change after all outputs are written and transmitted occurs after all of the received but
not yet // read data is discarded.
213 214 typedef int speed_t ;
// baud numeric types.
215
// returns the receive baud termios_p referred termios structure.

--495--
11.12 termios.h file

216 extern speed_t cfgetispeed (Struct termios * Termios_p); // return transmission baud
termios_p referred termios structure.
217 extern speed_t cfgetospeed (Struct termios * Termios_p); // the termios_p termios structure
referred receiver baud rate is set to speed.
218 extern int cfsetispeed (Struct termios * Termios_p, speed_t speed);
// Send baud termios_p referred termios structure to speed.
219 extern int cfsetospeed (Struct termios * Termios_p, speed_t speed);
// Wait fildes referent has been written output data is sent out.
220 extern int tcdrain (Int fildes);
// suspend / restart fildes referred to receive and transmit object data.

221 extern int tcflow (Int fildes, int action);


// discard all fildes specified object has been written but not yet transferred, and all have been received but not yet read the data.

222 extern int tcflush (Int fildes, int queue_selector);


// Get fildes parameter corresponds with the handle of the object, and save it in the local termios_p referred to.

223 extern int tcgetattr (Int fildes, struct termios * Termios_p); // if the terminal using asynchronous serial data transmission, the continuous

transmission of a series of bits 0 value within a certain time.

224 extern int tcsendbreak (Int fildes, int duration);


// the termios data structure pointer termios_p indicated, set the parameters associated with the terminal.

225 extern int tcsetattr (Int fildes, int optional_actions,


226 struct termios * Termios_p);
227 228 #endif

229

11.12.3 Other Information

11.12.3.1 Control characters TIME , MIN

In the non-canonical mode input process, the input character is not processed in rows, so the erase process is terminated, and will not occur. MIN with

TIMEDE I.e. values ​for determining how to handle the received characters.

MIN Represents a read operation when satisfied (i.e., when the character is returned to the user) minimum number of characters to be read. TIME It is 1/10 Sec count timer

values, timeout for the timing of data transmission and short-term. Four combinations of the two characters and their interactions are described below:

MIN> 0 , TIME> 0 Situation: in this case, TIME Since timer interaction between the two characters, and the reception of the first 1 It comes into play after the characters.

Because it is a timer between two characters, so restart each receive a character will be reset. MIN versus TIME The interaction between as follows: Upon receipt of an

inter-character character timer starts working. If the timer expires (note that each receive a character timer will start counting again) before receiving a MIN Characters, i.e., the

read operation is satisfied. If the MIN Characters are received before the timer expires, it will be received by the character this time returned to the user. Note that if TIME Timeout,

then at least there is a received character will be returned because the timer only after receiving a character comes into play (timing). under these circumstances( MIN> 0 , TIME>

0) , A read operation will sleep until the receipt of the first 1 Characters activate MIN versus TIME mechanism. If you read the number of characters is less than the existing number

of characters, then the timer will not be re-activated, and thus the subsequent read will be satisfied immediately.

MIN> 0 , TIME = 0 Case: in this case, since the TIME Values ​are 0 Therefore timer does not work, only MIN It makes sense. Waiting for a read operation only when

receiving the MIN Will be met (waiting time character of the operation will sleep until you receive MIN Characters). Using this case based on the record of the terminal to read IO

The program will be indefinitely (optionally) blocked in a read operation.

MIN = 0 , TIME> 0 Case:

--496--
11.13 time.h file

In this case, since the MIN = 0 ,then TIME No longer play the role of inter-character timer, but a read operation of the timer, and the read operation beginning work. As

long as a character is received or the timer expires already satisfy the read operation. Note that in this case, if the timer expires, will not read a character. If the timer has not

timed out, then only read operations will meet after reading a character. Therefore, in this case, the reading will not indefinitely (indefinitely) is blocked to wait for the

character. After the read operation begins, if TIME * 0.10 Character is not received within seconds, a read operation will receive 0 Characters to return.

MIN = 0 , TIME = 0 Case:


In this case, the read operation will return immediately. The number of characters of the requested read or buffered in the minimum number of characters in the queue will

be returned, without waiting for more characters in the input buffer.

Generally speaking, in the non-canonical mode, two values ​are character timeout timer value and the count value. MIN That in order to satisfy the read operation, the

minimum number of characters to be read. TIME It is a tenth of a second timer count value. When both are set, the read operation will wait until it reads at least one character,

and then to read MIN Characters or the time TIME Out after reading the last character. If you set only MIN Then read MIN Read will not return before the characters. If you set only TIME

, The read returns immediately after reading at least one character, or when the timer expires. If both are not set, the read will return immediately, only gives the number of bytes

has been read.

11.13 time.h file

11.13.1 Functional Description

The header file for functions involving the processing time. in MINIX There are some very interesting description of the time: The processing time for more complex, such as

what is GMT (GMT), local time, or other time. Although Bishop Ussher (1581-1656 Years) has calculated that, according to Scripture, is the beginning of World Day BC 4004 year 10 month

12 On the morning of 9 Point, but in UNIX World, time is from

GMT 1970 year 1 month 1 Midnight onwards, and before that, all are empty and (invalid).

11.13.2 Code comments

program 11-11 linux / include / time.h

1 #ifndef _TIME_H 2 #define _TIME_H


3 4 #ifndef _TIME_T 5 #define _TIME_T
6 typedef long time_t ;

// GMT from the beginning of January 1, 1970 to count time in seconds (calendar time).

7 #endif
89 #ifndef _SIZE_T 10 #define _SIZE_T 11 typedef
unsigned int size_t ;

12 #endif
1314 #define CLOCKS_PER_SEC 100
// frequency system clock tick, 100HZ.
1516 typedef long clock_t ;
// ticks from the beginning of the process through the system clock.

--497--
11.14 unistd.h file

1718 struct tm {

19 int tm_sec; // the number of seconds [0,59].

20 int tm_min; // number of minutes [0,59].


twenty one int tm_hour; Number [0,59] // hours.
twenty two int tm_mday; // number of days a month [0,31].
twenty three int tm_mon; // 1 year in January [0,11].
twenty four int tm_year; // number of years from the beginning of 1900.

25 int tm_wday; // 1 day of the week [0,6] (0 = Sunday).


26 int tm_yday; // 1 Day of the year [0,365].
27 int tm_isdst; // Daylight Savings Time flag.

28 };
29
// The following function prototype is about time operation.

// determine the processor time. The time to return to the program processor (ticks) by approximation.

30 clock_t clock (Void);


// take time (in seconds). Returned from 1970.1.1: (called calendar time) in seconds starting at 0: 0: 0.

31 time_t time ( time_t * Tp);


// Calculate the time difference. Returns the number of seconds elapsed between the time of time2 and time1.

32 double difftime ( time_t time2, time_t time1);


// will be converted to calendar time tm time structure represented.

33 time_t mktime (Struct tm * Tp);


34
// convert time tm structure represented by a string. Returns a pointer to the string pointer.

35 char * asctime (Const struct tm * Tp);


// converts the calendar time into a string, such as "Wed Jun 30 21: 49: 08: 1993 \ n".
36 char * ctime (Const time_t * Tp);
// Convert the calendar time into UTC time tm structure represented (UTC - Universal Time Code Universal Time Code).

37 struct tm * gmtime (Const time_t * Tp);


// convert calendar time to time the specified time zone (TimeZone) is represented by the structure tm.

38 struct tm * localtime (Const time_t * Tp);


// time tm structure represented by the format string fmt converted into a string of the maximum length of the result is stored in s smax.

39 size_t strftime (Char * s, size_t smax, const char * fmt, const struct tm * Tp); // initialize time conversion information, the environment variable TZ,

for zname variables are initialized. // associated with the time zone at the time of the conversion function will be called automatically.

40 void tzset (Void);


4142 #endif

43

11.14 unistd.h file

11.14.1 Functional Description

Standard symbol type header file and constants. This document defines a number of constants and a wide variety of types, and some function stated. If the symbol is

defined in the program __ LIBRARY__ , It also includes the kernel system call number and inline assembly _ syscall0 () Wait.

11.14.2 Code comments

program 11-12 linux / include / unistd.h

--498--
11.14 unistd.h file

1 #ifndef _UNISTD_H 2 #define _UNISTD_H 3 4 / * Ok, this may be a joke, but I'm
working on it * /

/ * Ok, this may be a joke, but I are working on * /


// version number indicated below symbolic constants conforming to the IEEE 1003.1 standard implemented, is an integer value.

5 #define _POSIX_VERSION 198808L


6
// chown () and fchown () rights of use is subject to the process. / * Only superusers can execute chown (I think ..) * /
7 #define _POSIX_CHOWN_RESTRICTED / * Only root can do a chown (I think ..) * /
// longer (of NAME_MAX) path name error, but it will not automatically cut off. / * Path names are not truncated (but see the kernel code) * /

8 #define _POSIX_NO_TRUNC / * No pathname truncation (but see in kernel) * /


// The following notation will be defined as a character value to the processing terminal thereof is prohibited. / * Prohibit such characters as ^ C * /

9 #define _POSIX_VDISABLE '\ 0' / * Character to disable things like ^ C * /


// Each process has a saved set-user-ID and a saved set-group-ID. / * We will begin this processing * /
10 / * # Define _POSIX_SAVED_IDS * / / * We'll get to this yet * /
// system implementation supports job control. / * We have not yet support this standard, hopefully soon on the line * /

11 / * # Define _POSIX_JOB_CONTROL * / / * We are not there quite yet. Soon hopefully * /


1213 #define STDIN_FILENO
0 // standard input file handle number (descriptors).

14 #define STDOUT_FILENO 1 // standard output file handle number.

15 #define STDERR_FILENO 2 // standard error file handle number.

1617 #ifndef NULL 18 #define


NULL
((Void *) 0) // define a null pointer.

19 #endif
2021 / * Access * /
/ * File access * /
// The following symbolic constants defined for access () function.

twenty two #define F_OK 0 // detect whether a file exists.


twenty three #define X_OK 1 // detect whether an executable (search).

twenty four #define W_OK 2 // detect whether or not writable.

25 #define R_OK 4 // Check whether read.


2627 / * Lseek * /
/ * File pointer relocation * /
// The following symbols are constant for lseek () and the fcntl () function.

28 #define SEEK_SET 0 // read the file pointer to the offset value.


29 #define SEEK_CUR 1 // read the file pointer is set to the current value plus an offset value.

30 #define SEEK_END 2 // read the file pointer for the file setting plus an offset length.
3132 / * _SC stands for System Configuration. We do not use them much * /

/ * _SC indicates that the system configuration. We rarely use * / // The

following symbolic constants for sysconf () function.

33 #define _SC_ARG_MAX 1 // The maximum number of variables.

34 #define _SC_CHILD_MAX 2 // The maximum number of child processes.

35 #define _SC_CLOCKS_PER_SEC 3 // the number of ticks per second.

36 #define _SC_NGROUPS_MAX 4 // maximum number of groups.

37 #define _SC_OPEN_MAX 5 // maximum number of open files.

38 #define _SC_JOB_CONTROL 6 // job control.


39 #define _SC_SAVED_IDS 7 // Save the identifier.
40 #define _SC_VERSION 8 // version.
4142 / * More (possibly) configurable things - now pathnames * /

--499--
11.14 unistd.h file

/ * More (possible) configurable parameter - is now a path name * / // constants for the

following symbols of pathconf () function.

43 #define _PC_LINK_MAX 1 // maximum number of connections.

44 #define _PC_MAX_CANON 2 // maximum number of regular file.

45 #define _PC_MAX_INPUT 3 // maximum input length.

46 #define _PC_NAME_MAX 4 // The maximum length of the name.

47 #define _PC_PATH_MAX 5 // maximum path length.


48 #define _PC_PIPE_BUF 6 // pipe buffer size.
49 #define _PC_NO_TRUNC 7 // file name is not truncated.

50 #define _PC_VDISABLE 8 //
51 #define _PC_CHOWN_RESTRICTED 9 // change the host is limited.

5253 #include <sys / stat.h>


// File Status header file. Containing configuration file or system state stat {} and constants.

54 #include <sys / times.h> // define the structure of the process of running time tms and times () function prototype.

55 #include <sys / utsname.h> // header file system name structure.


56 #include <utime.h> // user time header. It defines the access and modification time structure and utime () prototype.

5758 #ifdef __LIBRARY__ 59

// The following system call kernel implementation symbolic constant, the index value is used as a system call function table. (See include / linux /

sys.h)

60 #define __NR_setup 0 / * Used only by init, to get system going * /


/ * __NR_setup only used to initialize, to start the system * /

61 #define __NR_exit 1
62 #define __NR_fork 2
63 #define __NR_read 3
64 #define __NR_write 4
65 #define __NR_open 5
66 #define __NR_close 6
67 #define __NR_waitpid 7
68 #define __NR_creat 8
69 #define __NR_link 9
70 #define __NR_unlink 10
71 #define __NR_execve 11
72 #define __NR_chdir 12
73 #define __NR_time 13
74 #define __NR_mknod 14
75 #define __NR_chmod 15
76 #define __NR_chown 16
77 #define __NR_break 17
78 #define __NR_stat 18
79 #define __NR_lseek 19
80 #define __NR_getpid 20
81 #define __NR_mount twenty one

82 #define __NR_umount twenty two

83 #define __NR_setuid twenty three

84 #define __NR_getuid twenty four

85 #define __NR_stime 25
86 #define __NR_ptrace 26
87 #define __NR_alarm 27
88 #define __NR_fstat 28
89 #define __NR_pause 29
90 #define __NR_utime 30

--500--
11.14 unistd.h file

91 #define __NR_stty 31
92 #define __NR_gtty 32
93 #define __NR_access 33
94 #define __NR_nice 34
95 #define __NR_ftime 35
96 #define __NR_sync 36
97 #define __NR_kill 37
98 #define __NR_rename 38
99 #define __NR_mkdir 39
100 #define __NR_rmdir 40
101 #define __NR_dup 41
102 #define __NR_pipe 42
103 #define __NR_times 43
104 #define __NR_prof 44
105 #define __NR_brk 45
106 #define __NR_setgid 46
107 #define __NR_getgid 47
108 #define __NR_signal 48
109 #define __NR_geteuid 49
110 #define __NR_getegid 50
111 #define __NR_acct 51
112 #define __NR_phys 52
113 #define __NR_lock 53
114 #define __NR_ioctl 54
115 #define __NR_fcntl 55
116 #define __NR_mpx 56
117 #define __NR_setpgid 57
118 #define __NR_ulimit 58
119 #define __NR_uname 59
120 #define __NR_umask 60
121 #define __NR_chroot 61
122 #define __NR_ustat 62
123 #define __NR_dup2 63
124 #define __NR_getppid 64
125 #define __NR_getpgrp 65
126 #define __NR_setsid 66
127 #define __NR_sigaction 67
128 #define __NR_sgetmask 68
129 #define __NR_ssetmask 69
130 #define __NR_setreuid 70
131 #define __NR_setregid 71
132
// The following definitions are embedded assembler macro function system calls. System // no

arguments invoking the macro function. type name (void).

//% 0 - eax (__ res),% 1 - eax (__ NR _ ## name). Wherein the name is the name of the system call, the system call symbol is formed above __NR_ // constant in combination with such a

table for the system calls the function pointer addressing. // Returns: if the return value is greater than or equal to 0, the value is returned, otherwise set errno error number, and returns -1.

133 #define _syscall0 (Type, name) \


134 type name (void) \
135 {\
136 long __res; \
137 __asm__ volatile ( " int $ 0x80 "\ // Call system interrupt 0x80.
138 : "= a "(__ res) \ // return value eax (__ res).

--501--
11.14 unistd.h file

139 : "" (__NR _ ## name)); \ // interrupt input system call number __NR_name.

140 if (__res> = 0) \ // If the return value is> = 0, then return the value directly.

141 return (type) __res; \


142 errno = -__ res; \ // otherwise set error number and returns -1.

143 return -1; \


144 }
145
// there is a parameter of the system call macro function. type name (atype a) //% 0 - eax
(__ res),% 1 - eax (__ NR_name),% 2 - ebx (a).
146 #define _syscall1 (Type, name, atype, a) \
147 type name (atype a) \
148 {\
149 long __res; \
150 __asm__ volatile ( " int $ 0x80 "\
151 : "= a "(__ res) \
152 : "" (__NR _ ## name), " b "(( long) (a))); \
153 if (__res> = 0) \
154 return (type) __res; \
155 errno = -__ res; \
156 return -1; \
157 }
158
// There are two parameters of the system call macro function. type name (atype a, btype b) //% 0 - eax (__
res),% 1 - eax (__ NR_name),% 2 - ebx (a),% 3 - ecx (b).
159 #define _syscall2 (Type, name, atype, a, btype, b) \
160 type name (atype a, btype b) \
161 {\
162 long __res; \
163 __asm__ volatile ( " int $ 0x80 "\
164 : "= a "(__ res) \
165 : "" (__NR _ ## name), " b "(( long) (a)), " c "(( long) (b))); \
166 if (__res> = 0) \
167 return (type) __res; \
168 errno = -__ res; \
169 return -1; \
170 }
171
// There are three parameters of the system call macro function. type name (atype a, btype b, ctype c) //% 0 - eax (__ res),% 1 -
eax (__ NR_name),% 2 - ebx (a),% 3 - ecx (b),% 4 - edx (c).
172 #define _syscall3 (Type, name, atype, a, btype, b, ctype, c) \
173 type name (atype a, btype b, ctype c) \
174 {\
175 long __res; \
176 __asm__ volatile ( " int $ 0x80 "\
177 : "= a "(__ res) \
178 : "" (__NR _ ## name), " b "(( long) (a)), " c "(( long) (b)), " d "(( long) (c))); \
179 if (__res> = 0) \
180 return (type) __res; \
181 errno = -__ res; \
182 return -1; \
183 }
184 185 #endif / * __ LIBRARY__ * /

--502--
11.14 unistd.h file

186 187 extern int errno ;


// error number, global variables.

188
// function prototype is defined corresponding to each system call. (See details include / linux / sys.h)

189 int access (Const char * filename, mode_t mode);


190 int acct (Const char * filename);
191 int alarm (Int sec);
192 int brk (Void * end_data_segment);
193 void * sbrk ( ptrdiff_t increment);
194 int chdir (Const char * filename);
195 int chmod (Const char * filename, mode_t mode);
196 int chown (Const char * filename, uid_t owner, gid_t Group);
197 int chroot (Const char * filename);
198 int close (Int fildes);
199 int creat (Const char * filename, mode_t mode);
200 int dup (Int fildes);
201 int execve (Const char * filename, char ** argv , Char ** envp );
202 int execv (Const char * pathname, char ** argv );
203 int execvp (Const char * file , Char ** argv );
204 int execl (Const char * pathname, char * arg0, ...);
205 int execlp (Const char * file , Char * arg0, ...);
206 int execle (Const char * pathname, char * arg0, ...);
207 volatile void exit (Int status);
208 volatile void _exit (Int status);
209 int fcntl (Int fildes, int cmd, ...);
210 int fork (Void);
211 int getpid (Void);
212 int getuid (Void);
213 int geteuid (Void);
214 int getgid (Void);
215 int getegid (Void);
216 int ioctl (Int fildes, int cmd, ...);
217 int kill ( pid_t pid, int signal);
218 int link (Const char * filename1, const char * filename2);
219 int lseek (Int fildes, off_t offset, int origin );
220 int mknod (Const char * filename, mode_t mode, dev_t dev);
221 int mount (Const char * specialfile, const char * dir, int rwflag);
222 int nice (Int val);
223 int open (Const char * filename, int flag, ...);
224 int pause (Void);
225 int pipe (Int * fildes);
226 int read (Int fildes, char * buf , off_t count );
227 int setpgrp (Void);
228 int setpgid ( pid_t pid, pid_t pgid);
229 int setuid ( uid_t uid);
230 int setgid ( gid_t gid);
231 void (* signal (int sig, void (* fn) (int))) (int);
232 int stat (Const char * filename, struct stat * Stat_buf);
233 int fstat (Int fildes, struct stat * Stat_buf);
234 int stime ( time_t * Tptr);
235 int sync (Void);
236 time_t time ( time_t * Tloc);
237 time_t times (Struct tms * Tbuf);

--503--
11.15 utime.h file

238 int ulimit (Int cmd, long limit);


239 mode_t umask ( mode_t mask);
240 int umount (Const char * specialfile);
241 int uname (Struct utsname * Name);
242 int unlink (Const char * filename);
243 int ustat ( dev_t dev, struct ustat * Ubuf);
244 int utime (Const char * filename, struct utimbuf * times );
245 pid_t waitpid ( pid_t pid, int * wait_stat, int options);
246 pid_t wait (Int * wait_stat);
247 int write (Int fildes, const char * buf , off_t count );
248 int dup2 (Int oldfd, int newfd);
249 int getppid (Void);
250 pid_t getpgrp (Void);
251 pid_t setsid (Void);
252 253 #endif

254

11.15 utime.h file

11.15.1 Functional Description

The document defines the structure file access and modification times utimbuf {} as well as utime () Function prototype. Total time in seconds.

11.15.2 Code comments

program 11-13 linux / include / utime.h

1 #ifndef _UTIME_H 2 #define _UTIME_H 3 4 #include <sys / types.h> / * I know - should not do this, but ..
*/

5 / * I know - should not do that, but .. * /


6 struct utimbuf {
7 time_t actime; // file access time. From 1970.1.1: 0: 0: 0 Number of seconds to start.

8 time_t modtime; // file modification time. From 1970.1.1: 0: 0: 0 Number of seconds to start.

9 };
10
// Set file access and modification time function.

11 extern int utime (Const char * filename, struct utimbuf * times );


1213 #endif

14

--504--
File under 11.16 include / asm / directory

11.16 include / asm / File directory

List 11-2 linux / include / asm / File directory

name size Last Modified Time (GMT) Description

io.h 477 bytes 1991-08-07 10:17:51 m

memory.h 507 bytes 1991-06-15 20:54:44 m

segment.h 1366 bytes 1991-11-25 18:48:24 m


system.h 1711 bytes 1991-09-17 13:08:31 m

11.17 io.h file

11.17.1 Functional Description

The document defines the hardware IO Embedded assembler port access macro functions: outb () , inb () as well as outb_p () with inb_p () . The first two functions with two

rear main difference is that the latter uses a code jmp A time delay instruction.

11.17.2 Code comments

program 11-14 linux / include / asm / io.h

//// hardware port byte output functions.

// Parameters: value - to be output byte; port - port.


1 #define outb (Value, port) \
2 __asm__ ( " outb %% al, %% dx "::" a "( value), " d "( port))
34

//// hardware port byte input function.


// Parameters: port - port. Return of bytes read.
5 #define inb (Port) ({\
6 unsigned char _v; \
7 __asm__ volatile ( " inb %% dx, %% al ":" = a "(_ v): " d "( port)); \
8 _v; \
9 })
10
//// bytes of output ports with hardware delay function. // Parameters:
value - to be output byte; port - port.
11 #define outb_p (Value, port) \
12 __asm__ ( " outb %% al, %% dx \ n "\
13 "\ Tjmp 1f \ n" \
14 "1: \ tjmp 1f \ n" \
15 "1:" :: "a" ( value), " d "( port))
16
//// byte input port with hardware delay function.

--505--
11.18 memory.h file

// Parameters: port - port. Return of bytes read.


17 #define inb_p (Port) ({\
18 unsigned char _v; \
19 __asm__ volatile ( " inb %% dx, %% al \ n "\
20 "\ Tjmp 1f \ n" \
twenty one "1: \ tjmp 1f \ n" \
twenty two "1:": "= a" (_ v): " d "( port)); \
twenty three _v; \

twenty four })

25

11.18 memory.h file

11.18.1 Functional Description

This file contains a copy of memory macros embedded assembler memcpy () . versus string.h Defined memcpy () The same, but the latter is used in embedded assembly C Functional

form definition.

11.18.2 Code comments

program 11-15 linux / include / asm / memory.h

1/*
2 * NOTE !!! memcpy (dest, src, n) assumes ds = es = normal data segment. This
3 * Goes for all kernel functions (ds = es = kernel space, fs = local data,
4 * Gs = null), as well as for all well-behaving user programs (ds = es =
5 * User data space). This is NOT a bug, as any user program that changes
6 * Es deserves to die if it is not careful.
7*/
/*
* Note !!! memcpy (dest, src, n) is assumed segment register ds = es = normal data segment. Used in the kernel

* All functions are based on the assumption (ds = es = kernel space, fs = spatial local data, gs = null), having good

* The behavior of the application the same way (ds = es = user data space). If any arbitrary changes to the user program

* es register and error, not due to system program error.


*/
//// memory block copy. Start Copy n bytes at the destination address from the source address dest at src. // Parameters: dest -

copy destination address, src - copy source address, n - the number of bytes copied. //% 0 - edi (destination address dest),% 1 - esi

(source address src),% 2 - ecx (number of bytes n),

8 #define memcpy (Dest, src, n) ({\


9 void * _res = dest; \
10 __asm__ ( " cld; rep; movsb "\ // From the ds: [esi] Copy to es: [edi], and esi ++, edi ++. Co // Copy ecx (n)
bytes.
11 :: " D "(( long) (_ res)), " S "(( long) (src)), " c "(( long) (n)) \
12 : " di "," si "," cx "); \
13 _res; \
14 })
15

--506--
11.19 segment.h file

11.19 segment.h file

11.19.1 Functional Description

This document defines the access segment register or memory operation functions associated with segment register.

11.19.2 Code comments

program 11-16 linux / include / asm / segment.h

//// fs reading the byte at the specified address segment. //

Parameters: addr - specified memory address.

% // 0 - (bytes returned _v);% 1 - (memory address addr). // Returns:


Memory fs: byte [addr] at.
1 extern inline unsigned char get_fs_byte (Const char * addr)
2{
3 unsigned register char _v;
45
__asm__ ( " movb %% fs:% 1,% 0 ":" = r "(_ v): " m "(* addr));
6 return _v;
7}
8
//// fs reading section at the specified word address. // Parameters: addr -
specified memory address. % // 0 - (return word _v);% 1 - (memory
address addr). // Returns: Memory fs: word [addr] at.

9 extern inline unsigned short get_fs_word (Const unsigned short * addr)


10 {
11 unsigned short _v;
1213
__asm__ ( " movw %% fs:% 1,% 0 ":" = r "(_ v): " m "(* addr));
14 return _v;
15 }
16
//// reads a specified period fs long word (4 bytes) at the address. // Parameters:

addr - specified memory address.

% // 0 - (longword returned _v);% 1 - (memory address addr). // Returns:


Memory fs: long word [addr] at.
17 extern inline unsigned long get_fs_long (Const unsigned long * addr)
18 {
19 unsigned long _v;
2021
__asm__ ( " movl %% fs:% 1,% 0 ":" = r "(_ v): " m "(* addr)); \
twenty two return _v;
twenty three }

twenty four

The //// a byte is stored at the memory address specified in paragraph fs. // Parameters:

val - byte value; addr - memory address. //% 0 - Register (byte value val);% 1 - (memory

address addr).

25 extern inline void put_fs_byte (Char val, char * addr)


26 {

--507--
11.19 segment.h file

27 __asm__ ( " movb% 0, %% fs:% 1 "::" r "( val), " m "(* addr));
28 }
29
//// word will be placed in the designated fs segment at memory address. // Parameters: val

- word value; addr - memory address. //% 0 - Register (word value val);% 1 - (memory

address addr).

30 extern inline void put_fs_word (Short val, short * addr)


31 {
32 __asm__ ( " movw% 0, %% fs:% 1 "::" r "( val), " m "(* addr));
33 }
34
//// to a long word address stored in the specified memory segment fs. // Parameters: val -

long word value; addr - memory address. //% 0 - Register (longword value val);% 1 -

(memory address addr).

35 extern inline void put_fs_long (Unsigned long val, unsigned long * addr)
36 {
37 __asm__ ( " movl% 0, %% fs:% 1 "::" r "( val), " m "(* addr));
38 }
3940 / *

41 * Someone who knows GNU asm better than I should double check the followig.
42 * It seems to work, but I do not know if I'm doing something subtly wrong.
43 * --- TYT, 11/24/91
44 * [Nothing wrong here, Linus]
45 * /
/*
* I know better than the GNU assembler people should check the following code carefully. These codes can be used, but I do not know whether

* It contains some minor bugs.

* --- TYT, 1991 Nian 11 Yue 24-Ri


* [Code without error, Linus]
*/
46
//// taken fs segment register values ​(selectors). // Returns:

fs segment register values.

47 extern inline unsigned long get_fs ()


48 {
49 unsigned short _v;
50 __asm ​__ ( " mov %% fs, %% ax ":" = a "(_ v) :);
51 return _v;
52 }
53
//// take ds segment register values. // Returns:

ds segment register values.

54 extern inline unsigned long get_ds ()


55 {
56 unsigned short _v;
57 __asm ​__ ( " mov %% ds, %% ax ":" = a "(_ v) :);
58 return _v;
59 }
60
//// provided fs segment register. // Parameters: val -

segment value (selector).

61 extern inline void set_fs (Unsigned long val)

--508--
11.20 system.h file

62 {
63 __asm ​__ ( " mov% 0, %% fs "::" a "(( unsigned short) val));
64 }
6566

11.20 system.h file

11.20.1 Functional Description

This document defines a set or modify the descriptor / interrupt gate or the like embedded macro assembler.

Where the function move_to_user_mode () For initializing the kernel at the end of manual switching (moves) to the initial process (task 0 ) To do it. The method used was a

simulated interrupt procedure call returns, i.e. by Command iret Run the initial task 0 . See Fig. 11-2 Fig.

31 0 SP0- (TSS in the SS: ESP)


Former SS
Stack extension direction

CS original ESP

Original EFLAGS

Original

Original EIP
SP1-iret instructions before the implementation of the new SS: ESP

Map 11-2 When the content interrupt call stack to switch between layers

In to perform the task 0 Before the code, first set up the stack, the analog switch has a privileged layer of just entering the arrangement of the contents of the stack when

the interrupt calling procedure. Iret then execute instructions to cause the system to a task 0 In execution. In execution iret When the statement, the contents of the stack as shown 11.2

As shown, at this time esp for esp1 . task 0 The stack is a stack kernel. When executed iret After that, he moved to the task 0

In the execution. As the task 0 Is a descriptor privilege level 3 Therefore stack on ss: esp It will be ejected. Thus, in iret after that, esp And equal esp0 A. Note that this interruption

return instruction iret And will not cause CPU To perform the task switching operation, because before executing this function, the flag NT Already here sched_init () It is reset. in NT Perform

reset iret Instruction will not cause CPU Perform a task switch operation. task 0 The execution is purely artificial started.

task 0 Is a special process that data segment and code segment mapped directly to the kernel code and data space, i.e., from the physical address 0 Started 640K Memory

space, its stack address is the kernel code used in the stack. Thus the original stack in FIG. SS And former ESP Existing kernel stack pointer is pushed on the stack directly.

11.20.2 Code comments

program 11-17 linux / include / asm / system.h

//// moved to the user mode.

--509--
11.20 system.h file

// This function is implemented using iret instruction to move from kernel mode to perform the initial tasks 0.

1 #define move_to_user_mode () \
2 __asm__ ( " movl %% esp, %% eax \ n \ t "\ // save the stack pointer register eax esp.
3 "Pushl $ 0x17 \ n \ t" \ // first the stack segment selector (SS) stack.

4 "Pushl %% eax \ n \ t" \ // then the value of the saved stack pointer (ESP) stack.

5 "Pushfl \ n \ t" \ // The flag register (eflags) the contents of the stack.

6 "Pushl $ 0x0f \ n \ t" \ // The Task0 snippet selector (CS) stack.


7 "Pushl $ 1f \ n \ t" \ // offset address will now numeral (eip) 1 onto the stack.

8 "Iret \ n" \ // interrupt return instruction, a jump to the numeral 1 below.


9 "1: \ tmovl $ 0x17, %% eax \ n \ t" \ // Then began to perform the task 0,
10 "Movw %% ax, %% ds \ n \ t" \ // Initialize the segment registers point to the data segment according to the local table.

11 "Movw %% ax, %% es \ n \ t" \


12 "Movw %% ax, %% fs \ n \ t" \
13 "Movw %% ax, %% gs" \
14 ::: " ax ")
1516 #define sti () __Asm__ ( " sti ": :)
// open interrupt embedded assembler macro functions.

17 #define cli () __Asm__ ( " cli ": :) // disable interrupts.

18 #define nop () __Asm__ ( " nop ": :) // null operation.


1920 #define iret () __Asm__ ( " iret ": :)
// interrupt return.
twenty one

//// gate descriptor macro function is provided.

// Parameters: gate_addr - descriptor address; type - the type field value descriptor; dpl - descriptor privilege level value; addr - offset. % // 0 - (a dpl, type

combined into a type of flag word);% 1 - (4-byte descriptor Low); //% 2 - (4 descriptor high byte address);% 3 - edx (program offset address addr);% 4 - eax (high

word contains the segment selector).

twenty two #define _set_gate (Gate_addr, type, dpl, addr) \


twenty three __asm__ ( " movw %% dx, %% ax \ n \ t "\ // the low word and the offset address selector 4 are combined into a low byte descriptor (eax).

twenty four "Movw% 0, %% dx \ n \ t" \ // the offset type flag words and descriptor words into a high-high-order 4 bytes (edx).

25 "Movl %% eax,% 1 \ n \ t" \ // are provided gate descriptor and the lower 4 bytes 4 bytes higher.

26 "Movl %% edx,% 2" \


27 :\
28 : " i "(( short) (0x8000 + (dpl << 13) + (type << 8))), \
29 "O" (* (( char *) (gate_addr))), \
30 "O" (* ( 4+ (char *) (gate_addr))), \
31 "D" (( char *) (addr)), " a "( 0x00080000))
32
//// set interrupt gate function.
// Parameters: n - interrupt number; addr - interrupt program offset address.

// & idt [n] corresponding to the interrupt number in an interrupt descriptor offset values ​in the table; interrupt descriptor type is 14, the privilege level is zero.

33 #define set_intr_gate (N, addr) \


34 _set_gate (& idt [N], 14,0, addr)
35
//// set a trap door function.
// Parameters: n - interrupt number; addr - interrupt program offset address.

// & idt [n] corresponding to the interrupt number in an interrupt descriptor offset values ​in the table; interrupt descriptor type is 15, the privilege level is zero.

36 #define set_trap_gate (N, addr) \


37 _set_gate (& idt [N], 15,0, addr)
38
//// set the system call gate function.

// Parameters: n - interrupt number; addr - interrupt program offset address.

// & idt [n] corresponding to the interrupt number in an interrupt descriptor offset values ​in the table; interrupt descriptor type is 15, the privilege level is 3.

39 #define set_system_gate (N, addr) \

--510--
11.20 system.h file

40 _set_gate (& idt [N], 15,3, addr)


41
//// set descriptor function.
// Parameters: gate_addr - descriptor address; type - the type field value descriptor; dpl - descriptor privilege level value; // base - segment base

address; limit - long segment limit. (See segment descriptor format)

42 #define _set_seg_desc (Gate_addr, type, dpl, base, limit) {\


43 * (Gate_addr) = ((base) & 0xff000000) | \ // 4-byte descriptor low.
44 (((Base) & 0x00ff0000) >> 16) | \
45 ((Limit) & 0xf0000) | \
46 ((Dpl) << 13) | \
47 (0x00408000) | \
48 ((Type) << 8); \
49 * ((Gate_addr) +1) = (((base) & 0x0000ffff) << 16) | \ // 4-byte descriptor high.
50 ((Limit) & 0x0ffff);}
51
//// provided TSS / local descriptor table in the global table.
// Parameters: n - n Description address identifier corresponding entry in the global table; addr - Status segment / local memory table where the base address. //

type - Type flag byte descriptor.


//% 0 - eax (address addr);% 1 - (n descriptor entry address); 2% - (n descriptor entry address offset 2); //% 3 - (item descriptors of n
address offset 4);% 4 - (n descriptor entry address offset 5); // 5% - (n descriptor entry address offset 6); 6% - (n is the descriptor
entry address offset 7);
52 #define _set_tssldt_desc (N, addr, type) \
53 __asm__ ( " movw $ 104,% 1 \ n \ t "\ // length into the TSS descriptor length field (bytes 0-1).
54 "Movw %% ax,% 2 \ n \ t" \ // the low word into the descriptor base address of the first byte 2-3.

55 "Rorl $ 16, %% eax \ n \ t" \ // High word into the base address of the ax.

56 "Movb %% al,% 3 \ n \ t" \ // The base address low byte of the high word of the descriptor into 4 bytes.

57 "Movb $" type ",% 4 \ n \ t "\ // Type flag byte to the fifth byte of the descriptor.
58 "Movb $ 0x00,% 5 \ n \ t" \ // descriptor sixth byte set to zero.
59 "Movb %% ah,% 6 \ n \ t" \ // The base address high byte of the high word of the descriptor into 7 bytes.

60 "Rorl $ 16, %% eax" \ // eax cleared.


61 :: " a "( addr), " m "(* ( n)), " m "(* ( n + 2)), " m "(* ( n + 4)), \
62 "M" (* ( n + 5)), " m "(* ( n + 6)), " m "(* ( n + 7)) \
63 )
64
//// set the task state segment descriptor in the global table.

// n - is the descriptor pointer; addr - is the base address value descriptor. The type of task status segment descriptor is 0x89.

65 #define set_tss_desc (N, addr) _set_tssldt_desc (((Char *) (n)), addr, " 0x89 ")
//// set the local descriptor table in the global table.

// n - is the descriptor pointer; addr - is the base address value descriptor. Local descriptor table type is 0x82.
66 #define set_ldt_desc (N, addr) _set_tssldt_desc (((Char *) (n)), addr, " 0x82 ")
67

--511--
File under 11.21 include / linux / directory

11.21 include / linux / File directory

List 11-3 linux / include / linux / File directory

Name Size Last Modified Time (GMT) Description

config.h 1289 bytes 1991-12-08 18:37:16 m

fdreg.h 2466 bytes 1991-11-02 10:48:44 m

fs.h 5474 bytes 1991-12-01 19:48:26 m

hdreg.h 1968 bytes 1991-10-13 15:32:15 m

head.h 304 bytes 1991-06-19 19:24:13 m

kernel.h 734 bytes 1991-12-02 03:19:07 m

mm.h 219 bytes 1991-07-29 17:51:12 m

sched.h 5838 bytes 1991-11-20 14:40:46 m

sys.h 2588 bytes 1991-11-25 20:15:35 m


tty.h 2173 bytes 1991-09-21 11:58:05 m

11.22 config.h file

11.22.1 Functional Description

Kernel configuration header file. Custom keyboard language type and hard disk type used ( HD_TYPE ) Options.

11.22.2 Code comments

program 11-18 linux / include / linux / config.h

1 #ifndef _CONFIG_H 2 #define


_CONFIG_H 3 4 / *

5 * The root-device is no longer hard-coded. You can change the default


6 * Root-device by changing the line ROOT_DEV = XXX in boot / bootsect.s
7*/
/*
* Root file system device is no longer a hard-coded. By modifying the boot / bootsect.s lines in the file
* ROOT_DEV = XXX, you can change the default settings for the root device.

*/
89 / *

10 * Define your keyboard here -


11 * KBD_FINNISH for Finnish keyboards

--512--
11.22 config.h file

12 * KBD_US for US-type


13 * KBD_GR for German keyboards
14 * KBD_FR for Frech keyboard
15 * /
/*
* Here define your keyboard type -
* KBD_FINNISH Finland keyboard.
* KBD_US is a US keyboard.
* KBD_GR is a German keyboard.

* KBD_FR is a French keyboard.

*/
16 / * # Define KBD_US * /
17 / * # Define KBD_GR * /
18 / * # Define KBD_FR * /
19 #define KBD_FINNISH 20 21 / *

twenty two * Normally, Linux can get the drive parameters from the BIOS at
twenty three * Startup, but if this for some unfathomable reason fails, you'd
twenty four * Be left stranded. For this case, you can define HD_TYPE, which
25 * Contains all necessary info on your harddisk.
26 *
27 * The HD_TYPE macro should look like this:
28 *
29 * #Define HD_TYPE {head, sect, cyl, wpcom, lzone, ctl}
30 *
31 * In case of two harddisks, the info should be sepatated by
32 * Commas:
33 *
34 * #Define HD_TYPE {h, s, c, wpcom, lz, ctl}, {h, s, c, wpcom, lz, ctl}
35 * /
/*
* Usually, Linux can get the drive parameters from the BIOS in Germany at the start, but if an unknown reason

* But not when these parameters, the program will do nothing. In this case, you can define HD_TYPE,
* Including all hard drive information.

*
* HD_TYPE macro should like this in the form below:

*
* # define HD_TYPE {head, sect, cyl, wpcom, lzone, ctl}
*
* For two hard drives, the information required parameters separated by commas:

*
* # define HD_TYPE {h, s, c, wpcom, lz, ctl}, {h, s, c, wpcom, lz, ctl}
*/
36 / *
37 This is an example, two drives, first is type 2, second is type 3:
3839 #define HD_TYPE {4,17,615,300,615,8}, {6,17,615,300,615,0}

4041 NOTE: ctl is 0 for all drives with heads <= 8, and ctl = 8 for drives

42 with more than 8 heads.


4344 If you want the BIOS to tell what kind of drive you have, just

--513--
11.23 fdreg.h header file

45 leave HD_TYPE undefined. This is the normal thing to do.


46 * /
/*
* Here is an example, two hard disks, the first one is a Type 2, Type 3 is 2:
*
* # define HD_TYPE {4,17,615,300,615,8}, {6,17,615,300,615,0}
*
* Note: corresponding to all hard, if the number of heads which <= 8, ctl equals 0, if the number of heads is more than 8,

* The ctl = 8.
*
* If you want the type of BIOS given hard disk, simply do not define HD_TYPE. This is the default action.

*/
4748 #endif

49

11.23 fdreg.h head File

11.23.1 Functional Description

The header file for describing the floppy disk to the system used and the parameters used I / O port. Since the control of the floppy drive more cumbersome, but also

command more, so before you read the code, it is best reference books on the principle of micro-computer control interface, understand floppy disk controller ( FDC) Works, then

you will find the definition here is quite reasonable and orderly.

For access to programming 4 Ports, respectively corresponding to one or more registers. for 1.2M The table has a floppy disk controller 11-1 Some port.

table 11-1 Floppy disk controller port

I / O port Reading and writing of Register Name

0x3f2 Only Digital output register (Digital Control Register)

0x3f4 Write FDC Main Status Register

0x3f5 Only Read / Write FDC Data register

0x3f7 Read-only Digital input register

0x3f7 just write Disk control register (transmission rate control)

Digital output port (port number control) is a 8 Bit register which controls the drive motor is turned on, the drive selection, start / reset FDC As well as enable / disable DMA

And interrupt request.

FDC The status register is a main 8 Bit register is used to reflect the floppy disk controller FDC And a floppy disk drive FDD The basic state. Typically, CPU to FDC Before

sending a command or from FDC Before obtaining the operation result, the master must read the status register bits, to discriminate the current FDC Data register is ready and

determines the direction of data transfer.

FDC A plurality of registers corresponding to the data port (write only type parameter register and the command register, read-only result register), but any one time, only

one appears in the data port register 0x3f5 . When accessing the write-only register, the main state control DIO Direction bit must be 0 ( CPU FDC ), And vice versa when the read

access type register. When reading the results only in FDC After reading the results considered busy, usually resulting data Up 7 Bytes.

--514--
11.23 fdreg.h header file

The floppy disk controller can accept a total of 15 Command. Each command through three stages: the command phase, implementation phase and the results stage.

Command stage CPU to FDC Send command byte and parameter bytes. The first byte of each command byte is always the command (command code). Thereafter followed 0--8 Byte

parameters. The implementation phase is FDC Perform the operation specified command. In the implementation phase CPU That without intervention, usually through FDC It issues

an interrupt request to know the end of the command execution. in case CPU dispatched FDC Command is transmitted data, FDC You can interrupt or DMA Conducted. Interrupt

each transfer 1 byte. DMA Way in DMA Controller Management, FDC

Transmitting data to and from memory until all of the data transferred. at this time DMA Controller will signal the transfer byte count termination FDC Finally, the FDC Issues an

interrupt request signal inform CPU The implementation phase is completed. The result is a stage CPU Read FDC Data register return value, to thereby obtain FDC The results of the

command execution. Return result data length 0--7 byte. For data command does not return results, should the FDC Interrupt Status command transmission detecting operation state

is obtained.

11.23.2 File Comments

program 11-19 linux / include / linux / fdreg.h

1/*
2 * This file contains some defines for the floppy disk controller.
3 * Various sources Mostly "IBM Microcomputers:. A Programmers
4 * Handbook ", Sanches and Canton.
5*/
/*
* This file contains a number of definitions of the floppy disk controller. There are many sources of information, mostly taken from Sanches and Canton

* Compiled the "IBM microcomputers: Programmer's Guide," a book.

*/
6 #ifndef _FDREG_H // This code is defined to exclude this header file contains duplicate.

7 #define _FDREG_H 8

// function prototypes illustrate the type of floppy disk.

9 extern int ticks_to_floppy_on (Unsigned int nr);


10 extern void floppy_on (Unsigned int nr);
11 extern void floppy_off (Unsigned int nr);
12 extern void floppy_select (Unsigned int nr);
13 extern void floppy_deselect (Unsigned int nr);
14
// The following are definitions of some of the floppy disk controller ports and symbols.

15 / * Fd controller regs. S & C, about page 340 * /


/ * Floppy disk controller (FDC) interface register. Book taken from S & C to about 340 * /

16 #define FD_STATUS 0x3f4 // master state register ports.


17 #define FD_DATA 0x3f5 // data port.
18 #define FD_DOR 0x3f2 / * Digital Output Register * /
// Digital Output Register (also referred to as digital control register).

19 #define FD_DIR 0x3f7 / * Digital Input Register (read) * /


// digital input register.
20 #define FD_DCR 0x3f7 / * Diskette Control Register (write) * /
// data rate control register.
2122 / * Bits of main status register * /

/ * Each bit of the status register Meaning main * /

twenty three #define STATUS_BUSYMASK 0x0F / * Drive busy mask * /


// drive is busy bits (each corresponding to a drive).
twenty four #define STATUS_BUSY 0x10 / * FDC busy * /
// floppy disk controller is busy.

--515--
11.23 fdreg.h header file

25 #define STATUS_DMA 0x20 / * 0- DMA mode * /


// 0 - for the DMA data transfer mode of 1 - a non-DMA mode.
26 #define STATUS_DIR 0x40 / * 0- cpu-> fdc * /
@ Transmission direction: 0 - CPU fdc, 1 - the opposite.
27 #define STATUS_READY 0x80 / * Data reg ready * /
// Ready bit data register.
2829 / * Bits of FD_ST0 * /

/ * Status Byte 0 (ST0) the meaning of each bit * /


30 #define ST0_DS 0x03 / * Drive select mask * /
// drive select number (when the interrupt occurs drive letter).

31 #define ST0_HA 0x04 / * Head (Address) * /


// head number.
32 #define ST0_NR 0x08 / * Not Ready * /
// disk drive is not ready.
33 #define ST0_ECE 0x10 / * Equipment chech error * /
// error detection device (track zero calibration error).

34 #define ST0_SE 0x20 / * Seek end * /


// seek or recalibrate operation execution ends.

35 #define ST0_INTR 0xC0 / * Interrupt code mask * /


// interrupt code bits (interrupt cause), 00 - the end of the normal command; // 01 - command ends

abnormally; 10 - command invalid; 11 - FDD readiness to change.

3637 / * Bits of FD_ST1 * /

/ * Status Byte 1 (ST1) the meaning of each bit * /


38 #define ST1_MAM 0x01 / * Missing Address Mark * /
// address mark (ID AM) was not found.

39 #define ST1_WP 0x02 / * Write Protect * /


// write-protected.

40 #define ST1_ND 0x04 / * No Data - unreadable * /


// the specified sector was not found.

41 #define ST1_OR 0x10 / * OverRun * /


// Data transmission timeout (DMA controller failure).

42 #define ST1_CRC 0x20 / * CRC error in data or addr * /


// CRC check error.
43 #define ST1_EOC 0x80 / * End Of Cylinder * /
// access to more than the maximum number of sectors on a track.

4445 / * Bits of FD_ST2 * /

/ * Status byte 2 (ST2) the meaning of each bit * /


46 #define ST2_MAM 0x01 / * Missing Addess Mark (again) * /
// data address mark not found.
47 #define ST2_BC 0x02 / * Bad Cylinder * /
// bad track.
48 #define ST2_SNS 0x04 / * Scan Not Satisfied * /
// Retrieve (scanning) conditions are not met.

49 #define ST2_SEH 0x08 / * Scan Equal Hit * /


// Retrieve conditions are met.

50 #define ST2_WC 0x10 / * Wrong Cylinder * /


// number does not match the track (cylinder).

51 #define ST2_CRC 0x20 / * CRC error in data field * /


// Data Field CRC error.
52 #define ST2_CM 0x40 / * Control Mark = deleted * /

--516--
11.24 fs.h file

5354 / * Bits of FD_ST3 * /

/ * Byte state (ST3) the meaning of each bit 3 * /


55 #define ST3_HA 0x04 / * Head (Address) * /
// head number.
56 #define ST3_TZ 0x10 / * Track Zero signal (1 = track 0) * /
// zero track signal.
57 #define ST3_WP 0x40 / * Write Protect * /
// write-protected.

5859 / * Values ​for FD_COMMAND * /

/ * Floppy command code * /

60 #define FD_RECALIBRATE 0x07 / * Move to track 0 * /


// Re-calibration (zero head retreated track).

61 #define FD_SEEK 0x0F / * Seek track * /


// head seek.
62 #define FD_READ 0xE6 / * Read with MT, MFM, SKip deleted * /
// read data (MT multi-track operation, MFM format, skip, delete).
63 #define FD_WRITE 0xC5 / * Write with MT, MFM * /
// write data (MT, MFM).
64 #define FD_SENSEI 0x08 / * Sense Interrupt Status * /
// detect interrupt status.
65 #define FD_SPECIFY 0x03 / * Specify HUT etc * /
// set the drive parameters (step rate, the head unloading time, etc.).

6667 / * DMA commands * /

/ * DMA command * /
flag.
68 #define DMA_READ 0x46 // read the disk DMA, DMA mode word (send DMA port 12,11).
69 #define DMA_WRITE 0x4A // DMA write disk, DMA mode word.

7071 #endif

72

11.24 fs.h file

11.24.1 Functional Description

11.24.2 Code comments

program 11-20 linux / include / linux / fs.h

1/*
2 * This file has definitions for some important file table
3 * Structures etc.
4*/
/*
* This paper contains certain critical files define the table structure, and the like.

--517-- // read data experiences a delete


11.24 fs.h file

*/
56 #ifndef _FS_H 7 #define _FS_H 8 9 #include
<sys / types.h>

// type of header files. System defines the basic data types.

1011 / * Devices are as follows: (same as minix, so we can use the minix

12 * File system. These are major numbers.)


13 *
14 * 0 - unused (nodev)
15 * 1 - / dev / mem
16 * 2 - / dev / fd
17 * 3 - / dev / hd
18 * 4 - / dev / ttyx
19 * 5 - / dev / tty
20 * 6 - / dev / lp
twenty one * 7 - unnamed pipes

twenty two * /

/*
* Equipment contained in the system are as follows :( Like minix system, so we can use the minix

* File system. These are the major number. )


*
* 0 - not used (nodev)
* 1 - / dev / mem Memory device.

* 2 - / dev / fd Floppy device.


* 3 - / dev / hd Hard disk device.

* 4 - / dev / ttyx serial tty terminal device.


* 5 - / dev / tty tty terminal device.
* 6 - / dev / lp Printing equipment.

* 7 - unnamed pipes unnamed pipes.


*/
2324 #define IS_SEEKABLE ( x ) (( x )> 1 && = ( x ) <= 3)
// whether it is possible to find positioning device.

2526 #define READ 0

27 #define WRITE 1
28 #define READA 2 / * Read-ahead - do not pause * /
29 #define WRITEA 3 / * "Write-ahead" - silly, but somewhat useful * /
3031 void buffer_init (Long buffer_end);

3233 #define MAJOR (A) (((unsigned) (a)) >> 8)


// get the high byte (master number).

34 #define MINOR (A) ((a) & 0xff) // get low byte (the minor device number).

3536 #define NAME_LEN 14


// name length value.
37 #define ROOT_INO 1 I // root node.
3839 #define I_MAP_SLOTS 8
// i groove node bit map.
40 #define Z_MAP_SLOTS 8 // logical block (sector block) number of slots bitmap.

41 #define SUPER_MAGIC 0x137F // magic number of the file system.

4243 #define NR_OPEN 20


// number of open files.

--518--
11.24 fs.h file

44 #define NR_INODE 32
45 #define NR_FILE 64
46 #define NR_SUPER 8
47 #define NR_HASH 307
48 #define NR_BUFFERS nr_buffers 49 #define BLOCK_SIZE
1024 // Data block length.
50 #define BLOCK_SIZE_BITS 10 // number of bits occupied by the data block length.

51 #ifndef NULL 52 #define NULL ((Void *) 0)

53 #endif
54
// Each logical block may be stored in the nodes i.

55 #define INODES_PER_BLOCK (( BLOCK_SIZE ) / (Sizeof (struct d_inode ))) // number of directory entries can be stored in

each logical block.

56 #define DIR_ENTRIES_PER_BLOCK (( BLOCK_SIZE ) / (Sizeof (struct dir_entry )))


57
// pipe head, tail pipes, pipe size, pipe empty? Pipeline full? , The head pointer is incremented pipe.

58 #define PIPE_HEAD (Inode) ((inode) .i_zone [0])


59 #define PIPE_TAIL (Inode) ((inode) .i_zone [1])
60 #define PIPE_SIZE (Inode) (( PIPE_HEAD (Inode) - PIPE_TAIL (Inode)) & ( PAGE_SIZE -1))
61 #define PIPE_EMPTY (Inode) ( PIPE_HEAD (Inode) == PIPE_TAIL (Inode))
62 #define PIPE_FULL (Inode) ( PIPE_SIZE (Inode) == ( PAGE_SIZE -1))
63 #define INC_PIPE ( head ) \
64 __asm ​__ ( " incl% 0 \ n \ tandl $ 4095,% 0 "::" m "( head ))
6566 typedef char buffer_block [ BLOCK_SIZE ];
// block buffer.
67
// buffer header data structure. (Very important !!!) // common bh in a program to
represent buffer_head type of abbreviation.
68 struct buffer_head {
69 char * b_data; / * Pointer to data block (1024 bytes) * / // pointer.
70 unsigned long b_blocknr; / * Block number * / // block numbers.

71 unsigned short b_dev; / * Device (0 = free) * / // Device number data source.


72 unsigned char b_uptodate; // update flag: Indicates whether the data has been updated.

73 unsigned char b_dirt; / * 0-clean, 1-dirty * / // Modify flag: 0 unmodified, 1 has been modified.
74 unsigned char b_count; / * Users using this block * / // number of users.
75 unsigned char b_lock; / * 0 - ok, 1 -locked * / // Whether the buffer is locked.
76 struct task_struct * B_wait; // point to wait for the buffer to unlock the task.

77 struct buffer_head * B_prev; // hash approached a queue (these four pointers used to manage buffer).

78 struct buffer_head * B_next; // hash queue up and down one.

79 struct buffer_head * B_prev_free; // idle approached a table.


80 struct buffer_head * B_next_free; // free list from top to bottom one.
81 };
82
The index node (i node) // a data structure on the disk.

83 struct d_inode {
84 unsigned short i_mode; // file type and attributes (rwx bits).
85 unsigned short i_uid; // user id (file owner identifier).
86 unsigned long i_size; // File Size (bytes).
87 unsigned long i_time; // modification time (from 1970.1.1: 0, counting seconds).

88 unsigned char i_gid; // set id (the file belongs to the group).


89 unsigned char i_nlinks; // number of links (how many files directory entry points to the i-node).

90 unsigned short i_zone [9]; // Direct (0-6), indirect (7) or double indirectly (8) a logical block number.

--519--
11.24 fs.h file

// zone is meant the zone, can be translated into segments, or logical blocks.

91 };
92
// This is the i-node structure in memory. Before 7 and d_inode exactly the same.

93 struct m_inode {
94 unsigned short i_mode; // file type and attributes (rwx bits).
95 unsigned short i_uid; // user id (file owner identifier).
96 unsigned long i_size; // File Size (bytes).
97 unsigned long i_mtime; // modification time (from 1970.1.1: 0, counting seconds).

98 unsigned char i_gid; // set id (the file belongs to the group).


99 unsigned char i_nlinks; // file directory entry number of links.

100 unsigned short i_zone [9]; // Direct (0-6), indirect (7) or double indirectly (8) a logical block number.

101 / * These are in memory also * /


102 struct task_struct * I_wait; // wait for the process of the i node.
103 unsigned long i_atime; // last access time.
104 unsigned long i_ctime; // i node itself modified.
105 unsigned short i_dev; // device number i node is located.

106 unsigned short i_num; // i node number.


107 unsigned short i_count; // the number of i-nodes to be used, i 0 indicates that the node is idle.

108 unsigned char i_lock; // lock mark.


109 unsigned char i_dirt; // modified (dirty) mark.
110 unsigned char i_pipe; // pipeline signs.
111 unsigned char i_mount; // install signs.
112 unsigned char i_seek; // search flag (when lseek).
113 unsigned char i_update; // update flag.
114 };
115
// File Structure (used to establish the relationship between the file handle and the i-node)

116 struct file {


117 unsigned short f_mode; // file operation mode (RW bit)
118 unsigned short f_flags; // File Open and sign control.
119 unsigned short f_count; // the corresponding file handle (file descriptor) number.

120 struct m_inode * F_inode; // i pointing to the corresponding node.

121 off_t f_pos; // file location (write offset).


122 };
123
Superblock structure // memory disk.

124 struct super_block {


125 unsigned short s_ninodes; // nodes.
126 unsigned short s_nzones; // number of logical blocks.

127 unsigned short s_imap_blocks; // i-node number of blocks occupied by the bitmap.

128 unsigned short s_zmap_blocks; // logical block number of data blocks occupied by the bitmap.

129 unsigned short s_firstdatazone; // first logical block number of data.


130 unsigned short s_log_zone_size; // log (block number / logical blocks). (Base 2).
131 unsigned long s_max_size; The maximum length // file.

132 unsigned short s_magic; // magic number of the file system.

133 / * These are only in memory * /


134 struct buffer_head * S_imap [8]; // i node bitmap buffer block pointer array (occupying 8, may represent a 64M).
135 struct buffer_head * S_zmap [8]; // bitmap logic block buffer block pointer array (occupying 8).
136 unsigned short s_dev; // super block device number is located.

137 struct m_inode * S_isup; // i root node of the file system is mounted. (Isup-super i)
138 struct m_inode * S_imount; // i is attached to the node.
139 unsigned long s_time; // Change the time.

--520--
11.24 fs.h file

140 struct task_struct * S_wait; // Wait for the process of the superblock.

141 unsigned char s_lock; // locked flag.


142 unsigned char s_rd_only; // read-only flag.
143 unsigned char s_dirt; // modified (dirty) mark.
144 };
145
// disk superblock structure. 125-132 above line exactly the same.

146 struct d_super_block {


147 unsigned short s_ninodes; // nodes.
148 unsigned short s_nzones; // number of logical blocks.

149 unsigned short s_imap_blocks; // i-node number of blocks occupied by the bitmap.

150 unsigned short s_zmap_blocks; // logical block number of data blocks occupied by the bitmap.

151 unsigned short s_firstdatazone; // first logical block of data.


152 unsigned short s_log_zone_size; // log (block number / logical blocks). (Base 2).
153 unsigned long s_max_size; The maximum length // file.

154 unsigned short s_magic; // magic number of the file system.

155 };
156
// file directory entry structure.

157 struct dir_entry {


158 unsigned short inode; // i node.
159 char name [ NAME_LEN ]; // file name.
160 };
161 162 extern struct m_inode inode_table [ NR_INODE ];
// define an array of i-node table (32).
163 extern struct file file_table [ NR_FILE ]; // File Table array (64).
164 extern struct super_block super_block [ NR_SUPER ]; // array of super blocks (8).
165 extern struct buffer_head * start_buffer ; // start of the buffer memory location.

166 extern int nr_buffers ; // number of buffer blocks.

167
//// disk operations function prototypes. // Check whether the

floppy disk drive changes.

168 extern void check_disk_change (Int dev);


// Specify detecting floppy diskette replacement situation. If the disk is replaced returns 1, otherwise it returns 0.

169 extern int floppy_change (Unsigned int nr);


// set the start time required to wait for the specified drive (set to wait for a timer).

170 extern int ticks_to_floppy_on (Unsigned int dev);


// Start the specified drive.
171 extern void floppy_on (Unsigned int dev);
// Closes the specified floppy disk drive.

172 extern void floppy_off (Unsigned int dev);

//// The following is the function prototype with the file system operations management.

The i-node // specified file truncated to 0.

173 extern void truncate (Struct m_inode * Inode); // refresh the i-node
information.
174 extern void sync_inodes (Void);
// wait i node specified.
175 extern void wait_on (Struct m_inode * Inode);
// logical block (sector, disk blocks) bitmap operations. Block fetch data block corresponding to the logical block number in the device.

176 extern int bmap (Struct m_inode * Inode, int block);


// Create a data block corresponding to the block on the logical block devices, and returns the logical block number on the device.

177 extern int create_block (Struct m_inode * Inode, int block);

--521--
11.24 fs.h file

// Get the i-node number specified pathname.

178 extern struct m_inode * namei (Const char * pathname);


// Open the file operations to prepare the path named.

179 extern int open_namei (Const char * pathname, int flag, int mode,
180 struct m_inode ** res_inode);
// release a i-node (written back device).
181 extern void iput (Struct m_inode * Inode); // read the specified number
of slave node a node i.
182 extern struct m_inode * iget (Int dev, int nr);
// Get a free node i from the i-node table entry (inode_table) in.
183 extern struct m_inode * get_empty_inode (Void);
// Get the (applying a) pipeline node. It returns a pointer to the node i (if NULL is a failure).
184 extern struct m_inode * get_pipe_inode (Void);
// find the specified data block in a hash table. Returns a pointer to find the first buffer block.

185 extern struct buffer_head * get_hash_table (Int dev, int block);


// the specified block is read from the device (first looks in the hash table).

186 extern struct buffer_head * getblk (Int dev, int block);


// read / write data blocks.

187 extern void ll_rw_block (Int rw, struct buffer_head * Bh); // release a specified buffer block.

188 extern void brelse (Struct buffer_head * buf ); // read the specified data block.

189 extern struct buffer_head * bread (Int dev, int block);


4 // read buffer memory at the specified address.
190 extern void bread_page (Unsigned long addr, int dev, int b [4]);
// read head a specified data block and the subsequent block tag to be read.

191 extern struct buffer_head * breada (Int dev, int block, ...);
// apply a disk block (sector, logical blocks) to device dev. Returns the logical block number

192 extern int new_block (Int dev);


// release in the data area of ​the logical block (sector disk block) block. Reset logic block specified logical block block bitmap bits.

193 extern void free_block (Int dev, int block);


// Create a new i-node for the device dev, return to the i-node number.

194 extern struct m_inode * new_inode (Int dev);


// i release a node (when deleting files).
195 extern void free_inode (Struct m_inode * Inode); // refresh the specified device
buffer.
196 extern int sync_dev (Int dev);
// read the specified device superblock.

197 extern struct super_block * get_super (Int dev);


198 extern int ROOT_DEV ;
199
// install the root file system.

200 extern void mount_root (Void);


201202 #endif

203

--522--
11.25 hdreg.h file

11.25 hdreg.h file

11.25.1 Functional Description

11.25.2 Code comments

program 11-21 linux / include / linux / hdreg.h

1/*
2 * This file contains some defines for the AT-hd-controller.
3 * Various sources. Check out some definitions (see comments with
4 * A ques).
5*/
/*
* This document contains a number of definitions AT hard disk controllers. From a variety of materials. Please verify certain

* Defined (note with a question mark).

*/
6 #ifndef _HDREG_H 7 #define _HDREG_H 8 9 / * Hd controller regs Ref:. IBM AT
Bios-listing * /

/ * Hard disk controller port registers. See: IBM AT Bios program * /


10 #define HD_DATA 0x1f0 / * _CTL when writing * /
11 #define HD_ERROR 0x1f1 / * See err-bits * /
12 #define HD_NSECTOR 0x1f2 / * Nr of sectors to read / write * /
13 #define HD_SECTOR 0x1f3 / * Starting sector * /
14 #define HD_LCYL 0x1f4 / * Starting cylinder * /
15 #define HD_HCYL 0x1f5 / * High byte of starting cyl * /
16 #define HD_CURRENT 0x1f6 / * 101dhhhh, d = drive, hhhh = head * /
17 #define HD_STATUS 0x1f7 / * See status-bits * /
18 #define HD_PRECOMP HD_ERROR / * Same io address, read = error, write = precomp * /
19 #define HD_COMMAND HD_STATUS / * Same io address, read = status, write = cmd * /
2021 #define HD_CMD
0x3f6 // port control register.
2223 / * Bits of HD_STATUS * /

/ * Disk Status register bit definitions (HD_STATUS) * /


twenty four #define ERR_STAT 0x01 // command execution error.

25 #define INDEX_STAT 0x02 // received index.


26 #define ECC_STAT 0x04 / * Corrected error * / // ECC parity error.
27 #define DRQ_STAT 0x08 // request service.
28 #define SEEK_STAT 0x10 // seek an end.
29 #define WRERR_STAT 0x20 // drive failure.
30 #define READY_STAT 0x40 // drive ready (ready).
31 #define BUSY_STAT 0x80 // controller busy.
3233 / * Values ​for HD_COMMAND * /

/ * Hard disk command value (HD_CMD) * /

34 #define WIN_RESTORE 0x10 // drive recalibrate (driver reset).


35 #define WIN_READ 0x20 // Read Sector.

--523--
11.25 hdreg.h file

36 #define WIN_WRITE 0x30 // write sectors.


37 #define WIN_VERIFY 0x40 // sector inspection.
38 #define WIN_FORMAT 0x50 // Format Track.
39 #define WIN_INIT 0x60 // initialize the controller.
40 #define WIN_SEEK 0x70 // seek.
41 #define WIN_DIAGNOSE 0x90 // controller diagnostics.
42 #define WIN_SPECIFY 0x91 // establish drive parameters.
4344 / * Bits for HD_ERROR * /

Each bit of the / * Error Register Meaning (HD_ERROR) * /


// perform different meaning when other command controller diagnostic commands. The following are listed: //

=========================================== ======= //

When the diagnosis command When other commands

// ------------------------------------------------ - // 0x01
No error Data loss mark
// 0x02 Controller error Wrong track 0

// 0x03 Sector Buffer wrong


// 0x04 ECC wrong parts Give up command

// 0x05 Control processor error

// 0x10 ID not found


// 0x40 ECC error
// 0x80 Bad sector

// ------------------------------------------------ ---
45 #define MARK_ERR 0x01 / * Bad address mark? * /
46 #define TRK0_ERR 0x02 / * Could not find track 0 * /
47 #define ABRT_ERR 0x04 / *? * /
48 #define ID_ERR 0x10 / *? * /
49 #define ECC_ERR 0x40 / *? * /
50 #define BBD_ERR 0x80 / *? * /
51
// hard disk partition table structure. See the following list information.

52 struct partition {
53 unsigned char boot_ind; / * 0x80 - active (unused) * /
54 unsigned char head ; / *? * /
55 unsigned char sector ; / *? * /
56 unsigned char cyl; / *? * /
57 unsigned char sys_ind; / *? * /
58 unsigned char end_head; / *? * /
59 unsigned char end_sector; / *? * /
60 unsigned char end_cyl; / *? * /
61 unsigned int start_sect; / * Starting sector counting from 0 * /
62 unsigned int nr_sects; / * Nr of sectors in partition * /
63 };
6465 #endif

66

11.25.3 Other Information

11.25.3.1 Hard disk partition table

In order to realize a plurality of operating systems to share resources hard disk, the hard disk can be logically divided into 1--4 Partitions. Between the sector number of

each partition are contiguous. The partition table 4 Table entries, each entry is made 16 Byte, information corresponding to a partition, partition size and storing the cylinder

number, track number and sector number of the start and end, Table 11-2 Fig. Stored in the hard disk's partition table 0 cylinder 0 Head first 1 Sectors

--524--
11.26 head.h file

0x1BE - 0x1FD Place.

table 11-2 Hard disk partition table structure

position name Size Description

0x00 boot_ind byte Boot flags. 4 Partition at the same time only one partition is bootable.
0x00- Not boot the operating system from the partition; 0x80- Operating system from the boot partition.

0x01 head byte Partition start head number.

0x02 sector byte Partition start sector number (bits 0-5) And high starting cylinder number 2 Bit (Bit 6-7) .

0x03 cyl byte Low partition start cylinder number 8 Bit.

0x04 sys_ind byte Partition type byte. 0x0b-DOS; 0x80-Old Minix; 0x83-Linux ...

0x05 end_head byte The end of the head number of the partition.

0x06 end_sector byte End sector number (bits 0-5) And high-end cylinder number 2 Bit (Bit 6-7) .

0x07 end_cyl byte Low end cylinder number 8 Bit.

0x08--0x0b start_sect Long word Partition start physical sector number.

0x0c - 0x0f nr_sects Long word The number of sectors occupied by partitions.

11.26 head.h file

11.26.1 Functional Description

head Header files, define Intel CPU Simple structure descriptor, and the descriptor entry number specified.

11.26.2 Code comments

program 11-22 linux / include / linux / head.h

1 #ifndef _HEAD_H 2 #define _HEAD_H 3 4 typedef


struct desc_struct {

// define data structures segment descriptor. The structure described only each description

5 unsigned long a, b; // operator is composed of 8 bytes, a total of each descriptor table 256.

6 } desc_table [256];
78 extern unsigned long pg_dir [1024]; // array of memory pages directory. Each directory entry is 4 bytes. Starting from the physical address 0.

9 extern desc_table idt , gdt ; // interrupt descriptor table, GDT.


1011 #define GDT_NUL 0
0 // Global description of the symbol table, do not.

12 #define GDT_CODE 1 // Item 1, is the kernel code segment descriptor entry.

13 #define GDT_DATA 2 // Item 2, the kernel data segment descriptor entry.

14 #define GDT_TMP 3 // item 3, the system segment descriptors, Linux is not used.

1516 #define LDT_NUL 0


// each local descriptor table of 0, no.
17 #define LDT_CODE 1 // Item 1, user program code segment descriptor entry.

18 #define LDT_DATA 2 // Item 2, the program is user data segment descriptor entry.

1920 #endif

--525--
11.27 kernel.h file

twenty one

11.27 kernel.h file

11.27.1 Functional Description

It defines some commonly used kernel function prototypes and so on.

11.27.2 Code comments

program 11-23 linux / include / linux / kernel.h

1/*
2 * 'Kernel.h' contains some often-used function prototypes etc
3*/
/*
* 'Kernel.h' defines some common functions like prototype.
*/
// verify whether a given block of memory addresses starting overrun. If the additional memory overrun. (Kernel / fork.c, 24).

4 void verify_area (Void * addr, int count );


// display the kernel error message, and then enter an infinite loop. (Kernel / panic.c, 16).

5 volatile void panic (Const char * str ); // standard print (display) function. (Init /
main.c, 151).
6 int printf (Const char * fmt, ...);
// kernel dedicated print information function, function printf () the same. (Kernel / printk.c, 21).
7 int printk (Const char * fmt, ...);
// to specify the length of the string tty write. (Kernel / chr_drv / tty_io.c, 290).
8 int tty_write (Unsigned ch, char * buf , Int count ); // common core memory
allocation functions. (Lib / malloc.c, 117).
9 void * malloc (Unsigned int size);
// release the memory occupied by the specified object. (Lib / malloc.c, 182).

10 void free_s (Void * obj, int size);


1112 #define free ( x ) free_s (( x ), 0)

1314 / *

15 * This is defined as a macro, but at some point this might become a


16 * Real subroutine that sets a flag if it returns true (to do
17 * BSD-style accounting where the process is flagged if it uses root
18 * Privs). The implication of this is that you should do normal
19 * Permissions checks first, and check suser () last.
20 * /
/*
* The following functions are defined as macros, but in some ways it can be a real routine,
* If the return is that it will set a flag (if using root user privileges process flag is set to true, then use
* BSD to perform accounting processing mode). This means that you should first check the permissions to perform routine, and finally

* Detection suser ().


*/
twenty one #define suser () ( current -> euid == 0) // detect whether a super user.

--526--
11.28 mm.h file

2223

11.28 mm.h file

11.28.1 Functional Description

mm.h Memory management is the header file. Which defines the main memory page size and page release several function prototypes.

11.28.2 Code comments

program 11-24 linux / include / linux / mm.h

1 #ifndef _MM_H 2 #define _MM_H 3 4 #define


PAGE_SIZE 4096

// define the size of the memory page (in bytes).

5
// get free pages function. Return page address. Scanning the mem_map page mapping array [] get free pages.

6 extern unsigned long get_free_page (Void);


// placed in a physical page at the specified address. Specify the page to place the information in the page directory and page tables.

7 extern unsigned long put_page (Unsigned long page, unsigned long address);
// release a physical page of memory address addr began. Modify page mapping array mem_map [] in reference to the number of information.

8 extern void free_page (Unsigned long addr);


910 #endif

11

11.29 sched.h file

11.29.1 Functional Description

Scheduler header file that defines the task structure task_struct The initial task 0 Data, there are some relevant descriptors parameter set and get embedded assembly

function macro statement.

11.29.2 Code comments

program 11-25 linux / include / linux / sched.h

1 #ifndef _SCHED_H 2 #define _SCHED_H


3 4 #define NR_TASKS 64

// system up to the number of tasks (processes) at the same time.

5 #define HZ 100 // Define frequency of the system clock ticks (1 million Hertz, each tick 10ms)

67 #define FIRST_TASK task [0]


0 // task is rather special, so he gave it to define a single symbol.
8 #define LAST_TASK task [ NR_TASKS -1] // The final task in the task array.
910 #include <linux / head.h>
// head header file defines a simple structure segment descriptors, and several selectors constants.

--527--
11.29 sched.h file

11 #include <linux / fs.h> // file system header files. Table structure definition file (file, buffer_head, m_inode, etc.).
12 #include <linux / mm.h> // memory management header files. It contains the defined page size and page number of the release function prototypes.

13 #include <signal.h> // signal header files. Defined symbolic constant signal, the signal structure and the operation function prototype signal.

1415 #if ( NR_OPEN > 32)

16 #error " Currently the close-on-exec-flags are in one word, max 32 files / proc "
17 #endif
18
// This defines the state of the process may be run at.

19 #define TASK_RUNNING 0 // process is running or ready.


20 #define TASK_INTERRUPTIBLE 1 // process in an interruptible wait state.
twenty one #define TASK_UNINTERRUPTIBLE 2 // process is in an uninterruptible wait state, mainly for I / O operations to wait.

twenty two #define TASK_ZOMBIE 3 // process dead in the state, has stopped running, but the parent process has not signaled.

twenty three #define TASK_STOPPED 4 // The process has stopped.

2425 #ifndef NULL 26 #define NULL ((Void *) 0)

// NULL is defined as a null pointer.

27 #endif
28
// page directory page table replication process. Linus kernel think this is one of the most complex functions. (Mm / memory.c, 105)

29 extern int copy_page_tables (Unsigned long from, unsigned long to, long size);
// release the page table designated memory block and page table itself. (Mm / memory.c, 150)

30 extern int free_page_tables (Unsigned long from, unsigned long size);


31
// initialization function dispatcher. (Kernel / sched.c, 385)
32 extern void sched_init (Void);
// process scheduling function. (Kernel / sched.c, 104)
33 extern void schedule (Void);
// an exception (trap) interrupt handler initialization function sets the interrupt call gate and allow the interrupt request signal. (Kernel / traps.c, 181)

34 extern void trap_init (Void);


// display the kernel error message, and then enter an infinite loop. (Kernel / panic.c, 16).

35 extern void panic (Const char * str );


// to specify the length of the string tty write. (Kernel / chr_drv / tty_io.c, 290).
36 extern int tty_write (Unsigned minor, char * buf , Int count );
3738 typedef int (* fn_ptr ) ();
I // define the function pointer type.

39
// Here is the structure of a math coprocessor used mainly for the implementation of state i387 information when you save the process of switching.

40 struct i387_struct {
41 long cwd; // Control Word (Control word).
42 long swd; // Status word (Status word).
43 long twd; // marker word (Tag word).
44 long fip; // coprocessor code pointers.
45 long fcs; // coprocessor code segment register.

46 long foo; // offset memory operand.


47 long fos; // value of the segment memory operation.

48 long st_space [20]; / * 8 * 10 bytes for each FP-reg = 80 bytes * /


49 }; 10 // 8-byte accumulator coprocessor.
50
// task state segment data structure (TSS information see the list).
51 struct tss_struct {
52 long back_link; / * 16 high bits zero * /
53 long esp0;

--528--
11.29 sched.h file

54 long ss0; / * 16 high bits zero * /


55 long esp1;
56 long ss1; / * 16 high bits zero * /
57 long esp2;
58 long ss2; / * 16 high bits zero * /
59 long cr3;
60 long eip;
61 long eflags;
62 long eax, ecx, edx, ebx;
63 long esp;
64 long ebp;
65 long esi;
66 long edi;
67 long es; / * 16 high bits zero * /
68 long cs; / * 16 high bits zero * /
69 long ss; / * 16 high bits zero * /
70 long ds; / * 16 high bits zero * /
71 long fs; / * 16 high bits zero * /
72 long gs; / * 16 high bits zero * /
73 long ldt; / * 16 high bits zero * /
74 long trace_bitmap; / * Bits: trace 0, bitmap 16-31 * /
75 struct i387_struct i387;
76 };
77
// This is the task (process) data structure, otherwise known as the process descriptor. //

========================== // long state

Running status (-1 inoperable, 0 to run (Ready)> 0 is stopped).


// long counter Task running time count (decrement) (ticks), run time slice.
// long priority Run priority number. When the task starts running counter = priority, the greater the long run.

// long signal signal. Bitmap, each bit represents a signal, the signal value of the bit offset value = +1.

// struct sigaction sigaction [32] and the operation execution flag signal information attribute structure, a corresponding signal will be executed. // long blocked

Process mask signal (signal corresponding to the bit map).

// ------------------------- // int exit_code


Task exit code execution stops, the parent process will take.

// unsigned long start_code code segment address. // unsigned long end_code The code length
(number of bytes). // unsigned long end_data Code length + data length (number of bytes). //
unsigned long brk
Total length (number of bytes).

Stack segment // unsigned long start_stack address. // long pid


Process identification number (process ID).

// long father Parent process ID.

// long pgrp Parent group number.

// long session Session number.

// long leader Session leader.

// unsigned short uid User identification number (user id).

// unsigned short euid Effective user id.


// unsigned short suid Saved user id.
// unsigned short gid Group ID (group id).
// unsigned short egid Effective group id.

// unsigned short sgid Save the group id.

// long alarm Alarm timer value (number of ticks).

// long utime User mode run time (ticks).


// long stime Run-time system state (ticks).

--529--
11.29 sched.h file

// long cutime Sub-user mode processes run time.

// long cstime Child process state system uptime.

// long start_time Process starts running time.

// unsigned short used_math flag: whether to use a coprocessor. // ------------------------- //


int tty
Tty process uses sub-device number. -1 indicates no use.
// unsigned short umask Create a file attribute mask bits.

// struct m_inode * pwd The current working directory i-node structure.

// struct m_inode * root I root node structure.


// struct m_inode * executable file execute i-node structure.
Close the file handle bitmap flag execute // unsigned long close_on_exec. (See include / fcntl.h) // File Table Structure struct file *
filp [NR_OPEN] used by the process. // --------------------------

// struct desc_struct ldt [3] local descriptor table of the present task. 0- empty, 1- snippet cs, 2- data and stack segments ds & ss. //
------------------------- // struct tss_struct tss
TSS information structure in this process.

// ==========================
78 struct task_struct {
79 / * These are hardcoded - do not touch * /
80 long state ; / * -1 unrunnable, 0 runnable,> 0 stopped * /
81 long counter;
82 long priority;
83 long signal;
84 struct sigaction sigaction [32];
85 long blocked; / * Bitmap of masked signals * /
86 / * Various fields * /
87 int exit_code;
88 unsigned long start_code, end_code, end_data, brk , Start_stack;
89 long pid, father, pgrp, session, leader;
90 unsigned short uid, euid, suid;
91 unsigned short gid, egid, sgid;
92 long alarm ;
93 long utime , stime , Cutime, cstime, start_time;
94 unsigned short used_math;
95 / * File system info * /
96 int tty; / * -1 if no tty, so it must be signed * /
97 unsigned short umask ;
98 struct m_inode * Pwd;
99 struct m_inode * Root;
100 struct m_inode * Executable;
101 unsigned long close_on_exec;
102 struct file * Filp [ NR_OPEN ];
103 / * Ldt for this task 0 - zero 1 - cs 2 - ds & ss * /
104 struct desc_struct ldt [3];
105 / * Tss for this task * /
106 struct tss_struct tss;
107 };
108109 / *

110 * INIT_TASK is used to set up the first task table, touch at


111 * Your own risk !. Base = 0, limit = 0x9ffff (= 640kB)
112 * /
/*

--530--
11.29 sched.h file

* INIT_TASK The first task for setting the table, if you want to modify your own risk ☺ !
* Base Address Base = 0, segment length limit = 0x9ffff (= 640kB).

*/
// correspondence information of the first task of the task structure above.

113 #define INIT_TASK \


114 / * State etc * / { 0,15,15, \ // state, counter, priority
115 / * Signals * / 0 {{}}, 0, \ // signal, sigaction [32], blocked
116 / * Ec, brk ... * / 0,0,0,0,0,0, \ // exit_code, start_code, end_code, end_data, brk, start_stack
117 / * Pid etc .. * / 0, -1,0,0,0, \ // pid, father, pgrp, session, leader
118 / * Uid etc * / 0,0,0,0,0,0, \ // uid, euid, suid, gid, egid, sgid
119 / * Alarm * / 0,0,0,0,0,0, \ // alarm, utime, stime, cutime, cstime, start_time
120 / * Math * / 0\ // used_math
121 / * Fs info * / - 1,0022, NULL , NULL , NULL , 0, \ // tty, umask, pwd, root, executable, close_on_exec
122 / * Filp * / { NULL ,}, \ // filp [20]
123 {\ // ldt [3]
124 {0,0}, \
125 / * Ldt * / {0x9f, 0xc0fa00}, \ // code length 640K, base address 0x0, G = 1, D = 1, DPL = 3, P = 1 TYPE = 0x0a
126 {0x9f, 0xc0f200}, \ // data length 640K, base address 0x0, G = 1, D = 1, DPL = 3, P = 1 TYPE = 0x02
127 }\
128 / * Tss * / { 0 PAGE_SIZE + (Long) & init_task , 0x10,0,0,0,0, (long) & pg_dir , \ // tss
129 0,0,0,0,0,0,0,0, \
130 0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
131 _LDT (0), 0x80000000, \
132 {} \
133 }\
134 }
135 136 extern struct task_struct * task [ NR_TASKS ];
// array of tasks.
137 extern struct task_struct * last_task_used_math ; // on a process of co-processor used.
138 extern struct task_struct * current ; // current process structure pointer variable.

139 extern long volatile jiffies ; // ticks begin to run from the boot of (10ms / tick).
140 extern long startup_time ; // boot time. 0:: 0: 0 Number of seconds from the start time of 1970.

141142 #define CURRENT_TIME ( startup_time + jiffies / HZ ) // current time (in seconds).

143
// add a timer function (regular time jiffies ticks, call the function * fn () when the timer expires). (Kernel / sched.c, 272)
144 extern void add_timer (Long jiffies , Void (* fn) (void)); // wait for uninterruptible sleep.
(Kernel / sched.c, 151)
145 extern void sleep_on (Struct task_struct ** p); // wait interruptible sleep.
(Kernel / sched.c, 167)
146 extern void interruptible_sleep_on (Struct task_struct ** p); // clear wake-sleep process. (Kernel /
sched.c, 188)
147 extern void wake_up (Struct task_struct ** p);
148 149 /
*
150 * Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
151 * 4-TSS0, 5-LDT0, 6-TSS1 etc ...
152 * /
/*
* Find the first entry in a TSS global table. 0 - no use nul, 1- snippet cs, 2- segment ds, 3- syscall system segment
* 4- TSS TSS0,5- local table LTD0,6- task state segment TSS1, and the like.
*/
// global table of a task state segment (TSS) descriptor selector index.

--531--
11.29 sched.h file

153 #define FIRST_TSS_ENTRY 4


// global table of a local descriptor table (the LDT) selector index descriptor.
154 #define FIRST_LDT_ENTRY ( FIRST_TSS_ENTRY +1)
// macro definition, the global table is calculated in n-th task TSS descriptor index (selectors).
155 #define _TSS (N) ((((unsigned long) n) << 4) + ( FIRST_TSS_ENTRY << 3))
// macro definition, is calculated in the global table of the n tasks LDT described index breaks.

156 #define _LDT (N) ((((unsigned long) n) << 4) + ( FIRST_LDT_ENTRY << 3))
// macro definition, loading task register tr n-th task.
157 #define ltr (N) __asm ​__ ( " ltr %% ax "::" a "( _TSS (N-)))
// macro definition, Local Descriptor Table Register loading ldtr n-th task.
158 #define lldt (N) __asm ​__ ( " lldt %% ax "::" a "( _LDT (N-)))
// get the current task number to run the task (task array index value, unlike the process number pid). // returns: n -
the current task number. For (kernel / traps.c, 79).
159 #define str (N) \
160 __asm ​__ ( " str %% ax \ n \ t "\ // register the task effectively address TSS segment ax

161 "Subl% 2, %% eax \ n \ t" \ // (eax - FIRST_TSS_ENTRY * 8) eax


162 "Shrl $ 4, %% eax" \ // (eax / 16) eax = current task number.
163 : "= a "( n) \
164 : " a "( 0), " i "( FIRST_TSS_ENTRY << 3))
165 / *
166 * switch_to (n) should switch tasks to task nr n, first
167 * Checking that n is not the current task, in which case it does nothing.
168 * This also clears the TS-flag if the task we switched to has used
169 * Tha math co-processor latest.
170 * /
/*
* switch_to (n) to switch the current task to the task nr, i.e., n. First detection task n is not the current task,
* If nothing is done to exit. If we switch to task recently (last run) using mathematics
* Coprocessor, then need to reset the control flag register cr0 of TS.
*/
// jump to a TSS for the task selected segment of the address specifier cause CPU task switching operation. // Input:%
0 - offset address (* & __ tmp.a);% 1 - store the new TSS selector; //
dx - n new task of TSS segment selector; ecx - new task pointers task [n].
// temporary data structures which form the operands for __tmp 177 lines far jump (far jump) instructions. The 4 by the operand address and byte offset // 2-byte segment

selector composition. Thus __tmp value in a 32-bit offset value and the lower 2 bytes b // selector (not higher 2 bytes) and the new TSS segment. Jump to TSS segment

selector will cause TSS task switch to the corresponding process. For cause long jump // task switching, a value is useless. Indirect jump instruction memory 177 on line

using a 6-byte operand as long pointer jump destination, // the format: jmp 16-bit segment selector: 32-bit offset. However, in a sequence number memory operation

opposite herein. // When the judge whether to perform a new task last used coprocessor is used to compare the task state segment address coprocessor by the new

task state segment addresses stored in the variable // last_task_used_math made, // see kernel / sched.c a function math_state_restore ().

171 #define switch_to (N) {\


172 struct {long a, b;} __tmp; \
173 __asm ​__ ( " cmpl %% ecx, _current \ n \ t "\ // n is the task of the current task right? (Current == task [n]?)

174 "Je 1f \ n \ t" \ // yes, nothing to do, quit.


175 "Movw %% dx,% 1 \ n \ t" \ // The new 16-bit task selector into __tmp.b in.
176 "Xchgl %% ecx, _current \ n \ t" \ // current = task [n]; ecx = the task is switched out.
177 "Ljmp% 0 \ n \ t" \ // CEO Jump to * & __ tmp, resulting in task switching. // will continue with the

following statement after the task switch back.

178 "Cmpl %% ecx, _last_task_used_math \ n \ t" \ // The new task coprocessor last used it?
179 "Jne 1f \ n \ t" \ // do not jump, quit.
180 "Clts \ n" \ // new tasks last used coprocessor, the cr0 clear signs of TS.
181 "1:" \

--532--
11.29 sched.h file

182 :: " m "(* & __ tmp.a), " m "(* & __ tmp.b), \


183 "D" ( _TSS (N)), " c "(( long) task [N-])); \
184 }
185
// address page aligned. (Nowhere in the kernel code references !!)
186 #define PAGE_ALIGN (N) (((n) + 0xfff) & 0xfffff000)
187
Located at address addr // description of the character in the group address field (base address base), see list described later. % // 0 - 2 offset address addr;%

1 - Address Offset 4 addr;% 2 - offset address addr 7; edx - base address base.

188 #define _set_base (Addr, base) \


189 __asm ​__ ( " movw %% dx,% 0 \ n \ t "\ // 16-bit base address of the lower base (bits 15-0) [addr + 2].

190 "Rorl $ 16, %% edx \ n \ t" \ // the high edx base address (bits 31-16) dx.
191 "Movb %% dl,% 1 \ n \ t" \ The high 16-bit base address // lower 8 bits (bits 23-16) [addr + 4].

192 "Movb %% dh,% 2" \ The high 16-bit base address // upper 8 bits (bits 31-24) [addr + 7].

193 :: " m "(* (( addr) +2)), \


194 "M" (* (( addr) +4)), \
195 "M" (* (( addr) +7)), \
196 "D" ( base) \
197 : " dx ")
198
// located at address addr described herein indefinite length identifier field in the segment (a segment length limit). % // 0 -

address addr;%. 1 - Address addr offset 6; edx - segment length value limit.

199 #define _set_limit (Addr, limit) \


200 __asm ​__ ( " movw %% dx,% 0 \ n \ t "\ // lower limit 16-bit section length (bits 15-0) [addr].
201 "Rorl $ 16, %% edx \ n \ t" \ // segment length edx upper four bits (bits 19-16) dl.

202 "Movb% 1, %% dh \ n \ t" \ // take the original [addr + 6] bytes dh, wherein these flags is four bits.

203 "Andb $ 0xf0, %% dh \ n \ t" \ Dh // clear the lower 4 bits (bit length of the stored segment 19-16).

204 "Orb %% dh, %% dl \ n \ t" \ // the high four original segment length flag and high-order 4 bits (bits 19-16) Synthesis of 1 byte,

205 "Movb %% dl,% 1" \ // and will put [addr + 6] office.

206 :: " m "(* ( addr)), \


207 "M" (* (( addr) +6)), \
208 "D" ( limit) \
209 : " dx ")
210
// set the base address field of the local descriptor table descriptor ldt.

211 #define set_base (Ldt, base) _set_base (((Char *) & (ldt)), base)
// Set segment length field ldt local descriptor table descriptor.

212 #define set_limit (Ldt, limit) _set_limit (((Char *) & (ldt)), (limit-1) >> 12)
213
Symbol // fetch the base address from the address addr of the description. Functions and _set_base () just the opposite.

// edx - storage base address (__base);% 1 - 2 offset address addr;% 2 - offset address addr 4;% 3 - addr offset 7.
214 #define _get_base (Addr) ({\
215 unsigned long __base; \
216 __asm ​__ ( " movb% 3, %% dh \ n \ t "\ // get [addr + 7] at a high 16-bit base address of the upper 8 bits (bits 31-24) dh.

217 "Movb% 2, %% dl \ n \ t" \ // get [addr + 4] of the base address of the lower 8-bit high-order 16 bits (bits 23-16) dl.

218 "Shll $ 16, %% edx \ n \ t" \ @ 16 is shifted to the high base address edx high at 16.

219 "Movw% 1, %% dx" \ // get [addr + 2] of the base address of the lower 16 bits (bits 15-0) dx.

220 : "= d "(__ base) \ // edx thus contained 32-bit segment base address.

221 : " m "(* (( addr) +2)), \


222 "M" (* (( addr) +4)), \
223 "M" (* (( addr) +7))); \
224 __base;})
225

--533--
11.29 sched.h file

// get the local descriptor table descriptor base address indicated ldt of.

226 #define get_base (Ldt) _get_base (((Char *) & (ldt)))


227
// get selected segment length limit values ​specified segment identifier segment descriptor.

// Load Segment Limit command lsl is abbreviated. It is removed from the dispersion indefinite length designated segment descriptor bit segment makes up the complete // indefinite

length value into the designated register. The resulting long segment limit is 1 minus the actual number of bytes, so there is also a need to increase before returning. % // 0 - value

storing section length (number of bytes);% 1-- segment selector segment.

228 #define get_limit (Segment) ({\


229 unsigned long __limit; \
230 __asm ​__ ( " lsll% 1,% 0 \ n \ tincl% 0 ":" = r "(__ limit): " r "( segment)); \
231 __limit;})
232 233 #endif

234

11.29.3 Other Information

11.29.3.1 Task State Segment information

31 twenty three 15 7 0

I / O Map base address ( MAP BASE) 0,000,000,000,000,000 64

0,000,000,000,000,000 Local Descriptor Table ( LDT) Selector 60

0,000,000,000,000,000 GS 5C

0,000,000,000,000,000 FS 58

0,000,000,000,000,000 DS 54

0,000,000,000,000,000 SS 50

0,000,000,000,000,000 CS 4C

0,000,000,000,000,000 ES 48

EDI 44

ESI 40

EBP 3C

ESP 38

EBX 34

EDX 30

ECX 2C

EAX 28

EFLAGS twenty four

Instruction pointer ( EIP) 20

Page directory base address register CR3 ( PDBR ) 1C

0,000,000,000,000,000 SS2 18

ESP2 14

0,000,000,000,000,000 SS1 10

ESP1 0C

0,000,000,000,000,000 SS0 08

ESP0 04

--534--
12.9 malloc.c program

Bucket descriptor

free_bucket_desc page next page next page next page next


freeptr refcnt freeptr freeptr freeptr refcnt
bucketsize refcnt refcnt bucketsize
bucketsize bucketsize

Map 12-2 Idle bucket descriptor list structural diagram

malloc () The basic functions performed by the following steps:

1. First search the directory to find the corresponding directory entry for the requested descriptor linked list of memory block size. When the target byte length of directory entry

It is greater than the byte length of the request, even if found appropriate directory entry. If the search is complete directories have not found the right directory

entry, then the user requests a block of memory too much.

2. Find a free space having a descriptor in the directory entry corresponding descriptor list. If a free memory pointer descriptor

freeptr It is not NULL , It means to find the appropriate descriptor. If no descriptors have free space, then we need to create a new

descriptor. New process descriptor follows:

a. If the free list head pointer descriptor or NULL It indicates that the first call malloc () Function, this time need

init_bucket_desc () To create a free descriptor list.

b. Then take a descriptor from the free descriptor at the head of the list, initializes the descriptor, object reference count is allowed to 0 Objects

Size is equal to a value corresponding to the length of the directory entry of the specified object, and apply a memory page, so page pointer descriptor page Pointing

to the memory page descriptor pointer free memory freeptr Also pointing to the page start position.

c. According to the catalog entry for page initialization used memory object length of the page, to create a list of all objects. and also

I.e., the head of each object are stored a pointer pointing to the next object, beginning at the last object in a storage

NULL Pointer value.

d. The descriptor is then inserted into the descriptor list corresponding to the beginning of the directory entry.

3. The free memory pointer descriptor freeptr Replication is returned to the user memory pointer, then adjusting the freeptr Pointing Description

Character corresponding to the next free page memory object position, and the reference count by descriptor 1 .

free_s () Function is used to recover the user releases the memory block. The basic principle is first converted from the address of the memory block corresponding to the

memory block address of the page (the page length modulo operation performed by), and then searches all directory descriptors, descriptors should find the page. The released

memory block links freeptr The free list pointed to the object, and the object descriptor reference count Save 1 . At this time, if the reference count is equal to zero, it indicates that

the descriptor corresponding to the page has been completely vacated, the memory can be released and the page descriptor is retracted to the free descriptor list.

12.9.2 Code comments

program 12-8 linux / lib / malloc.c

1/*
2 * Malloc.c --- a general purpose kernel memory allocator for Linux.
3*
4 Written by Theodore Ts'o * ( [email protected] ), 11/29/91
5*
6 * This routine is written to be as fast as possible, so that it
7 * Can be called from the interrupt level.
8*
9 * Limitations: maximum size of memory we can allocate using this routine
10 * is 4k, the size of a page in Linux.

555
12.9 malloc.c program

11 *
12 * The general game plan is that each page (called a bucket) will only hold
13 * Objects of a given size. When all of the object on a page are released,
14 * The page can be returned to the general free pool. When malloc () is
15 * Called, it looks for the smallest bucket size which will fulfill its
16 * Request, and allocate a piece of memory from that bucket pool.
17 *
18 * Each bucket has as its control block a bucket descriptor which keeps
19 * Track of how many objects are in use on that page, and the free list
20 * For that page. Like the buckets themselves, bucket descriptors are
twenty one * Stored on pages requested from get_free_page (). However, unlike buckets,
twenty two * Pages devoted to bucket descriptor pages are never released back to the
twenty three * System. Fortunately, a system should probably only need 1 or 2 bucket
twenty four * Descriptor pages, since a page can hold 256 bucket descriptors (which
25 * Corresponds to 1 megabyte worth of bucket pages.) If the kernel is using
26 * That much allocated memory, it's probably doing something wrong. :-)
27 *
28 * Note: malloc () and free () both call get_free_page () and free_page ()
29 * in sections of code where interrupts are turned off, to allow
30 * malloc () and free () to be safely called from an interrupt routine.
31 * (We will probably need this functionality when networking code,
32 * particularily things like NFS, is added to Linux.) However, this
33 * presumes that get_free_page () and free_page () are interrupt-level
34 * safe, which they may not be once paging is added. If this is the
35 * case, we will need to modify malloc () to keep a few unused pages
36 * "Pre-allocated" so that it can safely draw upon those pages if
37 * it is called from an interrupt routine.
38 *
39 * Another concern is that get_free_page () should not sleep; if it
40 * does, the code is carefully ordered so as to avoid any race
41 * conditions. The catch is that if malloc () is called re-entrantly,
42 * there is a chance that unecessary pages will be grabbed from the
43 * system. Except for the pages for the bucket descriptor page, the
44 * extra pages will eventually get released back to the system, though,
45 * so it is not all that bad.
46 * /
47
/*
* malloc.c - Linux generic kernel memory allocation functions.

*
* Compiled by the Theodore Ts'o ( [email protected] ), 11/29/91
*
* The function is written as soon as possible, so you can call this function from the fault.

*
* Restrictions: Using this function can be assigned a maximum memory is 4k, namely the size of the Linux memory pages.

*
* Preparing the general rule is followed by the function page (called a bucket) assigned to only the size of the object to be accommodated.

* When all objects on a page are released, this page will be returned universal free memory pool. When malloc () is called

* When it looks for the smallest of buckets to meet the requirements, and allocate a chunk of memory from the bucket.

*
* Each bucket has a control as a bucket descriptor, which records the page number has an object being
* Use and a list of free memory on this page. The same as its own bucket, bucket descriptor is stored in the usage
* that get_free_page () on the page to apply, but with a different bucket, the bucket descriptor is occupied by page

556
12.9 malloc.c program

* It will no longer be released to the system. Fortunately, only about a system bucket descriptor page 1-2, because a
* Pages 256 can store descriptors buckets (buckets corresponding to 1MB of memory pages). If the system is a bucket descriptor points

* With a lot of memory, so be sure what went wrong system ☺ .


*
* note! malloc () and free () both closed the interrupt code sections are called get_free_page () and
* free_page () function, so that malloc () and free () can safely be called from an interrupt routine

* (When the network code, it may be necessary in particular when this function is added to the NFS, etc. Linux). But before

* Mentioning the assumption get_free_page () and free_page () can be safely used in the interrupt level program,

* This once the addition of paging through it may not be safe. If this is the case, then we
* You need to modify malloc () to "pre-allocated" a few pages of unused memory, if malloc () and free ()

* You can safely use these pages when it is called from an interrupt routine.

*
* Another consideration is to get_free_page () should not sleep; if it will sleep, then in order to prevent
* Any competitive conditions, the code needs to be carefully arranged order. The key is that if malloc () can be reentrant

* Is called, then it will have a chance to unnecessary page is removed from the system. In addition to describing barrel

* Fu pages, these additional pages will eventually be released to the system, so it is not as bad as imagined.

*/

48 #include <linux / kernel.h> // kernel headers. It contains some common prototype custom kernel function.

49 #include <linux / mm.h> // memory management header files. It contains the defined page size and page number of the release function prototypes.

50 #include <asm / system.h> // system header files. Set or modify the defined descriptors / interrupt gate or the like embedded macro assembler.

51
// bucket descriptor structure.
52 struct bucket_desc { / * 16 bytes * /
53 void * Page; // pointer to the memory page descriptor corresponding to the tub.

54 struct bucket_desc * Next; // pointer to the next descriptor.

55 void * Freeptr; // pointer to this free memory locations in the tub.

56 unsigned short refcnt; // reference count.


57 unsigned short bucket_size; // This descriptor corresponding to the size of the bucket.

58 };
59
// bucket descriptor directory structure.

60 struct _bucket_dir { / * 8 bytes * /


61 int size; // size of the bucket (number of bytes).

62 struct bucket_desc * Chain; The directory entry // bucket bucket list pointer descriptor.

63 };
6465 / *

66 * The following is the where we store a pointer to the first bucket


67 * Descriptor for a given size.
68 *
69 * If it turns out that the Linux kernel allocates a lot of objects of a
70 * Specific size, then we may want to add that specific size to this list,
71 * Since that will allow the memory to be allocated more efficiently.
72 * However, since an entire page must be dedicated to each specific size
73 * On this list, some amount of temperance must be exercised here.
74 *
75 * Note that this list * must * be kept in order.
76 * /
/*
* Here we are holding the first place given the size of the descriptor pointer of the bucket.

*
* If many objects of the specified size distribution of the Linux kernel, then we hope that this added to the specified size

557
12.9 malloc.c program

* The list (list), and because it allows more efficient allocation of memory. However, since a complete memory page
* The size of all the objects specified in the list must be used, it needs to be done to test the total number of operational aspects.

*/
// buckets directory listing (array).
77 struct _bucket_dir bucket_dir [] = {
78 {16, (Struct bucket_desc *) 0}, // Memory block 16 bytes in length.

79 {32, (Struct bucket_desc *) 0}, // memory block length of 32 bytes.

80 {64, (Struct bucket_desc *) 0}, // Memory block 64 bytes in length.

81 {128, (struct bucket_desc *) 0}, // memory block length of 128 bytes.

82 {256, (struct bucket_desc *) 0}, // memory block 256 bytes in length.

83 {512, (struct bucket_desc *) 0}, // memory block length of 512 bytes.

84 {1024, (struct bucket_desc *) 0}, // memory block length of 1024 bytes.

85 {2048, (struct bucket_desc *) 0}, // memory block length of 2048 bytes.

86 {4096, (struct bucket_desc *) 0}, // 4096 bytes (1) of memory.


87 {0, (Struct bucket_desc *) 0}}; / * End of list marker * /
8889 / *

90 * This contains a linked list of free bucket descriptor blocks


91 * /
/*
* The following is a list containing idle memory block descriptor of the tub.

*/
92 struct bucket_desc * free_bucket_desc = (Struct bucket_desc *) 0;
9394 / *

95 * This routine initializes a bucket description page.


96 * /
/*
* The following routine is used to initialize a bucket descriptor page.

*/
//// Initialization bucket descriptor.

// Create idle bucket descriptor list, and let free_bucket_desc points to the first empty bucket descriptor.

97 static inline void init_bucket_desc ()


98 {
99 struct bucket_desc * Bdesc, * first;
100 int i;
101
// apply a memory for storing the tub descriptor. If it fails, the display initialize barrels description is not enough memory error message during breaks, crashes.

102 first = bdesc = (struct bucket_desc *) get_free_page ();


103 if (! bdesc)
104 panic ( ' Out of memory in init_bucket_desc () ");
// first calculates the number of buckets descriptors can be stored in a memory, then subjected to establish a unidirectional connection pointer.

105 for (i = PAGE_SIZE / Sizeof (struct bucket_desc ); I> 1; i--) {


106 bdesc-> next = bdesc + 1;
107 bdesc ++;
108 }
109 /*
110 * This is done last, to avoid race conditions in case
111 * get_free_page () sleeps and this routine gets called again ....
112 */
/*
* This is the final process, the purpose is to avoid get_free_page () subroutine has been sleeping when the

* Call and competitive conditions caused.

558
12.9 malloc.c program

*/
// idle bucket descriptor pointer free_bucket_desc added to the list.
113 bdesc-> next = free_bucket_desc ;
114 free_bucket_desc = First;
115 }
116
//// dynamic memory allocation functions.

// Parameters: len - the length of the requested memory block.

// Returns: pointer to the allocated memory. If it fails it returns NULL.


117 void * malloc (Unsigned int len)
118 {
119 struct _bucket_dir * Bdir;
120 struct bucket_desc * Bdesc;
121 void * Retval;
122123
/*
124 * First we search the bucket_dir to find the right bucket change
125 * for this request.
126 */
/*
* First, we searched bucket bucket_dir directory to find the bucket size for the request.

*/
// search directory buckets, barrels descriptor list to find suitable application memory block size. If the number of barrels byte directory entry // is greater than the number of bytes requested, to

find the corresponding directory entry barrel.

127 for (bdir = bucket_dir ; Bdir-> size; bdir ++)


128 if (bdir-> size> = len)
129 break;
// If the search is complete directories have not found the appropriate size of a directory entry, it indicates that the memory block of the requested size is too large, beyond the limit

distribution of the // program (up to 1 page). Then an error message, crash.

130 if (! bdir-> size) {


131 printk ( ' malloc called with impossibly large argument (% d) \ n ",
132 len);
133 panic ( ' malloc: bad arg ");
134 }
135 /*
136 * Now we search for a bucket descriptor which has free space
137 */
/*
* Now we have to search the bucket descriptor free space.

*/
138 cli (); / * Avoid race conditions * / / * To avoid race conditions, first disable interrupts * /
// search for the corresponding directory entry in the bucket descriptor list, find the bucket descriptors have free space. If the bucket descriptor pointer // freeptr free memory is not

empty, it means to find the corresponding bucket descriptor.

139 for (bdesc = bdir-> chain; bdesc; bdesc = bdesc-> next)


140 if (bdesc-> freeptr)
141 break;
142 /*
143 * If we did not find a bucket with free space, then we'll
144 * allocate a new one.
145 */
/*
* If you do not find a bucket descriptors have free space, then we will establish a new descriptor of the directory entry.
*/

559
12.9 malloc.c program

146 if (! bdesc) {
147 char * Cp;
148 int i;
149
// If free_bucket_desc also empty, showing for the first time the program is called, then the descriptor list is initialized. // free_bucket_desc points

to the first empty bucket descriptor.

150 if (! free_bucket_desc )
151 init_bucket_desc ();
// points to take free_bucket_desc free bucket descriptor, and let free_bucket_desc point to the next free bucket descriptor.
152 bdesc = free_bucket_desc ;
153 free_bucket_desc = Bdesc-> next;
// initialize the new bucket descriptor. Make reference to a number equal to 0; bucket size equal to the corresponding size of the tub directory; application a memory page, the page descriptor //

make page pointer pointing to the page; free memory pointer also points to the beginning of the page, because the whole is in an idle .

154 bdesc-> refcnt = 0;


155 bdesc-> bucket_size = bdir-> size;
156 bdesc-> page = bdesc-> freeptr = (void *) cp = get_free_page ();
// allocate memory page if the operation fails, an error message is displayed, crash.

157 if (! cp)
158 panic ( ' Out of memory in kernel malloc () ");
159 / * Set up the chain of free objects * /
/ * Create a free object in the list of free memory in the page * /

// specified to the bucket size for the object directory entry barrel length, dividing the page in memory, and starts // 4 bytes is provided to point to the next pointer for each target

object.

160 for (i = PAGE_SIZE / Bdir-> size; i> 1; i--) {


161 * ((Char **) cp) = cp + bdir-> size;
162 cp + = bdir-> size;
163 }
// pointer is set at the beginning of the last object to 0 (NULL).

// then let the bucket descriptor next descriptor pointer field pointing to the corresponding directory entry pointer of the descriptor chain referred to in the tub, and the tub chain // directory

pointing to the bucket descriptor, the descriptor is about to be inserted into a descriptor chain head office.

164 * ((Char **) cp) = 0;


165 bdesc-> next = bdir-> chain; / * OK, link it in! * / / * OK, it links! * /
166 bdir-> chain = bdesc;
167 }
// returns a pointer to the descriptor is equal to the page corresponding to the current free pointer. Then adjust the free space a pointer to the next free object, the object reference symbol @

and described in the corresponding page count is incremented by one.

168 retval = (void *) bdesc-> freeptr;


169 bdesc-> freeptr = * ((void **) retval);
170 bdesc-> refcnt ++;
// finally break open, free memory and returns a pointer to an object pointer.

171 sti (); / * OK, we're safe again * / / * OK, now we are safe * /
172 return (retval);
173 }
174 175 /
*
176 * Here is the free routine. If you know the size of the object that you
177 * Are freeing, then free_s () will use that information to speed up the
178 * Search for the bucket descriptor.
179 *
180 * We will #define a macro so that "free (x)" is becomes "free_s (x, 0)"
181 * /
/*
* The following is a release subroutine. If you know the size of the object is released, the free_s () will use this information to accelerate

560
12.9 malloc.c program

* Search speed corresponds bucket descriptor.

*
* We will define a macro that "free (x)" becomes "free_s (x, 0)".
*/
//// release bucket objects.
// Parameters: obj - the object corresponding to the pointer; size - size.

182 void free_s (Void * obj, int size)


183 {
184 void * Page;
185 struct _bucket_dir * Bdir;
186 struct bucket_desc * bdesc, * prev;
187
188 / * Calculate what page this object lives in * /
/ * Calculate the page where the object * /

189 page = (void *) ((unsigned long) obj & 0xfffff000);


190 / * Now search the buckets looking for that page * /
/ * Now search for directory entries linked bucket bucket descriptor, find the page * / //

191 for (bdir = bucket_dir ; Bdir-> size; bdir ++) {


192 prev = 0;
193 / * If size is zero then this conditional is always false * /
/ * If the argument size is 0, the following conditions must be false * /

194 if (bdir-> size <size)


195 continue;
// search for the corresponding directory entries for all descriptors in the link, find the corresponding page. If a page descriptor is equal to said page pointer // find the appropriate descriptor,

jump to the found. If the descriptor does not contain the corresponding page, so that the descriptor pointer points to the descriptor prev.

196 for (bdesc = bdir-> chain; bdesc; bdesc = bdesc-> next) {


197 if (bdesc-> page == page)
198 goto found;
199 prev = bdesc;
200 }
201 }
// If the descriptor corresponding to the search of all catalog items are specified page not found, the error message is displayed, crash.

202 panic ( ' Bad address passed to kernel free_s () ");


203 found:
// find the corresponding bucket descriptor, first disable interrupts. Then the object into a free block of memory block chain in the object list, the object and symbol // description reference

count by 1.

204 cli (); / * To avoid race conditions * / / * To avoid race conditions * /


205 * ((Void **) obj) = bdesc-> freeptr;
206 bdesc-> freeptr = obj;
207 bdesc-> refcnt--;
// If the reference count is equal to 0, then we can release the corresponding memory page and the bucket descriptor.

208 if (bdesc-> refcnt == 0) {


209 /*
210 * We need to make sure that prev is still accurate. It
211 * may not be, if someone rudely interrupted us ....
212 */
/*
* We need to make sure prev is still correct, if a procedure rudely interrupted us
* It may not.
*/
// If the first descriptor of prev is not the search for a descriptor, then search again before the current descriptor is a descriptor.

213 if ((prev && (prev-> next! = bdesc)) ||

561
12.10 open.c program

214 (! Prev && (bdir-> chain! = Bdesc)))


215 for (prev = bdir-> chain; prev; prev = prev-> next)
216 if (prev-> next == bdesc)
217 break;
// If the preceding descriptor is found, the descriptor from the chain to remove the current descriptor.

218 if (prev)
219 prev-> next = bdesc-> next;
// if prev == NULL, then the current descriptor is the first directory entry descriptor, that directory entry directly // chain should point to the current descriptor bdesc, otherwise,

it indicates a problem with the list, the error message is displayed, crash. Thus, to the current descriptor // removed from the list, let the chain should point to the next

descriptor.

220 else {
221 if (bdir-> chain! = bdesc)
222 panic ( ' malloc bucket chains corrupted ");
223 bdir-> chain = bdesc-> next;
224 }
// release the current memory page descriptor operation, and the descriptor is inserted at the beginning of the free list descriptor.

225 free_page ((Unsigned long) bdesc-> page);


226 bdesc-> next = free_bucket_desc ;
227 free_bucket_desc = Bdesc;
228 }
// open break, return.
229 sti ();
230 return;
231 }
232
233

12.10 open.c program

12.10.1 Functional Description

open () System call is used to convert a file name into a file descriptor. When the call is successful, the file descriptor returned will be the process did not open the

minimum number of descriptors. The call creates a new open file, not shared with any other process. In execution

exec When the function, the new file descriptor will always maintained open. File read and write pointers at the beginning of a file are provided.

parameter flag Yes 0_RDONLY , O_WRONLY , O_RDWR One, representing a read-only file is opened, read and write and write-only open Open, it can

be used with other flags. (See fs / open.c , 138 Row)

12.10.2 Code comments

program 12-9 linux / lib / open.c

1/*
2 * Linux / lib / open.c
3*
4 * (C) 1991 Linus Torvalds
5*/
6

562
12.11 setsid.c program

7 #define __LIBRARY__ 8 #include


<unistd.h> // Linux standard header file. Symbols and constants defined type, and affirms that the various functions. // as defined __LIBRARY__, the

system call number and also contain embedded assembly _syscall0 () and the like.

9 #include <stdarg.h> // standard parameter header. In the form of macro variables defined parameter list. Mainly it described
- a type // (the va_list) and three macros (va_start, va_arg and va_end), for // vsprintf, vprintf, vfprintf
function.
10
//// open file functions.
// open and possibly create a file.
// Parameters: filename - file name; flag - File Open logo; ... // Returns: the file descriptor,
if the error is an error code is set, and returns -1.
11 int open (Const char * filename, int flag, ...)
12 {
13 register int res;
14 va_list arg;
15
// use va_start () macro function to obtain a pointer flag following the argument and then calling system interrupt int 0x80, // function performed open file open operation.

//% 0 - eax (or descriptor returned error code);% 1 - eax (interrupt system function call number __NR_open); //% 2 - ebx (file name filename);% 3 - ecx
(open file flag flag);% 4 - edx (parameter file with the attribute mode).
16 va_start (Arg, flag);
17 __asm ​__ ( " int $ 0x80 "
18 : "= a "( res)
19 : "" ( __NR_open ) " b "( filename), " c "( flag),
20 "D" ( va_arg (Arg, int)));
// interrupt system call returns a value greater than or equal to 0, which indicates that a file descriptor, then return it directly.

twenty one if (res> = 0)


twenty two return res;
// the return value is less than 0 otherwise described, it represents an error code. Set the error code and returns -1.

twenty three errno = -Res;


twenty four return -1;
25 }
26

12.11 setsid.c program

12.11.1 Functional Description

The program includes a setsid () System call function. If the calling process is not a group of leaders, this function is used to create a new session. The calling process will

be the leader of the new session, group leader of the new process group, and has no controlling terminal. The group calling process id

And session id It is set to process PID ( Process identifier). The calling process will be the only new process and new process group session.

12.11.2 Code comments

program 12-10 linux / lib / setsid.c

1/*
2 * Linux / lib / setsid.c
3*

563
12.12 string.c program

4 * (C) 1991 Linus Torvalds


5*/
67 #define __LIBRARY__ 8 #include
<unistd.h>
// Linux standard header file. Symbols and constants defined type, and affirms that the various functions. // as defined __LIBRARY__, the

system call number and also contain embedded assembly _syscall0 () and the like.

9
//// create a session and sets the process group number. // The following macro

corresponds to the system call function: pid_t setsid (). // returns: the calling process

session identifier (session ID).

10 _syscall0 ( pid_t , setsid )


11

12.12 string.c program

12.12.1 Functional Description

All string manipulation functions already string.h Implemented, and therefore string.c Program includes only string.h head File.

12.12.2 Code comments

program 12-11 linux / lib / string.c

1/*
2 * Linux / lib / string.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #ifndef __GNUC__
// need the GNU C compiler.
8 #error I want gcc!
9 #endif
1011 #define extern

12 #define inline
13 #define __LIBRARY__ 14 #include
<string.h>
15

12.13 wait.c program

12.13.1 Functional Description

The program includes a function waitpid () with wait () . These two functions allow a process to obtain the status of one of its child processes information. Various options

allow to obtain child process has been terminated or stopped status information. If there are two or more sub-process state information, the order of the report is not specified.

564
12.14 write.c program

wait () Suspends the current process until one of its child process exits (termination), or receiving a termination signal to the process or to call a signal handler (signal

handler) requirements.

waitpid () Suspends the current process until pid Specified child process exits (terminate) signal or receive to terminate the process, or the need to call a signal

handler (signal handler).

in case pid = -1 , options = 0 ,then waitpid () The role and wait () The same function. Otherwise, their behavior will vary pid with options They vary parameters. (See kernel

/ exit.c, 142 )

12.13.2 Code comments

program 12-12 linux / lib / wait.c

1/*
2 * Linux / lib / wait.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 #define __LIBRARY__ 8 #include
<unistd.h>
// Linux standard header file. Symbols and constants defined type, and affirms that the various functions. // as defined __LIBRARY__, the

system call number and also contain embedded assembly _syscall0 () and the like.

9 #include <sys / wait.h> // wait for the call header. The system defined call wait () and waitpid () and constants related symbols.

10
//// wait for its termination system calls.
// The following macro configuration corresponding to the function: pid_t waitpid (pid_t pid, int * wait_stat, int options) //

// Parameters: pid - waiting process is terminated process id, or for other special cases specified particular value; //
wait_stat - for storing status information; options - WNOHANG or WUNTRACED or 0.
11 _syscall3 ( pid_t , waitpid , pid_t , Pid, ​int *, wait_stat, int, options)
12
//// wait () system call. Direct call waitpid () function.
13 pid_t wait (Int * wait_stat)
14 {
15 return waitpid (-1, wait_stat, 0);
16 }
17

12.14 write.c program

12.14.1 Functional Description

The program includes a function to write a file descriptor write () . The function specified file is written to the file descriptor count Bytes of data to the buffer buf in.

12.14.2 Code comments

program 12-13 linux / lib / write.c

1/*

565
12.14 write.c program

2 * Linux / lib / write.c


3*
4 * (C) 1991 Linus Torvalds
5*/
67 #define __LIBRARY__ 8 #include
<unistd.h>
// Linux standard header file. Symbols and constants defined type, and affirms that the various functions. // as defined __LIBRARY__, the

system call number and also contain embedded assembly _syscall0 () and the like.

9
//// write file system calls.
// This macro configuration corresponding to the function: int write (int fd, const char * buf, off_t count) // Parameters: fd - file

descriptors; buf - the write buffer pointer; count - the number of bytes written.

// Return: Returns the number of bytes written (for write 0 bytes 0) success; -1 returns an error, and if the error number.

10 _syscall3 (Int, write , Int, fd, const char *, buf , off_t , count )
11

566
13.1 Overview

The first 13 Chapter build tool ( tools)

13.1 Outline

Linux Kernel source code tools Directory contains a utility to build the kernel disk image file build.c The individual program compiled executable in linux / Directory

Makefile Called file operation for connecting and merging all kernel code into compiled kernel image file that can be run image . The specific method is boot / middle bootsect.s

, setup.s use 8086 Compile assembler respectively generate respective execution module. Re-use of all other program source code GNU Compiler gcc / gas Compiling

and connected module system . Then use build These three tools are combined into a kernel image file image . Basic compiler connection

/ FIG combined structure 13-1 Fig.

head main kernel mm fs lib

bootsect setup system

Build Tools
Kernel image file

Image

Map 13-1 Compiling and linking the kernel / combined structure

13.2 build.c program

13.2.1 Functional Overview

build Program uses 4 Parameters, namely, bootsect file name, setup file name, system File name and an optional root file system device file name.

Program first checks the last root device filename optional parameter on the command line, if it exists, the state information of the device configuration file is read ( stat ),

Remove the device number. If it is not specified on the command line, the default value.

Then bootsect File is processed, read the file minix Performing header information, determine its validity, and then subsequently read

512 Code data bytes of the boot, it is determined whether the flag has a bootable 0xAA55 And the number in front of the acquired root device to write 508, 509,

567
13.2 build.c program

At the displacement, the final 512 Byte code data written to stdout Standard output, by the Make File redirects to Image file.

The next process in a similar manner setup file. If the file is smaller than 4 Sectors, with the 0 It is filled with 4 The length of the sectors, and writes to standard output stdout

in.

The last treatment system file. The file is to use GCC Produced by a compiler, so the header format is performed GCC Types, and linux

Defined a.out The same format. Execution entry point is determined 0 After data is written to standard output will stdout in. If the code data whose length exceeds 128KB , The error

message is displayed.

13.2.2 Code comments

program 13-1 linux / tools / build.c

1/*
2 * Linux / tools / build.c
3*
4 * (C) 1991 Linus Torvalds
5*/
67 / *

8 * This file builds a disk-image from three different files:


9*
10 * - bootsect: max 510 bytes of 8086 machine code, loads the rest
11 * - setup: max 4 sectors of 8086 machine code, sets up system parm
12 * - system: 80386 code for actual system
13 *
14 * It does some checking that all files are of the correct type, and
15 * Just writes the result to stdout, removing headers and padding to
16 * The right amount. It also writes some system data to stderr.
17 * /
/*
* The program creates a disk image file from three different programs:

*
* - bootsect: 8086 machine code of the file up to 510 bytes, for loading other programs.
* - setup: 8086 machine code of the file up to four disk sectors, for setting the system parameters.

* - system: 80386 code for the actual system.


*
* The program first checks all types of program modules is correct, and the test results are displayed on the terminal,

* Then remove the head module and a large expansion correct length. The program will also write data to some systems stderr.

*/
1819 / *

20 * Changes by tytso to allow root device specification


twenty one * /

/*
* tytso the program was modified to allow the device to specify the root file.

*/
2223 #include <stdio.h>
/ * Fprintf * / / * Fprintf used therein () * /
twenty four #include <string.h> / * String operations * /
25 #include <stdlib.h> / * Contains exit * / / * Comprising Exit () * /
26 #include <sys / types.h> / * unistd.h needs this * / / * for use unistd.h * /
27 #include <sys / stat.h> / * File status information structure * /

28 #include <linux / fs.h> /* File system*/

568
13.2 build.c program

29 #include <unistd.h> / * Contains read / write * / / * contains read () / write () * /


30 #include <fcntl.h> / * File operation mode symbol constant * /

3132 #define MINIX_HEADER 32


// minix binary modules header length is 32 bytes.
33 #define GCC_HEADER 1024 // GCC header information length is 1024 bytes.

3435 #define SYS_SIZE 0x2000


The maximum number of sections // system files (the number of bytes SYS_SIZE * 16 = 128KB).

3637 #define DEFAULT_MAJOR_ROOT 3


// default master root device number - 3 (hard disk).

38 #define DEFAULT_MINOR_ROOT 6 // default root device minor number - 6 (2nd hard Partition 1).
3940 / * Max nr of sectors of setup: do not change unless you also change

41 * Bootsect etc * /
/ * The following specifies the maximum number of sectors account setup module: Do not change this value, unless you also change the corresponding file bootsect and so on.

42 #define SETUP_SECTS 4 // setup maximum length of 4 sectors (4 * 512 bytes).


4344 #define STRINGIFY ( x ) #X
// display the statement for the number of sectors when an error occurs.

45
//// displays an error message and terminates the program.

46 void die (Char * str )


47 {
48 fprintf (stderr, "% s \ n ", str );
49 exit (1);
50 }
51
// display program to use, and exit.
52 void usage (Void)
53 {
54 die ( ' Usage: build bootsect setup system [rootdev] [> image] ");
55 }
5657 int main (Int argc, char ** argv )

58 {
59 int i, c, id;
60 char buf [1024];
61 char major_root, minor_root;
62 struct stat sb;
63
// If the command line parameter is not a 4 or 5, the display program usage and exit.

64 if ((argc! = 4) && (argc! = 5))


65 usage ();
// If the parameter is 5, then the device name with the root.

66 if (argc == 5) {
// If the root device names are floppy disk ( "FLOPPY"), then take the status information of the device file when an error message is displayed, quit.

67 if ( strcmp ( argv [4], " FLOPPY ")) {


68 if ( stat ( argv [4], & sb)) {
69 perror ( argv [4]);
70 die ( ' Could not stat root device ").;
71 }
// If successful then take the name of the device state structure major and minor numbers.

72 major_root = MAJOR (Sb.st_rdev);


73 minor_root = MINOR (Sb.st_rdev);
74 } Else {

569
13.2 build.c program

// otherwise make major and minor device number set to 0.

75 major_root = 0;
76 minor_root = 0;
77 }
// If the parameter is only 4, so that the major and minor device number equal to the system default root device.

78 } Else {
79 major_root = DEFAULT_MAJOR_ROOT ;
80 minor_root = DEFAULT_MINOR_ROOT ;
81 }
// display apparatus main root of the selected number of times on standard error device terminal.

82 fprintf (stderr, " Root device is (% d,% d) \ n ", major_root, minor_root); // if the primary number is not equal to 2 (floppy disk) or 3 (a hard disk),
not equal to 0 (default take root device), an error message is displayed exits.
83 if ((major_root! = 2) && (major_root! = 3) &&
84 (Major_root! = 0)) {
85 fprintf (stderr, " Illegal root device (major =% d) \ n ",
86 major_root);
87 die ( ' Bad root device --- major # ");
88 }
// Initialize the buffer buf, all set to zero.
89 for (i = 0; i <sizeof buf ; I ++) buf [I] = 0;
// Open the file specified parameter 1 (bootsect) as read-only, if the error is an error message and exit.

90 if ((id = open ( argv [1], O_RDONLY , 0)) <0)


91 die ( ' Unable to open 'boot' ");
// read the file minix execution header information (see list described later), the error if the error message is displayed, quit.

92 if ( read (Id, buf , MINIX_HEADER )! = MINIX_HEADER )


93 die ( ' Unable to read header of 'boot' ");
// 0x0301 - a_magic magic number minix head; 0x10 - a_flag executable; 0x04 - a_cpu, Intel 8086 machine code.
94 if (((long *) buf ) [0]! = 0x04100301)
95 die ( ' Non-Minix header of 'boot' ");
Analyzing // header length field a_hdrlen (bytes) is correct. (Useless after just three bytes, 0)
96 if (((long *) buf ) [1]! = MINIX_HEADER )
97 die ( ' Non-Minix header of 'boot' ");
Analyzing the data segment length a_data // field (long) content is zero.

98 if (((long *) buf ) [3]! = 0)


99 die ( ' Illegal data segment in 'boot' ");
Analyzing // stack a_bss field (long) content is zero.
100 if (((long *) buf ) [4]! = 0)
101 die ( ' Illegal bss in 'boot' ");
Analyzing execution point a_entry field // (long) content is zero.
102 if (((long *) buf ) [5]! = 0)
103 die ( ' Non-Minix header of 'boot' ");
Analyzing the content of the symbol table // a_sym length field is 0.

104 if (((long *) buf ) [7]! = 0)


105 die ( ' Illegal symbol table in 'boot' ");
// read the actual code data, should return the number of bytes read is 512 bytes.

106 i = read (Id, buf , Sizeof buf );


107 fprintf (stderr, " Boot sector% d bytes. \ N ", I);
108 if (i! = 512)
109 die ( ' Boot block must be exactly 512 bytes ");
// determines whether the boot block 0x510 bootable flag 0xAA55.

110 if ((* (unsigned short *) ( buf +510))! = 0xAA55)


111 die ( ' Boot block has not got boot flag (0xAA55) ");
// offset stored in the boot block 508, 509 is a root device number.

570
13.2 build.c program

112 buf [508] = (char) minor_root;


113 buf [509] = (char) major_root;
// The boot block 512-byte data is written to standard output stdout, if not the number of bytes written, an error message is displayed exits.

114 i = write (1, buf , 512);


115 if (i! = 512)
116 die ( ' Write call failed ");
// Finally close bootsect module file.
117 close (Id);
118
// now start processing setup module. First, a read-only open the module, an error message is displayed if an error exit.

119 if ((id = open ( argv [2], O_RDONLY , 0)) <0)


120 die ( ' Unable to open 'setup' ");
// read minix performs a header information (32 bytes) of the file, an error message is displayed if an error exit.

121 if ( read (Id, buf , MINIX_HEADER )! = MINIX_HEADER )


122 die ( ' Unable to read header of 'setup' ");
// 0x0301 - a_magic magic number minix head; 0x10 - a_flag executable; 0x04 - a_cpu, Intel 8086 machine code.
123 if (((long *) buf ) [0]! = 0x04100301)
124 die ( ' Non-Minix header of 'setup' ");
Analyzing // header length field a_hdrlen (bytes) is correct. (Useless after just three bytes, 0)
125 if (((long *) buf ) [1]! = MINIX_HEADER )
126 die ( ' Non-Minix header of 'setup' ");
Analyzing the data segment length a_data // field (long) content is zero.

127 if (((long *) buf ) [3]! = 0)


128 die ( ' Illegal data segment in 'setup' ");
Analyzing // stack a_bss field (long) content is zero.
129 if (((long *) buf ) [4]! = 0)
130 die ( ' Illegal bss in 'setup' ");
Analyzing execution point a_entry field // (long) content is zero.
131 if (((long *) buf ) [5]! = 0)
132 die ( ' Non-Minix header of 'setup' ");
Analyzing the content of the symbol table // a_sym length field is 0.

133 if (((long *) buf ) [7]! = 0)


134 die ( ' Illegal symbol table in 'setup' ");
// read subsequent execution code data, and writes to standard output stdout.

135 for (i = 0; (c = read (Id, buf , Sizeof buf ))> 0; i + = c)


136 if ( write (1, buf , C)! = C)
137 die ( ' Write call failed ");
// close the setup module file.
138 close (Id);
// If the setup module length is greater than four sectors, the error count, error message is displayed exit.

139 if (i> SETUP_SECTS * 512)


140 die ( ' Setup exceeds " STRINGIFY ( SETUP_SECTS )
141 "Sectors - rewrite build / boot / setup");
// display the length value setup file in the standard error stderr.

142 fprintf (stderr, " Setup is% d bytes. \ N ", I);


// clear the buffer buf.
143 for (c = 0; c <sizeof ( buf ); C ++)
144 buf [C] = '\ 0 ';
// setup length is less than 4 * If 512 bytes, then use \ 0 to 4 will be well filled with the setup * 512 bytes.

145 while (i < SETUP_SECTS 512 *) {


146 c = SETUP_SECTS * 512-i;
147 if (c> sizeof ( buf ))
148 c = sizeof ( buf );

571
13.2 build.c program

149 if ( write (1, buf , C)! = C)


150 die ( ' Write call failed ");
151 i + = c;
152 }
153
// The following processing system module. First, open the file in read-only mode.

154 if ((id = open ( argv [3], O_RDONLY , 0)) <0)


155 die ( ' Unable to open 'system' ");
// system module is a file format GCC, GCC first read configuration information header format (linux executable file also uses the format).

156 if ( read (Id, buf , GCC_HEADER )! = GCC_HEADER )


157 die ( ' Unable to read header of 'system' ");
// value field a_entry execution entry points in the structure should be zero.

158 if (((long *) buf ) [5]! = 0)


159 die ( ' Non-GCC header of 'system' ");
// read subsequent execution code data, and writes to standard output stdout.

160 for (i = 0; (c = read (Id, buf , Sizeof buf ))> 0; i + = c)


161 if ( write (1, buf , C)! = C)
162 die ( ' Write call failed ");
// close the file system, the number of bytes of system to print on stderr.
163 close (Id);
164 fprintf (stderr, " System is% d bytes. \ N ", I);
// If the system code data length exceeds SYS_SIZE section (128KB or bytes), an error message is displayed, exits.

165 if (i> SYS_SIZE * 16)


166 die ( ' System is too big ");
167 return (0);
168 }
169

13.2.3 Related Information

13.2.3.1 Executable header data structure

Minix executable file a.out The head structure is shown below (see minix 2.0 Source 01400 Line start):

struct exec {
unsigned char a_magic [2]; // perform file magic number.

unsigned char a_flags; // logo (see below explanation).


unsigned char a_cpu; // cpu identification number.

unsigned char a_hdrlen; // length of the head.

unsigned char a_unused; // reserved for future use.


unsigned short a_version; // version information (currently unused).

long a_text; // the code length, the number of bytes.

long a_data; // Data length, the number of bytes.

long a_bss; // stack length, the number of bytes.

long a_entry; // execute the entry point address.

long a_total; // total amount of memory allocated.

long a_syms; // size of the symbol table.

. . .
};

Where the flag field is defined as:

A_UZP 0x01 // unmapped 0 (pages).

572
13.2 build.c program

A_PAL 0x02 // executable file on a page boundary adjustment.

A_NSYM 0x04 // The new symbol table.

A_EXEC 0x10 // executable file.


A_SEP 0x20 // code and data are separated.

CPU identification number:


A_NONE 0x00 // unknown.
A_I8086 0x04 // Intel i8086 / 8088.
A_M68K 0x0B // Motorola m68000.
A_NS16K 0x0C // National Semiconductor 16032.
A_I80386 0x10 // Intel i80386.
A_SPARC 0x17 Company // Sun SPARC.

GCC Execute the file header structure information see linux / include / a.out.h file.

573
14.1 Overview

The first 14 Chapter test environment setup and use

14.1 Outline

To cope with Linux 0.11 Core operating principle of learning, this chapter describes the use of PC Machine simulation software and run on the actual computer

Linux 0.11 Systematic approach. These include the kernel compilation process, PC Production methods simulation environment to access and copy files, boot disk and root file

system and Linux 0.11 The method of using the system. Finally it explains how to make a small amount of syntax modifications to the kernel code to the existing RedHat 9 system( gcc

3.x ) Under smooth compile.

Before starting the experiment, first prepare some useful tools. in Windows The platform can be prepared following software:

Bochs 2.x Open source PC Machine simulation software package.

UltraEdit Super editor. It can be used to edit binary files.

WinImage DOS Format a floppy disk image file read and write software.

run Linux 0.11 The best way is to use the system PC Simulation software. Popular world face PC There are simulation software system 3

Species: VMware company's VMware Workstation , Connectix company's Virtual PC (Now the software has been acquired by Microsoft) and open source Bochs (With pronunciation ' box

' the same). This 3 Kinds of software are virtual or simulated Intel x86 Hardware environment that allows us to run a variety of other "guest" operating systems on the system

platform running the software.

The scope of use and operating performance, this 3 A simulation software still has some differences. Bochs Simulated x86 Hardware environment and its peripherals, it can

easily be ported to many operating systems on different platforms or architectures. Since the main use of simulation technology, its operating performance and speed to be slower

than the other two software a lot. Virtual PC The performance of the sector in Bochs with VMware Workstation between. It simulates x86 Most, while the other part is the use of

virtual technologies. VMware Workstation Only a few simulation I / O Function, while all other parts are in x86 Performed directly on real-time hardware. That is when a client

operating system requires to execute an instruction, VMware Not a simulation method to simulate this directive, but this instruction "pass" to the actual system hardware to

complete. therefore VMware Yes 3 One of the highest speed and performance types of software. On this 3 Specific differences and performance differences between the kinds of

software, please refer to the online review article ( http://www.osnews.com/story.php?news_id=1054 ).

From the application point of view, if the simulation environment is mainly used for application development, then VMware Workstation with Virtual PC

It may be a better choice. But if you need to develop some low-level system software (such as operating system development and debugging, compiler system development, etc.),

then Bochs It is a good choice. use Bochs You can know the hardware in the simulation environment specifically state the exact timing and execution of the program, rather than the

result of the actual hardware implementation of the system. This is why many operating system developers prefer

Bochs s reason. Therefore, this chapter focuses on the use of Bochs Simulation environment running Linux 0.11 Methods. Currently, Bochs Web site name

http://sourceforge.net/projects/bochs/ . You can download the latest release from the top to the Bochs Software system and many have made a good run disk image

file.

14.2 Bochs Simulation System

Bochs It is a completely simulation Intel x86 Program of the computer. It can be configured to emulate 386 , 486 , Pentium Or more of the new CPU . Throughout the

implementation process, Bochs Simulation of all instructions, and contains standard PC Peripherals all modules.

574
14.2 Bochs emulation system

due to Bochs Simulation of the entire PC Environment, in which the execution of the software "thinks" that it is running on a real machine. This approach allows us to complete the

simulation in Bochs Without modification to run a lot of software systems.

Bochs Yes Kevin Lawton to 1994 Started using C ++ Language development software system, is designed to be able to Intel x86 , PPC ,

Alpha , Sun with MIPS Run on the hardware. Regardless of the host running uses what hardware platform, Bochs Still Simulation x86 Software. This is the other two simulation

software can not do. In order to perform any activity on the simulated machine, Bochs You need to interact with the host operating system. When Bochs When a key is pressed the

display window, a keystroke will be sent to the keyboard device processing module. When the simulated machine requires performing a read operation from the analog disk, Bochs Will

perform a read operation from the hard disk image file on the host.

Bochs Software installation is very easy. You can directly from the bochs.sourceforge.net On the site to download Bochs Installation package. If you are using a computer

operating system Windows Is a commonly used software installation process exactly the same. After installation will C Generating a directory on a disc: ' C: \ Program Files \

Bochs-2.1.1 \ ' (The version number of different versions with different). If your system is RedHat

9 Or other Linux System, you can download Bochs of RPM To install the package and as follows:

user $ su
Password:
root # rpm -i bochs-1.2.1.i386.rpm root # exit user $ _

You need to install root Permissions, otherwise you might have to recompile in their own directory Bochs system. In addition, Bochs Need X11

Environment to run, so the system must already be installed X Windows The system can use Bochs . After installing, you can use Bochs

Comes with Linux dlx Packages to test and familiarize yourself with the system. It is also possible from Bochs On the site to download some ready made

Linux Disk image file. Recommended download Bochs On a website SLS Linux Simulation system: sls-0.99pl.tar.bz2 As the founder Linux

0.11 Auxiliary platform simulation system. When creating a new hard disk image file need to use these systems to the hard disk image file to partition and format operations.

About recompiling Bochs Or the system Bochs The method of operation of the installation to other hardware platforms, refer to Bochs User manual for instructions.

14.2.1 Set up Bochs system

In order to Bochs Running an operating system that requires a minimum of resources or some of the following information:

bochs executable file;

bios Image file (commonly referred to as' BIOS-bochs-latest ' );

vga bios Image file (e.g., ' VGABIOS-lgpl-latest ' ); At least a boot disk image file (floppy disk,
hard disk or CDROM The image file).

But we often need to pre-set some parameters for the operation of the system during use. These parameters can be uploaded and handed the command line

Bochs Execution of the program, but we usually uses a configuration file (for example, Sample.bxrc ) Is a specialized application to set. In the following description Windows Set

configuration files of the environment.

14.2.2 Profiles bochsrc


Bochs Use the information in the configuration file to find the information set disk image files used to configure the operating environment of peripheral devices and some

other analog machines. Each simulation systems need to set a corresponding configuration file. If installed Bochs System is

2.1 Or later, then Bochs The system will automatically identify the suffix '. bxrc ' Configuration file, and it will automatically start when double-clicking the file icon Bochs system

running. For example, we can take for the configuration file name ' bochsrc-0.11.bxrc ' . in Bochs There is installed a main directory name ' bochsrc-sample.txt ' A model configuration

file, which lists all the available parameter settings, and with detailed

575
14.2 Bochs emulation system

Instructions. Following is a brief introduction of several parameters in experiments often you want to modify.

1. megs

Contained in the system for setting the analog memory. The default value is 32MB . For example, if we want to simulate machine comprising 128MB System, is required to

contain the following line in the configuration file:

megs: 128

2. floppya ( floppyb )
floppya It represents a floppy drive, floppyb It represents the second floppy drive. If you need to boot up from a floppy disk, then floppya

We need to point to a bootable disk. If you want to use the disk image file, write the name of the disk image file later. In many operating systems, Bochs Floppy disk

drive can read and write directly to the host system. To access the actual disk drive, use the device name ( Linux System) or drive letter ( Windows system). You can

also use status To indicate the status of the disk is inserted. ejected

Representation is not inserted, inserted It indicates that the disk has been inserted. Here are a few examples, wherein all the discs are inserted state.

floppya: 1_44 = / dev / fd0, status = inserted # A direct access to the disk under Linux systems 1.44MB.

floppya: 1_44 = b :, status = inserted # Direct access to the disk 1.44MB B win32 system.
floppya: 1_44 = bootimage.img, status = inserted # Pointing to a disk image file bootimage.img.
floppyb: 1_44 = .. \ Linux \ rootimage.img, status = inserted # pointing to the parent directory Linux / under rootimage.img.

In the configuration file, if the parameter of the same name a few lines exist, then only the last row of function parameters.

3. ata0 , ata1 , ata2 , ata3


This 4 Parameter name used to start the system up to simulate 4 More ATA aisle. For each enabled channel, you must specify two IO A base address and interrupt request

number. By default, only ata0 It is enabled, and default parameter values ​as follows:

ata0: enabled = 1, ioaddr1 = 0x1f0, ioaddr2 = 0x3f0, irq = 14 ata1: enabled = 1,


ioaddr1 = 0x170, ioaddr2 = 0x370, irq = 15 ata2: enabled = 1, ioaddr1 = 0x1e8,
ioaddr2 = 0x3e0, irq = 11 ata3: enabled = 1, ioaddr1 = 0x168, ioaddr2 = 0x360, irq =
9

4. ata0-master ( ata0-slave )
ata0-master It is used to indicate the first simulation system 1 More ATA aisle( 0 A first upper channel connected) 1 More ATA Device (hard drive or CDROM

Wait); ata0-slave The first specified 1 Connecting the first channels 2 More ATA device. As shown in the example below, the meaning of the option configuration wherein, as shown

in Table devices 14-1 Fig.

ata0-master: type = disk, path = hd.img, mode = flat, cylinders = 306, heads = 4, spt = 17, translation = none ata1-master: type = disk, path =

2G.cow, mode = vmware3 , cylinders = 5242, heads = 16, spt = 50, translation = echs ata1-slave:

type = disk, path = 3G.img, mode = sparse, cylinders = 6541, heads = 16, spt = 63, translation = auto

ata2-master: type = disk, path = 7G.img, mode = undoable, cylinders = 14563, heads = 16, spt = 63, translation = lba ata2-slave:

type = cdrom, path = iso.sample, status = inserted

ata0-master: type = disk, path = "hdc-large.img", mode = flat, cylinders = 487, heads = 16, spt = 63 ata0-slave:

type = disk, path = ".. \ hdc-0.11.img", mode = flat, cylinders = 121, heads = 16, spt = 63

table 14-1 Options configured devices

Options Explanation Possible values

576
14.2 Bochs emulation system

type Connected device type [Disk | cdrom]

path Image file pathname

[Flat | concat | external | dll | sparse | vmware3 |


mode Image file types, only the disk effective
undoable | growing | volatile]

cylinders Only disk effective

heads Only disk effective

spt Only disk effective

status Only cdrom effective [Inserted | ejected]

biosdetect bios Detection Type [None | auto], Only ata0 on disk Effective [ cmos]

bios The type of conversion ( int13), Only disk effective


translation [None | lba | large | rechs | auto]

model Confirm Device ATA Command returns the string

In the configuration ATA The device must be connected to specify the type of device type , May be disk or cdrom . Must also indicate "pathname" equipment path .

"Pathname" may be a hard disk image file, CDROM of iso File or directly to the system CDROM driver. in Linux System, the system can be used as a device Bochs Hard

disk, but due to security reasons, windows In favor of the physical hard disk directly on the system.

For type disk Equipment, options path , cylinders , heads with spt It's required. For type cdrom Equipment, options path It's required.

Disk Transformation program (in the traditional int13 bios Function implemented, and used as DOS This old operating system) can be defined as:

none : No conversion for capacity is less than 528MB ( 1032192 Sectors) of the hard disk;

large : Standard bit shift algorithms for capacity is less than 4.2GB ( 8257536 Sectors) of the hard disk;

rechs : Shift correction algorithm, using 15 Dummy heads physical drive parameters for capacity is less than 7.9GB ( 15,482,880 Sectors) of the hard disk;

lba :standard lba- Aided algorithm. Suitable capacity is less than 8.4GB ( 16,450,560 Sectors) of the hard disk;

auto : Automatically select the best transform scheme. (Analog system will not start if it should be changed).

mode Options for how to use the hard disk image file. It can be one of the following modes:

flat : A flat sequential file;


concat : Multiple files;
external : Dedicated by the developer, by C ++ Class to specify;

dll : Developers dedicated, by DLL Use;


sparse : The pile can be confirmed, returnable;

vmware3 :stand by vmware3 Hard disk format;

undoable : Confirm redo having a flat file;


growing : Capacity can be expanded image file;

volatile : A variable redo the flat file. The default value of the

above options are:

mode = flag, biosdetect = auto, translation = auto, model = "Generic 1234"

5. boot

boot Machine used to define the simulation for the boot drive. You can specify a floppy disk, hard disk or CDROM . You can also use drive letters' c ' with' a ' . Examples are

as follows:

boot: a

577
14.3 create a disk image file

boot: c boot: floppy


boot: disk boot:
cdrom

6. ips ips ( Instructions Per Second ) Specifies the number of instructions per second strip simulation. this is Bochs Running on the host system IPS Value. This value will affect

many event simulation system with time-dependent. Such as changing IPS Value will affect VGA The update rate, and some other systems Simulation evaluation value. It is

necessary to set the value according to the properties of the host used. Refer to Table 14-2 Set.

table 14-2 The number of instructions per second simulation

speed Machine configuration IPS Typical values

650Mhz Athlon K-7 with Linux 2.4.x 2 to 2.5 million

400Mhz Pentium II with Linux 2.0.x 1 to 1.8 million

166Mhz 64bit Sparc with Solaris 2.x 0.75 million

200Mhz Pentium with Linux 2.x 0.5 million

E.g:
ips: 1000000

7. log
Designation log Pathname can make Bochs Some record log information execution. If the Bochs Running phylogenetic not run correctly, you can refer to the

information which is essential to find out the reason. log Usually set to:

log: bochsout.txt

14.2.3 Debugging functions

See also bochs Debugger

14.3 Create a disk image file

Disk image file ( Disk Image File ) Is a complete hard disk or floppy disk map information, and save it as a file. Disk image file format to save the information on exactly the

same format as the corresponding disk to store information. Empty disk capacity and disk image file is created we are all the same but the content 0 Of a file. These empty image

file as just bought a new floppy or hard disk, also need to go through partition or / and format to use.

Before making a disk image file, we first need to determine the capacity of the image file is created. For the floppy disk image files, a variety of ( 1.2MB or 1.44MB )

Are fixed capacity. So here mainly describes how to determine the capacity of the hard disk image file you need. Normal hard disk structure composed by a pile of the

metal disc. The upper and lower surfaces of each disc for storing data, and a concentric manner into the entire surface of a dividing tracks, or cylinders called ( Cylinder ).

Thus a need for a disk head ( Head ) Above to read and write data. When the disk rotary head only radial movement can be moved over any of the tracks, it is possible to

access all the active position of the disk surface. Each track is divided into a number of sectors, sector length by the general 256--1024 Bytes. For most systems, are

typically sector length 512 byte. A typical disk structure is shown in 14-1 Fig.

578
14.3 create a disk image file

Top
A sector

Tracks

magnetic head

Map 14-1 The internal structure of a typical hard disk

It is shown a structure with two hard metal disc. So the hard disk has 4 Physical heads. The maximum number of cylinders contained in the production have been

identified. When the hard disk partition and format, the surface of the magnetic media disk is initialized to the specified data format, so that each track (or cylinder) is divided into a

specified number of sectors. So the total number of sectors of the hard disk as follows:

Total number of sectors = hard Physical track number X Physical heads X The number of sectors per track

These parameters will be different with the actual physical parameters of an operating system used in the hard disk or more, referred to as logical parameters. But the total

number of sectors of the parameters calculated with the hard physical parameters must be calculated the same. Due to the design PC Without considering the capacity and

performance of hardware systems developed so fast, ROM BIOS Some drive parameters represent bits used is too small to meet the requirements of actual physical parameters of

the hard disk. Therefore, the current operating system or machine BIOS Measures commonly used is appropriately adjusted in the case where the total number of sectors equal to

the hard disk to ensure the number of tracks, the number of prefixes and the number of sectors per track, in order to meet the requirements of the capabilities and limitations represented. in Bochs

Profile parameters related to the device's hard drive transformation ( Translation ) Option is also provided for this purpose.

We are in Linux 0.11 Production of hard disk system Image When the file, taking into account its own small amount of code, and the use of MINIX

1.5 The maximum capacity of the file system 64MB The restrictions, the maximum size of each hard disk partition can only be 64MB . In addition, Linux 0.11

The system is not support extended partitions, so for a hard disk Image Files, up to 4 Partitions. therefore, Linux 0.11 The system can be used in hard disk Image The maximum

capacity of the file 64 x 4 = 256MB . In the following description, we will have to create a 4 Partitions, each partition is 60MB Hard drive Image Document described as an

example.

For floppy disks, we can see it as having a fixed number (cylinders) of tracks, the number of heads and sectors per track ( spt Sectors Per Track ) Ultra-small hard

disk. For example, capacity 1.44MB Floppy disk parameters 80 Tracks, 2 And have heads per track 18

Sectors, each sector has 512 byte. Its total number of sectors is 2880 The total capacity is 80 x 2 x 18 x 512 = 1474560 byte. Therefore, all production methods described below for

the hard disk image file can be used to create a floppy disk image file. In order to facilitate the narrative, particularly in the absence of that we all collectively referred to as disk

image files Image file.

14.3.1 use Bochs Software comes with Image Generation tool

Bochs System with a Image Generation tool " Disk Image Creation Tool "( bximage.exe ). It can be used to make floppy and hard disk space Image file. And the emergence of

running Image When you create the interface, the program first prompted to select the need to create Image Type (hard disk hd Or floppy disk fd ). If the hard disk is created, there

will be prompted for hard disk Image of mode Types of. Usually only need to select their default values flat It can be. Then you need to create input Image capacity. Corresponding to

the hard disk the program displays the parameters: number of cylinders (track number, the head number and the number of sectors per track, and requests a Image Name of the file.

Program generated Image After the file is displayed for a Bochs Profile settings configuration information for the hard disk parameters. Write down this information and edit the

configuration file. The following is to create a

579
14.3 create a disk image file

256MB hard disk Image Process file.

================================================== ======================
bximage
Disk Image Creation Tool for Bochs
$ Id: bximage.c, v 1.19 2003/08/01 01:20:00 cbothamy Exp $ ============================
============================================ Do you want to create a floppy disk image or a hard disk
image? Please type hd or fd. [hd]

What kind of image should I create? Please type flat, sparse or


growing. [Flat]

Enter the hard disk size in megabytes, between 1 and 32255 [10] 256

I will create a 'flat' hard disk image with


cyl = 520
heads = 16
sectors per track = 63 total sectors =
524160 total size = 255.94 megabytes

What should I name the image? [C.img] hdc.img

Writing: [] Done.

I wrote 268369920 bytes to (null).

The following line should appear in your bochsrc:


ata0-master: type = disk, path = "hdc.img", mode = flat, cylinders = 520, heads = 16, spt = 63

Press any key to continue

If you already have a capacity to meet the requirements of the hard disk Image File, you can directly copy the file to generate a different Image

file. Then the file can be processed according to their own requirements. To create a floppy disk Image The procedure is similar to the above documents, but also prompts you to

select the type of floppy tips. Similarly, if you have other floppy disk Image File, then copy the direct method can be.

14.3.2 in Linux Under the system uses dd Create a command Image file.

As already explained, the newly created Image It is a full file content is 0 Just empty file its capacity consistent with the requirements. Therefore, we can first calculate the

capacity requirements Image Number of sectors in the file, and then use dd Command to generate a corresponding Image file.

For example, we want to build a number of cylinders 520 The number of heads is 16 , The number of sectors per track is 63 Hard drive Image File, the total number of its

sectors: 520 * 16 * 63 = 524160 , The command is:

dd if = / dev / zero of = hdc.img bs = 512 count = 524160

1.44MB floppy disk Image files for which the number of sectors is 2880, so the command is:

dd if = / dev / zero of = diska.img bs = 512 count = 2880

580
14.4 Information access disk image file

14.3.3 use WinImage create DOS Format a floppy disk Image file

WinImage Is a DOS format Image File access and creation tools. Double-click DOS floppy disk Image Icon files can browse, delete or add files inside. In

addition, it is also used for browsing CDROM of iso file. use WinImage Create a floppy disk

Image It may be generated with a time DOS Formats Image file. Methods as below:

a) run WinImage . select "Options-> Settings" Menu, select one of the Image Settings page. Set up Compression

for "None" (Ie, the scale indicating pulled the left).

b) create Image file. Select the menu File-> New Will pop up a floppy disk format selection box. Select capacity 1.44MB

Format.
c) Select the boot sector properties menu item Image-> Boot Sector properties , Click the dialog box MS-DOS Button.

d) save document.

Note that the "Save as type" in Save File dialog box, be sure to select " All files (*. *) " Otherwise created Image File will contain some WinImage Own information, which will

result in Image Documents Bochs Under it is not working. Can be determined by looking at the length of the newly created file Image does it reach the requirement. standard 1.44MB

Floppy disk capacity should be 1474560 byte. If the new Image

File length is greater than this value, in strict accordance with the method used to re-create or UltraEdit And other binary editor to remove the extra bytes. Delete operations as

follows:

use UltraEdit Opened in binary mode Image file. The disk image file first 511 , 512 Byte 55, AA Two hexadecimal digits, we push down 512 Bytes,

delete all bytes before that. For this time MSDOS5.0 As the boot disk is concerned, the first few bytes of the file should look like "EB 3C 90 4D ..." .

Then drop down on the right scroll bar to move img At the end of the file. delete "... F6 F6 F6" All the data back. Generally speaking is to remove from 0x168000

All data begins. When the operation is complete the last line should be complete row "F6 F6 F6 ..." . Save and exit to use this Image Files.

14.4 Information Access disk image file

Bochs To simulate the analog system external storage device, all files are saved in the operating system simulation are floppy or hard disk devices in the image file format

used in the disk image file. Thus to bring the host operating system and Bochs Problems are exchanged information between the analog system. although Bochs The system can

be configured to direct the host to use a floppy disk drive, CDROM And other physical device drivers to run, but the use of such information exchange method is relatively

cumbersome. Therefore it is best to directly read and write Image Information in the file. If you need to add a file, put the file into the operating system to be simulated in Image File.

If you want to remove the files from Image File read. However, due to save Image Not only the information in the file is located in a corresponding format floppy or hard disk, but

also to store a certain file system format. Therefore access Image Program information file must be able to identify where the file system to operate. For the application of this

chapter, we need some tools to identify Image File MINIX and / or) DOS File system format.

Generally speaking, if the file length and simulation systems exchange is relatively small, we can use a floppy disk Image File as a medium of exchange. If there are large

quantities of files need to be removed or placed in the analog system from an analog system, then we can use the existing Linux System to operate. Here are several ways from

two aspects discussed may be employed.

The use of tools to read and write disk image access information floppy disk image files (small files or split files) in Linux The main use of the

environment loop Devices to access information in the hard disk image file. (Large quantities of information exchange) use iso File format for

information exchange (large quantities of information exchange)

14.4.1 use WinImage Software Tools

A floppy disk Image File, we can exchange a few files with the analog system. Provided that the simulation system support DOS

581
14.4 Information access disk image file

Reading and writing floppy disk format (e.g., by mtools command). In the following example to illustrate the specific methods of operation.

Prior to read and write files, you need to be prepared first according to a previously described method 1.44MB Image File (the file name is the assumption

diskb.img ). And modify Linux 0.11 of bochs.bxrc Profile, floppya Add the following line of information the following parameters:

floppyb: 1_44 = "diskb.img", status = inserted

I.e. an increase of the system to the analog 2 More 1.44MB Floppy disk device, and the device corresponding to Image The file name is diskb.img . If you want to Linux 0.11 A

file system is taken out, so now you can double-click the icon to start running configuration file Linux 0.11

system. Entering Linux 0.11 After the system, use DOS Floppy disk read and write tool mtools The hello.c The first written document 2 A floppy disk Image

in. If the floppy disk Image It is to use Bochs Created or has not been formatted, you can use mformat b: Command to format it first.

[/ Usr / root] # mcopy hello.cb:


Copying HELLO.C [/ usr / root]
# mdir b:
Volume in drive B has no label Directory for B: /

HELLO C 74 4-30-104 4: 47p


1 File (s) 1457152 bytes free
[/ Usr / root] #

Exit now Bochs System and use WinImage turn on diskb.img File, WinImage The main window will have a hello.c

File exists. Select the file with your mouse and drag it to the desktop to complete the entire operation takes files. If a file requires the input to an analog system, then just

the opposite to the above steps.

14.4.2 Use of existing Linux system

existing Linux System (for example, RedHat 9 ) To access a variety of file systems, including the use of loop File in the file system to access the storage device. For

floppy disk Image File, we can directly use mount Command to load Image The file system read and write access. For example, we need access rootimage-0.11 Files, as long

as the following command.

[ Root @ a plinux ImagesRF Royalty Free] # mount -t minix rootimage-0.11 / mnt -o loop

[ Root @ a plinux ImagesRF Royalty Free] # cd / mnt

[ Root @ a plinux mnt] # ls


dev etc root tmp usr bin [ root @ a plinux mnt] #

among them mount Command - t minix Option indicates the type of file system is read MINIX - o loop Option Description by loop Device to load the file system. If you need to

access DOS Format a floppy disk Image File, simply mount Command in the File Type Options minix Replaced msdos It can be.

If you want to access the hard disk Image File, then the process operation different from the above. Since the floppy disk Image General image file contains a complete file

system, it can be used directly mount Command loads the floppy disk Image The file system, but the hard disk Image Generally contain partition information file, and the file system

is built in each partition. That we can put the hard drive of each partition as a complete "big" floppy disk.

Therefore, in order to access a hard disk Image Information files in a partition, we need to first understand the hard disk Image File partition information to determine the

need to access partitions Image Starting file offset position. On the hard disk Image File partition information, we can use the simulation system is running fdisk View command,

you can view here, too. Here in the following package includes a hard disk

582
14.4 Information access disk image file

Image file hdc-0.11.img An example to illustrate where the first visit 1 The method of file system a partition.

http://oldlinux.org/Linux.old/bochs/linux-0.11-devel-040329.zip

It should be used loop The device is provided with a control command losetup . This command is mainly used to block a normal file or a device

loop Associated with the device, or for releasing a loop Device, a query loop Status of the device. Detailed description of the command refer to the online manual pages.

First execute the following command hdc-0.11.img Files with the loop1 Associate, and use fdisk Command to view the partition information therein.

[ Root @ a plinux devel] # losetup / dev / loop1 hdc-0.11.img


[ Root @ a plinux devel] # fdisk / dev / loop1
Command (m for help): x # Enter the extension menu

Expert command (m for help): p # Display the partition table

Disk / dev / loop1: 16 heads, 63 sectors, 121 cylinders

Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID


180 1 1 01,563,119 1 12,095,981
200 0 0 0 0 0 0 0 000
300 0 0 0 0 0 0 0 000
400 0 0 0 0 0 0 0 000
Command Expert (for Help m): Q [ the root @ a
plinux devel] #

from above fdisk Partition information given can be seen that Image File containing only 1 Partitions. Note of the starting sector of the partition (i.e., the partition table Start A

bar content). If you need to access the hard drive with multiple partitions Image , Then you need to remember the starting sector number associated partition.

Next, let's use losetup of- d Options to hdc-0.11.img Files with the loop1 The association is released, it re-associate

hdc-0.11.img Paper 1 At the start position of the partition. This requires the use losetup of- o Option, which specifies the byte offset associated with the starting position. Partition

information is apparent from the above, where the first 1 Beginning offset partitions is 1 * 512 byte. In the first 1 Partitions and

loop1 After the re-association, we can use mount Command to access its files.

[ Root @ a plinux devel] # losetup -d / dev / loop1


[ Root @ a plinux devel] # losetup -o 512 / dev / loop1 hdc-0.11.img
[ Root @ a plinux devel] # mount -t minix / dev / loop1 / mnt
[ Root @ a plinux devel] # cd / mnt
[ Root @ a plinux mnt] # ls
dev etc Image mnt tmp bin usr var [ the root @ a plinux mnt] #

After the partition of the file system access end, and finally uninstall and remove the association.

[ Root @ a plinux mnt] # cd


[ Root @ a plinux root] # umount / dev / loop1
[ Root @ a plinux root] # losetup -d / dev / loop1
[ Root @ a plinux root] #

583
14.5 Production root file system

14.5 Production root file system

Goal of this section is to establish a root file system on the hard disk. Although oldlinux.org It can be downloaded on to floppy and hard disks have produced a good root file

system Image File, but it was still the production process is described in detail again, for them to learn. In the production process can also refer Linus Base: INSTALL-0.11 . Before

making the root file system disk, we must first download rootimage-0.11 with

bootimage-0.11 Image file (please download the latest documents date):

http://oldlinux.org/Linux.old/images/bootimage-0.11-20040305
http://oldlinux.org/Linux.old/images/rootimage-0.11-20040305

Modify these two files into easy to remember bootimage-0.11 with rootimage-0.11 And the establishment of a special called Linux-0.11

Subdirectory. In the production process, we need to copy rootimage-0.11 Some in the execution of the program and use the floppy disk bootimage-0.11 Boot disk to start the

simulation system. So before you started work on the root file system, you first need to confirm've been able to run both Floppy

Image The smallest files Linux system.

14.5.1 Root file system and the root file device

Linux When booting, the default file system is the root file system. Which typically include some of the following subdirectories and files:

etc / The main directory contains a number of system configuration files;

dev / Containing a special device file, the file manipulation statements using the operation device;

bin / Storage system executes the program. E.g sh , mkfs , fdisk Wait;

usr / Repository functions, manuals and other documents;

usr / bin Ordinary users to store frequently used commands;

var / A variable storage system runtime data, or logging information.

Storage device file system is the file system device. For example, for general use Windows2000 Operating system, hard drive C Disk is a file system device, and the file on

the hard disk storage according to certain rules on the composition of the file system, Windows2000 Have NTFS or FAT32

And other file systems. and Linux 0.11 Supported by the kernel file system MINIX 1.0 File system.

14.5.2 Create a file system

For hard disk created above Image File, also can be used before it must be partition and create a file system. The usual practice is hard to need to be addressed Image Documents

attached to Bochs Under the existing analog system (e.g., the above-mentioned SLS Linux ), Then use the simulation system for the new command Image File for processing. The

following assumes that you have installed SLS Linux Analog system, and the system is stored in the name SLS-Linux Subdirectory. We use it to create the above 256MB hard disk Image

file hdc.img

Partition and create MINIX File system. We will in this Image Create a file 1 Partitions, and to establish MINIX File system. We perform the following steps:

1. in SLS-Linux Under the same directory as the establishment of a name Linux-0.11 Subdirectory, the hdc.img Move a file to the directory.

2. enter SLS-Linux Directory, edit SLS Linux systematic Bochs Profiles bochsrc.bxrc . in ata0-master Plus a line under

Into our hard drives Image Configuration parameters line of the file:

ata0-slave: type = disk, path = .. \ Linux-0.11 \ hdc.img, cylinders = 520, heads = 16, spt = 63

3. Exit the editor. Double-click bochsrc.bxrc Icon, run SLS Linux Analog system. In the event Login When the prompt, type ' root '

584
14.5 Production root file system

And press Enter. If at this time Bochs Can not operate normally, generally due to the profile information is incorrect, please re-edit the configuration file.

4. use fdisk Command hdc.img File establish 1 Partitions. Below is the establishment of the first 1 Partition command sequences. Build another 3 More

The process is similar to this partition. due to SLS Linux The default partition type is to support the establishment of MINIX2.0 File System 81 Types of( Linux / MINIX ), It is

necessary to use fdisk of t The command type modified 80 ( Old MINIX )Types of. Note here that we have put hdc.img Hook into SLS Linux Under the first system 2 A hard

disk. according to Linux 0.11 For naming the hard disk, the hard disk should be the overall device name / dev / hd5 (See Table 14-3 ). But from Linux 0.95 Hard disk version

began naming rules have been modified to use the current rules, so SLS Linux Lower Dir 2 The whole hard disk device name is / dev / hdb .

[/] # Fdisk / dev / hdb Command (m


for help): n
Command action
e extended
p primary partition (1-4) p

Partition number (1-4): 1


First cylinder (1-520): 1
Last cylinder or + size or + sizeM or + sizeK (1-520): + 63M

Command (m for help): t


Partition number (1-4): 1
Hex code (type L to list codes): L
0 Empty 8 AIX 75 PC / IX b8 BSDI swap
1 DOS 12-bit FAT 9 AIX bootable 80 Old MINIX c7 Syrinx
2 XENIX root a OPUS 81 Linux / MINIX db CP / M
3 XENIX user 40 Venix 82 Linux swap e1 DOS access
4 DOS 16-bit <32M 51 Novell? 83 Linux extfs e3 DOS R / O
5 Extended 52 Microport 93 Amoeba f2 DOS secondary
6 DOS 16-bit> = 32 63 GNU HURD 94 Amoeba BBT ff BBT
7 OS / 2 HPFS 64 Novell b7 BSDI fs
Hex code (type L to list codes): 80

Command (m for help): p


Disk / dev / hdb: 16 heads, 63 sectors, 520 cylinders Units = cylinders of 1008 *
512 bytes
Device Boot Begin Start End Blocks Id System
/ Dev / hdb1 1 1 129 65015+ 80 Old MINIX

Command (m for help): w


The partition table has been altered. Please reboot before doing
anything else. [/] #

table 14-3 Hard disk logical device number

Logical device number The corresponding device description file

0x300 / Dev / hd0 The first representative of the 1 Hard drive

0x301 / Dev / hd1 Represents 1 The first hard disk 1 Partition

0x302 / Dev / hd2 Represents 1 The first hard disk 2 Partition

0x303 / Dev / hd3 Represents 1 The first hard disk 3 Partition

585
14.5 Production root file system

0x304 / Dev / hd4 Represents 1 The first hard disk 4 Partition

0x305 / Dev / hd5 The first representative of the 2 Hard drive

0x306 / Dev / hd6 Represents 2 The first hard disk 1 Partition

0x307 / Dev / hd7 Represents 2 The first hard disk 2 Partition

0x308 / Dev / hd8 Represents 2 The first hard disk 3 Partition

0x309 / Dev / hd9 Represents 2 The first hard disk 4 Partition

5. Keep in mind that the number of data block partition size (here 65015 ), When you create a file system will be used to this value. When the partition is set up

After, as you typically would need to reboot the system to allow SLS Linux System kernel can correctly identify the newly added partition.

6. Re-enter SLS Linux After the simulation system, we use mkfs The first command just created 1 Create a partition on MINIX File system

System. As shown in the following command information. It has created here 64000 Partition data block (a data block 1KB byte).

[/] # Mkfs / dev / hdb1 64000 21333


inodes 64000 blocks

Firstdatazone = 680 (680) Zonesize =


1024 Maxsize = 268966912 [/] #

So far, we have completed in hdc.img The first file 1 Partitions created in the working file system. Of course, establishing create a file system can also be run Linux

0.11 Establish the root file system on the floppy disk. Now we can use that partition as a root file system build.

14.5.3 Linux-0.11 of Bochs Profiles


in Bochs Run Linux 0.11 When the analog system, its configuration file bochsrc.bxrc Usually requires the following content.

romimage: file = $ BXSHARE \ BIOS-bochs-latest, address = 0xf0000 megs: 16

vgaromimage: $ BXSHARE \ VGABIOS-elpin-2.40 floppya: 1_44 =


"bootimage-0.11", status = inserted
ata0-master: type = disk, path = "hdc.img", mode = flat, cylinders = 520, heads = 16, spt = 63 boot: a

log: bochsout.txt panic:


action = ask
# error: action = report
# info: action = report
# debug: action = ignore ips:
1000000 mouse: enabled = 0

We can SLS Linux of Bochs Profiles bochsrc.bxrc copy to Linux-0.11 Directory, and then the same as above modified content. Need special attention floppya ,

ata0-master with boot ,This 3 Parameter must be consistent with the above.

Now double-click the configuration file with the mouse. First of all Bochs Map display window should appear 14-2 In the picture.

586
14.5 Production root file system

Map 14-2 Bochs The system is running Window

At this point you should click on the menu bar ' CONFIG ' Icon to enter Bochs Settings window (need to use the mouse to click in order to put the window to the front).

Setting window displays the contents shown in Figure 14-3 Fig.

Map 14-3 Bochs System Configuration window

587
14.5 Production root file system

The first modification 1 The floppy disk settings to point to rootimage-0.11 plate. Then press the Enter key continuously, until the last line window set ' Continuing simulation ' until.

At this time, and then switch to Bochs Run window. Click the Enter key after the formal entry into the Linux

0.11 system. See Fig. 14-4 Fig.

Map 14-4 Bochs Running Linux 0.11 system

14.5.4 in hdc.img On the establishment of the root file system

Since the floppy disk capacity is too small, to make Linux 0.11 The system can really do something, then you need a hard disk (here it refers to the hard disk Image

Create a root file system on the file). We have already established a 256MB Hard drive Image file hdc.img , And at this time it connected to a running Bochs Environment,

information on a hard disk and therefore the above figure appears:

"Ata0 master: Generic 1234 ATA-2 Hard-Disk (255 Mbytes)"

If you do not see this message, state your Linux 0.11 The configuration file is not set correctly. Please re-edit bochsrc.bxrc File, and re-run Bochs Systems, described

above until the same picture.

We have in front hdc.img The first 1 The establishment of the partitions MINIX File system. If not built or want to try the side of it, then type the following

command to create a 64MB File system:

[/ Usr / root] # mkfs / dev / hd1 64000

Now you can start to load the file system on the hard drive. Execute the following command to load the new file system to / mnt Directory.

588
14.5 Production root file system

[/ Usr / root] # cd /

[/] # Mount / dev / hd1 / mnt [/] #

After loading the file system on the hard disk partition, we can copy the root file system on a floppy disk to the hard drive. Execute the following command:

[/] # cd / mnt

[/ Mnt] # for i in bin dev etc usr tmp

> do
> cp + recursive + verbose / $ i $ i done

At this time, all the files on the floppy disk root file system is copied into the file system on the hard disk. Many like the following message appears during the copying

process.

/ Usr / bin / mv -> usr / bin / mv / usr / bin / rm ->


usr / bin / rm / usr / bin / rmdir -> usr / bin / rmdir /
usr / bin / tail -> usr / bin / tail / usr / bin / more ->
usr / bin / more / usr / local -> usr / local / usr / root
-> usr / root

/usr/root/.bash_history -> usr / root / .bash_history /usr/root/a.out -> usr / root /


a.out /usr/root/hello.c -> usr / root / hello.c / tmp -> tmp [/ mnt] #

Now that you have established a good basic root file system on the hard disk. You can look everywhere in the new file system. And then uninstall the hard disk file system,

and type ' logout ' or' exit ' drop out Linux 0.11 system. The following information is displayed:

[/ Mnt] # cd /

[/] # umount / dev / hd1

[/] # logout

child 4 died with code 0000 [/ usr /

root] #

14.5.5 Hard disk Image On the root file system

Once you are on the hard disk Image Establish good file on a file system, you can make Linux 0.11 With its start as the root file system. This is achieved by modifying the

boot disk bootimage-0.11 The first file 509 , 510 Content bytes can be achieved. Please to follow these steps.

1. First Copy bootimage-0.11 with bochsrc.bxrc Two documents, produce bootimage-0.11-hd with bochsrc-hd.bxrc file.

2. edit bochsrc-hd.bxrc Profile. To which ' floppya: ' File name on the modified ' bootimage-0.11-hd ' And save.

589
14.6 0.11 compiled on Linux 0.11 kernel system

3. use UltraEdit Or any other modifications binary file editor ( winhex Etc.) Edit bootimage-0.11-hd binary file.

The first modification 509 , 510 Byte (original value should be 00 , 00 )for 01 , 03 , Represents the root file system device on the hard disk Image First 1

A partition. Then save and exit. If the file system is installed in a different partition, you need to modify ago 1 Bytes corresponding to your partition.

000001f0h: 00 00 00 00 00 00 00 00 00 00 00 00 0103 55 AA; .............. U?

You can now double-click bochsrc-hd.bxrc Configuration icon file, Bochs The system should quickly enter Linux 0.11 And shows the system of FIG. 14-5 In graphics.

Map 14-5 Hard disk Image File system on the file

14.6 in Linux 0.11 The build system 0.11 Kernel

At present author has been re-established with a gcc 1.40 Compiler environment Linux 0.11 System software package. The system is arranged to

Bochs Run simulation system and have configured the appropriate bochs Profile. The package can be obtained from the address below.

http://oldlinux.org/Linux.old/bochs/linux-0.11-devel-040329.zip

The package contains a README , Which described the package and usage of all files. If your system has been installed bochs System, you can

simply double-click configuration file bochs-hd.bxrc The hard disk icon to run Image File as the root file system Linux 0.11 . in/ usr / src / linux Directory type ' make

' Command can be compiled Linux 0.11 Kernel source, and generates a boot image file Image . If you need to output this Image Files can be backed up first bootimage-0.11-hd

File, then

590
14.7 In Redhat 9 system kernel compile Linux 0.11

Use the following command will put bootimage-0.11-hd Replaced with the new boot file. Direct Restart Bochs You can use the new compiler generated bootimage-0.11-hd To

boot the system.

[/ Usr / src / linux] # make

[/ Usr / src / linux] # dd bs = 8192 if = Image of = / dev / fd0 [/ usr / src /

linux] #

You can also use mtools Command of the new generation Image The first written document 2 A floppy disk image file diskb.img And then use software tools WinImage will diskb.img

middle' Image ' Remove the file.

[/ Usr / src / linux] # mcopy Image b:


Copying IMAGE
[/ Usr / src / linux] # mcopy System.map b: Copying
SYSTEM.MAP [/ usr / src / linux] # mdir b:

Volume in drive B is B. Directory for


B: / GCCLIB-1 TAZ
934 577 3-29-104 7: 49p
IMAGE 121 344 4-29-104 11: 46p
SYSTEM MAP 17162 4-29-104 11: 47p
README 764 3-29-104 8: 03p
4 File (s) 382976 bytes free
[/ Usr / src / linux] #

If you want to start a new guide Image Root file system on the floppy disk files rootimage-0.11 Used together, first edit before compilation Makefile File, use

# to comment out ' ROOT_DEV = ' Line of the content.

It can usually be completed very smoothly when compiling the kernel. Possible problem is that the compiler gcc Identification parameter is not '- mstring-ins' ,this is Linus To

compile yourself gcc Do extended experimental parameters, you can delete all Makefile In this parameter and then recompile the kernel. Another possible problem can not be

found gar Command, and the can / usr / local / bin / Under the ar Direct link or copy / renamed

gar It can be.

14.7 in Redhat 9 Under the build system Linux 0.11 Kernel

initial Linux The operating system kernel is in Minix 1.5.10 The extended version of the operating system Minix-i386 On cross-compiler development.

Minix 1.5.10 The version of the operating system is included with the AS Tanenbaum of" Minix Design and Implementation, "a book first 1 A version with Prentice Hall

Offering. This version of Minix Although it can run 80386 And compatible microcomputer, but did not use 80386 of 32 Bit mechanism. In order to carry out on the system 32 Bit

operating system development, Linus used Bruce Evans The patch will upgrade it to MINIX-386 And put GNU A series of development tools gcc , gld , emacs , bash And other

transplanted to Minix-386 on. On this platform, Linus Cross-compile, develop Linux 0.01 , 0.03 , 0.11 Other versions of the kernel. The authors have based on Linux The article

describes the mailing list, established a similar Linus At that time development platform, and successfully compile Linux Early versions of the kernel (see http://oldlinux.org Introduction

forum).

However, due to Minix 1.5.10 Outdated, but the establishment of the development platform is very cumbersome, so here only briefly explain how to modify the Linux 0.11 Version

of the kernel source code, so that it can be used in the current RedHat 9 Compile the operating system standard compiler environment, that can be run boot image file bootimage .

Readers can in general PC Machine or Bochs Run it and other virtual machine software. Here are the only major modification terms, all the tools can be used to modify the

Department diff After comparing modified and unmodified code before, to find out the difference.

591
14.7 In Redhat 9 system kernel compile Linux 0.11

If, over the unmodified code linux Directory, the modified code linux-mdf , You need to execute the following command:

diff -r linux linux-mdf> dif.out

Which documents dif.out That is included in the code all over the place modifications. It has been modified and can be good at RedHat 9 Under compiled Linux 0.11 Kernel source

code can be downloaded from the following address:

http://oldlinux.org/Linux.old/kernel/linux-0.11-040327-rh9.tar.gz
http://oldlinux.org/Linux.old/kernel/linux-0.11-040327-rh9.diff.gz

When a good start with a floppy boot image file compilation, the following information should be displayed on the screen:

Booting from Floppy ...


Loading system ...

Insert root floppy and press ENTER

If the "display Loding system ... " After no response, indicating that the hard disk controller does not recognize the kernel subsystem in the computer. You can find an

old-fashioned PC Machine to try again, or use vmware , bochs And other virtual machine software testing. When asked to insert the root disk, if simply press the Enter key, the root

file system information can not be loaded, and the crash appears. To run a complete

linux 0.11 Operating system, you also need to match with the root file system, to oldlinux.org Download a use on the site.

http://oldlinux.org/Linux.old/images/rootimage-0.11-for-orig

14.7.1 modify makefile file

in Linux 0.11 Kernel code file, almost every subdirectory includes a makefile File, they need to make the following modifications:

a. will gas => as, gld => ld . just now gas with gld It has been renamed called directly as with ld A.

b. as ( original gas) I have not - c Option, so to Makefile, It is necessary to remove it - c Compiler option. In the main kernel directory Linux

under makefile File, is in 34 Row.


c. Remove gcc Compiler flags options: - fcombine-regs - mstring-insns And all subdirectories Makefile The two

Options. in 94 Year gcc Manual had not found - fcombine-regs Options, and - mstring-insns Yes Linus On their own

gcc The modification increases the options so you and me gcc This certainly does not include the optimization options.

d. in gcc Compiler flags options, increase - m386 Options. In this way RedHat 9 Under compile the kernel image file is not

contain 80486 And above CPU Instruction, so that the core can run 80386 On the machine.

14.7.2 Modify assembler comments

as86 The compiler does not recognize c Comment statement language, it is necessary to use! Commented boot / bootsect.s File C Comment statement.

14.7.3 Align statement memory location align Modify the value of

in boot Three assembler in the directory, align The method used at present statement has changed. original align Value refers to the back belt of the power of the value

from memory location, and now needs to be given an integer value from address directly. Therefore, the original statement:

592
14.7 In Redhat 9 system kernel compile Linux 0.11

. align 3

Need to revise ( 2 of 3 Power value 2 ^ 3 = 8) :

. align 8

14.7.4 Modify the embedded Macro Assembler

Because of the as Continuous improvement, which is currently increasing degree of automation, and therefore do not need to be manually specify a variable used

CPU register. Thus kernel code __ asm __ ( "ax") All need to be removed. E.g fs / bitmap.c The first file 20 Row, 26 Row,

fs / namei.c The first file 65 OK fine.

Embedded assembly code, also need to remove all of the contents of the register is invalid declaration. E.g include / string.h B 84 Row:

: "Si", "di", "ax", "cx");

Need to be modified to look like this:

:);

14.7.5 c Program variables in assembler statements, indicate

In the development Linux 0.11 Used in the assembler, in reference C You need to add the program variables in the variable name with an underscore character '_', and the

current gcc The compiler can be used to identify those compiled directly referenced c Variable, it is necessary to compile a program (including an embedded assembler statement)

all c Remove the underscore before the variable. E.g boot / head.s The first program 15 Line statement:

. globl _idt, _gdt, _pg_dir, _tmp_floppy_area

We need to change:

. globl idt, gdt, pg_dir, tmp_floppy_area

The first 31 Line statement:

lss _stack_start,% esp

We need to change:

lss stack_start,% esp

14.7.6 Debugging display function in protected mode

Before entering protected mode, you can use ROM BIOS middle int 0x10 Call display information on the screen, but after entering the protected mode, which can not use the

interrupt calls. In order to understand the state of internal data structures and the protected mode kernel operating environment, we can use the following function data check_data32

() 5 . Although the kernel printk () Display function, but it needs to call tty_write (),

In the kernel is not fully up and running this function can not be used. This one check_data32 () Function can print what you're interested in on the screen after entering the

protected mode. Page feature only use it or not, does not affect the results, because virtual memory 4M Within just use the first page table directory entry, and the page table

directory from the physical address 0 Start, plus the kernel data segment base address 0 ,and so 4M The range, the same virtual memory and physical memory and linear memory

address. linus This may also be had advisedly, that this setting more convenient to use ☺ .

Embedded assembler statements using the method, see 5.4.3.1 Section below.

/*
* Effects: on screen display with a 32-bit hexadecimal integer.

* Parameters: value - integer to be displayed.

* pos -- Screen position, character width of 16 units, for example 2, i.e., the display 32 indicates the start of the character width at the upper left corner.

* Returns: None.

* If you are using assembler, to ensure that the function is compiled and linked into the kernel .gcc usage compilation is as follows:

* pushl pos // pos use your actual data instead of, for example pushl $ 4

* pushl value // pos and value can be any valid addressing modes

5 This function is provided by a friend on oldlinux.org forum notrump.

593
14.8 kernel debugging using the bochs

* call check_data32
*/
inline void check_data32 (int value, int pos) {

__asm__ __volatile __ ( % // 0 - value containing the value to be displayed; ebx - screen position.

"Shl $ 4, %% ebx \ n \ t " // the pos value multiplied by 16, the start address of the display memory plus VGA,

"Addl $ 0xb8000, %% ebx \ n \ t " // ebx obtained display character position in the upper left corner of the screen to start.

"Movl $ 0xf0000000, %% eax \ n \ t " // 4-bit mask is provided.


"Movb $ 28, %% cl \ n " // set the initial value of the right bit.
"1: \ n \ t"
"movl % 0, %% edx \ n \ t " // get the value to be displayed value edx

"Andl %% eax, %% edx \ n \ t " Take edx eax // specified has 4 bits.
"Shr %% cl, %% edx \ n \ t " // right 28, 4-bit value that is taken in edx.
"Add $ 0x30, %% dx \ n \ t " // This value is converted into ASCII code.

"Cmp $ 0x3a, %% dx \ n \ t " // If the 4-bit value is less than 10, the forward jump to numeral 2.
"Jb2f \ n \ t" "add
$ 0x07, %% dx \ n " // Otherwise, plus 7, to convert the value to a corresponding character A-F.

"2: \ n \ t" "add


$ 0x0c00, %% dx \ n \ t " // set the display properties.

"Movw %% dx, (%% ebx) \ n \ t " // display the value into memory.
"Sub $ 0x04, %% cl \ n \ t " // prepare a hexadecimal display, the right number of bits minus 4.

"Shr $ 0x04, %% eax \ n \ t " // bit right shift mask 4.


"Add $ 0x02, %% ebx \ n \ t " // update the display memory location.

"Cmpl $ 0x0, %% eax \ n \ t " // right end has moved out of the mask value (8 have been displayed in hexadecimal)?

"Jnz1b \ n" // there is a value to be displayed, the backward jump to a label.

:: "m" (value), "b" (pos));}

14.8 use bochs Debugging kernel

(use System.map Information in the file)

594
references

references

[1] Intel Co. INTEL 80386 Programmer's Reference Manual 1986, INTEL CORPORATION, 1987. [2]

James L. Turley. Advanced 80386 Programming Technigues. Osborne McGraw-Hill, 1988. [3] Brian W. Kernighan, Dennis M. Ritchie. The C programming Language.

Prentice-Hall 1988. [4] Leland L. Beck System Software:. An Introduction to Systems Programming, 3 nd. Addison-Wesley, 1997. [5] Richard M. Stallman, Using and Porting the GNU

Compiler Collection, the Free Software Foundation, 1998. [6] The Open Group Base Specifications Issue 6 IEEE Std 1003.1-2001, The IEEE and The Open Group. [7] David A

Rusling, The Linux Kernel, 1999. http://www.tldp.org/ [8] Linux Kernel Source Code , http://www.kernel.org/ [9] Digital co.ltd. VT100 User Guide, http://www.vt100.net/ [10] Clark L.

Coleman. Using Inline Assembly with gcc. Http://oldlinux.org/Linux.old/ [11] John H. Crawford, Patrick P. Gelsinger. Programming the 80386. Sybex, 1988. [12] FreeBSD Online

Manual, http://www.freebsd.org/cgi/man.cgi [13] Andrew S.Tanenbaum The Luyou Shan, Shi Zhenchuan translation, operating system Tutorial MINIX Design and Implementation.

World Publishing Company, 1990.4 [14] Maurice J. Bach , And Chen Bao Jue, Wang Xu, willow pure record, Feng translated snow-capped mountains, UNIX Operating system design.

Machinery Industry Press, 2000.4 [15] John Lions With, Jinyuan translation, Leon's UNIX Source code analysis, Machinery Industry Press, 2000.7 [16] Andrew S. Tanenbaum The Translation,

operating system, Wang Peng, Jinyuan et al: Design and Implementation (first 2 Version), Electronic Industry Press, 1998.8 [17] Alessandro Rubini , Jonathan With, Wei Yongming,

Luo Gang, Jiang Jun translation, Linux Device drivers, China Electric Power Press, 2002.11 [18] Daniel P. Bovet, Marco Cesati With, Chen Lijun, Feng Rui, cattle Xinyuan translation,

in-depth understanding LINUX Kernel, China Electric Power Press 2001. [19] Chang Tsai Hung. Microcomputers ( PC Series) interface control tutorial, Tsinghua University Press, 1992.

[20] Li Fenghua, ZHOU Li-hua, Zhao Lisong. MS-DOS 5.0 Core analysis. Xi'an University of Electronic Science and Technology Press, 1992. [21] RedHat 7.3 Online manual operating

system. http://www.plinux.org/cgi-bin/man.cgi [22] W.Richard Stevens The Jinyuan such as translation, UNIX High-level programming environment. Machinery Industry Press, 2000.2

[23] Linux Weekly Edition News. Http://lwn.net/ [24] PJ Plauger. The Standard C Library. Prentice Hall, 1992 [25] Free Software Foundation. The GNU C Library. Http://www.gnu.org/

2001 [26] Chuck Allison. The Standard C Library. C / C ++ Users Journal CD-ROM, Release 6. 2003 [27] Bochs simulation system. Http://bochs.sourceforge.net/

595
Appendix 1 constant major core

appendix

appendix 1 The main constant kernel

1. Maximum number of processes


The maximum process system (task) number 64 .

2. Timer list number


# define TIME_REQUESTS 64 // can have up to 64 timer list (64 tasks).

3. Operational status of the process

# define TASK_RUNNING 0 // process is running or ready.


# define TASK_INTERRUPTIBLE 1 // process in an interruptible wait state.
# define TASK_UNINTERRUPTIBLE 2 // process is in an uninterruptible wait state, mainly for I / O operations to wait.

# define TASK_ZOMBIE 3 // process is in a dead state, has stopped running, but the parent process has not signaled.

# define TASK_STOPPED 4 // The process has stopped.

4. Memory page length


PAGE_SIZE = 4096 byte
5. Data block length
BLOCK_SIZE = 1024 byte
6. At the same time the number of open file system
NR_FILE = 64
7. Processes simultaneously open files
NR_OPEN = 20
8. System main device number
versus Minix Equipment numbering system of the same, so you can use minix File system.

0 - not used (nodev) 1 - / dev /


mem Memory device.

2 - / dev / fd Floppy device.

3 - / dev / hd Hard disk device.

4 - / dev / ttyx serial tty terminal device.


5 - / dev / tty tty terminal device.
6 - / dev / lp Printing equipment.

7 - unnamed pipes unnamed pipes.

9. Method hard disk logical unit numbers


due to 1 A hard disk can exist 1--4 Partition, so the hard disk partition also be specified depending on the partition with minor number. Thus the hard disk logical device

number consists of the following ways:

Master device number = device number * 256 + Minor

number that is dev_no = (major << 8) + minor

Two drives all logical device number shown in the table below.

Schedule 1 Hard disk logical device number

Logical device number The corresponding device description file

0x300 / Dev / hd0 The first representative of the 1 Hard drive

--596--
Appendix 1 constant major core

0x301 / Dev / hd1 Represents 1 The first hard disk 1 Partition

0x302 / Dev / hd2 Represents 1 The first hard disk 2 Partition

0x303 / Dev / hd3 Represents 1 The first hard disk 3 Partition

0x304 / Dev / hd4 Represents 1 The first hard disk 4 Partition

0x305 / Dev / hd5 The first representative of the 2 Hard drive

0x306 / Dev / hd6 Represents 2 The first hard disk 1 Partition

0x307 / Dev / hd7 Represents 2 The first hard disk 2 Partition

0x308 / Dev / hd8 Represents 2 The first hard disk 3 Partition

0x309 / Dev / hd9 Represents 2 The first hard disk 4 Partition

among them 0x300 with 0x305 Which does not correspond to the partition, but on behalf of the entire hard disk. From linux Kernel 0.95 After using this version is

no longer cumbersome naming, but now using the same naming method.

--597--
Appendix 2 kernel data structures

appendix 2 Kernel data structures

Here lists the main focus of the kernel data structures, and gives a brief description, specify the file and the specific location of each structure is located. As you read

reference.

1. Execute the file structure a.out ( include / a.out.h The first 6 Row)
a.out ( Assembly out ) Executable file header format structure.

struct exec {
unsigned long a_magic // perform file magic number. Use N_MAGIC and other macro access.

unsigned a_text // the code length, the number of bytes.

unsigned a_data // Data length, the number of bytes.

unsigned a_bss // length uninitialized data area in the file, the number of bytes.

unsigned a_syms // the length of the symbol table file, the number of bytes.

unsigned a_entry // execution start address.

unsigned a_trsize // the code length of relocation information, the number of bytes.

unsigned a_drsize // Data length relocation information, the number of bytes.

};

2. File locking operation structure flock ( include / fcntl.h , 43 Row)


File locking operation of the data structure.

struct flock {
short l_type; // lock type (F_RDLCK, F_WRLCK, F_UNLCK).
short l_whence; // start offset (SEEK_SET, SEEK_CUR or SEEK_END).
off_t l_start; // blocked at the start of the lock. Relative offset (number of bytes).

off_t l_len; // blocked Locked size; if it is 0, compared to the end of the file.

pid_t l_pid; // locked process id.


};

3. sigaction Data structures ( include / signal.h , 48 Row)


sigaction Data structure.

struct sigaction {
void (* sa_handler) (int);
sigset_t sa_mask; int
sa_flags;
void (* sa_restorer) (void);};

sa_handler Action is to be taken for a signal corresponding to the specified. Above may be SIG_DFL ,or SIG_IGN To ignore this signal may be a pointer to a function of

the signal processing.

sa_mask Given mask on the signal, when the signal blocking program execution processing of these signals. In addition, the signal causes the trigger signal processing will

also be blocked, unless the SA_NOMASK Mark.

sa_flags Designated set of signal change signal processing procedure.

sa_restorer Restore function pointer from the library Libc Provided, for cleaning the user mode stack.

4. Terminal window size attribute structure ( include / termios.h , 36 Row)


Window size ( Window size) Attribute structure. In a windowing environment it can be used to screen-based applications. ioctls middle TIOCGWINSZ

with TIOCSWINSZ It can be used to set or read the information.

struct winsize {

--599--
Appendix 2 kernel data structures

unsigned short ws_row; The number of lines of characters // window.

unsigned short ws_col; The number of character columns // window.

unsigned short ws_xpixel; // window width, pixel value.


unsigned short ws_ypixel; // window height, pixel value.
};

5. termio (s) structure( include / termios.h , 44 Row)


AT & T system V of termio structure. Wherein the data length of the control character NCC = 8 .

struct termio {
unsigned short c_iflag; // input mode flag.
unsigned short c_oflag; // output mode flag.
unsigned short c_cflag; // control mode flag.
unsigned short c_lflag; // local mode flag.
unsigned char c_line; // line discipline (rate).
unsigned char c_cc [ NCC ]; // control character array.

};

POSIX of termios Structure (first 54 Row). Wherein the data length of the control character NCC = 17 .

struct termios {
unsigned long c_iflag; // input mode flag.
unsigned long c_oflag; // output mode flag.
unsigned long c_cflag; // control mode flag.
unsigned long c_lflag; // local mode flag.
unsigned char c_line; // line discipline (rate).
unsigned char c_cc [ NCCS ]; // control character array.

};

Two terminals defined above data structure termio with termios Respectively in two categories UNIX Series (or carved Long), termio It is in AT & T

system V Defined, and termios Yes POSIX Standard specified. Two structure is basically the same, just termio Using the short integer type definition mode flag is set, and termios With

a length of custom mode flag set. Due to the current two structures are in use, so for compatibility, most systems are at the same time support them. In addition, previously used a

similar sgtty Structure, has the basic need.

6. Time structure ( include / time.h The first 18 Row)

struct tm {
int tm_sec; // the number of seconds [0,59].

int tm_min; // number of minutes [0,59].


int tm_hour; Number [0,59] // hours.
int tm_mday; // number of days a month [0,31].
int tm_mon; // 1 year in January [0,11].
int tm_year; // number of years from the beginning of 1900.

int tm_wday; // 1 day of the week [0,6] (0 = Sunday).


int tm_yday; // 1 Day of the year [0,365].
int tm_isdst; // Daylight Savings Time flag.

};

7. File access / modify the structure ( include / utime.h The first 6 Row)

struct utimbuf {
time_t actime; // file access time. From 1970.1.1: 0: 0: 0 Number of seconds to start.

time_t modtime; // file modification time. From 1970.1.1: 0: 0: 0 Number of seconds to start.

--600--
Appendix 2 kernel data structures

};

8. Buffer header structure buffer_head ( include / linux / fs.h The first 68 Row)
Buffer header data structure. Commonly used in the program bh To represent buffer_head Abbreviations type of the variable.

struct buffer_head {
char * b_data; // pointer to the data block (data block of 1024 bytes).
unsigned long b_blocknr; // block numbers.

unsigned short b_dev; // number of data source devices (not represented by 0).

unsigned char b_uptodate; // update flag: Indicates whether the data has been updated.

unsigned char b_dirt; // modify flags: 0 unmodified, 1 has been modified.

unsigned char b_count; // Use the number of users of the data block.

unsigned char b_lock; // if the buffer is locked, 0 unlocked; 1- locked.


struct task_struct * b_wait; // point to wait for the buffer to unlock the task.

struct buffer_head * b_prev; // a former (four pointer for buffer management).


struct buffer_head * b_next; // next block.
struct buffer_head * b_prev_free; // before a free block.
struct buffer_head * b_next_free; // next free block.
};

9. Memory disk inode structure ( include / linux / fs.h The first 93 Row)
This is in memory i Node structure. On-disk inode structure d_inode It includes only the first 7 item.

struct m_inode {
unsigned short i_mode; // file type and attributes (rwx bits).
unsigned short i_uid; // user id (file owner identifier).
unsigned long i_size; // File Size (bytes).
unsigned long i_mtime; // file modification time (from 1970.1.1: 0, counting seconds).

unsigned char i_gid; // set id (the file belongs to the group).


unsigned char i_nlinks; // file directory entry number of links.

unsigned short i_zone [9]; // Direct (0-6), indirect (7) or double indirectly (8) a logical block number. // zone is meant the

zone, can be translated into segments, or logical blocks.

// the following fields in memory.

struct task_struct * I_wait; // wait for the i-node process.


unsigned long i_atime; // last access time.
unsigned long i_ctime; // i node itself modified.
unsigned short i_dev; // device number i node is located.

unsigned short i_num; // i node number.


unsigned short i_count; // the number of i-nodes to be used, i 0 indicates that the node is idle.

unsigned char i_lock; // lock mark.


unsigned char i_dirt; // modified (dirty) mark.
unsigned char i_pipe; // pipeline signs.
unsigned char i_mount; // install signs.
unsigned char i_seek; // search flag (when lseek).
unsigned char i_update; // update flag.
};

10. File Structure ( include / linux / fs.h The first 116 Row)
File structure for the file handle i Establish a relationship between the nodes.

struct file {
unsigned short f_mode; // file operation mode (RW bit)

--601--
Appendix 2 kernel data structures

unsigned short f_flags; // File Open and sign control.


unsigned short f_count; // the corresponding file handle (file descriptor) number.

struct m_inode * F_inode; // i pointing to the corresponding node.

off_t f_pos; // file location (write offset).


};

11. Disk superblock structure ( include / linux / fs.h The first 124 Row)
Superblock structure memory disk. Superblock structure on disk d_super_block It includes only the first 8 item.

struct super_block {
unsigned short s_ninodes; // nodes.
unsigned short s_nzones; // number of logical blocks.

unsigned short s_imap_blocks; // i-node number of blocks occupied by the bitmap.

unsigned short s_zmap_blocks; // logical block number of data blocks occupied by the bitmap.

unsigned short s_firstdatazone; // first logical block number of data. unsigned short s_log_zone_size; // log (block
number / logical blocks). (Base 2). unsigned long s_max_size;
The maximum length // file.

unsigned short s_magic; // magic number of the file system.

// The following fields are only in memory.

struct buffer_head * s_imap [8]; // i node bitmap buffer block pointer array (occupying 8, may represent a 64M). struct buffer_head *
s_zmap [8]; // bitmap logic block buffer block pointer array (occupying 8). unsigned short s_dev;
// super block device number is located.

struct m_inode * s_isup; // i root node of the file system is mounted. (Isup-super i)
struct m_inode * s_imount; // i is attached to the node.
unsigned long s_time; // Change the time.

struct task_struct * s_wait; // Wait for the process of the superblock.

unsigned char s_lock; // locked flag.


unsigned char s_rd_only; // read-only flag.
unsigned char s_dirt; // modified (dirty) mark.
};

12. Directory entry structure ( include / linux / fs.h The first 157 Row)
File directory entry structure.

struct dir_entry {
unsigned short inode; // i node.
char name [ NAME_LEN ]; // file name.
};

13. Hard disk partition table structure ( include / linux / hdreg.h The first 52 Row)
Hard disk partition table structure. See the following list information.

struct partition {
unsigned char boot_ind; // boot flags. 0x80- bootable operating system partition.
unsigned char head ; // partition start head number.

unsigned char sector ; // start sector number of the partition (bits 0-5) and the starting cylinder number upper 2 bits (bits 6-7).

unsigned char cyl; // starting cylinder number of the partition the lower 8 bits.

unsigned char sys_ind; // partition type byte. 0x0b-DOS; 0x80-Old Minix; 0x83-Linux
unsigned char end_head; // end head number partition.
unsigned char end_sector; // end sector number (bits 0-5) and an end cylinder 2 bits (bits 6-7) is high.

unsigned char end_cyl; // lower end of the cylinder number eight.

unsigned int start_sect; // partition start physical sector number (the count starts from 0).

--602--
Appendix 2 kernel data structures

unsigned int nr_sects; // number of sectors occupied by partitions.

};

In order to realize a plurality of operating systems to share resources hard disk, the hard disk can be logically divided into 1--4 Partitions. Between the sector number of each

partition are contiguous. The partition table 4 Table entries, each entry is made 16 Byte, information corresponding to a partition, partition size and storing the start and end of the

cylinder number, track number, sector number and the guide mark. Stored in the hard disk's partition table 0 cylinder 0 Head first 1 Sectors 0x1BE - 0x1FD

Place. 4 Partition at the same time only one partition is bootable.

14. Descriptor structure ( include / linux / head.h The first 4 Row)


CPU Described in simple format breaks.

struct desc_struct { // define data structures segment descriptor. The structure described only each description

unsigned long a, b; // operator is composed of 8 bytes, a total of each descriptor table 256.

} desc_table [256];

15. i387 Use of structure ( include / linux / sched.h The first 40 Row)
This is a structural math coprocessor used, mainly for the save process when switching i387 The execution status information.

struct i387_struct {
long cwd; // Control Word (Control word).
long swd; // Status word (Status word).
long twd; // marker word (Tag word).
long fip; // coprocessor code pointers.
long fcs; // coprocessor code segment register.

long foo; // offset memory operand.


long fos; // value of the segment memory operation.

long st_space [20]; 10 // 8-byte accumulator coprocessor.


};

16. Task state segment structure ( include / linux / sched.h The first 51 Row)
Task State Segment data structure (see Appendix).

struct tss_struct {
long back_link; / * 16 high bits zero * /
long esp0;
long ss0; / * 16 high bits zero * /
long esp1;
long ss1; / * 16 high bits zero * /
long esp2;
long ss2; / * 16 high bits zero * /
long cr3;
long eip;
long eflags; long
eax, ecx, edx, ebx; long
esp;
long ebp;
long esi; long
edi;
long es; / * 16 high bits zero * /
long cs; / * 16 high bits zero * /
long ss; / * 16 high bits zero * /
long ds; / * 16 high bits zero * /
long fs; / * 16 high bits zero * /

--603--
Appendix 2 kernel data structures

long gs; / * 16 high bits zero * /


long ldt; / * 16 high bits zero * /
long trace_bitmap; / * Bits: trace 0, bitmap 16-31 * /
struct i387_struct i387;};

17. Process (task) data structure task ( include / linux / sched.h The first 78 Row)
This is the task (process) data structure, otherwise known as the process descriptor.

struct task_struct {
long state // task of running state (-1 inoperable, 0 run (ready),> 0 has stopped).
long counter // task running time count (decrement) (ticks), run time slice.
long priority // Run priority number. When the task starts running counter = priority, the greater the long run.

long signal // signal. Bitmap, each bit represents a signal, the signal value of the bit offset value = +1.

struct sigaction sigaction [32] // flag information signal and performs the operation attribute structure, a corresponding signal will be executed. long blocked

// mask process signal (signal corresponding to the bit map).

int exit_code // task exit code execution stops, the parent process will take.

unsigned long start_code // code segment address.

unsigned long end_code // the code length (number of bytes).

unsigned long end_data // the code length + data length (number of bytes).

unsigned long brk // Total length (number of bytes).

unsigned long start_stack // stack segment address.

long pid // process identification number (process ID).

long father // parent process ID.

long pgrp // parent group number.

long session // session number.

long leader // session leader.


unsigned short uid // user identification number (user id).

unsigned short euid // effective user id.


unsigned short suid // Save the user id.
unsigned short gid // Group ID (group id).
unsigned short egid // effective group id.

unsigned short sgid // set id saved.


long alarm // alarm timer value (number of ticks).

long utime // user mode run time (ticks).


long stime // run time system state (ticks).
long cutime // child process run time user mode.

long cstime // child process state system uptime.

long start_time // process starts running time.


unsigned short used_math // flag: whether to use a coprocessor.
int tty // process uses sub-tty device number. -1 indicates no use.
unsigned short umask // Create a file attribute mask bits.

struct m_inode * pwd // current working directory i-node structure.

struct m_inode * root I // root node structure.


struct m_inode * executable // perform file i-node structure.
Close the file handle bitmap flag // execute unsigned long close_on_exec. (See include / fcntl.h) struct file * filp [NR_OPEN] // file
structure pointer list, a maximum of 32. Entry number that is the value of the file descriptor. struct desc_struct ldt [3]
// Local Descriptor Table task. 0- empty, 1- snippet cs, 2- data and stack segments ds & ss.

struct tss_struct tss TSS information structure // process.


};

18. tty Pending queue structure ( include / linux / tty.h The first 16 Row)

--604--
Appendix 2 kernel data structures

tty Waiting queue data structure.

struct tty_queue {
unsigned long data; // wait queue buffer pointer current data (number of characters [??]). // For serial

terminal, then store the serial port address.

unsigned long head ; // data buffer head pointer.


unsigned long tail; // data buffer tail pointer.
struct task_struct * Proc_list; // wait for the process list. char buf [ TTY_BUF_SIZE ];
// buffer queue.
};

19. tty structure( include / linux / tty.h The first 45 Row)

tty data structure.


struct tty_struct {
struct termios termios ; // io terminal control characters and attribute data structure.

int pgrp; // belongs to the process group.

int stopped; // stop sign.


void (* write ) (Struct tty_struct * Tty); // tty write function pointer.

struct tty_queue read_q; // tty read queue.


struct tty_queue write_q; // tty write queue.
struct tty_queue secondary; // tty auxiliary queue (stored character sequence mode specification),

};
extern struct tty_struct tty_table []; // tty structure array.

20. File status structure ( include / sys / stat.h The first 6 Row)

struct stat {
dev_t st_dev; // number of the file containing the device.

ino_t st_ino; // file i node number.


umode_t st_mode; // file attributes (see below).
nlink_t st_nlink; // Specify the number of connections file.

uid_t st_uid; // No user files (logo).


gid_t st_gid; // set number of files.
dev_t st_rdev; // device number (if the file is a character special file or block the file).

off_t st_size; // file size (in bytes) (if the file is a regular file).
time_t st_atime; // last (last) access time.
time_t st_mtime; // Last Modified.
time_t st_ctime; // node last modified time.
};

twenty one. File access and modification time structure ( include / sys / times.h The first 6 Row)

struct tms {
time_t tms_utime; // CPU time used by the user.
time_t tms_stime; // system (core) CPU time.
time_t tms_cutime; User CPU time // child process terminated used.
time_t tms_cstime; The system CPU time // child process terminated used.

};

22. ustat structure( include / sys / types.h The first 39 Row)

File system parameter structure, a function ustat () .

--605--
Appendix 2 kernel data structures

struct ustat {
daddr_t f_tfree; The total number of free blocks // System.

ino_t f_tinode; // i idle total number of nodes.

char f_fname [6]; // file system name.


char f_fpack [6]; // name of the compressed file system.

};

The last two fields are not in use, always return NULL pointer.

twenty three. System name of the header file ( include / sys / utsname.h The first 6 Row)

struct utsname {
char sysname [9]; // name of the version of the operating system.

char nodename [9]; // associated with the realization of the network node name.

char release [9]; // this implementation of the current release level.

char version [9]; // The issue of the release level.


char machine [9]; Hardware Type Name // system operation.

};

twenty four. Block device configuration requested item ( kernel / blk_drv / blk.h The first twenty three Row)

The following is the structure of a queue entry request. Which if dev = -1 , Then do not use that. struct request {

int dev; // use the device number, when unused -1.

int cmd; // command (READ or WRITE).


int errors; // generated when the number of errors made.

unsigned long sector ; // start sector. (1 sector = 2)


unsigned long nr_sectors; // read / write the number of sectors.

char * buffer; // data buffer.


struct task_struct * Waiting; // wait for local operations performed tasks completed.

struct buffer_head * Bh; // buffer header pointer (include / linux / fs.h, 68).
struct request * Next; // points to the next request entry.

};

--606--
Appendix 3 80x86 protection operating mode

appendix 3 80x86 Protection operating mode

1.80386 Outline
80386 Is an advanced 32 Bit microprocessor, designed for multi-tasking operating system, and for applications requiring high performance design.

32 Bit registers and data channels support 32 Bit addressing modes and data types, the processor can address up to 4GB As well as physical memory 64TB ( 2 46 Bytes) of virtual

memory. On-chip memory management include address translation registers, advanced multitasking hardware protection mechanisms and paged virtual memory mechanism.

Below for system programming, an overview of the use of 80386 These basic principles.

1.1 System register

System designed for programming system registers include the following categories:

Flag register EFALGS ; Memory management register; control register; debug register; test register. System flag register EFLAGS Controls I / O , Maskable

interrupt, virtual debugging, task switching and protection mode and multi-tasking environments 8086 Execution of the program. Where the main symbol see photos 1 Fig.

31 twenty three 15 7 0

R IO O D I T S Z
000000000000O0V
M F0N T PL F F F F F F0A F0P F1C F

Drawings 1 System flag register

Wherein the system flags: VM - virtual 8086 mode; RF - Recovery signs; NT - Nested task flag; IO PL - I / O Privileged class notation;

IF - Interrupt enable flag.

Memory management registers have 4 One for the segment memory management:

• GDTR - Global Descriptor Table Register ( Global Descriptor Table Register) ;

• LDTR - Local Descriptor Table Register ( Local Descriptor Table Register) ;

• IDTR - Interrupt Descriptor Table Register ( Interrupt Descriptor Table Register) ;

• TR - Task register. Wherein the first two registers ( GDTR, LDTR) Pointing to descriptor table GDT with LDT . IDTR Register points to interrupt vector table.

TR Information required by the processor register points to the current task.

80386 A total of 4 Control registers, respectively, CR0 , CR1 , CR2 with CR3 . See attached format 2 Fig.

31 twenty three 15 7 0

Page directory base address register Reserved


CR3
Page Directory Base Register (PDBR) Reserved

Page abnormalities linear address Page


CR2
Fault Linear Address

Reserved
CR1
Reserved

P Reserved E T E M P

G Reserved T S M P E CR0

--607--
Appendix 3 80x86 protection operating mode

Drawings 2 System Control Registers

Control register CR0 Containing overall control flag system. among them:

• PE - Protected Mode open position ( Protection Enable , Bit 0 ). If this bit set, it will cause the processor to start running in protected mode.

• MP - Coprocessor existence flag ( Math Present , Bit 1 ). For control WAIT Function instruction to run with the co-processing.

• EM - Simulation Control ( Emulation , Bit 2 ). Indicates whether the need for emulation coprocessor.

• TS - Task switching ( Task Switch , Bit 3 ). Whenever a task switch processor will set this bit and the test bit coprocessor instructions

explained before.

• ET - Extension type ( Extention Type , Bit 4 ). This bit indicates the type of co-processor system contained (YES 80287

still is 80387 ).
• PG - Paging operations ( Paging , Bit 31 ). This bit indicates whether the page tables using the linear address into a physical address.

1.2 Memory Management

Memory management mainly related to memory addressing mechanism processors. 80x86 The two-step segment forms a logical address into a physical address of the

physical memory.

• Converting section, a logical address composed of selectors and offsets by the inner segment to segment a linear address;

• Page conversion to convert the linear address to a physical address corresponding to the. This step is optional.

When paging is turned on, and by the conversion section converts the foregoing pages together, i.e. the two conversion stages to achieve from a logical address to a

physical address.

1.3 Segment transformation

Drawings 3 The processor is shown how to convert a logical address into a linear address. During the conversion process CPU Use the following data structures:

• Descriptor ( Segment Descriptors );


• Descriptor Table ( Descriptor tables );

• Selectors ( Selectors );
• Segment register ( Segment Registers ).

15 0 31 0
logical address: Selectors Offset

Descriptor Table

Base address
directory descriptor +

131 222 1211 0


Linear Address: Page Page table entry page offset value

Drawings 3 Converting a schematic section

--608--
Appendix 3 80x86 protection operating mode

1.4 Descriptor
Descriptor to CPU Providing the information to map the logical address to a linear address necessary. Descriptor is a program compiler, linker, loader or operating system

created. The following figure shows two general Format Descriptor. All types of descriptors having one of these two formats. The meaning of each field of the segment descriptor

see FIG. 4 Fig.

31 twenty three 15 7 0

AVL TYPE
Base address (BASE) Length limit (LIMIT) Base address (BASE)
GXO P DPL 1 4
bits 31..24 bits 19..16 bits 23..16
A

The base address (BASE) bits 15..0 Segment length limit (LIMIT) bits 15..0 0

a. program code and data segments descriptor

31 twenty three 15 7 0

AVL
Base address (BASE) Length limit (LIMIT) Base address (BASE)
GXO P DPL 0 TYPE 4
bits 31..24 bits 19..16 bits 23..16

The base address (BASE) bits 15..0 Segment length limit (LIMIT) bits 15..0 0

b. for a particular system segment descriptor

Drawings 4 General Format Descriptor

Base address ( BASE ): In the definition section 4GB Linear position in space. Three parts of the processor will be combined into a group address 32

Bit value. Segment limit long ( LIMIT ): Defines the maximum length of the segment. Processor indefinite length segments form a two part composition 20 Bit value. The

processor will be based on particle size ( Granularity Value) of the bit field to interpret the actual meaning of the segment limit field length: when to 1 A byte as a unit, is

defined as the maximum 1MB Length in bytes; when to 4KB A byte as a unit, is defined as the maximum 4GB Length in bytes. In the long-time load value will be left 12 Bit.

Graininess( Granularity ): Specifies the length field value means limit the meaning of the representative. When is 0 , The limit value of unit length 1 Bytes; when the bit 1 When

the unit is indefinite length 4KB byte. Types of( TYPE ): Used to distinguish the various types of descriptors. Descriptor privilege level ( Descriptor Privilege Level - DPL ): For

protection. A total of 4 level: 0-3 . 0 Level is the highest privilege level, 3 Level is the lowest privilege level. Paragraph presence bits ( Segment-Present bit - P ): If this bit is

zero, then the descriptor is invalid for the address transformation process. When the point descriptor segment selector is loaded into the register, the processor will send

an abnormality signal. Access Bit ( Accessed bit - A ): When a processor accesses through the segment will set this bit.

1.5 Descriptor Table

Descriptor is stored in the descriptor table, the descriptor table there are two types:

• Global Descriptor Table ( Global descriptor table - GDT );

• Local Descriptor Table ( Local descriptor table - LDT ). Descriptor table by 8 A memory array entry descriptor in bytes of the configuration, see FIG.

5 Fig. Descriptor table is variable in length, containing up to 8192 ( 2 13 ) Descriptor. But for GDT Table, which is the first descriptor (Index 0 ) Is not used.

--609--
Appendix 3 80x86 protection operating mode

1N+2N+3M

The GDTR (or LDTR) N N +

Drawings 5 Descriptor indicates intent

The processor is through the use of GDTR with LDTR Location register GDT And the current table LDT table. This register contains the length of the two descriptor table in a

linear base address and the address table. instruction lgdt with sgdt For access GDTR Registers; Instruction lldt with sldt

For access LDTR register. lgdt Using a memory 6 Operand bytes to load GDTR Register. The first two bytes represent the length of the descriptor table, after 4 Byte base

address is described in the descriptor table. Note, however, visit LDTR An instruction register lldt As used operand is a 2 Byte operand representing global descriptor table GDT

A character selector item description. The selectors corresponding GDT Descriptor table entries should correspond to a local descriptor table. Meaning selectors see FIG. 6 Explained.

31 twenty three 15 7 0

Base address (BASE) 2

Table length limit (LIMIT) 0

Drawings 6 GDTR Contents

1.6 Selectors (the Selectors)

Selector is part of the logical address for designating a descriptor, which is designated by a descriptor table in which the index and a descriptor entry completed. Drawings 7

It illustrates the format selectors. The meaning of each field is:

Index value ( Index) : Used to select descriptor table specifies 8192 A description of a character. The index value is multiplied by the processor 8( Byte length descriptor),

plus the descriptor table and the base address to access the segment descriptor specified in the table.

Table indicator ( Table Indicator - TI) : Specify the selection identifier descriptor table referenced. Value 0 Indicates that the specified GDT Table, value 1 Indicates that the

specified current LDT table.

Requestor's privilege level ( Requestor's Privalege Level - RPL) : For protection.

15 3210

Index TI RPL
(INDEX)

Drawings 7 Format selector

--610--
Appendix 3 80x86 protection operating mode

due to GDT A first table entry (index value 0) Is not used, therefore an index value having 0 Table indicator value and also 0 Selectors (i.e. directed GDT First

selector) may be used as a blank ( null) Selectors. When a segment register (not a CS

or SS ) Loading empty when a selector, and the processor will not generate an exception. However, if the use of this segment will register an exception when accessing memory.

For the segment registers are initialized to fall into the accident has not been used in reference to, this feature is very useful.

1.7 Segment register

Processor information descriptor is stored in segment registers, and thus avoid the query descriptor table each time a memory access. Each segment

register has a "visible" part and a "invisible" part, see Fig. 8 Fig. The visible part of the segment address register is operated by a program, as if they are simply 16

Bit registers. Invisible part is handled by the processor.

Loading operation of these registers using a common program instructions that can be divided into two categories:

1. Direct load instructions; e.g., MOV , POP , LDS , LSS , LGS , LFS . These instructions refers explicitly specified segment

register.
2. Implicit load instruction; e.g., far call CALL And far jump JMP . These instruction implicitly references CS Segment register, and with

The new value is loaded into CS in. These instructions will use the program 16 Bit selector loaded into the visible portion of the segment register, the processor will

automatically breaks a base address in the descriptor table from the description, segment limit length, type, and other information is loaded into the invisible part of the

segment registers in the go with.

16 visible portion Hide part

CS

SS

DS

ES

FS

GS

Drawings 8 Segment register

2. Transform page

In the second stage of address translation, CPU Converts linear addresses into physical addresses. Address translation at this stage to achieve the basic functions of

page-based virtual memory and paging system level protection. Page change this step is optional, only set up conversion page CR0 of PG Function bits after the bit is initialized when

the software provided by the operating system. If you need to implement multiple virtual operating system 8086 Task-based protection mechanisms paging or page-based virtual

memory, then you must set this bit.

2.1 Page frame (frames) (Page Frame)

A physical memory page frame address is contiguous 4K Byte units. It byte boundaries, fixed size.

2.2 Linear address (Linear Address)

A linear address specified by the page table, the page table and a page in the page offset value to point to a corresponding physical address indirectly. Drawings 9 It

illustrates the format of the linear addresses.

31 twenty two twenty one 12 11 0

Page Page An offset value

directory (DIR) (PAGE) (the OFFSET)

Drawings 9 Linear address

--611--
Appendix 3 80x86 protection operating mode

Drawings 10 It shows a method to convert linear processor address into a physical address. By using two page tables, a linear processor address field of the page

directory ( DIR) , Page field ( PAGE) And an offset field ( OFFSET) Translated into a corresponding physical address. Addressing mechanism uses page directory field value as an

index of the linear address of the page directory, the page table field using the index value as specified in the page table directory pages, using a page table offset field as

identified in byte memory page offset value.

131 222 1211 0

Linear Address: Page directory page table entry page offset value

Page directory table Page table Page frame

Page table entry

Page directory entry Physical address

CR3

Drawings 10 Linear address into a physical address

2.3 Page table (Page Table)

Just a simple page table 32 An array of page bit indicator. Page table itself is also a memory, so it contains 4K Bytes of memory, can hold 1K More 32 Bit key.

This uses two page tables to locate a memory page. The highest level is a page directory, page directory can be positioned up to 1K Second-level page table, and each page

table may be located up to two 1K Memory pages. Therefore, a page directory location of all page tables that can be addressed 1M Memory page ( 2 20 ). Since each page contains a

memory 4K byte( 2 12 ), A final page directory specified by the page table can be addressed 80386 The entire physical address space ( 2 * 20 2 12 = 2 32 ).

Current physical address of the page directory is stored in CPU Control register CR3 In, this register is also called a page directory base address register ( page directory

base register - PDBR ). Memory management software can choose to use a directory page, or a page directory for each task using only all the tasks, you can also use a

combination of two task page directory.

2.4 Page table entry (Page-Table Entries)

A page table page table entry used by all levels are the same, see Fig format 11 Fig.

31 12 11 0

U/ R/
Page frame address bits 31..12 Available
P
(PAGE FRAME ADDRESS) (AVAIL) 0 0 DA 0 0
S W

Drawings 11 Page table entry structure

Among them, the page frame address ( PAGE FRAME ADDRESS) It specifies a physical memory starting address. Because the memory pages are located 4K

On the border, so its low 12 Bit is always 0 . In a page directory, the page frame address of the page table entry is the starting address of a page table; in a second stage page

table, the page frame address of the page table entry contains the page frame address of the desired memory operation.

Presence bits ( PRESENT - P ) To determine whether a page table entry can be used to address the conversion process. P = 1 It indicates that the item is available. When a

directory entry or a second entry level P = 0 , Then when the entry is invalid, address translation can not be used. At this time, all other than the entry

--612--
Appendix 3 80x86 protection operating mode

Special bits are available to the program; processor these bits are not tested.

when CPU When trying to use a page table entry for address translation, if any at this time a page table entry P = 0 , The processor will send abnormal signals page. For

software support paged virtual memory system, the page does not exist ( page-not-present) The exception handler can put the requested page into physical memory. At this time,

the instruction that caused the exception may be re-executed.

I visited ( Accessed - A ) And modified ( Dirty - D ) Bit provides information about the pages used. In addition to the modified bits of the page directory entries, these bits

are set by hardware, but not reset.

Before a memory read or write operation, the processor has access to the provision of the relevant bits and secondary directory page table entry. Before a write to an

address covered by the page table entry two, the processor will set the two page table entry modified bit, and the page directory entry is modified bit unused. When demand for

memory exceeds the actual amount of physical memory, it supports paged virtual memory operating system can use these bits to determine which pages can be removed from

memory. The operating system must be reset and is responsible for detecting these bits.

Read / Write bit ( Read / Write - R / W ) And user / super user bits ( User / Supervisor - U / S ) Are not used for address conversion, but for protecting the mechanism of the

paging stage, while the processor is operating in the address translation process.

2.5 Conversion page cache

In order to increase the maximum efficiency of address conversion, the processor recently used page table data stored in the cache on the chip. Operating system

designers must refresh the cache when the current page table change, you can use one of two ways:

1. by using MOV Command to reload CR3 Page directory base register;

2. By switching to perform a task.

3. Multitasking( Multitasking )
In order to provide an effective, multi-tasking mechanism protected, 80x86 Use some special data structure. Support multi-task operation of registers and data

structures main task state segment ( Task State Segment ) And task register ( Task register ). Using these data structures, CPU It can quickly switch from one task to perform

another task, and save the contents of the original task.

3.1 TSS (Task State Segment - TSS)


All information is stored in the processor management task a particular type of segment, i.e., Task State Segment TSS ,see Attachment 12 Fig. Gives TSS Format. Which

fields can be divided into two categories:

• Wherein the read-only information processor set static field (the gray portion in the drawing);

• Each dynamic field is set when a task switching processor will update. Figure SS0: ESP0 Task stack pointer for storing run-time kernel mode. SS1: ESP1 with SS2:

ESP2 Respectively correspond to the privileged class run 1 with 2 When using the stack pointer, the two privilege levels in Linux Not used. And the task operating in the user

mode stack pointer is held in the SS: ESP Register.

31 twenty three 15 7 0

I / O Map base address ( MAP BASE) 0,000,000,000,000,000 64

0,000,000,000,000,000 Local Descriptor Table ( LDT) Selector 60

0,000,000,000,000,000 GS 5C

0,000,000,000,000,000 FS 58

0,000,000,000,000,000 DS 54

0,000,000,000,000,000 SS 50

0,000,000,000,000,000 CS 4C

0,000,000,000,000,000 ES 48

EDI 44

ESI 40

--613--
Appendix 3 80x86 protection operating mode

EBP 3C

ESP 38

EBX 34

EDX 30

ECX 2C

EAX 28

EFLAGS twenty four

Instruction pointer ( EIP) 20

Page directory base address register CR3 ( PDBR ) 1C

0,000,000,000,000,000 SS2 18

ESP2 14

0,000,000,000,000,000 SS1 10

ESP1 0C

0,000,000,000,000,000 SS0 08

ESP0 04

0,000,000,000,000,000 Previous mission TSS Descriptor 00

Drawings 12 Task State Segment TSS

Task State Segment TSS It may be in any position of the linear space. TSS Like other segments, using the descriptor is defined. access TSS Descriptor task

switching will result. Thus, in most systems will descriptor DPL (Descriptor privilege level) field is set to the highest privilege level 0 , So switching trusted software to

perform tasks can allow only. TSS Descriptor in global descriptor table only GDT in.

3.2 Task register


Task register ( Task Register - TR ) A similar effect to the general segment registers, by pointing to it TSS To determine the currently executing task. It also has 16 Bit of

visible and non-visible part of the section. Visible portion of selectors for GDT Select a table TSS Descriptor, the processor used to store the invisible portion of the base address

and the segment limit value descriptor length. instruction LTR with STR A visible part modifications and read task register operands used by the instruction is a 16 Bit selector.

In addition, there is an offer for TSS Indirect, task gate descriptor references the protected ( Task Gete Descriptor ). This descriptor is the descriptor base address bits in a

general format 15..0 Field (first 3 , 4 Byte) is stored in a TSS Descriptor selector, and using which the privilege level field ( DPL) Usage rights to control descriptor is performing task

switching. See below for the interrupt descriptor table IDT DESCRIPTION descriptor.

In the following 4 Kind of case, CPU You will switch tasks performed:

1. A reference to the current task execution TSS Descriptor JMP or CALL instruction;

2. A reference to the current task execution of a task gate JMP or CALL instruction;

3. He cited the interrupt descriptor table ( IDT ) Task door interrupt or exception;

4. When nested task flag NT When set, a current task execution IRET instruction.

4. Interrupt and exception

Interrupt and exception control is a special type of conversion. They alter the normal program flow away for further processing events (e.g., external events, error reporting,

or exception condition). The main difference is that interrupt the abnormal commonly used in the treatment interruption CPU External asynchronous events, and abnormal

--614--
Appendix 3 80x86 protection operating mode

It is the process CPU In the implementation process itself detected the problem.

There are two external interrupt sources: the CPU of INTR Maskable interrupt input pin and NMI The non-maskable interrupt input pin. Similarly, there are two types of

anomalies: the CPU Detected erroneous, or abandon the trap event and the programmed "soft interrupt" (such as INT 3 Instructions, etc.).

The processor using the identification number (interrupt number) to identify each type of interrupt or exception. The processor can identify nonmaskable interrupt NMI

And an abnormality identification number is determined in advance, the range 0 To 31 ( 0x00-0x1f ). At present, these numbers do not all use, undetermined number of Intel The

company reserved for future use.

Maskable interrupt identification number of the interrupt by an external controller (e.g. 8259A Programmable Interrupt Controller) is determined, and CPU The notification

interrupt identification stage CPU . 8259A The interrupt number assigned can be programmed to specify the range of usable identification number is 32 To 255

( 0x20-0xff ). Linux The system will 32-47 Assigned to the maskable interrupt, the remaining 48-255 Used to identify other soft interrupt. when Linux

Only a number 128 ( 0x80 ) As a system interrupt vector number to call.

4.1 Interrupt Descriptor Table

Interrupt Descriptor Table ( Interrupt Descriptor Table - IDT ) Each interrupt or exception processing corresponding event identification numbers and program instructions

associated with a character described. versus GDT with LDT similar, IDT Is a 8 Byte descriptor array, but its 1 A descriptor may contain items. Processor interrupt number by

multiplying the number of abnormal 8 To index IDT In the corresponding descriptor. IDT It can be located anywhere in physical memory. The processor is using IDT register( IDTR ) To

locate IDT of. Modify and copy IDT Instruction is LIDT with SIDT . versus GDT Like operating table, IDT Also use 6 Byte data memory address as an operand. The first two bytes long

table limit, after 4 It is linear byte base address table.

4.2 IDT descriptor

In the interrupt descriptor table IDT It may contain any of a three descriptor:

• Task gate ( Task gates );

• Interrupt gate ( Interrupt gates );

• Trap Door ( Trap gates ); Drawings 13 Given the task gate, doors and trap doors

interruption format descriptors.

31 twenty three 15 7 0

(Unused) P DPL 0 0 1 0 1 (Unused) 4

TSS Segment selector ( SELECTOR ) (Unused) 0

80X86 task gate descriptor

31 twenty three 15 7 0

Offset value ( OFFSET) Place 31..16 P DPL 0 1 1 1 0 0 0 0 (Not used) 4

Segment selector ( SELECTOR ) An offset value (the OFFSET) bits 15..0 0

80X86 interrupt gate descriptor

31 twenty three 15 7 0

Offset value ( OFFSET) Place 31..16 P DPL 0 1 1 1 1 0 0 0 (Not used) 4

Segment selector ( SELECTOR ) An offset value (the OFFSET) bits 15..0 0

80X86 trapdoor descriptor

Drawings 13 Task gate, door and interrupt descriptor trap door

--615--
Appendix 3 80x86 protection operating mode

4.3 Interrupt tasks and interrupt the process

Just like CALL Command can call a procedure or task as an interrupt or exception can "call" interrupt handler, the program is a process or a task. When

an interrupt or exception, CPU Use interrupt or exception identification number to index IDT Descriptor table. in case CPU When the index to break a door or trap

door, it calls the process; if it is a task gate, it will cause a task switch.

Interrupt gate or trap doors indirectly point to a process that will be executed in the context of the current mission. Gate descriptor segment selector points GDT Or current LDT

The executable segment descriptor. Offset field value gate descriptor points to the beginning of the interrupt or exception handling process.

80X86 Executing an interrupt or exception handling process with the way CALL Instruction calls a procedure is very similar, but slightly different both in the use of the stack.

Before the original interrupt instruction pointer onto the stack, the original flag register EFLAGS The content is pushed onto the stack. For the segment-related abnormalities, CPU An

error code will be pushed on the stack exception handler.

For the interrupt process ends the processing returns to operation, the interrupt return instruction IRET versus RET Similar, but IRET To remove the push-down stack EFLAGS

value, ESP It will be more incremental 4 Bytes.

Interrupt gate and trap doors difference is that the interrupt enable flag IF Impact. By the interrupt vector door interruptions caused by reset IF Because other interrupts

interfere with the current process to avoid interruptions. Subsequent IRET Instruction will be restored from the stack IF The original value; without interruption change generated by

the trap door IF .

IDT Table task gate descriptor indirectly points to a task state segment TSS . Task gate descriptor segment selector points GDT

Table a TSS Descriptor. When an interrupt or generate abnormal point IDT In a task gate descriptor, it will cause the task switching, interrupt processing which will separate

task. Linux The system does not use the task gate descriptor.

--616--
appendix

appendix 4 ASCII Stopwatch

DEC HEX CHR DEC HEX CHR DEC HEX CHR


0 00 NUL 43 2B + 86 56 V
1 01 SOH 44 2C , 87 57 W
2 02 STX 45 2D - 88 58 X
3 03 ETX 46 2E . 89 59 Y
4 04 EOT 47 2F / 90 5A Z
5 05 ENQ 48 30 0 91 5B [
6 06 ACK 49 31 1 92 5C \
7 07 BEL 50 32 2 93 5D ]
8 08 BS 51 33 3 94 5E ^
9 09 TAB 52 34 4 95 5F _
10 0A LF 53 35 5 96 60 `
11 0B VT 54 36 6 97 61 a
12 0C FF 55 37 7 98 62 b
13 0D CR 56 38 8 99 63 c
14 0E SO 57 39 9 100 64 d
15 0F SI 58 3A : 101 65 e

16 10 DLE 59 3B ; 102 66 f
17 11 DC1 60 3C < 103 67 g
18 12 DC2 61 3D = 104 68 h
19 13 DC3 62 3E > 105 69 i
20 14 DC4 63 3F ? 106 6A j
twenty one 15 NAK 64 40 @ 107 6B k
twenty two 16 SYN 65 41 A 108 6C l
twenty three 17 ETB 66 42 B 109 6D m
twenty four 18 CAN 67 43 C 110 6E n
25 19 EM 68 44 D 111 6F o
26 1A SUB 69 45 E 112 70 p
27 1B ESC 70 46 F 113 71 q
28 1C FS 71 47 G 114 72 r
29 1D GS 72 48 H 115 73 s
30 1E RS 73 49 I 116 74 t
31 1F US 74 4A J 117 75 u
32 20 (Space) 75 4B K 118 76 v
33 twenty one ! 76 4C L 119 77 w
34 twenty two " 77 4D M 120 78 x
35 twenty three # 78 4E N 121 79 y
36 twenty four $ 79 4F O 122 7A z
37 25 % 80 50 P 123 7B {
38 26 & 81 51 Q 124 7C |
39 27 ' 82 52 R 125 7D }
40 28 ( 83 53 S 126 7E ~
41 29 ) 84 54 T 127 7F DEL
42 2A * 85 55 U

--617--
index

index

Since the kernel code is relatively large, a lot of variables / functions to be used / called in a lot of program source code, and therefore more difficult to index them. This index

gives the definition of its main program file name, line number and page numbers based on a variable or function name.

___strtok __NR_fork include / unistd.h, 62, Pretreatment is defined as

include / string.h, 275, Defined as a variable macro

__GNU_EXEC_MACROS__ include / a.out.h, 4, Pretreatment __NR_fstat include / unistd.h, 88, Pretreatment is defined as

is defined as macro macro

__LIBRARY__ init / main.c, 7, Pretreatment is defined __NR_ftime include / unistd.h, 95, Pretreatment is defined as

as macro macro

lib / close.c, 7, Pretreatment is defined as macro __NR_getegid include / unistd.h, 110, Pretreatment is defined as

lib / dup.c, 7, Pretreatment is defined as macro macro

lib / _exit.c, 7, Pretreatment is defined as macro __NR_geteuid include / unistd.h, 109, Pretreatment is defined as

macro
lib / open.c, 7, Pretreatment is defined as macro
__NR_getgid include / unistd.h, 107, Pretreatment is defined as
lib / execve.c, 7, Pretreatment is defined as macro
macro
lib / setsid.c, 7, Pretreatment is defined as macro
__NR_getpgrp include / unistd.h, 125, Pretreatment is defined as
lib / string.c, 13, Pretreatment is defined as macro
macro
lib / wait.c, 7, Pretreatment is defined as macro
__NR_getpid include / unistd.h, 80, Pretreatment is defined as
lib / write.c, 7, Pretreatment is defined as macro
macro
__NR_access include / unistd.h, 93, Pretreatment is defined as
__NR_getppid include / unistd.h, 124, Pretreatment is defined as
macro
macro
__NR_acct
__NR_getuid include / unistd.h, 84, Pretreatment is defined as
include / unistd.h, 111, Pretreatment is defined as macro
macro
__NR_alarm
__NR_gtty include / unistd.h, 92, Pretreatment is defined as
include / unistd.h, 87, Pretreatment is defined as macro
macro
__NR_break
__NR_ioctl include / unistd.h, 114, Pretreatment is defined as
include / unistd.h, 77, Pretreatment is defined as macro
macro
__NR_brk
__NR_kill include / unistd.h, 97, Pretreatment is defined as
include / unistd.h, 105, Pretreatment is defined as macro
macro
__NR_chdir
__NR_link include / unistd.h, 69, Pretreatment is defined as
include / unistd.h, 72, Pretreatment is defined as macro
macro
__NR_chmod include / unistd.h, 75, Pretreatment is defined as
__NR_lock include / unistd.h, 113, Pretreatment is defined as
macro
macro
__NR_chown include / unistd.h, 76, Pretreatment is defined as
__NR_lseek include / unistd.h, 79, Pretreatment is defined as
macro
macro
__NR_chroot
__NR_mkdir include / unistd.h, 99, Pretreatment is defined as
include / unistd.h, 121, Pretreatment is defined as macro
macro
__NR_close
__NR_mknod include / unistd.h, 74, Pretreatment is defined as
include / unistd.h, 66, Pretreatment is defined as macro
macro
__NR_creat
__NR_mount include / unistd.h, 81, Pretreatment is defined as
include / unistd.h, 68, Pretreatment is defined as macro
macro
__NR_dup
__NR_mpx include / unistd.h, 116, Pretreatment is defined as
include / unistd.h, 101, Pretreatment is defined as macro
macro
__NR_dup2
__NR_nice include / unistd.h, 94, Pretreatment is defined as
include / unistd.h, 123, Pretreatment is defined as macro
macro
__NR_execve include / unistd.h, 71, Pretreatment is defined as
__NR_open include / unistd.h, 65, Pretreatment is defined as
macro
macro
__NR_exit
__NR_pause include / unistd.h, 89, Pretreatment is defined as
include / unistd.h, 61, Pretreatment is defined as macro
macro
__NR_fcntl
__NR_phys include / unistd.h, 112, Pretreatment is defined as
include / unistd.h, 115, Pretreatment is defined as macro
macro

--618--
index

__NR_pipe include / unistd.h, 122, Pretreatment is defined as macro

include / unistd.h, 102, Pretreatment is defined as macro __NR_utime include / unistd.h, 90, Pretreatment is defined as

__NR_prof macro

include / unistd.h, 104, Pretreatment is defined as macro __NR_waitpid include / unistd.h, 67, Pretreatment is defined as

__NR_ptrace macro

include / unistd.h, 86, Pretreatment is defined as macro __NR_write include / unistd.h, 64, Pretreatment is defined as

__NR_read macro

include / unistd.h, 63, Pretreatment is defined as macro __va_rounded_size include / stdarg.h, 9, Pretreatment is

__NR_rename include / unistd.h, 98, Pretreatment is defined as defined as macro

macro _A_OUT_H include / a.out.h, 2, Pretreatment is defined as

__NR_rmdir macro

include / unistd.h, 100, Pretreatment is defined as macro _BLK_H kernel / blk_drv / blk.h, 2, Pretreatment is defined as macro

__NR_setgid
include / unistd.h, 106, Pretreatment is defined as macro _BLOCKABLE kernel / sched.c, 24, Pretreatment is defined

__NR_setpgid include / unistd.h, 117, Pretreatment is defined as as macro

macro _bmap fs / inode.c, 72, Defined as a function

__NR_setregid include / unistd.h, 131, Pretreatment is defined as

macro _bucket_dir lib / malloc.c, 60, defined as struct Types


__NR_setreuid include / unistd.h, 130, Pretreatment is defined as of
macro _C include / ctype.h, 7, Pretreatment is defined as macro

__NR_setsid
include / unistd.h, 126, Pretreatment is defined as macro _CONFIG_H include / config.h, 2, Pretreatment is defined as

__NR_setuid macro

include / unistd.h, 83, Pretreatment is defined as macro _CONST_H include / const.h, 2, Pretreatment is defined as

__NR_setup macro

include / unistd.h, 60, Pretreatment is defined as macro _ctmp include / ctype.h, 14, Defined as a variable
__NR_sgetmask include / unistd.h, 128, Pretreatment is defined

as macro lib / ctype.c, 9, Defined as a variable


__NR_sigaction include / unistd.h, 127, Pretreatment is defined _ctype include / ctype.h, 13, Defined as a variable
as macro

__NR_signal lib / ctype.c, 10, Defined as a variable


include / unistd.h, 108, Pretreatment is defined as macro _CTYPE_H include / ctype.h, 2, Pretreatment is defined as
__NR_ssetmask include / unistd.h, 129, Pretreatment is defined macro
as macro _D include / ctype.h, 6, Pretreatment is defined as macro
__NR_stat
include / unistd.h, 78, Pretreatment is defined as macro _ERRNO_H include / errno.h, 2, Pretreatment is defined as
__NR_stime macro
include / unistd.h, 85, Pretreatment is defined as macro _exit include / unistd.h, 208, Defined as a function prototype
__NR_stty
include / unistd.h, 91, Pretreatment is defined as macro
lib / _exit.c, 10, Defined as a function
__NR_sync _FCNTL_H include / fcntl.h, 2, Pretreatment is defined as
include / unistd.h, 96, Pretreatment is defined as macro
macro
__NR_time _FDREG_H include / fdreg.h, 7, Pretreatment is defined as
include / unistd.h, 73, Pretreatment is defined as macro
macro
__NR_times _fs kernel / traps.c, 34, Pretreatment is defined as macro
include / unistd.h, 103, Pretreatment is defined as macro

__NR_ulimit _FS_H include / fs.h, 7, Pretreatment is defined as


include / unistd.h, 118, Pretreatment is defined as macro
macro
__NR_umask _get_base include / sched.h, 214, Pretreatment is defined as macro
include / unistd.h, 120, Pretreatment is defined as macro

__NR_umount include / unistd.h, 82, Pretreatment is defined as


_hashfn fs / buffer.c, 128, Pretreatment is defined as
macro
macro
__NR_uname _HDREG_H include / hdreg.h, 7, Pretreatment is defined as
include / unistd.h, 119, Pretreatment is defined as macro
macro
__NR_unlink include / unistd.h, 70, Pretreatment is defined as
_HEAD_H include / head.h, 2, Pretreatment is defined as
macro
macro
__NR_ustat

--619--
index

_HIGH include / stddef.h, 5, Pretreatment is defined as macro

include / sys / wait.h, 7, Pretreatment is defined as macro _S include / ctype.h, 9, Pretreatment is defined as macro

_I_FLAG
kernel / chr_drv / tty_io.c, 29, Pretreatment is defined as macro kernel / sched.c, 23, Pretreatment is defined as macro
_L _SC_ARG_MAX include / unistd.h, 33, Pretreatment is defined
include / ctype.h, 5, Pretreatment is defined as macro as macro
_L_FLAG _SC_CHILD_MAX include / unistd.h, 34, Pretreatment is
kernel / chr_drv / tty_io.c, 28, Pretreatment is defined as macro defined as macro
_LDT _SC_CLOCKS_PER_SEC include / unistd.h, 35, Pretreatment
include / sched.h, 156, Pretreatment is defined as macro is defined as macro
_LOW _SC_JOB_CONTROL include / unistd.h, 38, Pretreatment is
include / sys / wait.h, 6, Pretreatment is defined as macro defined as macro
_MM_H _SC_NGROUPS_MAX include / unistd.h, 36, Pretreatment is
include / mm.h, 2, Pretreatment is defined as macro defined as macro
_N_BADMAG include / a.out.h, 36, Pretreatment is defined _SC_OPEN_MAX include / unistd.h, 37, Pretreatment is
as macro defined as macro
_N_HDROFF include / a.out.h, 40, Pretreatment is defined as _SC_SAVED_IDS include / unistd.h, 39, Pretreatment is
macro defined as macro
_N_SEGMENT_ROUND include / a.out.h, 95, Pretreatment _SC_VERSION include / unistd.h, 40, Pretreatment is defined
is defined as macro as macro
_N_TXTENDADDR include / a.out.h, 97, Pretreatment is _SCHED_H include / sched.h, 2, Pretreatment is defined as

defined as macro macro


_NSIG _set_base include / sched.h, 188, Pretreatment is defined as macro

include / signal.h, 9, Pretreatment is defined as macro

_O_FLAG _set_gate include / asm / system.h, 22, Pretreatment is defined as macro

kernel / chr_drv / tty_io.c, 30, Pretreatment is defined as macro

_P _set_limit include / sched.h, 199, Pretreatment is defined as macro

include / ctype.h, 8, Pretreatment is defined as macro

_PC_CHOWN_RESTRICTED include / unistd.h, 51, Pretreatment _set_seg_desc include / asm / system.h, 42, Pretreatment is defined as

is defined as macro macro


_PC_LINK_MAX include / unistd.h, 43, Pretreatment is _set_tssldt_desc include / asm / system.h, 52, Pretreatment is defined as
defined as macro macro
_PC_MAX_CANON include / unistd.h, 44, Pretreatment is _SIGNAL_H include / signal.h, 2, Pretreatment is defined as
defined as macro macro
_PC_MAX_INPUT include / unistd.h, 45, Pretreatment is _SIZE_T include / sys / types.h, 5, Pretreatment is defined as macro

defined as macro

_PC_NAME_MAX include / unistd.h, 46, Pretreatment is include / time.h, 10, Pretreatment is defined as macro
defined as macro include / stddef.h, 10, Pretreatment is defined as macro
_PC_NO_TRUNC include / unistd.h, 49, Pretreatment is
include / string.h, 9, Pretreatment is defined as macro
defined as macro
_SP include / ctype.h, 11, Pretreatment is defined as macro
_PC_PATH_MAX include / unistd.h, 47, Pretreatment is

defined as macro
_STDARG_H include / stdarg.h, 2, Pretreatment is defined as
_PC_PIPE_BUF include / unistd.h, 48, Pretreatment is defined
macro
as macro
_STDDEF_H include / stddef.h, 2, Pretreatment is defined as
_PC_VDISABLE include / unistd.h, 50, Pretreatment is defined
macro
as macro
_STRING_H_ include / string.h, 2, Pretreatment is defined as
_POSIX_CHOWN_RESTRICTED include / unistd.h, 7, Pretreatment
macro
is defined as macro
_SYS_STAT_H include / sys / stat.h, 2, Pretreatment is defined
_POSIX_NO_TRUNC include / unistd.h, 8, Pretreatment is
as macro
defined as macro
_SYS_TYPES_H include / sys / types.h, 2, Pretreatment is defined
_POSIX_VDISABLE include / unistd.h, 9, Pretreatment is
as macro
defined as macro
_SYS_UTSNAME_H include / sys / utsname.h, 2, Pretreatment is
_POSIX_VERSION include / unistd.h, 5, Pretreatment is
defined as macro
defined as macro
_SYS_WAIT_H include / sys / wait.h, 2, Pretreatment is defined
_PTRDIFF_T
as macro
include / sys / types.h, 15, Pretreatment is defined as macro
_syscall0

--620--
index

include / unistd.h, 133, Pretreatment is defined as macro include / termios.h, 133, Pretreatment is defined as macro

_syscall1 B110 include / termios.h, 136, Pretreatment is defined as macro

include / unistd.h, 146, Pretreatment is defined as macro

_syscall2 B1200 include / termios.h, 142, Pretreatment is defined as macro

include / unistd.h, 159, Pretreatment is defined as macro

_syscall3 B134 include / termios.h, 137, Pretreatment is defined as macro

include / unistd.h, 172, Pretreatment is defined as macro

_TERMIOS_H include / termios.h, 2, Pretreatment is defined as B150 include / termios.h, 138, Pretreatment is defined as macro

macro

_TIME_H B1800 include / termios.h, 143, Pretreatment is defined as macro

include / time.h, 2, Pretreatment is defined as macro

_TIME_T B19200 include / termios.h, 147, Pretreatment is defined as macro

include / sys / types.h, 10, Pretreatment is defined as macro

include / time.h, 5, Pretreatment is defined as macro B200 include / termios.h, 139, Pretreatment is defined as macro

_TIMES_H
include / sys / times.h, 2, Pretreatment is defined as macro B2400 include / termios.h, 144, Pretreatment is defined as macro

_TSS
include / sched.h, 155, Pretreatment is defined as macro B300 include / termios.h, 140, Pretreatment is defined as macro

_TTY_H
include / tty.h, 10, Pretreatment is defined as macro B38400 include / termios.h, 148, Pretreatment is defined as macro

_U
include / ctype.h, 4, Pretreatment is defined as macro B4800 include / termios.h, 145, Pretreatment is defined as macro

_UNISTD_H include / unistd.h, 2, Pretreatment is defined as

macro B50 include / termios.h, 134, Pretreatment is defined as macro

_UTIME_H include / utime.h, 2, Pretreatment is defined as

macro B600 include / termios.h, 141, Pretreatment is defined as macro

_X
include / ctype.h, 10, Pretreatment is defined as macro B75 include / termios.h, 135, Pretreatment is defined as macro

ABRT_ERR
include / hdreg.h, 47, Pretreatment is defined as macro B9600 include / termios.h, 146, Pretreatment is defined as macro

ACC_MODE fs / namei.c, 21, Pretreatment is defined as

macro bad_flp_intr kernel / blk_drv / floppy.c, 233, Defined as a

access function

include / unistd.h, 189, Defined as a function prototype bad_rw_intr kernel / blk_drv / hd.c, 242, Defined as a

acct function

include / unistd.h, 190, Defined as a function prototype BADNESS fs / buffer.c, 205, Pretreatment is defined as

add_entry fs / namei.c, 165, Defined as a macro

function BBD_ERR include / hdreg.h, 50, Pretreatment is defined as

add_request macro

kernel / blk_drv / ll_rw_blk.c, 64, Defined as a function BCD_TO_BIN init / main.c, 74, Pretreatment is defined

add_timer as macro

include / sched.h, 144, Defined as a function prototype beepcount kernel / chr_drv / console.c, 697, Defined as a variable

kernel / sched.c, 272, Defined as a function

alarm blk_dev
include / unistd.h, 191, Defined as a function prototype kernel / blk_drv / ll_rw_blk.c, 32, defined as struct Types of

ALRMMASK kernel / blk_drv / blk.h, 50, defined as struct Types of

kernel / chr_drv / tty_io.c, 17, Pretreatment is defined as macro blk_dev_init init / main.c, 46, Defined as a function

argv prototype

init / main.c, 165, Defined as a variable kernel / blk_drv / ll_rw_blk.c, 157, Defined as a function
argv_rc blk_dev_struct kernel / blk_drv / blk.h, 45, defined as struct Types
init / main.c, 162, Defined as a variable of
asctime block_read fs / read_write.c, 18, Defined as a function

include / time.h, 35, Defined as a function prototype prototype

attr fs / block_dev.c, 47, Defined as a function

kernel / chr_drv / console.c, 77, Defined as a variable BLOCK_SIZE include / fs.h, 49, Pretreatment is defined

B0 as macro

--621--
index

BLOCK_SIZE_BITS include / fs.h, 50, Pretreatment is include / termios.h, 132, Pretreatment is defined as macro

defined as macro cfgetispeed include / termios.h, 216, Defined as a function

block_write prototype

fs / read_write.c, 19, Defined as a function prototype cfgetospeed include / termios.h, 217, Defined as a function

fs / block_dev.c, 14, Defined as a function prototype

bmap cfsetispeed include / termios.h, 218, Defined as a function

fs / inode.c, 140, Defined as a function prototype

include / fs.h, 176, Defined as a function prototype cfsetospeed include / termios.h, 219, Defined as a function

bottom prototype

kernel / chr_drv / console.c, 73, Defined as a variable change_ldt fs / exec.c, 154, Defined as a

bounds function

kernel / traps.c, 48, Defined as a function prototype change_speed kernel / chr_drv / tty_ioctl.c, 24, Defined as a

bread function

fs / buffer.c, 267, Defined as a function CHARS include / tty.h, 30, Pretreatment is defined as macro

include / fs.h, 189, Defined as a function prototype

bread_page fs / buffer.c, 296, Defined as a chdir include / unistd.h, 194, Defined as a function prototype

function

include / fs.h, 190, Defined as a function prototype check_disk_change fs / buffer.c, 113, Defined

breada as a function

fs / buffer.c, 322, Defined as a function include / fs.h, 168, Defined as a function prototype

include / fs.h, 191, Defined as a function prototype chmod include / sys / stat.h, 51, Defined as a function prototype

brelse
fs / buffer.c, 253, Defined as a function include / unistd.h, 195, Defined as a function prototype

include / fs.h, 188, Defined as a function prototype chown include / unistd.h, 196, Defined as a function prototype

brk
include / unistd.h, 192, Defined as a function prototype chr_dev_init init / main.c, 47, Defined as a function

BRKINT prototype

include / termios.h, 84, Pretreatment is defined as macro kernel / chr_drv / tty_io.c, 347, Defined as a function

BS0 chroot include / unistd.h, 197, Defined as a function prototype

include / termios.h, 122, Pretreatment is defined as macro

BS1 CIBAUD include / termios.h, 162, Pretreatment is defined as macro

include / termios.h, 123, Pretreatment is defined as macro

BSDLY clear_bit fs / bitmap.c, 25, Pretreatment is defined as

include / termios.h, 121, Pretreatment is defined as macro macro

bucket_desc lib / malloc.c, 52, defined as struct Types clear_block fs / bitmap.c, 13, Pretreatment is defined as

of macro

bucket_dir lib / malloc.c, 77, Defined as a cli


variable include / asm / system.h, 17, Pretreatment is defined as macro

buffer_block include / fs.h, 66, Defined as CLOCAL include / termios.h, 161, Pretreatment is defined as macro

a type
BUFFER_END include / const.h, 4, Pretreatment is defined clock include / time.h, 30, Defined as a function prototype

as macro

buffer_head include / fs.h, 68, defined as struct Types clock_t include / time.h, 16, Defined as a type

of
buffer_init fs / buffer.c, 348, Defined as a CLOCKS_PER_SEC include / time.h, 14, Pretreatment is

function defined as macro

include / fs.h, 31, Defined as a function prototype close include / unistd.h, 198, Defined as a function prototype

buffer_memory_end init / main.c, 99, Defined

as a variable CMOS_READ init / main.c, 69, Pretreatment is defined

buffer_wait fs / buffer.c, 33, Defined as a as macro

variable kernel / blk_drv / hd.c, 28, Pretreatment is defined as macro

BUSY_STAT include / hdreg.h, 31, Pretreatment is defined as CODE_SPACE mm / memory.c, 49, Pretreatment is defined

macro as macro

calc_mem command kernel / blk_drv / floppy.c, 121, Defined as a variable

mm / memory.c, 413, Defined as a function

CBAUD con_init

--622--
index

include / tty.h, 66, Defined as a function prototype fs / exec.c, 46, Defined as a function

kernel / chr_drv / console.c, 617, Defined as a function CRTSCTS include / termios.h, 163, Pretreatment is defined as macro

con_write
include / tty.h, 73, Defined as a function prototype crw_ptr fs / char_dev.c, 19, Defined as a type

kernel / chr_drv / console.c, 445, Defined as a function

controller_ready crw_table fs / char_dev.c, 85, Defined as a

kernel / blk_drv / hd.c, 161, Defined as a function variable

coprocessor_error kernel / traps.c, 58, Defined as a CS5 include / termios.h, 152, Pretreatment is defined as macro

function prototype

coprocessor_segment_overrun kernel / traps.c, 52, Defined CS6 include / termios.h, 153, Pretreatment is defined as macro

as a function prototype

copy_buffer CS7 include / termios.h, 154, Pretreatment is defined as macro

kernel / blk_drv / floppy.c, 155, Pretreatment is defined as macro

copy_mem kernel / fork.c, 39, Defined as a CS8 include / termios.h, 155, Pretreatment is defined as macro

function

copy_page csi_at
mm / memory.c, 54, Pretreatment is defined as macro kernel / chr_drv / console.c, 391, Defined as a function

copy_page_tables include / sched.h, 29, Defined as a function csi_J


prototype kernel / chr_drv / console.c, 239, Defined as a function

mm / memory.c, 150, Defined as a function csi_K


copy_process kernel / fork.c, 68, Defined as a kernel / chr_drv / console.c, 268, Defined as a function

function csi_L
copy_strings fs / exec.c, 104, Defined as a kernel / chr_drv / console.c, 401, Defined as a function

function csi_m
copy_to_cooked include / tty.h, 75, Defined as a function kernel / chr_drv / console.c, 299, Defined as a function

prototype csi_M

kernel / chr_drv / tty_io.c, 145, Defined as a function kernel / chr_drv / console.c, 421, Defined as a function

COPYBLK fs / buffer.c, 283, Pretreatment is defined as


csi_P

macro
kernel / chr_drv / console.c, 411, Defined as a function

CSIZE include / termios.h, 151, Pretreatment is defined as macro


cp_stat fs / stat.c, 15, Defined as a

function
CSTOPB include / termios.h, 156, Pretreatment is defined as macro
CPARENB
include / termios.h, 158, Pretreatment is defined as macro
ctime include / time.h, 36, Defined as a function prototype
CPARODD
include / termios.h, 159, Pretreatment is defined as macro

cr cur_rate kernel / blk_drv / floppy.c, 113, Defined as a variable

kernel / chr_drv / console.c, 224, Defined as a function

CR0 cur_spec1 kernel / blk_drv / floppy.c, 112, Defined as a variable

include / termios.h, 111, Pretreatment is defined as macro


CURRENT kernel / blk_drv / blk.h, 93, Pretreatment is defined as
CR1
macro
include / termios.h, 112, Pretreatment is defined as macro
CURRENT_DEV kernel / blk_drv / blk.h, 94, Pretreatment is defined
CR2
as macro
include / termios.h, 113, Pretreatment is defined as macro

CR3 current_DOR kernel / sched.c, 204, Defined as a

include / termios.h, 114, Pretreatment is defined as macro


variable

CRDLY kernel / blk_drv / floppy.c, 48, Defined as a variable

include / termios.h, 110, Pretreatment is defined as macro current_drive kernel / blk_drv / floppy.c, 115, Defined as a

CREAD variable

include / termios.h, 157, Pretreatment is defined as macro CURRENT_TIME include / sched.h, 142, Pretreatment is

creat defined as macro

include / unistd.h, 199, Defined as a function prototype current_track kernel / blk_drv / floppy.c, 120, Defined as a

include / fcntl.h, 51, Defined as a function prototype


variable

create_block fs / inode.c, 145, Defined as a d_inode include / fs.h, 83, defined as struct Types of

function
d_super_block include / fs.h, 146, defined as struct Types
include / fs.h, 177, Defined as a function prototype
of
create_tables

--623--
index

daddr_t DIR_ENTRIES_PER_BLOCK include / fs.h, 56, Pretreatment

include / sys / types.h, 31, Defined as a type is defined as macro

DAY dir_entry include / fs.h, 157, defined as struct Types of

kernel / mktime.c, 22, Pretreatment is defined as macro

debug dir_namei fs / namei.c, 278, Defined as a

kernel / traps.c, 44, Defined as a function prototype function

DEC div_t include / sys / types.h, 36, Defined as a type

include / tty.h, 25, Pretreatment is defined as macro

DEFAULT_MAJOR_ROOT tools / build.c, 37, Pretreatment divide_error kernel / traps.c, 43, Defined as a function

is defined as macro prototype

DEFAULT_MINOR_ROOT tools / build.c, 38, Pretreatment DMA_READ include / fdreg.h, 68, Pretreatment is defined as

is defined as macro macro

del DMA_WRITE include / fdreg.h, 69, Pretreatment is defined as

kernel / chr_drv / console.c, 230, Defined as a function macro

delete_char do_bounds kernel / traps.c, 134, Defined as a

kernel / chr_drv / console.c, 363, Defined as a function function

delete_line do_coprocessor_error kernel / traps.c, 169, Defined

kernel / chr_drv / console.c, 378, Defined as a function as a function


desc_struct do_coprocessor_segment_overrun kernel / traps.c,

include / head.h, 4, defined as struct Types of 149, Defined as a function


desc_table do_debug kernel / traps.c, 124, Defined as a

include / head.h, 6, Defined as a type function

dev_t do_device_not_available kernel / traps.c, 144, Defined

include / sys / types.h, 26, Defined as a type as a function


DEVICE_INTR do_div kernel / vsprintf.c, 35, Pretreatment is defined as macro

kernel / blk_drv / blk.h, 72, Pretreatment is defined as macro

kernel / blk_drv / blk.h, 81, Pretreatment is defined as macro do_divide_error kernel / traps.c, 97, Defined as

kernel / blk_drv / blk.h, 97, Defined as a function prototype a function

DEVICE_NAME kernel / blk_drv / blk.h, 63, Pretreatment is defined do_double_fault kernel / traps.c, 87, Defined as

as macro a function

kernel / blk_drv / blk.h, 71, Pretreatment is defined as macro do_execve fs / exec.c, 182, Defined as a

function
kernel / blk_drv / blk.h, 80, Pretreatment is defined as macro
do_exit kernel / exit.c, 102, Defined as a function
device_not_available kernel / traps.c, 50, Defined as a

function prototype

DEVICE_NR kernel / traps.c, 39, Defined as a function prototype

kernel / blk_drv / blk.h, 65, Pretreatment is defined as macro kernel / signal.c, 13, Defined as a function prototype

kernel / blk_drv / blk.h, 74, Pretreatment is defined as macro mm / memory.c, 31, Defined as a function prototype

kernel / blk_drv / blk.h, 83, Pretreatment is defined as macro do_fd_request kernel / blk_drv / floppy.c, 417, Defined as a

DEVICE_OFF function

kernel / blk_drv / blk.h, 67, Pretreatment is defined as macro do_floppy_timer kernel / sched.c, 245, Defined as

kernel / blk_drv / blk.h, 76, Pretreatment is defined as macro


a function
do_general_protection kernel / traps.c, 92, Defined
kernel / blk_drv / blk.h, 85, Pretreatment is defined as macro
as a function
DEVICE_ON
do_hd_request kernel / blk_drv / hd.c, 294, Defined as a
kernel / blk_drv / blk.h, 66, Pretreatment is defined as macro
function
kernel / blk_drv / blk.h, 75, Pretreatment is defined as macro
do_int3 kernel / traps.c, 102, Defined as a function
kernel / blk_drv / blk.h, 84, Pretreatment is defined as macro

DEVICE_REQUEST kernel / blk_drv / blk.h, 64, Pretreatment is


do_invalid_op kernel / traps.c, 139, Defined as a
defined as macro
function
kernel / blk_drv / blk.h, 73, Pretreatment is defined as macro
do_invalid_TSS kernel / traps.c, 154, Defined as
kernel / blk_drv / blk.h, 82, Pretreatment is defined as macro
a function
kernel / blk_drv / blk.h, 99, Defined as a function prototype
do_nmi kernel / traps.c, 119, Defined as a function
die
kernel / traps.c, 63, Defined as a function
do_no_page mm / memory.c, 365, Defined as a
tools / build.c, 46, Defined as a function
function
difftime
do_overflow
include / time.h, 32, Defined as a function prototype

--624--
index

kernel / traps.c, 129, Defined as a function include / termios.h, 173, Pretreatment is defined as macro

do_rd_request ECHOK include / termios.h, 174, Pretreatment is defined as macro

kernel / blk_drv / ramdisk.c, 23, Defined as a function

do_reserved ECHOKE include / termios.h, 180, Pretreatment is defined as macro

kernel / traps.c, 176, Defined as a function

do_segment_not_present kernel / traps.c, 159, Defined ECHONL include / termios.h, 175, Pretreatment is defined as macro

as a function
do_signal ECHOPRT include / termios.h, 179, Pretreatment is defined as

kernel / signal.c, 82, Defined as a function macro

do_stack_segment kernel / traps.c, 164, Defined EDEADLK include / errno.h, 54, Pretreatment is defined as

as a function macro

do_timer EDOM include / errno.h, 52, Pretreatment is defined as macro

kernel / sched.c, 305, Defined as a function

do_tty_interrupt EEXIST include / errno.h, 36, Pretreatment is defined as macro

kernel / chr_drv / tty_io.c, 342, Defined as a function

do_wp_page EFAULT include / errno.h, 33, Pretreatment is defined as macro

mm / memory.c, 247, Defined as a function

double_fault kernel / traps.c, 51, Defined as a function EFBIG include / errno.h, 46, Pretreatment is defined as macro

prototype

DRIVE EINTR include / errno.h, 23, Pretreatment is defined as macro

kernel / blk_drv / floppy.c, 54, Pretreatment is defined as macro

drive_busy EINVAL include / errno.h, 41, Pretreatment is defined as macro

kernel / blk_drv / hd.c, 202, Defined as a function

DRIVE_INFO init / main.c, 59, Pretreatment is defined EIO include / errno.h, 24, Pretreatment is defined as macro

as macro

drive_info init / main.c, 102, defined as struct Types EISDIR include / errno.h, 40, Pretreatment is defined as macro

of
DRQ_STAT EMFILE include / errno.h, 43, Pretreatment is defined as macro

include / hdreg.h, 27, Pretreatment is defined as macro

dup EMLINK include / errno.h, 50, Pretreatment is defined as macro

include / unistd.h, 200, Defined as a function prototype

dup2 EMPTY include / tty.h, 26, Pretreatment is defined as macro

include / unistd.h, 248, Defined as a function prototype

dupfd empty_dir fs / namei.c, 543, Defined as a

fs / fcntl.c, 18, Defined as a function function

E2BIG ENAMETOOLONG include / errno.h, 55, Pretreatment is

include / errno.h, 26, Pretreatment is defined as macro defined as macro

EACCES end fs / buffer.c, 29, Defined as a variable

include / errno.h, 32, Pretreatment is defined as macro

EAGAIN end_request kernel / blk_drv / blk.h, 109, Defined as a

include / errno.h, 30, Pretreatment is defined as macro function


EBADF ENFILE include / errno.h, 42, Pretreatment is defined as macro

include / errno.h, 28, Pretreatment is defined as macro

EBUSY ENODEV include / errno.h, 38, Pretreatment is defined as

include / errno.h, 35, Pretreatment is defined as macro macro

ECC_ERR ENOENT include / errno.h, 21, Pretreatment is defined as macro

include / hdreg.h, 49, Pretreatment is defined as macro

ECC_STAT ENOEXEC include / errno.h, 27, Pretreatment is defined as

include / hdreg.h, 26, Pretreatment is defined as macro macro

ECHILD ENOLCK include / errno.h, 56, Pretreatment is defined as

include / errno.h, 29, Pretreatment is defined as macro macro

ECHO ENOMEM include / errno.h, 31, Pretreatment is defined as

include / termios.h, 172, Pretreatment is defined as macro macro

ECHOCTL ENOSPC include / errno.h, 47, Pretreatment is defined as macro

include / termios.h, 178, Pretreatment is defined as macro

ECHOE ENOSYS

--625--
index

include / errno.h, 57, Pretreatment is defined as macro include / unistd.h, 203, Defined as a function prototype

ENOTBLK exit include / unistd.h, 207, Defined as a function prototype

include / errno.h, 34, Pretreatment is defined as macro

ENOTDIR EXT_MEM_K init / main.c, 58, Pretreatment is defined

include / errno.h, 39, Pretreatment is defined as macro as macro

ENOTEMPTY include / errno.h, 58, Pretreatment is defined as EXTA include / termios.h, 149, Pretreatment is defined as macro

macro

ENOTTY EXTB include / termios.h, 150, Pretreatment is defined as macro

include / errno.h, 44, Pretreatment is defined as macro

envp F_DUPFD include / fcntl.h, 23, Pretreatment is defined as

init / main.c, 166, Defined as a variable macro

envp_rc F_GETFD include / fcntl.h, 24, Pretreatment is defined as

init / main.c, 163, Defined as a variable macro

ENXIO F_GETFL include / fcntl.h, 26, Pretreatment is defined as

include / errno.h, 25, Pretreatment is defined as macro macro

EOF_CHAR include / tty.h, 40, Pretreatment is defined as F_GETLK include / fcntl.h, 28, Pretreatment is defined as

macro macro

EPERM F_OK include / unistd.h, 22, Pretreatment is defined as macro

include / errno.h, 20, Pretreatment is defined as macro

EPIPE F_RDLCK include / fcntl.h, 38, Pretreatment is defined as

include / errno.h, 51, Pretreatment is defined as macro macro

ERANGE F_SETFD include / fcntl.h, 25, Pretreatment is defined as

include / errno.h, 53, Pretreatment is defined as macro macro

ERASE_CHAR include / tty.h, 38, Pretreatment is defined F_SETFL include / fcntl.h, 27, Pretreatment is defined as

as macro macro

EROFS F_SETLK include / fcntl.h, 29, Pretreatment is defined as

include / errno.h, 49, Pretreatment is defined as macro macro

ERR_STAT F_SETLKW include / fcntl.h, 30, Pretreatment is defined as

include / hdreg.h, 24, Pretreatment is defined as macro macro

errno F_UNLCK include / fcntl.h, 40, Pretreatment is defined as

include / unistd.h, 187, Defined as a variable macro

include / errno.h, 17, Defined as a variable F_WRLCK include / fcntl.h, 39, Pretreatment is defined as

lib / errno.c, 7, Defined as a variable macro

ERROR fcntl include / unistd.h, 209, Defined as a function prototype

include / errno.h, 19, Pretreatment is defined as macro

ESPIPE include / fcntl.h, 52, Defined as a function prototype

include / errno.h, 48, Pretreatment is defined as macro FD_CLOEXEC include / fcntl.h, 33, Pretreatment is defined

ESRCH as macro

include / errno.h, 22, Pretreatment is defined as macro FD_DATA include / fdreg.h, 17, Pretreatment is defined as

ETXTBSY macro

include / errno.h, 45, Pretreatment is defined as macro FD_DCR include / fdreg.h, 20, Pretreatment is defined as macro

EXDEV
include / errno.h, 37, Pretreatment is defined as macro FD_DIR include / fdreg.h, 19, Pretreatment is defined as macro

exec
include / a.out.h, 6, defined as struct Types of FD_DOR include / fdreg.h, 18, Pretreatment is defined as macro

execl
include / unistd.h, 204, Defined as a function prototype FD_READ include / fdreg.h, 62, Pretreatment is defined as

execle macro

include / unistd.h, 206, Defined as a function prototype FD_RECALIBRATE include / fdreg.h, 60, Pretreatment is

execlp defined as macro

include / unistd.h, 205, Defined as a function prototype FD_SEEK include / fdreg.h, 61, Pretreatment is defined as

execv macro

include / unistd.h, 202, Defined as a function prototype FD_SENSEI include / fdreg.h, 64, Pretreatment is defined as

execve macro

include / unistd.h, 201, Defined as a function prototype FD_SPECIFY include / fdreg.h, 65, Pretreatment is defined as

execvp macro

--626--
index

FD_STATUS include / fdreg.h, 16, Pretreatment is defined as include / fdreg.h, 10, Defined as a function prototype

macro kernel / sched.c, 232, Defined as a function


FD_WRITE floppy_on_interrupt kernel / blk_drv / floppy.c, 404, Defined as
include / fdreg.h, 63, Pretreatment is defined as macro a function
FF0 floppy_select include / fdreg.h, 12, Defined as a function
include / termios.h, 128, Pretreatment is defined as macro prototype
FF1 floppy_struct kernel / blk_drv / floppy.c, 82, defined as struct Types
include / termios.h, 129, Pretreatment is defined as macro of
FFDLY floppy_type kernel / blk_drv / floppy.c, 85, Defined as a
include / termios.h, 127, Pretreatment is defined as macro variable
file flush
include / fs.h, 116, defined as struct Types of kernel / chr_drv / tty_ioctl.c, 39, Defined as a function
file_read FLUSHO include / termios.h, 181, Pretreatment is defined as macro

fs / read_write.c, 20, Defined as a function prototype

fs / file_dev.c, 17, Defined as a function fn_ptr include / sched.h, 38, Defined as a type
file_table
fs / file_table.c, 9, Defined as a variable fork include / unistd.h, 210, Defined as a function prototype

include / fs.h, 163, Defined as a variable

file_write free include / kernel.h, 12, Pretreatment is defined as macro

fs / read_write.c, 22, Defined as a function prototype

fs / file_dev.c, 48, Defined as a function free_block fs / bitmap.c, 47, Defined as a

find_buffer fs / buffer.c, 166, Defined as a function

function include / fs.h, 193, Defined as a function prototype

find_empty_process kernel / fork.c, 135, Defined free_bucket_desc lib / malloc.c, 92, Defined

as a function as a variable
find_entry fs / namei.c, 91, Defined as a free_dind fs / truncate.c, 29, Defined as a

function function

find_first_zero fs / bitmap.c, 31, Pretreatment is defined free_ind fs / truncate.c, 11, Defined as a

as macro function

FIRST_LDT_ENTRY include / sched.h, 154, Pretreatment is free_inode fs / bitmap.c, 107, Defined as a

defined as macro function

FIRST_TASK include / sched.h, 7, Pretreatment is defined as include / fs.h, 195, Defined as a function prototype

macro free_list fs / buffer.c, 32, Defined as a


FIRST_TSS_ENTRY include / sched.h, 153, Pretreatment is variable
defined as macro free_page include / mm.h, 8, Defined as a function

flock prototype

include / fcntl.h, 43, defined as struct Types of mm / memory.c, 89, Defined as a function
floppy free_page_tables include / sched.h, 30, Defined as a function
kernel / blk_drv / floppy.c, 114, Defined as a variable prototype
floppy_change include / fs.h, 169, Defined as a function mm / memory.c, 105, Defined as a function
prototype free_s include / kernel.h, 10, Defined as a function prototype

kernel / blk_drv / floppy.c, 139, Defined as a function

floppy_deselect include / fdreg.h, 13, Defined as a function lib / malloc.c, 182, Defined as a function
prototype free_super fs / super.c, 40, Defined as a
kernel / blk_drv / floppy.c, 125, Defined as a function function
floppy_init init / main.c, 49, Defined as a function fstat include / sys / stat.h, 52, Defined as a function prototype

prototype

kernel / blk_drv / floppy.c, 457, Defined as a function include / unistd.h, 233, Defined as a function prototype
floppy_interrupt FULL include / tty.h, 29, Pretreatment is defined as macro

kernel / blk_drv / floppy.c, 104, Defined as a function prototype

floppy_off GCC_HEADER tools / build.c, 33, Pretreatment is defined

include / fs.h, 172, Defined as a function prototype as macro

include / fdreg.h, 11, Defined as a function prototype gdt include / head.h, 9, Defined as a variable

kernel / sched.c, 240, Defined as a function

floppy_on GDT_CODE include / head.h, 12, Pretreatment is defined as

include / fs.h, 171, Defined as a function prototype macro

--627--
index

GDT_DATA include / head.h, 13, Pretreatment is defined as getegid include / unistd.h, 215, Defined as a function prototype

macro

GDT_NUL geteuid include / unistd.h, 213, Defined as a function prototype

include / head.h, 11, Pretreatment is defined as macro

GDT_TMP getgid include / unistd.h, 214, Defined as a function prototype

include / head.h, 14, Pretreatment is defined as macro

general_protection kernel / traps.c, 56, Defined as a getpgrp include / unistd.h, 250, Defined as a function prototype

function prototype

get_base getpid include / unistd.h, 211, Defined as a function prototype

include / sched.h, 226, Pretreatment is defined as macro

get_dir getppid include / unistd.h, 249, Defined as a function prototype

fs / namei.c, 228, Defined as a function

get_ds getuid include / unistd.h, 212, Defined as a function prototype

include / asm / segment.h, 54, Defined as a function

get_empty_inode fs / inode.c, 194, Defined gid_t include / sys / types.h, 25, Defined as a type

as a function

include / fs.h, 183, Defined as a function prototype gmtime include / time.h, 37, Defined as a function prototype

get_empty_page mm / memory.c, 274, Defined as

a function gotoxy
get_free_page include / mm.h, 6, Defined as a function kernel / chr_drv / console.c, 88, Defined as a function

prototype hash fs / buffer.c, 129, Pretreatment is defined as macro

mm / memory.c, 63, Defined as a function

get_fs hash_table fs / buffer.c, 31, Defined as a

include / asm / segment.h, 47, Defined as a function variable

get_fs_byte hd
include / asm / segment.h, 1, Defined as a function kernel / blk_drv / hd.c, 59, Defined as a variable

get_fs_long HD_CMD include / hdreg.h, 21, Pretreatment is defined as

include / asm / segment.h, 17, Defined as a function macro

get_fs_word HD_COMMAND include / hdreg.h, 19, Pretreatment is

include / asm / segment.h, 9, Defined as a function defined as macro

get_hash_table fs / buffer.c, 183, Defined as HD_CURRENT include / hdreg.h, 16, Pretreatment is defined

a function as macro

include / fs.h, 185, Defined as a function prototype HD_DATA include / hdreg.h, 10, Pretreatment is defined as

get_limit macro

include / sched.h, 228, Pretreatment is defined as macro HD_ERROR include / hdreg.h, 11, Pretreatment is defined as

get_new macro

kernel / signal.c, 40, Defined as a function HD_HCYL include / hdreg.h, 15, Pretreatment is defined as

get_pipe_inode fs / inode.c, 228, Defined as macro

a function hd_i_struct kernel / blk_drv / hd.c, 45, defined as struct Types of

include / fs.h, 184, Defined as a function prototype

get_seg_byte kernel / traps.c, 22, Pretreatment is defined as


hd_info kernel / blk_drv / hd.c, 49, defined as struct Types of

macro

get_seg_long kernel / traps.c, 28, Pretreatment is defined as kernel / blk_drv / hd.c, 52, defined as struct Types of

macro hd_init init / main.c, 48, Defined as a function prototype

get_super fs / super.c, 56, Defined as a

function kernel / blk_drv / hd.c, 343, Defined as a function

include / fs.h, 197, Defined as a function prototype hd_interrupt kernel / blk_drv / hd.c, 67, Defined as a function

get_termio prototype

kernel / chr_drv / tty_ioctl.c, 76, Defined as a function HD_LCYL include / hdreg.h, 14, Pretreatment is defined as

get_termios macro

kernel / chr_drv / tty_ioctl.c, 56, Defined as a function HD_NSECTOR include / hdreg.h, 12, Pretreatment is defined

getblk as macro

fs / buffer.c, 206, Defined as a function hd_out kernel / blk_drv / hd.c, 180, Defined as a function

include / fs.h, 186, Defined as a function prototype


HD_PRECOMP include / hdreg.h, 18, Pretreatment is defined
GETCH
as macro
include / tty.h, 31, Pretreatment is defined as macro

--628--
index

HD_SECTOR include / hdreg.h, 13, Pretreatment is defined as include / fs.h, 182, Defined as a function prototype

macro IGNBRK include / termios.h, 83, Pretreatment is defined as macro

HD_STATUS include / hdreg.h, 17, Pretreatment is defined as

macro IGNCR include / termios.h, 90, Pretreatment is defined as macro

hd_struct
kernel / blk_drv / hd.c, 56, defined as struct Types of IGNPAR include / termios.h, 85, Pretreatment is defined as macro

head
kernel / blk_drv / floppy.c, 117, Defined as a variable IMAXBEL include / termios.h, 96, Pretreatment is defined as

HIGH_MEMORY mm / memory.c, 52, Defined macro

as a variable immoutb_p kernel / blk_drv / floppy.c, 50, Pretreatment is defined as macro

HOUR
kernel / mktime.c, 21, Pretreatment is defined as macro IN_ORDER kernel / blk_drv / blk.h, 40, Pretreatment is defined as

HUPCL macro

include / termios.h, 160, Pretreatment is defined as macro inb include / asm / io.h, 5, Pretreatment is defined as macro

HZ
include / sched.h, 5, Pretreatment is defined as macro inb_p include / asm / io.h, 17, Pretreatment is defined as macro

I_BLOCK_SPECIAL include / const.h, 9, Pretreatment is

defined as macro INC include / tty.h, 24, Pretreatment is defined as macro

I_CHAR_SPECIAL include / const.h, 10, Pretreatment is

defined as macro INC_PIPE include / fs.h, 63, Pretreatment is defined as

I_CRNL macro

kernel / chr_drv / tty_io.c, 42, Pretreatment is defined as macro INDEX_STAT include / hdreg.h, 25, Pretreatment is defined as

I_DIRECTORY include / const.h, 7, Pretreatment is defined macro

as macro init init / main.c, 45, Defined as a function prototype

I_MAP_SLOTS include / fs.h, 39, Pretreatment is defined

as macro init / main.c, 168, Defined as a function


I_NAMED_PIPE include / const.h, 11, Pretreatment is defined kernel / chr_drv / serial.c, 26, Defined as a function
as macro init_bucket_desc lib / malloc.c, 97, Defined
I_NLCR as a function
kernel / chr_drv / tty_io.c, 41, Pretreatment is defined as macro INIT_C_CC include / tty.h, 63, Pretreatment is defined as
I_NOCR macro
kernel / chr_drv / tty_io.c, 43, Pretreatment is defined as macro INIT_REQUEST kernel / blk_drv / blk.h, 127, Pretreatment is defined
I_REGULAR include / const.h, 8, Pretreatment is defined as as macro
macro INIT_TASK include / sched.h, 113, Pretreatment is defined as
I_SET_GID_BIT include / const.h, 13, Pretreatment is defined macro
as macro init_task kernel / sched.c, 58, defined as union Types of
I_SET_UID_BIT include / const.h, 12, Pretreatment is defined

as macro INLCR include / termios.h, 89, Pretreatment is defined as macro


I_TYPE
include / const.h, 6, Pretreatment is defined as macro ino_t include / sys / types.h, 27, Defined as a type
I_UCLC
kernel / chr_drv / tty_io.c, 40, Pretreatment is defined as macro inode_table fs / inode.c, 15, Defined as a
i387_struct variable
include / sched.h, 40, defined as struct Types of include / fs.h, 162, Defined as a variable
ICANON INODES_PER_BLOCK include / fs.h, 55, Pretreatment
include / termios.h, 170, Pretreatment is defined as macro
is defined as macro
ICRNL INPCK include / termios.h, 87, Pretreatment is defined as macro
include / termios.h, 91, Pretreatment is defined as macro

ID_ERR insert_char kernel / chr_drv / console.c, 336, Defined as a function


include / hdreg.h, 48, Pretreatment is defined as macro

idt insert_into_queues fs / buffer.c, 149, Defined


include / head.h, 9, Defined as a variable
as a function
IEXTEN insert_line kernel / chr_drv / console.c, 350, Defined as a function
include / termios.h, 183, Pretreatment is defined as macro

iget int3 kernel / traps.c, 46, Defined as a function prototype


fs / inode.c, 244, Defined as a function

--629--
index

interruptible_sleep_on include / sched.h, 146, Defined as a ISTRIP include / termios.h, 88, Pretreatment is defined as macro

function prototype

kernel / sched.c, 167, Defined as a function isupper include / ctype.h, 25, Pretreatment is defined as macro

INTMASK
kernel / chr_drv / tty_io.c, 19, Pretreatment is defined as macro isxdigit include / ctype.h, 26, Pretreatment is defined as macro

INTR_CHAR include / tty.h, 36, Pretreatment is defined as

macro IUCLC include / termios.h, 92, Pretreatment is defined as macro

invalid_op
kernel / traps.c, 49, Defined as a function prototype IXANY include / termios.h, 94, Pretreatment is defined as macro

invalid_TSS kernel / traps.c, 53, Defined as a function

prototype IXOFF include / termios.h, 95, Pretreatment is defined as macro

invalidate
mm / memory.c, 39, Pretreatment is defined as macro IXON include / termios.h, 93, Pretreatment is defined as macro

invalidate_buffers fs / buffer.c, 84, Defined

as a function jiffies include / sched.h, 139, Defined as a variable

invalidate_inodes fs / inode.c, 43, Defined

as a function kernel / sched.c, 60, Defined as a variable

ioctl KBD_FINNISH include / config.h, 19, Pretreatment is defined

include / unistd.h, 216, Defined as a function prototype as macro

ioctl_ptr fs / ioctl.c, 15, Defined as a kernel_mktime init / main.c, 52, Defined as a function

type prototype

ioctl_table fs / ioctl.c, 19, Defined as a kernel / mktime.c, 41, Defined as a function

variable keyboard_interrupt kernel / chr_drv / console.c, 56, Defined as a function


iput prototype
fs / inode.c, 150, Defined as a function kill include / unistd.h, 217, Defined as a function prototype

include / fs.h, 181, Defined as a function prototype

iret include / signal.h, 57, Defined as a function prototype

include / asm / system.h, 20, Pretreatment is defined as macro KILL_CHAR include / tty.h, 39, Pretreatment is defined as

irq13 macro

kernel / traps.c, 61, Defined as a function prototype kill_session kernel / exit.c, 46, Defined as a
is_digit function
kernel / vsprintf.c, 16, Pretreatment is defined as macro KILLMASK kernel / chr_drv / tty_io.c, 18, Pretreatment is defined as

IS_SEEKABLE include / fs.h, 24, Pretreatment is defined macro


as macro L_CANON kernel / chr_drv / tty_io.c, 32, Pretreatment is defined as macro

isalnum
include / ctype.h, 16, Pretreatment is defined as macro L_ECHO kernel / chr_drv / tty_io.c, 34, Pretreatment is defined as macro

isalpha
include / ctype.h, 17, Pretreatment is defined as macro L_ECHOCTL kernel / chr_drv / tty_io.c, 37, Pretreatment is defined as

isascii macro

include / ctype.h, 28, Pretreatment is defined as macro L_ECHOE kernel / chr_drv / tty_io.c, 35, Pretreatment is defined as macro

iscntrl
include / ctype.h, 18, Pretreatment is defined as macro L_ECHOK kernel / chr_drv / tty_io.c, 36, Pretreatment is defined as macro

isdigit
include / ctype.h, 19, Pretreatment is defined as macro L_ECHOKE kernel / chr_drv / tty_io.c, 38, Pretreatment is defined as

isgraph macro

include / ctype.h, 20, Pretreatment is defined as macro L_ISIG kernel / chr_drv / tty_io.c, 33, Pretreatment is defined as macro

ISIG
include / termios.h, 169, Pretreatment is defined as macro LAST include / tty.h, 28, Pretreatment is defined as macro

islower
include / ctype.h, 21, Pretreatment is defined as macro last_pid kernel / fork.c, 22, Defined as a variable
isprint
include / ctype.h, 22, Pretreatment is defined as macro LAST_TASK include / sched.h, 8, Pretreatment is defined as

ispunct macro

include / ctype.h, 23, Pretreatment is defined as macro last_task_used_math include / sched.h, 137, Defined
isspace as a variable
include / ctype.h, 24, Pretreatment is defined as macro kernel / sched.c, 63, Defined as a variable

--630--
index

LATCH MARK_ERR include / hdreg.h, 45, Pretreatment is defined as

kernel / sched.c, 46, Pretreatment is defined as macro macro

ldiv_t match fs / namei.c, 63, Defined as a function

include / sys / types.h, 37, Defined as a type


LDT_CODE include / head.h, 17, Pretreatment is defined as math_emulate kernel / math / math_emulate.c, 18, Defined as a

macro function
LDT_DATA include / head.h, 18, Pretreatment is defined as math_error kernel / math / math_emulate.c, 37, Defined as a function

macro

LDT_NUL math_state_restore kernel / sched.c, 77, Defined

include / head.h, 16, Pretreatment is defined as macro as a function


LEFT MAX fs / file_dev.c, 15, Pretreatment is defined as macro

include / tty.h, 27, Pretreatment is defined as macro

kernel / vsprintf.c, 31, Pretreatment is defined as macro MAX_ARG_PAGES fs / exec.c, 39, Pretreatment is

lf defined as macro

kernel / chr_drv / console.c, 204, Defined as a function MAX_ERRORS kernel / blk_drv / hd.c, 34, Pretreatment is defined

link as macro

include / unistd.h, 218, Defined as a function prototype kernel / blk_drv / floppy.c, 60, Pretreatment is defined as macro

ll_rw_block include / fs.h, 187, Defined as a function MAX_HD kernel / blk_drv / hd.c, 35, Pretreatment is defined as macro

prototype

kernel / blk_drv / ll_rw_blk.c, 145, Defined as a function MAX_REPLIES kernel / blk_drv / floppy.c, 65, Pretreatment is defined as

lldt macro

include / sched.h, 158, Pretreatment is defined as macro MAY_EXEC fs / namei.c, 29, Pretreatment is defined as

localtime macro

include / time.h, 38, Defined as a function prototype MAY_READ fs / namei.c, 31, Pretreatment is defined as

lock_buffer macro

kernel / blk_drv / ll_rw_blk.c, 42, Defined as a function MAY_WRITE fs / namei.c, 30, Pretreatment is defined

lock_inode fs / inode.c, 28, Defined as a as macro

function mem_init init / main.c, 50, Defined as a function

lock_super fs / super.c, 31, Defined as a prototype

function mm / memory.c, 399, Defined as a function

LOW_MEM mm / memory.c, 43, Pretreatment is defined as mem_map mm / memory.c, 57, Defined as a

macro variable

lseek mem_use kernel / sched.c, 48, Defined as a function prototype

include / unistd.h, 219, Defined as a function prototype

ltr memchr include / string.h, 379, Defined as a function

include / sched.h, 157, Pretreatment is defined as macro

m_inode memcmp include / string.h, 363, Defined as a function

include / fs.h, 93, defined as struct Types of

main memcpy include / string.h, 336, Defined as a function

init / main.c, 104, Defined as a function

tools / build.c, 57, Defined as a function include / asm / memory.h, 8, Pretreatment is defined as macro

main_memory_start init / main.c, 100, Defined memmove include / string.h, 346, Defined as a

as a variable function
MAJOR memory_end init / main.c, 98, Defined as a

include / fs.h, 33, Pretreatment is defined as macro variable

MAJOR_NR memset include / string.h, 395, Defined as a function

kernel / blk_drv / hd.c, 25, Pretreatment is defined as macro

kernel / blk_drv / floppy.c, 41, Pretreatment is defined as macro MIN fs / file_dev.c, 14, Pretreatment is defined as macro

kernel / blk_drv / ramdisk.c, 17, Pretreatment is defined as macro

make_request MINIX_HEADER tools / build.c, 32, Pretreatment is

kernel / blk_drv / ll_rw_blk.c, 88, Defined as a function defined as macro

malloc MINOR include / fs.h, 34, Pretreatment is defined as

include / kernel.h, 9, Defined as a function prototype macro

lib / malloc.c, 117, Defined as a function MINUTE kernel / mktime.c, 20, Pretreatment is defined as macro

MAP_NR
mm / memory.c, 46, Pretreatment is defined as macro mkdir

--631--
index

include / sys / stat.h, 53, Defined as a function prototype N_SETV include / a.out.h, 184, Pretreatment is defined as macro

mkfifo
include / sys / stat.h, 54, Defined as a function prototype N_STAB include / a.out.h, 153, Pretreatment is defined as macro

mknod
include / unistd.h, 220, Defined as a function prototype N_STROFF include / a.out.h, 64, Pretreatment is defined as

mktime macro

include / time.h, 33, Defined as a function prototype N_SYMOFF include / a.out.h, 60, Pretreatment is defined as

mode_t macro

include / sys / types.h, 28, Defined as a type N_TEXT include / a.out.h, 131, Pretreatment is defined as macro

moff_timer
kernel / sched.c, 203, Defined as a variable N_TRELOFF include / a.out.h, 52, Pretreatment is defined as

mon_timer macro

kernel / sched.c, 202, Defined as a variable N_TXTADDR include / a.out.h, 69, Pretreatment is defined as

month macro

kernel / mktime.c, 26, Defined as a variable N_TXTOFF include / a.out.h, 43, Pretreatment is defined as

mount macro

include / unistd.h, 221, Defined as a function prototype N_TYPE include / a.out.h, 150, Pretreatment is defined as macro

mount_root fs / super.c, 242, Defined as a

function N_UNDF include / a.out.h, 125, Pretreatment is defined as macro

include / fs.h, 200, Defined as a function prototype

move_to_user_mode include / asm / system.h, 1, Pretreatment is NAME_LEN include / fs.h, 36, Pretreatment is defined as

defined as macro macro

N_ABS namei fs / namei.c, 303, Defined as a function

include / a.out.h, 128, Pretreatment is defined as macro

N_BADMAG include / a.out.h, 31, Pretreatment is defined as include / fs.h, 178, Defined as a function prototype

macro NCC include / termios.h, 43, Pretreatment is defined as macro

N_BSS
include / a.out.h, 137, Pretreatment is defined as macro NCCS include / termios.h, 53, Pretreatment is defined as macro

N_BSSADDR include / a.out.h, 107, Pretreatment is defined as

macro new_block fs / bitmap.c, 75, Defined as a

N_COMM function

include / a.out.h, 140, Pretreatment is defined as macro include / fs.h, 192, Defined as a function prototype

N_DATA new_inode fs / bitmap.c, 136, Defined as a

include / a.out.h, 134, Pretreatment is defined as macro function

N_DATADDR include / a.out.h, 100, Pretreatment is defined as include / fs.h, 194, Defined as a function prototype

macro next_timer kernel / sched.c, 270, Defined as a


N_DATOFF include / a.out.h, 48, Pretreatment is defined as variable
macro nice include / unistd.h, 222, Defined as a function prototype

N_DRELOFF include / a.out.h, 56, Pretreatment is defined as

macro NL0 include / termios.h, 108, Pretreatment is defined as macro

N_EXT
include / a.out.h, 147, Pretreatment is defined as macro NL1 include / termios.h, 109, Pretreatment is defined as macro

N_FN
include / a.out.h, 143, Pretreatment is defined as macro NLDLY include / termios.h, 107, Pretreatment is defined as macro

N_INDR
include / a.out.h, 164, Pretreatment is defined as macro nlink_t include / sys / types.h, 30, Defined as a type
N_MAGIC
include / a.out.h, 18, Pretreatment is defined as macro nlist include / a.out.h, 111, defined as struct Types of
N_SETA
include / a.out.h, 178, Pretreatment is defined as macro NMAGIC include / a.out.h, 25, Pretreatment is defined as

N_SETB macro

include / a.out.h, 181, Pretreatment is defined as macro nmi kernel / traps.c, 45, Defined as a function prototype

N_SETD
include / a.out.h, 180, Pretreatment is defined as macro NOFLSH include / termios.h, 176, Pretreatment is defined as macro

N_SETT
include / a.out.h, 179, Pretreatment is defined as macro nop

--632--
index

include / asm / system.h, 18, Pretreatment is defined as macro O_NDELAY include / fcntl.h, 17, Pretreatment is defined as

NPAR macro

kernel / chr_drv / console.c, 54, Pretreatment is defined as macro O_NLCR kernel / chr_drv / tty_io.c, 46, Pretreatment is defined as macro

npar
kernel / chr_drv / console.c, 75, Defined as a variable O_NLRET kernel / chr_drv / tty_io.c, 48, Pretreatment is defined as macro

NR_BLK_DEV kernel / blk_drv / blk.h, 4, Pretreatment is defined as

macro O_NOCTTY include / fcntl.h, 13, Pretreatment is defined as

NR_BUFFERS fs / buffer.c, 34, Defined as macro

a variable O_NONBLOCK include / fcntl.h, 16, Pretreatment is defined

include / fs.h, 48, Pretreatment is defined as macro as macro

nr_buffers O_POST kernel / chr_drv / tty_io.c, 45, Pretreatment is defined as macro

include / fs.h, 166, Defined as a variable

NR_FILE include / fs.h, 45, Pretreatment is defined as O_RDONLY include / fcntl.h, 8, Pretreatment is defined as

macro macro

NR_HASH include / fs.h, 47, Pretreatment is defined as O_RDWR include / fcntl.h, 10, Pretreatment is defined as

macro macro

NR_HD O_TRUNC include / fcntl.h, 14, Pretreatment is defined as

kernel / blk_drv / hd.c, 50, Pretreatment is defined as macro macro

kernel / blk_drv / hd.c, 53, Defined as a variable O_WRONLY include / fcntl.h, 9, Pretreatment is defined as

NR_INODE include / fs.h, 44, Pretreatment is defined as macro

macro OCRNL include / termios.h, 102, Pretreatment is defined as macro

NR_OPEN include / fs.h, 43, Pretreatment is defined as

macro OFDEL include / termios.h, 106, Pretreatment is defined as macro

NR_REQUEST
kernel / blk_drv / blk.h, 15, Pretreatment is defined as macro off_t include / sys / types.h, 32, Defined as a type

NR_SUPER include / fs.h, 46, Pretreatment is defined as

macro offsetof include / stddef.h, 17, Pretreatment is defined as macro

NR_TASKS include / sched.h, 4, Pretreatment is defined as

macro OFILL include / termios.h, 105, Pretreatment is defined as macro

NRDEVS
fs / char_dev.c, 83, Pretreatment is defined as macro OLCUC include / termios.h, 100, Pretreatment is defined as macro

fs / ioctl.c, 17, Pretreatment is defined as macro


OMAGIC include / a.out.h, 23, Pretreatment is defined as
NSIG
macro
include / signal.h, 10, Pretreatment is defined as macro
ONLCR include / termios.h, 101, Pretreatment is defined as macro
NULL
include / sys / types.h, 20, Pretreatment is defined as macro
ONLRET include / termios.h, 104, Pretreatment is defined as macro
include / unistd.h, 18, Pretreatment is defined as macro

include / stddef.h, 14, Pretreatment is defined as macro


ONOCR include / termios.h, 103, Pretreatment is defined as macro
include / stddef.h, 15, Pretreatment is defined as macro

include / string.h, 5, Pretreatment is defined as macro


oom mm / memory.c, 33, Defined as a function
include / sched.h, 26, Pretreatment is defined as macro

include / fs.h, 52, Pretreatment is defined as macro


open include / unistd.h, 223, Defined as a function prototype
number
kernel / vsprintf.c, 40, Defined as a function
include / fcntl.h, 53, Defined as a function prototype
O_ACCMODE include / fcntl.h, 7, Pretreatment is defined
lib / open.c, 11, Defined as a function
as macro
open_namei fs / namei.c, 337, Defined as a
O_APPEND include / fcntl.h, 15, Pretreatment is defined as
function
macro
include / fs.h, 179, Defined as a function prototype
O_CREAT
OPOST include / termios.h, 99, Pretreatment is defined as macro
include / fcntl.h, 11, Pretreatment is defined as macro

O_CRNL
ORIG_ROOT_DEV init / main.c, 60, Pretreatment is
kernel / chr_drv / tty_io.c, 47, Pretreatment is defined as macro
defined as macro
O_EXCL
ORIG_VIDEO_COLS kernel / chr_drv / console.c, 43, Pretreatment is
include / fcntl.h, 12, Pretreatment is defined as macro
defined as macro
O_LCUC
ORIG_VIDEO_EGA_AX
kernel / chr_drv / tty_io.c, 49, Pretreatment is defined as macro

--633--
index

kernel / chr_drv / console.c, 45, Pretreatment is defined as macro pause include / unistd.h, 224, Defined as a function prototype

ORIG_VIDEO_EGA_BX kernel / chr_drv / console.c, 46, Pretreatment is

defined as macro PENDIN include / termios.h, 182, Pretreatment is defined as macro

ORIG_VIDEO_EGA_CX kernel / chr_drv / console.c, 47, Pretreatment is

defined as macro permission fs / namei.c, 40, Defined as a

ORIG_VIDEO_LINES kernel / chr_drv / console.c, 44, Pretreatment is function

defined as macro pg_dir include / head.h, 8, Defined as a variable

ORIG_VIDEO_MODE kernel / chr_drv / console.c, 42, Pretreatment is

defined as macro pid_t include / sys / types.h, 23, Defined as a type

ORIG_VIDEO_PAGE kernel / chr_drv / console.c, 41, Pretreatment is

defined as macro pipe include / unistd.h, 225, Defined as a function prototype

ORIG_X
kernel / chr_drv / console.c, 39, Pretreatment is defined as macro PIPE_EMPTY include / fs.h, 61, Pretreatment is defined

ORIG_Y as macro

kernel / chr_drv / console.c, 40, Pretreatment is defined as macro PIPE_FULL include / fs.h, 62, Pretreatment is defined as

origin macro

kernel / chr_drv / console.c, 69, Defined as a variable PIPE_HEAD include / fs.h, 58, Pretreatment is defined as

outb macro

include / asm / io.h, 1, Pretreatment is defined as macro PIPE_SIZE include / fs.h, 60, Pretreatment is defined as

outb_p macro

include / asm / io.h, 11, Pretreatment is defined as macro PIPE_TAIL include / fs.h, 59, Pretreatment is defined as

output_byte macro

kernel / blk_drv / floppy.c, 194, Defined as a function PLUS kernel / vsprintf.c, 29, Pretreatment is defined as macro

overflow
kernel / traps.c, 47, Defined as a function prototype port_read kernel / blk_drv / hd.c, 61, Pretreatment is defined as macro

PAGE_ALIGN include / sched.h, 186, Pretreatment is defined as

macro port_write kernel / blk_drv / hd.c, 64, Pretreatment is defined as macro

page_exception kernel / traps.c, 41, Defined as a function

prototype pos
page_fault kernel / chr_drv / console.c, 71, Defined as a variable

kernel / traps.c, 57, Defined as a function prototype printbuf init / main.c, 42, Defined as a

PAGE_SIZE include / a.out.h, 79, Pretreatment is defined as variable

macro printf include / kernel.h, 6, Defined as a function prototype

include / a.out.h, 88, Pretreatment is defined as macro

include / a.out.h, 92, Pretreatment is defined as macro init / main.c, 151, Defined as a function

include / mm.h, 4, Pretreatment is defined as macro printk include / kernel.h, 7, Defined as a function prototype

PAGING_MEMORY mm / memory.c, 44, Pretreatment is

defined as macro kernel / printk.c, 21, Defined as a function

PAGING_PAGES mm / memory.c, 45, Pretreatment is ptrdiff_t include / sys / types.h, 16, Defined as a type

defined as macro

panic include / stddef.h, 6, Defined as a type

include / kernel.h, 5, Defined as a function prototype put_fs_byte include / asm / segment.h, 25, Defined as a

include / sched.h, 35, Defined as a function prototype function

kernel / panic.c, 16, Defined as a function put_fs_long include / asm / segment.h, 35, Defined as a

par function

kernel / chr_drv / console.c, 75, Defined as a variable put_fs_word include / asm / segment.h, 30, Defined as a

parallel_interrupt kernel / traps.c, 60, Defined as a function function

prototype put_page include / mm.h, 7, Defined as a function prototype

PARENB
include / termios.h, 165, Pretreatment is defined as macro mm / memory.c, 197, Defined as a function

PARMRK put_super fs / super.c, 74, Defined as a

include / termios.h, 86, Pretreatment is defined as macro function

PARODD PUTCH include / tty.h, 33, Pretreatment is defined as macro

include / termios.h, 166, Pretreatment is defined as macro

partition ques

include / hdreg.h, 52, defined as struct Types of kernel / chr_drv / console.c, 76, Defined as a variable

--634--
index

QUIT_CHAR include / tty.h, 37, Pretreatment is defined as request


macro kernel / blk_drv / ll_rw_blk.c, 21, Defined as a variable
QUITMASK kernel / blk_drv / blk.h, 23, defined as struct Types of
kernel / chr_drv / tty_io.c, 20, Pretreatment is defined as macro kernel / blk_drv / blk.h, 51, Defined as a variable
quotient reserved kernel / traps.c, 59, Defined as a function prototype

kernel / chr_drv / tty_ioctl.c, 18, Defined as a variable

R_OK reset kernel / blk_drv / hd.c, 40, Defined as a variable


include / unistd.h, 25, Pretreatment is defined as macro

raise kernel / blk_drv / floppy.c, 45, Defined as a variable


include / signal.h, 56, Defined as a function prototype reset_controller kernel / blk_drv / hd.c, 217, Defined as a
rd_init function
init / main.c, 51, Defined as a function prototype reset_floppy kernel / blk_drv / floppy.c, 386, Defined as a
kernel / blk_drv / ramdisk.c, 52, Defined as a function function
rd_length reset_hd kernel / blk_drv / hd.c, 230, Defined as a function
kernel / blk_drv / ramdisk.c, 21, Defined as a variable

rd_load reset_interrupt kernel / blk_drv / floppy.c, 373, Defined as a


kernel / blk_drv / hd.c, 68, Defined as a function prototype function
kernel / blk_drv / ramdisk.c, 71, Defined as a function respond
rd_start kernel / chr_drv / console.c, 323, Defined as a function
kernel / blk_drv / ramdisk.c, 20, Defined as a variable RESPONSE kernel / chr_drv / console.c, 85, Pretreatment is defined as

read macro

include / unistd.h, 226, Defined as a function prototype restore_cur kernel / chr_drv / console.c, 440, Defined as a function
READ
include / fs.h, 26, Pretreatment is defined as macro result
read_inode fs / inode.c, 17, Defined as a function kernel / blk_drv / floppy.c, 212, Defined as a function
prototype ri
fs / inode.c, 294, Defined as a function kernel / chr_drv / console.c, 214, Defined as a function

read_intr ROOT_DEV fs / super.c, 29, Defined as a

kernel / blk_drv / hd.c, 250, Defined as a function variable

read_pipe include / fs.h, 198, Defined as a variable

fs / read_write.c, 16, Defined as a function prototype ROOT_INO include / fs.h, 37, Pretreatment is defined as

fs / pipe.c, 13, Defined as a function macro

read_super fs / super.c, 100, Defined as a rs_init include / tty.h, 65, Defined as a function prototype

function

READA kernel / chr_drv / serial.c, 37, Defined as a function

include / fs.h, 28, Pretreatment is defined as macro rs_write include / tty.h, 72, Defined as a function prototype

READY_STAT include / hdreg.h, 30, Pretreatment is defined

as macro kernel / chr_drv / serial.c, 53, Defined as a function


recal_interrupt rs1_interrupt kernel / chr_drv / serial.c, 23, Defined as a function
kernel / blk_drv / floppy.c, 343, Defined as a function prototype
recal_intr rs2_interrupt kernel / chr_drv / serial.c, 24, Defined as a function
kernel / blk_drv / hd.c, 37, Defined as a function prototype prototype
kernel / blk_drv / hd.c, 287, Defined as a function rw_char fs / read_write.c, 15, Defined as a function prototype

recalibrate
kernel / blk_drv / hd.c, 39, Defined as a variable fs / char_dev.c, 95, Defined as a function

kernel / blk_drv / floppy.c, 44, Defined as a variable rw_interrupt kernel / blk_drv / floppy.c, 250, Defined as a
recalibrate_floppy function
kernel / blk_drv / floppy.c, 362, Defined as a function rw_kmem fs / char_dev.c, 44, Defined as a
release function
kernel / exit.c, 19, Defined as a function rw_mem fs / char_dev.c, 39, Defined as a
relocation_info include / a.out.h, 193, defined as struct Types function
of rw_memory fs / char_dev.c, 65, Defined as a
remove_from_queues fs / buffer.c, 131, Defined function
as a function rw_port fs / char_dev.c, 49, Defined as a function
reply_buffer
kernel / blk_drv / floppy.c, 66, Defined as a variable rw_ram

--635--
index

fs / char_dev.c, 34, Defined as a function include / sys / stat.h, 39, Pretreatment is defined as macro

rw_tty SA_NOCLDSTOP include / signal.h, 37, Pretreatment is

fs / char_dev.c, 27, Defined as a function defined as macro

rw_ttyx SA_NOMASK include / signal.h, 38, Pretreatment is defined as

fs / char_dev.c, 21, Defined as a function macro

S_IFBLK SA_ONESHOT include / signal.h, 39, Pretreatment is defined

include / sys / stat.h, 22, Pretreatment is defined as macro as macro

S_IFCHR save_cur kernel / chr_drv / console.c, 434, Defined as a function

include / sys / stat.h, 24, Pretreatment is defined as macro

S_IFDIR save_old kernel / signal.c, 28, Defined as a

include / sys / stat.h, 23, Pretreatment is defined as macro function

S_IFIFO saved_x
include / sys / stat.h, 25, Pretreatment is defined as macro kernel / chr_drv / console.c, 431, Defined as a variable

S_IFMT saved_y
include / sys / stat.h, 20, Pretreatment is defined as macro kernel / chr_drv / console.c, 432, Defined as a variable

S_IFREG sbrk include / unistd.h, 193, Defined as a function prototype

include / sys / stat.h, 21, Pretreatment is defined as macro

S_IRGRP sched_init include / sched.h, 32, Defined as a function

include / sys / stat.h, 42, Pretreatment is defined as macro prototype

S_IROTH kernel / sched.c, 385, Defined as a function

include / sys / stat.h, 47, Pretreatment is defined as macro schedule include / sched.h, 33, Defined as a function prototype

S_IRUSR
include / sys / stat.h, 37, Pretreatment is defined as macro kernel / sched.c, 104, Defined as a function
S_IRWXG scr_end
include / sys / stat.h, 41, Pretreatment is defined as macro kernel / chr_drv / console.c, 70, Defined as a variable
S_IRWXO scrdown
include / sys / stat.h, 46, Pretreatment is defined as macro kernel / chr_drv / console.c, 170, Defined as a function
S_IRWXU scrup
include / sys / stat.h, 36, Pretreatment is defined as macro kernel / chr_drv / console.c, 107, Defined as a function
S_ISBLK sector
include / sys / stat.h, 33, Pretreatment is defined as macro kernel / blk_drv / floppy.c, 116, Defined as a variable
S_ISCHR seek
include / sys / stat.h, 32, Pretreatment is defined as macro kernel / blk_drv / floppy.c, 46, Defined as a variable
S_ISDIR SEEK_CUR include / unistd.h, 29, Pretreatment is defined as

include / sys / stat.h, 31, Pretreatment is defined as macro macro


S_ISFIFO SEEK_END include / unistd.h, 30, Pretreatment is defined as

include / sys / stat.h, 34, Pretreatment is defined as macro macro


S_ISGID seek_interrupt kernel / blk_drv / floppy.c, 291, Defined as a
include / sys / stat.h, 27, Pretreatment is defined as macro function
S_ISREG SEEK_SET include / unistd.h, 28, Pretreatment is defined as

include / sys / stat.h, 30, Pretreatment is defined as macro macro


S_ISUID SEEK_STAT include / hdreg.h, 28, Pretreatment is defined as

include / sys / stat.h, 26, Pretreatment is defined as macro macro


S_ISVTX seek_track kernel / blk_drv / floppy.c, 119, Defined as a variable
include / sys / stat.h, 28, Pretreatment is defined as macro

S_IWGRP segment_not_present kernel / traps.c, 54, Defined as a


include / sys / stat.h, 43, Pretreatment is defined as macro function prototype
S_IWOTH SEGMENT_SIZE include / a.out.h, 76, Pretreatment is
include / sys / stat.h, 48, Pretreatment is defined as macro defined as macro
S_IWUSR include / a.out.h, 82, Pretreatment is defined as macro
include / sys / stat.h, 38, Pretreatment is defined as macro
include / a.out.h, 85, Pretreatment is defined as macro
S_IXGRP
include / a.out.h, 89, Pretreatment is defined as macro
include / sys / stat.h, 44, Pretreatment is defined as macro
include / a.out.h, 93, Pretreatment is defined as macro
S_IXOTH
selected kernel / blk_drv / floppy.c, 122, Defined as a variable
include / sys / stat.h, 49, Pretreatment is defined as macro

S_IXUSR
send_break

--636--
index

kernel / chr_drv / tty_ioctl.c, 51, Defined as a function SIG_DFL include / signal.h, 45, Pretreatment is defined as macro

send_sig
kernel / exit.c, 35, Defined as a function SIG_IGN include / signal.h, 46, Pretreatment is defined as macro

set_base
include / sched.h, 211, Pretreatment is defined as macro SIG_SETMASK include / signal.h, 43, Pretreatment is defined

set_bit as macro

fs / super.c, 22, Pretreatment is defined as macro SIG_UNBLOCK include / signal.h, 42, Pretreatment is defined

fs / bitmap.c, 19, Pretreatment is defined as macro as macro

set_cursor SIGABRT include / signal.h, 17, Pretreatment is defined as

kernel / chr_drv / console.c, 313, Defined as a function macro

set_fs sigaction include / signal.h, 48, defined as struct Types of

include / asm / segment.h, 61, Defined as a function

set_intr_gate include / signal.h, 66, Defined as a function prototype

include / asm / system.h, 33, Pretreatment is defined as macro sigaddset include / signal.h, 58, Defined as a function prototype

set_ldt_desc
include / asm / system.h, 66, Pretreatment is defined as macro SIGALRM include / signal.h, 26, Pretreatment is defined as

set_limit macro

include / sched.h, 212, Pretreatment is defined as macro SIGCHLD include / signal.h, 29, Pretreatment is defined as

set_origin macro

kernel / chr_drv / console.c, 97, Defined as a function SIGCONT include / signal.h, 30, Pretreatment is defined as

set_system_gate macro

include / asm / system.h, 39, Pretreatment is defined as macro sigdelset include / signal.h, 59, Defined as a function prototype

set_termio
kernel / chr_drv / tty_ioctl.c, 97, Defined as a function sigemptyset include / signal.h, 60, Defined as a function

set_termios prototype

kernel / chr_drv / tty_ioctl.c, 66, Defined as a function sigfillset include / signal.h, 61, Defined as a function prototype

set_trap_gate
include / asm / system.h, 36, Pretreatment is defined as macro SIGFPE include / signal.h, 20, Pretreatment is defined as macro

set_tss_desc
include / asm / system.h, 65, Pretreatment is defined as macro SIGHUP include / signal.h, 12, Pretreatment is defined as macro

setgid
include / unistd.h, 230, Defined as a function prototype SIGILL include / signal.h, 15, Pretreatment is defined as macro

setpgid
include / unistd.h, 228, Defined as a function prototype SIGINT include / signal.h, 13, Pretreatment is defined as macro

setpgrp
include / unistd.h, 227, Defined as a function prototype SIGIOT include / signal.h, 18, Pretreatment is defined as macro

setsid
include / unistd.h, 251, Defined as a function prototype sigismember include / signal.h, 62, Defined as a function

setuid prototype

include / unistd.h, 229, Defined as a function prototype SIGKILL include / signal.h, 21, Pretreatment is defined as macro

setup_DMA
kernel / blk_drv / floppy.c, 160, Defined as a function SIGN kernel / vsprintf.c, 28, Pretreatment is defined as macro

setup_rw_floppy
kernel / blk_drv / floppy.c, 269, Defined as a function sigpending include / signal.h, 63, Defined as a function

SETUP_SECTS tools / build.c, 42, Pretreatment is defined prototype

as macro SIGPIPE include / signal.h, 25, Pretreatment is defined as macro

share_page
mm / memory.c, 344, Defined as a function sigprocmask include / signal.h, 64, Defined as a function

show_stat prototype

kernel / sched.c, 37, Defined as a function SIGQUIT include / signal.h, 14, Pretreatment is defined as macro

show_task
kernel / sched.c, 26, Defined as a function SIGSEGV include / signal.h, 23, Pretreatment is defined as

sig_atomic_t include / signal.h, 6, Defined as a macro

type sigset_t include / signal.h, 7, Defined as a type

SIG_BLOCK include / signal.h, 41, Pretreatment is defined as

macro SIGSTKFLT

--637--
index

include / signal.h, 28, Pretreatment is defined as macro include / fdreg.h, 34, Pretreatment is defined as macro

SIGSTOP ST1
include / signal.h, 31, Pretreatment is defined as macro kernel / blk_drv / floppy.c, 68, Pretreatment is defined as macro

sigsuspend ST1_CRC include / fdreg.h, 42, Pretreatment is defined as

include / signal.h, 65, Defined as a function prototype macro

SIGTERM ST1_EOC include / fdreg.h, 43, Pretreatment is defined as

include / signal.h, 27, Pretreatment is defined as macro macro

SIGTRAP ST1_MAM include / fdreg.h, 38, Pretreatment is defined as

include / signal.h, 16, Pretreatment is defined as macro macro

SIGTSTP ST1_ND include / fdreg.h, 40, Pretreatment is defined as macro

include / signal.h, 32, Pretreatment is defined as macro

SIGTTIN ST1_OR include / fdreg.h, 41, Pretreatment is defined as macro

include / signal.h, 33, Pretreatment is defined as macro

SIGTTOU ST1_WP include / fdreg.h, 39, Pretreatment is defined as macro

include / signal.h, 34, Pretreatment is defined as macro

SIGUNUSED include / signal.h, 19, Pretreatment is defined as ST2


macro kernel / blk_drv / floppy.c, 69, Pretreatment is defined as macro

SIGUSR1 ST2_BC include / fdreg.h, 47, Pretreatment is defined as macro

include / signal.h, 22, Pretreatment is defined as macro

SIGUSR2 ST2_CM include / fdreg.h, 52, Pretreatment is defined as macro

include / signal.h, 24, Pretreatment is defined as macro

size_t ST2_CRC include / fdreg.h, 51, Pretreatment is defined as

include / sys / types.h, 6, Defined as a type macro

include / time.h, 11, Defined as a type ST2_MAM include / fdreg.h, 46, Pretreatment is defined as

include / stddef.h, 11, Defined as a type macro

include / string.h, 10, Defined as a type ST2_SEH include / fdreg.h, 49, Pretreatment is defined as

skip_atoi macro

kernel / vsprintf.c, 18, Defined as a function ST2_SNS include / fdreg.h, 48, Pretreatment is defined as

sleep_if_empty macro

kernel / chr_drv / tty_io.c, 122, Defined as a function ST2_WC include / fdreg.h, 50, Pretreatment is defined as macro

sleep_if_full
kernel / chr_drv / tty_io.c, 130, Defined as a function ST3
sleep_on kernel / blk_drv / floppy.c, 70, Pretreatment is defined as macro

include / sched.h, 145, Defined as a function prototype ST3_HA include / fdreg.h, 55, Pretreatment is defined as macro

kernel / sched.c, 151, Defined as a function


ST3_TZ include / fdreg.h, 56, Pretreatment is defined as macro
SMALL
kernel / vsprintf.c, 33, Pretreatment is defined as macro
ST3_WP include / fdreg.h, 57, Pretreatment is defined as macro
SPACE
kernel / vsprintf.c, 30, Pretreatment is defined as macro
stack_segment kernel / traps.c, 55, Defined as a function
SPECIAL
prototype
kernel / vsprintf.c, 32, Pretreatment is defined as macro
start_buffer fs / buffer.c, 30, Defined as a
speed_t
include / termios.h, 214, Defined as a type variable

ST0 include / fs.h, 165, Defined as a variable

kernel / blk_drv / floppy.c, 67, Pretreatment is defined as macro START_CHAR include / tty.h, 41, Pretreatment is defined

ST0_DS as macro

include / fdreg.h, 30, Pretreatment is defined as macro startup_time include / sched.h, 140, Defined as a

ST0_ECE variable

include / fdreg.h, 33, Pretreatment is defined as macro init / main.c, 53, Defined as a variable

ST0_HA kernel / sched.c, 61, Defined as a variable

include / fdreg.h, 31, Pretreatment is defined as macro stat include / sys / stat.h, 6, defined as struct Types of

ST0_INTR
include / fdreg.h, 35, Pretreatment is defined as macro include / sys / stat.h, 55, Defined as a function prototype

ST0_NR include / unistd.h, 232, Defined as a function prototype

include / fdreg.h, 32, Pretreatment is defined as macro state


ST0_SE kernel / chr_drv / console.c, 74, Defined as a variable

--638--
index

STATUS_BUSY include / fdreg.h, 24, Pretreatment is defined include / string.h, 277, Defined as a function

as macro super_block fs / super.c, 27, Defined as a


STATUS_BUSYMASK include / fdreg.h, 23, Pretreatment is variable
defined as macro include / fs.h, 124, defined as struct Types of
STATUS_DIR include / fdreg.h, 26, Pretreatment is defined as include / fs.h, 164, Defined as a variable
macro SUPER_MAGIC include / fs.h, 41, Pretreatment is
STATUS_DMA include / fdreg.h, 25, Pretreatment is defined defined as macro
as macro suser include / kernel.h, 21, Pretreatment is defined as macro
STATUS_READY include / fdreg.h, 27, Pretreatment is

defined as macro SUSPEND_CHAR include / tty.h, 43, Pretreatment is


STDERR_FILENO include / unistd.h, 15, Pretreatment is defined as macro
defined as macro switch_to include / sched.h, 171, Pretreatment is defined as macro
STDIN_FILENO include / unistd.h, 13, Pretreatment is defined

as macro sync include / unistd.h, 235, Defined as a function prototype


STDOUT_FILENO include / unistd.h, 14, Pretreatment is

defined as macro sync_dev fs / buffer.c, 59, Defined as a


sti function
include / asm / system.h, 16, Pretreatment is defined as macro
fs / super.c, 18, Defined as a function prototype
stime
include / fs.h, 196, Defined as a function prototype
include / unistd.h, 234, Defined as a function prototype
sync_inodes fs / inode.c, 59, Defined as a
STOP_CHAR include / tty.h, 42, Pretreatment is defined as
function
macro
include / fs.h, 174, Defined as a function prototype
str
sys_access fs / open.c, 47, Defined as a
include / sched.h, 159, Pretreatment is defined as macro
function
strcat
include / sys.h, 34, Defined as a function prototype
include / string.h, 54, Defined as a function
sys_acct include / sys.h, 52, Defined as a function prototype
strchr
include / string.h, 128, Defined as a function
kernel / sys.c, 77, Defined as a function
strcmp
sys_alarm include / sys.h, 28, Defined as a function
include / string.h, 88, Defined as a function
prototype
strcpy
kernel / sched.c, 338, Defined as a function
include / string.h, 27, Defined as a function
sys_break include / sys.h, 18, Defined as a function
strcspn
prototype
include / string.h, 185, Defined as a function
kernel / sys.c, 21, Defined as a function
strerror
sys_brk include / sys.h, 46, Defined as a function prototype
include / string.h, 13, Defined as a function prototype

strftime
kernel / sys.c, 168, Defined as a function
include / time.h, 39, Defined as a function prototype
sys_call_table include / sys.h, 74, Defined as a
STRINGIFY tools / build.c, 44, Pretreatment is defined as
variable
macro
sys_chdir fs / open.c, 75, Defined as a
strlen
function
We include / string.h, 263, Defined as a function
include / sys.h, 13, Defined as a function prototype
strncat
sys_chmod fs / open.c, 105, Defined as a
include / string.h, 68, Defined as a function
function
strncmp
include / sys.h, 16, Defined as a function prototype
include / string.h, 107, Defined as a function

strncpy sys_chown fs / open.c, 121, Defined as a

include / string.h, 38, Defined as a function function

strpbrk include / sys.h, 17, Defined as a function prototype

include / string.h, 209, Defined as a function sys_chroot fs / open.c, 90, Defined as a

strrchr function

include / string.h, 145, Defined as a function include / sys.h, 62, Defined as a function prototype

strspn sys_close fs / open.c, 192, Defined as a

include / string.h, 161, Defined as a function function

strstr fs / exec.c, 32, Defined as a function prototype

include / string.h, 236, Defined as a function fs / fcntl.c, 16, Defined as a function prototype

strtok

--639--
index

include / sys.h, 7, Defined as a function prototype sys_kill include / sys.h, 38, Defined as a function prototype

kernel / exit.c, 17, Defined as a function prototype

sys_creat fs / open.c, 187, Defined as a kernel / exit.c, 60, Defined as a function

function sys_link fs / namei.c, 721, Defined as a

include / sys.h, 9, Defined as a function prototype function

sys_dup fs / fcntl.c, 42, Defined as a include / sys.h, 10, Defined as a function prototype

function sys_lock include / sys.h, 54, Defined as a function prototype

include / sys.h, 42, Defined as a function prototype

sys_dup2 fs / fcntl.c, 36, Defined as a kernel / sys.c, 87, Defined as a function

function sys_lseek fs / read_write.c, 25, Defined as a

include / sys.h, 64, Defined as a function prototype function

sys_execve include / sys.h, 12, Defined as a function include / sys.h, 20, Defined as a function prototype

prototype sys_mkdir fs / namei.c, 463, Defined as a

sys_exit fs / exec.c, 31, Defined as a function function

prototype include / sys.h, 40, Defined as a function prototype

include / sys.h, 2, Defined as a function prototype sys_mknod fs / namei.c, 412, Defined as a

kernel / exit.c, 137, Defined as a function function

sys_fcntl fs / fcntl.c, 47, Defined as a include / sys.h, 15, Defined as a function prototype

function sys_mount fs / super.c, 200, Defined as a

include / sys.h, 56, Defined as a function prototype function

sys_fork include / sys.h, 22, Defined as a function prototype

include / sys.h, 3, Defined as a function prototype sys_mpx include / sys.h, 57, Defined as a function prototype

sys_fstat fs / stat.c, 47, Defined as a

function kernel / sys.c, 92, Defined as a function

include / sys.h, 29, Defined as a function prototype sys_nice include / sys.h, 35, Defined as a function prototype

sys_ftime
include / sys.h, 36, Defined as a function prototype kernel / sched.c, 378, Defined as a function

kernel / sys.c, 16, Defined as a function sys_open fs / open.c, 138, Defined as a

sys_getegid include / sys.h, 51, Defined as a function function

prototype include / sys.h, 6, Defined as a function prototype

kernel / sched.c, 373, Defined as a function sys_pause include / sys.h, 30, Defined as a function

sys_geteuid include / sys.h, 50, Defined as a function prototype

prototype kernel / sched.c, 144, Defined as a function

kernel / sched.c, 363, Defined as a function kernel / exit.c, 16, Defined as a function prototype

sys_getgid sys_phys include / sys.h, 53, Defined as a function prototype

include / sys.h, 48, Defined as a function prototype

kernel / sched.c, 368, Defined as a function kernel / sys.c, 82, Defined as a function

sys_getpgrp include / sys.h, 66, Defined as a function sys_pipe fs / pipe.c, 71, Defined as a

prototype function

kernel / sys.c, 201, Defined as a function include / sys.h, 43, Defined as a function prototype

sys_getpid sys_prof include / sys.h, 45, Defined as a function prototype

include / sys.h, 21, Defined as a function prototype

kernel / sched.c, 348, Defined as a function kernel / sys.c, 46, Defined as a function

sys_getppid include / sys.h, 65, Defined as a function sys_ptrace include / sys.h, 27, Defined as a function

prototype prototype

kernel / sched.c, 353, Defined as a function kernel / sys.c, 26, Defined as a function

sys_getuid sys_read fs / read_write.c, 55, Defined as a function

include / sys.h, 25, Defined as a function prototype

kernel / sched.c, 358, Defined as a function include / sys.h, 4, Defined as a function prototype

sys_gtty sys_rename include / sys.h, 39, Defined as a function

include / sys.h, 33, Defined as a function prototype prototype

kernel / sys.c, 36, Defined as a function kernel / sys.c, 41, Defined as a function

sys_ioctl fs / ioctl.c, 30, Defined as a sys_rmdir fs / namei.c, 587, Defined as a

function function

include / sys.h, 55, Defined as a function prototype include / sys.h, 41, Defined as a function prototype

--640--
index

sys_setgid include / sys.h, 59, Defined as a function prototype

include / sys.h, 47, Defined as a function prototype kernel / sys.c, 97, Defined as a function

kernel / sys.c, 72, Defined as a function sys_umask include / sys.h, 61, Defined as a function

sys_setpgid include / sys.h, 58, Defined as a function prototype

prototype kernel / sys.c, 230, Defined as a function

kernel / sys.c, 181, Defined as a function sys_umount fs / super.c, 167, Defined as a


sys_setregid include / sys.h, 72, Defined as a function function
prototype include / sys.h, 23, Defined as a function prototype

kernel / sys.c, 51, Defined as a function sys_uname include / sys.h, 60, Defined as a function

sys_setreuid include / sys.h, 71, Defined as a function prototype

prototype kernel / sys.c, 216, Defined as a function

kernel / sys.c, 118, Defined as a function sys_unlink fs / namei.c, 663, Defined as a


sys_setsid function
include / sys.h, 67, Defined as a function prototype include / sys.h, 11, Defined as a function prototype

kernel / sys.c, 206, Defined as a function sys_ustat fs / open.c, 19, Defined as a

sys_setuid function

include / sys.h, 24, Defined as a function prototype include / sys.h, 63, Defined as a function prototype

kernel / sys.c, 143, Defined as a function sys_utime fs / open.c, 24, Defined as a

sys_setup function

include / sys.h, 1, Defined as a function prototype include / sys.h, 31, Defined as a function prototype

kernel / blk_drv / hd.c, 71, Defined as a function sys_waitpid include / sys.h, 8, Defined as a function

sys_sgetmask include / sys.h, 69, Defined as a function prototype

prototype kernel / exit.c, 142, Defined as a function

kernel / signal.c, 15, Defined as a function sys_write fs / read_write.c, 83, Defined as a


sys_sigaction include / sys.h, 68, Defined as a function function
prototype include / sys.h, 5, Defined as a function prototype

kernel / signal.c, 63, Defined as a function sysbeep kernel / chr_drv / console.c, 79, Defined as a function prototype

sys_signal
include / sys.h, 49, Defined as a function prototype kernel / chr_drv / console.c, 699, Defined as a function
kernel / signal.c, 48, Defined as a function sysbeepstop kernel / chr_drv / console.c, 691, Defined as a
SYS_SIZE tools / build.c, 35, Pretreatment is defined as function
macro system_call kernel / sched.c, 51, Defined as a function

sys_ssetmask include / sys.h, 70, Defined as a function prototype

prototype TAB0 include / termios.h, 116, Pretreatment is defined as macro

kernel / signal.c, 20, Defined as a function

sys_stat fs / stat.c, 36, Defined as a TAB1 include / termios.h, 117, Pretreatment is defined as macro

function

include / sys.h, 19, Defined as a function prototype TAB2 include / termios.h, 118, Pretreatment is defined as macro

sys_stime
include / sys.h, 26, Defined as a function prototype TAB3 include / termios.h, 119, Pretreatment is defined as macro

kernel / sys.c, 148, Defined as a function

sys_stty TABDLY include / termios.h, 115, Pretreatment is defined as macro

include / sys.h, 32, Defined as a function prototype

kernel / sys.c, 31, Defined as a function table_list kernel / chr_drv / tty_io.c, 99, Defined as a variable

sys_sync fs / buffer.c, 44, Defined as a

function task include / sched.h, 136, Defined as a variable

include / sys.h, 37, Defined as a function prototype


kernel / sched.c, 65, Defined as a variable
kernel / panic.c, 14, Defined as a function prototype
TASK_INTERRUPTIBLE include / sched.h, 20, Pretreatment
sys_time
include / sys.h, 14, Defined as a function prototype
is defined as macro

TASK_RUNNING include / sched.h, 19, Pretreatment is


kernel / sys.c, 102, Defined as a function
defined as macro
sys_times
TASK_STOPPED include / sched.h, 23, Pretreatment is
include / sys.h, 44, Defined as a function prototype
defined as macro
kernel / sys.c, 156, Defined as a function
task_struct include / sched.h, 78, defined as struct Types
sys_ulimit
of

--641--
index

TASK_UNINTERRUPTIBLE include / sched.h, 21, Pretreatment include / termios.h, 10, Pretreatment is defined as macro

is defined as macro TCXONC include / termios.h, 17, Pretreatment is defined as macro

task_union
kernel / sched.c, 53, defined as union Types of tell_father kernel / exit.c, 83, Defined as a
TASK_ZOMBIE include / sched.h, 22, Pretreatment is defined function
as macro termio include / termios.h, 44, defined as struct Types of
tcdrain
include / termios.h, 220, Defined as a function prototype termios include / termios.h, 54, defined as struct Types of
tcflow
include / termios.h, 221, Defined as a function prototype ticks_to_floppy_on include / fs.h, 170, Defined as a
TCFLSH function prototype
include / termios.h, 18, Pretreatment is defined as macro include / fdreg.h, 9, Defined as a function prototype
tcflush kernel / sched.c, 206, Defined as a function
include / termios.h, 222, Defined as a function prototype time include / unistd.h, 236, Defined as a function prototype
TCGETA
include / termios.h, 12, Pretreatment is defined as macro
include / time.h, 31, Defined as a function prototype
tcgetattr time_init init / main.c, 76, Defined as a
include / termios.h, 223, Defined as a function prototype
function
TCGETS TIME_REQUESTS kernel / sched.c, 264, Pretreatment is
include / termios.h, 8, Pretreatment is defined as macro
defined as macro
TCIFLUSH time_t include / sys / types.h, 11, Defined as a type
include / termios.h, 205, Pretreatment is defined as macro

TCIOFF
include / time.h, 6, Defined as a type
include / termios.h, 201, Pretreatment is defined as macro
timer_interrupt kernel / sched.c, 50, Defined as a function
TCIOFLUSH
prototype
include / termios.h, 207, Pretreatment is defined as macro
timer_list kernel / sched.c, 266, defined as struct Types of
TCION
include / termios.h, 202, Pretreatment is defined as macro
kernel / sched.c, 270, Defined as a variable
TCOFLUSH
times include / sys / times.h, 13, Defined as a function prototype
include / termios.h, 206, Pretreatment is defined as macro

TCOOFF
include / unistd.h, 237, Defined as a function prototype
include / termios.h, 199, Pretreatment is defined as macro
TIOCEXCL include / termios.h, 19, Pretreatment is defined as
TCOON
macro
include / termios.h, 200, Pretreatment is defined as macro
TIOCGPGRP include / termios.h, 22, Pretreatment is defined as
TCSADRAIN
macro
include / termios.h, 211, Pretreatment is defined as macro
TIOCGSOFTCAR include / termios.h, 32, Pretreatment is
TCSAFLUSH
defined as macro
include / termios.h, 212, Pretreatment is defined as macro
TIOCGWINSZ include / termios.h, 26, Pretreatment is defined as
TCSANOW
macro
include / termios.h, 210, Pretreatment is defined as macro
TIOCINQ include / termios.h, 34, Pretreatment is defined as macro
TCSBRK
include / termios.h, 16, Pretreatment is defined as macro
TIOCM_CAR include / termios.h, 192, Pretreatment is defined as
tcsendbreak
macro
include / termios.h, 224, Defined as a function prototype
TIOCM_CD include / termios.h, 195, Pretreatment is defined as
TCSETA
macro
include / termios.h, 13, Pretreatment is defined as macro
TIOCM_CTS include / termios.h, 191, Pretreatment is defined as
TCSETAF
macro
include / termios.h, 15, Pretreatment is defined as macro
TIOCM_DSR include / termios.h, 194, Pretreatment is defined as
tcsetattr
macro
include / termios.h, 225, Defined as a function prototype
TIOCM_DTR include / termios.h, 187, Pretreatment is defined as
TCSETAW
macro
include / termios.h, 14, Pretreatment is defined as macro
TIOCM_LE include / termios.h, 186, Pretreatment is defined as
TCSETS
macro
include / termios.h, 9, Pretreatment is defined as macro
TIOCM_RI include / termios.h, 196, Pretreatment is defined as
TCSETSF
macro
include / termios.h, 11, Pretreatment is defined as macro
TIOCM_RNG
TCSETSW

--642--
index

include / termios.h, 193, Pretreatment is defined as macro include / fs.h, 173, Defined as a function prototype

TIOCM_RTS try_to_share mm / memory.c, 292, Defined as a

include / termios.h, 188, Pretreatment is defined as macro function


TIOCM_SR tss_struct include / sched.h, 51, defined as struct Types of

include / termios.h, 190, Pretreatment is defined as macro

TIOCM_ST TSTPMASK kernel / chr_drv / tty_io.c, 21, Pretreatment is defined as

include / termios.h, 189, Pretreatment is defined as macro macro

TIOCMBIC TTY_BUF_SIZE include / termios.h, 4, Pretreatment is defined

include / termios.h, 30, Pretreatment is defined as macro as macro

TIOCMBIS include / tty.h, 14, Pretreatment is defined as macro

include / termios.h, 29, Pretreatment is defined as macro tty_init include / tty.h, 67, Defined as a function prototype

TIOCMGET
include / termios.h, 28, Pretreatment is defined as macro kernel / chr_drv / tty_io.c, 105, Defined as a function
TIOCMSET tty_intr
include / termios.h, 31, Pretreatment is defined as macro kernel / chr_drv / tty_io.c, 111, Defined as a function
TIOCNXCL tty_ioctl fs / ioctl.c, 13, Defined as a function

include / termios.h, 20, Pretreatment is defined as macro prototype


TIOCOUTQ kernel / chr_drv / tty_ioctl.c, 115, Defined as a function
include / termios.h, 24, Pretreatment is defined as macro tty_queue include / tty.h, 16, defined as struct Types
TIOCSCTTY of
include / termios.h, 21, Pretreatment is defined as macro tty_read fs / char_dev.c, 16, Defined as a function prototype
TIOCSPGRP
include / termios.h, 23, Pretreatment is defined as macro
include / tty.h, 69, Defined as a function prototype
TIOCSSOFTCAR include / termios.h, 33, Pretreatment is
kernel / chr_drv / tty_io.c, 230, Defined as a function
defined as macro
tty_struct include / tty.h, 45, defined as struct Types of
TIOCSTI
include / termios.h, 25, Pretreatment is defined as macro
tty_table include / tty.h, 55, defined as struct Types of
TIOCSWINSZ include / termios.h, 27, Pretreatment is defined as

macro
kernel / chr_drv / tty_io.c, 51, defined as struct Types of
tm
tty_write fs / char_dev.c, 17, Defined as a function prototype
include / time.h, 18, defined as struct Types of
tmp_floppy_area
include / kernel.h, 8, Defined as a function prototype
kernel / blk_drv / floppy.c, 105, Defined as a variable
include / sched.h, 36, Defined as a function prototype
tms
include / tty.h, 70, Defined as a function prototype
include / sys / times.h, 6, defined as struct Types of
kernel / chr_drv / tty_io.c, 290, Defined as a function
toascii
TYPE
include / ctype.h, 29, Pretreatment is defined as macro
kernel / blk_drv / floppy.c, 53, Pretreatment is defined as macro
tolower
tzset include / time.h, 40, Defined as a function prototype
include / ctype.h, 31, Pretreatment is defined as macro

top
u_char include / sys / types.h, 33, Defined as a type
kernel / chr_drv / console.c, 73, Defined as a variable

TOSTOP
uid_t include / sys / types.h, 24, Defined as a type
include / termios.h, 177, Pretreatment is defined as macro

toupper
ulimit include / unistd.h, 238, Defined as a function prototype
include / ctype.h, 32, Pretreatment is defined as macro

track
umask include / sys / stat.h, 56, Defined as a function prototype
kernel / blk_drv / floppy.c, 118, Defined as a variable

transfer
include / unistd.h, 239, Defined as a function prototype
kernel / blk_drv / floppy.c, 309, Defined as a function
umode_t include / sys / types.h, 29, Defined as a type
trap_init
include / sched.h, 34, Defined as a function prototype
umount include / unistd.h, 240, Defined as a function prototype
kernel / traps.c, 181, Defined as a function

TRK0_ERR
un_wp_page mm / memory.c, 221, Defined as a
include / hdreg.h, 46, Pretreatment is defined as macro
function
truncate
uname include / sys / utsname.h, 14, Defined as a function prototype
fs / truncate.c, 47, Defined as a function

--643--
index

include / unistd.h, 241, Defined as a function prototype kernel / chr_drv / console.c, 64, Defined as a variable

unexpected_floppy_interrupt kernel / blk_drv / floppy.c, 353, Defined video_mem_start kernel / chr_drv / console.c, 63, Defined as a

as a function variable
unexpected_hd_interrupt kernel / blk_drv / hd.c, 237, Defined video_num_columns kernel / chr_drv / console.c, 59, Defined

as a function as a variable
unlink video_num_lines kernel / chr_drv / console.c, 61, Defined as a

include / unistd.h, 242, Defined as a function prototype variable


unlock_buffer video_page kernel / chr_drv / console.c, 62, Defined as a

kernel / blk_drv / ll_rw_blk.c, 51, Defined as a function variable

kernel / blk_drv / blk.h, 101, Defined as a function video_port_reg kernel / chr_drv / console.c, 65, Defined as a

unlock_inode fs / inode.c, 37, Defined as a variable

function video_port_val kernel / chr_drv / console.c, 66, Defined as a

usage variable

tools / build.c, 52, Defined as a function video_size_row kernel / chr_drv / console.c, 60, Defined as a

USED variable

mm / memory.c, 47, Pretreatment is defined as macro video_type kernel / chr_drv / console.c, 58, Defined as a variable

user_stack
kernel / sched.c, 67, Defined as a variable VIDEO_TYPE_CGA kernel / chr_drv / console.c, 50, Pretreatment is

ushort defined as macro

include / sys / types.h, 34, Defined as a type VIDEO_TYPE_EGAC kernel / chr_drv / console.c, 52, Pretreatment is

ustat defined as macro

include / sys / types.h, 39, defined as struct Types of VIDEO_TYPE_EGAM kernel / chr_drv / console.c, 51, Pretreatment is

include / unistd.h, 243, Defined as a function prototype defined as macro

utimbuf VIDEO_TYPE_MDA kernel / chr_drv / console.c, 49, Pretreatment is

include / utime.h, 6, defined as struct Types of defined as macro

utime VINTR include / termios.h, 64, Pretreatment is defined as macro

include / unistd.h, 244, Defined as a function prototype

include / utime.h, 11, Defined as a function prototype VKILL include / termios.h, 67, Pretreatment is defined as macro

utsname
include / sys / utsname.h, 6, defined as struct Types of VLNEXT include / termios.h, 79, Pretreatment is defined as macro

va_arg
include / stdarg.h, 24, Pretreatment is defined as macro VMIN include / termios.h, 70, Pretreatment is defined as macro

va_end
include / stdarg.h, 22, Pretreatment is defined as macro VQUIT include / termios.h, 65, Pretreatment is defined as macro

include / stdarg.h, 21, Defined as a function prototype


VREPRINT include / termios.h, 76, Pretreatment is defined as
va_list
macro
include / stdarg.h, 4, Defined as a type
vsprintf init / main.c, 44, Defined as a function prototype
va_start
include / stdarg.h, 13, Pretreatment is defined as macro
kernel / printk.c, 19, Defined as a function prototype
include / stdarg.h, 16, Pretreatment is defined as macro

VDISCARD kernel / vsprintf.c, 92, Defined as a function

include / termios.h, 77, Pretreatment is defined as macro VSTART include / termios.h, 72, Pretreatment is defined as macro

VEOF
include / termios.h, 68, Pretreatment is defined as macro VSTOP include / termios.h, 73, Pretreatment is defined as macro

VEOL
include / termios.h, 75, Pretreatment is defined as macro VSUSP include / termios.h, 74, Pretreatment is defined as macro

VEOL2
include / termios.h, 80, Pretreatment is defined as macro VSWTC include / termios.h, 71, Pretreatment is defined as macro

VERASE
include / termios.h, 66, Pretreatment is defined as macro VT0 include / termios.h, 125, Pretreatment is defined as macro

verify_area
include / kernel.h, 4, Defined as a function prototype VT1 include / termios.h, 126, Pretreatment is defined as macro

kernel / fork.c, 24, Defined as a function


VTDLY include / termios.h, 124, Pretreatment is defined as macro
video_erase_char
kernel / chr_drv / console.c, 67, Defined as a variable

video_mem_end VTIME

--644--
index

include / termios.h, 69, Pretreatment is defined as macro kernel / blk_drv / hd.c, 169, Defined as a function

VWERASE WIN_SEEK include / hdreg.h, 40, Pretreatment is defined as

include / termios.h, 78, Pretreatment is defined as macro macro

W_OK WIN_SPECIFY include / hdreg.h, 42, Pretreatment is defined

include / unistd.h, 24, Pretreatment is defined as macro as macro

wait WIN_VERIFY include / hdreg.h, 37, Pretreatment is defined as

include / sys / wait.h, 20, Defined as a function prototype macro

include / unistd.h, 246, Defined as a function prototype WIN_WRITE include / hdreg.h, 36, Pretreatment is defined as

lib / wait.c, 13, Defined as a function macro

wait_for_keypress fs / super.c, 19, Defined as a winsize include / termios.h, 36, defined as struct Types of

function prototype

kernel / chr_drv / tty_io.c, 140, Defined as a function WNOHANG include / sys / wait.h, 10, Pretreatment is defined as

wait_for_request macro

kernel / blk_drv / ll_rw_blk.c, 26, Defined as a variable WRERR_STAT include / hdreg.h, 29, Pretreatment is defined

as macro
kernel / blk_drv / blk.h, 52, Defined as a variable
write include / unistd.h, 247, Defined as a function prototype
wait_motor
kernel / sched.c, 201, Defined as a variable
WRITE include / fs.h, 27, Pretreatment is defined as macro
wait_on
include / fs.h, 175, Defined as a function prototype
write_inode fs / inode.c, 18, Defined as a function
wait_on_buffer fs / buffer.c, 36, Defined as
prototype
a function
wait_on_floppy_select kernel / blk_drv / floppy.c, 123, Defined fs / inode.c, 314, Defined as a function

as a variable write_intr kernel / blk_drv / hd.c, 269, Defined as a function

wait_on_inode fs / inode.c, 20, Defined as

a function write_pipe fs / read_write.c, 17, Defined as a function

wait_on_super fs / super.c, 48, Defined as prototype

a function fs / pipe.c, 41, Defined as a function

wait_until_sent write_verify kernel / fork.c, 20, Defined as a function

kernel / chr_drv / tty_ioctl.c, 46, Defined as a function prototype

waitpid mm / memory.c, 261, Defined as a function

include / sys / wait.h, 21, Defined as a function prototype WRITEA include / fs.h, 29, Pretreatment is defined as

include / unistd.h, 245, Defined as a function prototype macro

wake_up WSTOPSIG include / sys / wait.h, 17, Pretreatment is defined as

include / sched.h, 147, Defined as a function prototype macro

kernel / sched.c, 188, Defined as a function WTERMSIG include / sys / wait.h, 16, Pretreatment is defined as

WAKEUP_CHARS kernel / chr_drv / serial.c, 21, Pretreatment is macro

defined as macro WUNTRACED include / sys / wait.h, 11, Pretreatment is defined as

WEXITSTATUS include / sys / wait.h, 15, Pretreatment is defined macro

as macro X_OK include / unistd.h, 23, Pretreatment is defined as macro

WIFEXITED
include / sys / wait.h, 13, Pretreatment is defined as macro XCASE include / termios.h, 171, Pretreatment is defined as macro

WIFSIGNALED include / sys / wait.h, 18, Pretreatment is defined

as macro XTABS include / termios.h, 120, Pretreatment is defined as macro

WIFSTOPPED include / sys / wait.h, 14, Pretreatment is defined as

macro y kernel / chr_drv / console.c, 72, Defined as a variable

WIN_DIAGNOSE include / hdreg.h, 41, Pretreatment is

defined as macro YEAR kernel / mktime.c, 23, Pretreatment is defined as macro

WIN_FORMAT include / hdreg.h, 38, Pretreatment is defined

as macro Z_MAP_SLOTS include / fs.h, 40, Pretreatment is

WIN_INIT defined as macro

include / hdreg.h, 39, Pretreatment is defined as macro ZEROPAD kernel / vsprintf.c, 27, Pretreatment is defined as

WIN_READ macro

include / hdreg.h, 35, Pretreatment is defined as macro ZMAGIC include / a.out.h, 27, Pretreatment is defined as macro

WIN_RESTORE include / hdreg.h, 34, Pretreatment is defined

as macro

win_result

--645--
index

--646--

You might also like