当前位置:网站首页>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:java
Enter a very simple command on the command line .
[[email protected]] cat info.txt | wc -l
3
This 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]] c
Let's press again 'a'
[[email protected]] ca
Next , Then we press 't'、 Space 、'i' wait , That's what happened .
[[email protected]] cat info.txt | wc -l
We 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_queue
You 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 -l
So 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
边栏推荐
- 降本40%!Redis多租户集群的容器化实践
- 搜索 正排索引 和 倒排索引 区别
- 【漏洞预警】CVE-2022-26134 Confluence 远程代码执行漏洞POC验证与修复过程
- Mistakes made when writing unit tests
- Use of set tag in SQL
- abstract关键字和哪些关键字会发生冲突呢
- 单商户 V4.4,初心未变,实力依旧!
- 详解SQL中Groupings Sets 语句的功能和底层实现逻辑
- Using graylog alarm function to realize the regular work reminder of nail group robots
- Cartoon: what is distributed transaction?
猜你喜欢
抽象类中子类与父类
后台系统发送验证码功能
数据湖(十四):Spark与Iceberg整合查询操作
ES6 deep - ES6 class class
五种常见的咨询公司谈判策略以及如何维护自己的利益
【刷题篇】鹅厂文化衫问题
The visual experience has been comprehensively upgraded, and Howell group and Intel Evo 3.0 have jointly accelerated the reform of the PC industry
Single merchant v4.4 has the same original intention and strength!
普洛斯数据中心发布DC Brain系统,科技赋能智慧化运营管理
vant tabbar遮挡内容的解决方式
随机推荐
视觉体验全面升级,豪威集团与英特尔Evo 3.0共同加速PC产业变革
效果编辑器新版上线!3D渲染、加标注、设置动画,这次一个编辑器就够了
Explain in detail the functions and underlying implementation logic of the groups sets statement in SQL
《MongoDB入门教程》第04篇 MongoDB客户端
对象和类的关系
漫画:什么是八皇后问题?
CISP-PTE之SQL注入(二次注入的应用)
详解SQL中Groupings Sets 语句的功能和底层实现逻辑
Single merchant v4.4 has the same original intention and strength!
开发中Boolean类型使用遇到的坑
The list set is summed up according to a certain attribute of the object, the maximum value, etc
写单元测试的时候犯的错
HiEngine:可媲美本地的云原生内存数据库引擎
Cartoon: what is the eight queens problem?
Apiccloud cloud debugging solution
详解SQL中Groupings Sets 语句的功能和底层实现逻辑
Data access - entityframework integration
Transaction rollback exception
迁移/home分区
"21 days proficient in typescript-3" - install and build a typescript development environment md