当前位置:网站首页>Enter a command with the keyboard
Enter a command with the keyboard
2022-07-05 16:31:00 【CSDN cloud computing】

author | Dodger
source | Low concurrency programming
Create a very simple info.txt file .
name:flash
age:28
language:javaEnter a very simple command on the command line .
[[email protected]] cat info.txt | wc -l
3This command means to read the just info.txt file , Output its rows .
Let's start with the initial state .
The initial state , There is only one sentence in front of the computer screen .
[[email protected]]then , We press the button 'c', It will be like this .
[[email protected]] cLet's press again 'a'
[[email protected]] caNext , Then we press 't'、 Space 、'i' wait , That's what happened .
[[email protected]] cat info.txt | wc -lWe are going to explain this today. It looks very " normal " The process of .
Why should we press the keyboard , Such changes will appear on the screen ? Is it stipulated by God ?
We'll start by pressing on the keyboard 'c' The key starts talking .
First , Thanks to the The first 16 return | Console initialization tty_init A line of code described in .
// console.c
void con_init(void) {
...
set_trap_gate(0x21,&keyboard_interrupt);
...
}We successfully bound the keyboard interrupt to keyboard_interrupt On this interrupt handler , That is, when we press the keyboard 'c' when ,CPU The interrupt mechanism of will be triggered , Finally, this keyboard_interrupt Function .
We are here keyboard_interrupt Function to find out .
// keyboard.s
keyboard_interrupt:
...
// Read the keyboard scan code
inb $0x60,%al
...
// Call the handler of the corresponding key
call *key_table(,%eax,4)
...
// 0 As a parameter , call do_tty_interrupt
pushl $0
call do_tty_interrupt
...It's simple , First, through IO Port operation , Read the newly generated keyboard scan code from the keyboard , Just press 'c' Keyboard scan code generated when .
And then , stay key_table Search for different processing functions corresponding to different keys , For example, the character corresponding to a common letter 'c' The processing function of is do_self, This function converts the scan code to ASCII Character code , And put yourself in a queue , We will talk about the details of this part later .
Next , It's called do_tty_interrupt function , See the meaning of the name is to process the interrupt processing function of the terminal , Notice that a parameter is passed here 0.
Let's continue to explore , open do_tty_interrupt function .
// tty_io.c
void do_tty_interrupt(int tty) {
copy_to_cooked(tty_table+tty);
}
void copy_to_cooked(struct tty_struct * tty) {
...
}This function does almost nothing , take keyboard_interrupt Is the parameter passed in 0, As tty_table The index of , find tty_table No 0 As the input parameter of the next function , That's it .
tty_table yes Terminal equipment list , stay Linux 0.11 Three items are defined in , Namely Console 、 Serial terminal 1 and Serial terminal 2.
// tty.h
struct tty_struct tty_table[] = {
{
{...},
0, /* initial pgrp */
0, /* initial stopped */
con_write,
{0,0,0,0,""}, /* console read-queue */
{0,0,0,0,""}, /* console write-queue */
{0,0,0,0,""} /* console secondary queue */
},
{...},
{...}
};The terminal we use to output content to the screen , Namely 0 Console terminal at index position No , So I omit the code defined by the other two terminals .
tty_table Structure of each item in the terminal equipment table , yes tty_struct, Used to describe the properties of a terminal .
struct tty_struct {
struct termios termios;
int pgrp;
int stopped;
void (*write)(struct tty_struct * tty);
struct tty_queue read_q;
struct tty_queue write_q;
struct tty_queue secondary;
};
struct tty_queue {
unsigned long data;
unsigned long head;
unsigned long tail;
struct task_struct * proc_list;
char buf[TTY_BUF_SIZE];
};Talk about some of the key .
termios It defines various modes of the terminal , Including read mode 、 Write mode 、 Control mode, etc , Let's talk about it later .
void (*write)(struct tty_struct * tty) It's an interface function , In just tty_table We can also see that it is defined as con_write, That is to say, in the future, we will call this 0 During the write operation of terminal , What will be called is this con_write function , This is the idea of interface .
There are also three queues Read the queue read_q, Write a queue write_q And one. Secondary queue secondary.
What's the use of these , We'll talk about it later , Follow me and watch .
// tty_io.c
void do_tty_interrupt(int tty) {
copy_to_cooked(tty_table+tty);
}
void copy_to_cooked(struct tty_struct * tty) {
signed char c;
while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
// from read_q Middle out character
GETCH(tty->read_q,c);
...
// A lot of rule processing code is omitted here
...
// Put the processed characters into secondary
PUTCH(c,tty->secondary);
}
wake_up(&tty->secondary.proc_list);
}an copy_to_cooked We find that , A general framework has been established .
stay copy_to_cooked Function is a big loop , Just read the queue read_q Not empty , And auxiliary queue secondary Not full , From read_q Middle out character , After a big lump of treatment , write in secondary In the queue .

otherwise , Wake up and wait for the auxiliary queue secondary The process of , What to do next is up to the process itself .
Let's move on , What did the big lump in the middle do ?
This big lump has too many if Judge , But they all revolve around the same purpose , Let's give a simple example .
#define IUCLC 0001000
#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
#define I_UCLC(tty) _I_FLAG((tty),IUCLC)
void copy_to_cooked(struct tty_struct * tty) {
...
// A lot of rule processing code is omitted here
if (I_UCLC(tty))
c=tolower(c);
...
}In short , By judgment tty Medium termios, To determine the characters read c Do something about it .
ad locum , It is judgement. termios Medium c_iflag No 4 Whether a is 1, To decide whether to read the characters c From uppercase to lowercase .
This termios It defines the terminal Pattern .
struct termios {
unsigned long c_iflag; /* input mode flags */
unsigned long c_oflag; /* output mode flags */
unsigned long c_cflag; /* control mode flags */
unsigned long c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCCS]; /* control characters */
};For example, whether you want to change uppercase to lowercase , Whether to replace carriage return character with newline character , Whether to accept keyboard control character signals, such as ctrl + c etc. .
These patterns are not Linux 0.11 I dreamed it up , It's about achieving POSIX.1 Stipulated in termios standard , For details, please refer to :
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html#tag_11

Okay , We can conclude at present , What did you do after pressing the keyboard .

Here we should have a few questions .
One 、 Read the queue read_q When were the characters in it put in ?
Do you remember what I first said keyboard_interrupt function , We have a method that we haven't discussed .
// keyboard.s
keyboard_interrupt:
...
// Read the keyboard scan code
inb $0x60,%al
...
// Call the handler of the corresponding key
call *key_table(,%eax,4)
...
// 0 As a parameter , call do_tty_interrupt
pushl $0
call do_tty_interrupt
...This is this. key_table, We expand it .
// keyboard.s
key_table:
.long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */
.long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */
...
.long do_self,do_self,do_self,do_self /* 20-23 d f g h */
...It can be seen that , Ordinary characters abcd such , The corresponding processing function is do_self, Let's continue .
// keyboard.s
do_self:
...
// The scan code is converted to ASCII code
lea key_map,%ebx
1: movb (%ebx,%eax),%al
...
// Put in queue
call put_queueYou can see the last call put_queue function , seeing the name of a thing one thinks of its function Put in queue , It seems that we are going to find the answer , Continue to expand .
// tty_io.c
struct tty_queue * table_list[]={
&tty_table[0].read_q, &tty_table[0].write_q,
&tty_table[1].read_q, &tty_table[1].write_q,
&tty_table[2].read_q, &tty_table[2].write_q
};
// keyboard.s
put_queue:
...
movl table_list,%edx # read-queue for console
movl head(%edx),%ecx
...It can be seen that ,put_queue It is the operation of us tty_table Zero position in the array , That is, console terminal tty Of read_q queue , Join the team .
The answer is out , Then our overall flow chart can also be enriched .

Two 、 Put in secondary After the queue ?
After pressing the keyboard , A series of codes put our characters in secondary In line , so what ?
This involves the upper process calling the terminal's read function , Take this character away .
The upper layer passes through the library function 、 File system functions, etc , Will eventually be called to tty_read function , Change characters from secondary Take it from the queue .
// tty_io.c
int tty_read(unsigned channel, char * buf, int nr) {
...
GETCH(tty->secondary,c);
...
}What will you do after taking it , That's what the upper application decides .
If you want to write to the console terminal , Then the upper application will pass through the library function 、 File system functions are called layer by layer , Finally call to tty_write function .
// tty_io.
int tty_write(unsigned channel, char * buf, int nr) {
...
PUTCH(c,tty->write_q);
...
tty->write(tty);
...
}This function first converts the character c Put in write_q This line , And then call tty It's set in write function .
Terminal console tty We said that before , The initialization of the write The function is con_write, That is to say console Write function of .
// console.c
void con_write(struct tty_struct * tty) {
...
}Finally, it will cooperate with the graphics card , Output the characters we give on our screen .

Then our picture can be supplemented .

The core point is three queues read_q,secondary as well as write_q.
among read_q After the keyboard presses the key , Enter the keyboard interrupt handler keyboard_interrupt in , Finally through put_queue Put function characters into read_q This line .
secondary yes read_q Unprocessed characters in the queue , adopt copy_to_cooked function , After a certain termios After standard treatment , Put the processed characters into secondary.( After processing, the characters become " Ripe " The characters of , So called cooked, It's not very image ?)
then , Process passing tty_read from secondary Read character inside , adopt tty_write Write characters to write_q, Final write_q Characters in can be passed through con_write This console writes functions , Print characters on the display .
This completes a cycle from keyboard input to display output , That is what this time is about .
Okay , Now we have succeeded in inputting such a string and displaying it back on the display .
[[email protected]] cat info.txt | wc -lSo next ,shell How does the program read this string , How to deal with it after reading it ?

Previous recommendation
read How much disk does a byte of file actually take place on IO?
Docker Why is the container proud ? All supported by mirror image !
Redis What to do when the memory is full ? This is the correct setting !
The original hand of cloud 、 Good hands and bad hands

Share

Point collection

A little bit of praise

Click to see
边栏推荐
- 迁移/home分区
- Intel 13th generation Raptor Lake processor information exposure: more cores, larger cache
- RLock锁的使用
- 普洛斯数据中心发布DC Brain系统,科技赋能智慧化运营管理
- 今日睡眠质量记录79分
- ES6 drill down - Async functions and symbol types
- 单商户 V4.4,初心未变,实力依旧!
- Exception com alibaba. fastjson. JSONException: not match : - =
- Cartoon: what is service fusing?
- Quelques réflexions cognitives
猜你喜欢

Spring Festival Limited "forget trouble in the year of the ox" gift bag waiting for you to pick it up~

Single merchant v4.4 has the same original intention and strength!

写单元测试的时候犯的错
Intel 13th generation Raptor Lake processor information exposure: more cores, larger cache

CISP-PTE之PHP伪协议总结

抽象类中子类与父类

Single merchant v4.4 has the same original intention and strength!

开发中Boolean类型使用遇到的坑

Subclasses and superclasses of abstract classes

Research and development efficiency measurement index composition and efficiency measurement methodology
随机推荐
Explain in detail the functions and underlying implementation logic of the groups sets statement in SQL
2020-2022两周年创作纪念日
求解汉诺塔问题【修改版】
sql中查询最近一条记录
给自己打打气
降本40%!Redis多租户集群的容器化实践
服务器的数据库连不上了2003,10060“Unknown error“【服务已起、防火墙已关、端口已开、netlent 端口不通】
APICloud云调试解决方案
漫画:什么是MapReduce?
Single merchant v4.4 has the same original intention and strength!
[echart] resize lodash 实现窗口缩放时图表自适应
公司自用的国产API管理神器
ES6 deep - ES6 class class
Obj resolves to a set
数据湖(十四):Spark与Iceberg整合查询操作
How can programmers improve their situation?
HiEngine:可媲美本地的云原生内存数据库引擎
Batch update in the project
ES6 drill down - ES6 generator function
程序员如何提升自己的格局?