⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tty layer - the kernel structures.htm

📁 LINUX内核编程的一些程序例子
💻 HTM
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0059)http://www.geocities.com/marco_corvi/games/lkpe/tty/tty.htm -->
<HTML><HEAD><TITLE>The TTY layer</TITLE>
<META http-equiv=Content-Type content="text/html; charset=windows-1252"><LINK 
href="tty layer - The kernel structures_file/style.css" rel=stylesheet>
<META content="MSHTML 6.00.2800.1170" name=GENERATOR></HEAD>
<BODY>
<H2>tty layer - The kernel structures</H2>
<DIV>References:<BR>G. Kroah-Hartman, "The tty layer", Linux Journal, Aug. 2002, 
40-47<BR>G. Kroah-Hartman, "The tty layer - Part II", Linux Journal, Oct. 2002, 
50-58<BR>G. Kroah-Hartman, "The USB serial driver layer", Linux Journal, Feb. 
2003, 38-41<BR>G. Kroah-Hartman, "The USB serial driver layer - Part II" Linux 
Journal, Apr. 2003, 32-35<BR></DIV><BR clear=all><BR clear=all><BR clear=all>
<DIV>The tty layer is split into two structures: the tty driver and the line 
discipline. The driver handles the backend hardware; the line discipline is like 
a filter on the input/output. These two structures are contained in the 
<CODE>tty_struct</CODE>, which has also a structure, called flip buffer, for 
buffering input characters, and pointers to the termios. These structures are 
defined in four header files, in the include/linux subdirectory, 
<UL>
  <LI><CODE>tty.h</CODE>, with <CODE>screen_info</CODE>, 
  <CODE>tty_flip_buffer</CODE> and <CODE>tty_struct</CODE>; 
  <LI><CODE>tty_driver.h</CODE>, with <CODE>tty_driver</CODE>; 
  <LI><CODE>tty_ldisc.h</CODE>, with <CODE>tty_ldisc</CODE>; 
  <LI><CODE>tty_flip.h</CODE>, defines two inline routines 
  <UL>
    <LI><CODE>tty_insert_flip_char</CODE>: insert a char and a flag into the 
    <CODE>flip</CODE> buffers; 
    <LI><CODE>tty_schedule_flip</CODE>: append the flip <CODE>tqueue</CODE> to 
    the timer task queue. The routine <CODE>tty_flip_buffer_push</CODE> either 
    calls <CODE>flush_to_ldisc()</CODE>, if the low-latency flag is set, or 
    submit the tty's flip buffer <CODE>tqueue</CODE> on the timer queue. This 
    tqueue is initialized with the <CODE>flush_to_ldisc()</CODE> routine and the 
    tty data: see the description of <CODE>initialize_tty_struct</CODE> below. 
    </LI></UL></LI></UL></DIV><BR clear=all><IMG height=320 alt="tty structures" 
src="tty layer - The kernel structures_file/tty_struct.gif" width=480> <BR 
clear=all>
<DIV>The <CODE>screen_info</CODE> contains video informations, and data for the 
linear frame buffer of VESA graphic mode. </DIV>
<DIV>The <CODE>tty_flip_buffer</CODE> contains two input buffers of size twice 
<CODE>TTY_FLIPBUF_SIZE</CODE> (512), one of characters the other of flags (for 
parity errors). The flip buffers are logically made of two parts, and the code 
fills alternatively one or the other. <CODE>buf_num</CODE> denotes the part in 
use, and <CODE>count</CODE> the number of bytes that have been received. There 
is a task_queue <CODE>tqueue</CODE> and a semaphore <CODE>pty_sem</CODE>. 
</DIV><BR clear=all><B>TTY, tty_struct</B> <BR clear=all>
<DIV>
<UL>
  <LI>It contains a tty_driver <CODE>driver</CODE>; 
  <LI>a line discipline <CODE>ldisc</CODE>; 
  <LI>pointers to the <CODE>termios</CODE> and <CODE>termios_locked</CODE>; 
  <LI>several flags and counters; 
  <LI>a <CODE>link</CODE> to another tty_struct's (for ptty). It is used in the 
  <CODE>stop</CODE>/<CODE>start</CODE> methods of the tty_driver: the link's 
  read_wait queue is waken up if its <CODE>packet</CODE> flag is set; 
  <LI>a tty_flip_buffer <CODE>flip</CODE>; 
  <LI>two wait_queue_head_t, <CODE>write_wait</CODE> and <CODE>read_wait</CODE>; 

  <LI>a tq_struct <CODE>tq_hangup</CODE>; 
  <LI>a list of <CODE>tty_files</CODE>; 
  <LI>other fields for the N_TTY line discipline. </LI></UL></DIV><BR 
clear=all><B>Device driver, tty_driver</B> <BR clear=all>
<DIV>
<UL>
  <LI>It contains accessory informations: <CODE>driver_name</CODE>, 
  <CODE>name</CODE>, <CODE>major</CODE>, <CODE>num</CODE> (number of devices), 
  <CODE>type</CODE> and <CODE>subtype</CODE> (type and subtype of the tty 
  driver), <CODE>flags</CODE>, and others 
  <LI>the pointer to the <CODE>table</TABLE> of tty_struct; 
  <LI><CODE>termios</CODE> and <CODE>termios_locked</CODE>; 
  <LI>two pointers for a doubly-linked list, <CODE>next</CODE> and 
  <CODE>prev</CODE>. 
  <LI>the tty_driver methods: 
  <UL>
    <LI><CODE>open</CODE>, called after a user open.2; 
    <LI><CODE>close</CODE>, called after a user close.2 
    <LI><CODE>write</CODE>, called after a user write.2 or when the kernel needs 
    to write to the tty device 
    <LI><CODE>put_char</CODE>, called by the kernel to write a single character; 

    <LI><CODE>flush_chars</CODE>, called by the kernel after writing a number of 
    characters to the tty device using put_char. 
    <LI><CODE>write_room</CODE>, returns the number of characters the tty device 
    will accept for writing. 
    <LI><CODE>ioctl</CODE>, driver specific ioctl's 
    <LI><CODE>set_termios</CODE>, used to notify the tty driver of a change of 
    termios; 
    <LI><CODE>set_ldisc</CODE>, used to notify the tty driver of a change of 
    line discipline; 
    <LI><CODE>throttle</CODE>, tells the tty driver that the input buffers of 
    the line discipline are close to full; 
    <LI><CODE>unthrottle</CODE>, tells the tty driver that the input buffers of 
    the line discipline have enough space; 
    <LI><CODE>stop</CODE>, stops the tty driver from sending out characters to 
    the tty device; 
    <LI><CODE>start</CODE>, starts the tty driver to send out characters to the 
    device; 
    <LI><CODE>hangup</CODE>, tells the tty driver to hang up the tty device; 
    <LI><CODE>break_ctl</CODE>, toggle the BREAK status on the RS-232 port; 
    <LI><CODE>wait_until_sent</CODE>, the tty driver waits until the device has 
    written out all the characters in its FIFO queue; 
    <LI><CODE>send_xchar</CODE>, send a high-priority XON-XOFF character to the 
    device. </LI></UL></LI></UL></DIV><BR clear=all><B>Line discipline, 
tty_ldisc</B> <BR clear=all>
<DIV>
<UL>
  <LI>A line discipline consists of a <CODE>magic</CODE> number, a 
  <CODE>name</CODE>, <CODE>flags</CODE> (of the line discipline), 
  <CODE>num</CODE> (index of the line discipline in the global 
  <CODE>ldiscs</CODE> array); 
  <LI>It has methods called from above, ie, from the user perspective, 
  <UL>
    <LI><CODE>open</CODE>, called when the line discipline is associated with 
    the tty. The line discipline can do any suitable initialization and return 
    negative on failure. 
    <LI><CODE>close</CODE>, called when the line discipline is shut down, either 
    because the tty is closed or it changes the line discipline. 
    <LI><CODE>read</CODE>, called after a user read.2. 
    <LI><CODE>write</CODE>, called after a user write.2. It must deliver the 
    characters to the low-level tty device. 
    <LI><CODE>ioctl</CODE>, called after a user ioctl.2 that is not handled by 
    the tty layer or the low-level tty driver. 
    <LI><CODE>poll</CODE>, called after a user select/poll. 
    <LI><CODE>set_termios</CODE>, called after a user set_termios. 
    <LI><CODE>flush_buffer</CODE>, called to tell the line discipline to send 
    any input character in the buffer to the user process. 
    <LI><CODE>chars_in_buffer</CODE>, returns the number of input characters 
    buffered by the line discipline. </LI></UL>
  <LI>It defines methods called from below, ie from the low-level tty_driver 
  <UL>
    <LI><CODE>receive_buf</CODE>, called to send characters to the line 
    discipline. 
    <LI><CODE>receive_room</CODE>, returns the number of characters that the 
    line discipline can accept. 
    <LI><CODE>write_wakeup</CODE>, called to tell the line discipline that it 
    can send down more characters. </LI></UL></LI></UL></DIV><BR 
clear=all><B>tty_fops</B> <BR clear=all>
<DIV><CODE>tty_register_driver()</CODE> inserts the tty_driver into the list of 
the <CODE>tty_drivers</CODE>, and if it does not provide its own routine 
<CODE>put_char()</CODE> assignes the <CODE>tty_default_put_char()</CODE> to it. 
It registers the tty_driver with the devfs (devfs_register_chrdev), and with the 
proc filesystem (proc_tty_register_driver). The file operations are 
<CODE>tty_fops</CODE>): 
<UL>
  <LI><CODE>tty_read</CODE>: after some checks it locks the kernel and calls the 
  line discipline read function. Then it unlocks the kernel; 
  <LI><CODE>tty_write</CODE>: it does some checks and then calls 
  <CODE>do_tty_write()</CODE> which down's the semaphore 
  <CODE>atomic_write</CODE>, locks the kernel, calls the write function (of the 
  line discipline), and unlocks and ups; 
  <LI><CODE>tty_poll</CODE> calls the poll routine of the line discipline; 
  <LI><CODE>tty_ioctl</CODE>; 
  <LI><CODE>tty_open</CODE>: essentially it calls <CODE>init_dev()</CODE> to 
  retrieve the tty_struct for the device number, and the <CODE>open</CODE> 
  routine of the tty's driver; 
  <LI><CODE>tty_release</CODE> calls <CODE>release_dev()</CODE>; 
  <LI><CODE>tty_fasync</CODE>; </LI></UL></DIV>
<DIV><B><CODE>init_dev()</CODE></B> allocates a new tty_struct, and initializes 
it (by calling <CODE>initialize_tty_struct()</CODE>); sets up the tty's termios, 
termios_locked, device, driver, count; sets up the driver's table entry for this 
device; finally it calls the tty's line discipline <CODE>open()</CODE>. </DIV>
<DIV><B><CODE>initialize_tty_struct()</CODE></B> performs the initialization of 
a tty_struct. It sets the magic number (TTY_MAGIC), the line discipline (with 
the default ldiscs[N_TTY]), the fields in the tty flip_buffer (in particular the 
<CODE>tqueue</CODE> with routine <CODE>flush_to_ldisc</CODE> and data the 
<CODE>tty</CODE>), the write and read wait_queues, the task_queue 
<CODE>tq_hangup</CODE> (routine <CODE>do_tty_hangup</CODE>, data 
<CODE>tty</CODE>). Finally it initializes the semaphores 
<CODE>atomic_read</CODE> and <CODE>atomic_write</CODE>, the list_head 
<CODE>tty_files</CODE>, and the secure-attention-key task_queue 
<CODE>SAK_tq</CODE>. </DIV>
<DIV><B><CODE>flush_to_ldisc()</CODE></B>: if the tty has the TTY_DONT_FLIP flag 
set, the flip <CODE>tqueue</CODE> is queued on the timer queue. Otherwise the 
buffer pairs are "flipped", the flip count is reset to zero, and the line 
discipline <CODE>receive_buf</CODE> is called. </DIV><BR clear=all><B>The line 
discipline tty_ldisc_N_TTY</B> <BR clear=all>
<DIV>The line discipline <CODE>tty_ldisc_N_TTY</CODE> is defined in n_tty.c with 
the following methods, 
<UL>
  <LI><CODE>n_tty_open</CODE> allocates a <CODE>read_buf</CODE> for the 
  tty_struct; 
  <LI><CODE>n_tty_close</CODE> flushes the buffer and frees the 
  <CODE>read_buf</CODE> 
  <LI><CODE>n_tty_flush_buffer</CODE> clears everything and unthrottle the 
  driver; 
  <LI><CODE>n_tty_chars_in_buffer</CODE> returns the number of characters in the 
  buffer to be delivered to the user, ie, the difference between 
  <CODE>read_head</CODE> and <CODE>read_tail</CODE> 
  <LI><CODE>read_chan</CODE> is rather complicated, but essentially it amounts 
  to add the current process to the tty_struct <CODE>read_wait</CODE> queue; 
  copy characters from the buffer to the user buf. When done remove the current 
  process from the wait_queue. 
  <LI><CODE>write_chan</CODE> adds the current process to the tty_struct 
  <CODE>write_wait</CODE> queue; calls the tty driver write(tty, 1, buf, count) 
  routine; possibly schedule(). When done removes the current process from the 
  wait_queue. 
  <LI><CODE>n_tty_ioctl</CODE> 
  <LI><CODE>n_tty_settermios</CODE> 
  <LI><CODE>normal_poll</CODE> 
  <LI><CODE>n_tty_receive_buf</CODE> copies the received chars in the 
  <CODE>read_buf</CODE> with possible line discipline processing. If the 
  tty_struct is not ICANON and the <CODE>read_cnt</CODE> is more than the 
  <CODE>minimum_to_wake</CODE> calls the fasync method on the tty_struct. 
  Finally it checks whether to throttle or not the device. 
  <LI><CODE>n_tty_receive_room</CODE> 
  <LI><CODE>n_tty_write_wakeup</CODE> calls the fasync method on the tty_struct 
  </LI></UL></DIV><BR clear=all><FONT size=-1>Marco Corvi - 2003</FONT> <!-- text below generated by server. PLEASE REMOVE --></OBJECT></LAYER>
<DIV></DIV></SPAN></STYLE></NOSCRIPT></TABLE></SCRIPT></APPLET>
<SCRIPT 
language=JavaScript>var PUpage="76001084"; var PUprop="geocities"; </SCRIPT>

<SCRIPT language=JavaScript 
src="tty layer - The kernel structures_file/pu5geo.js"></SCRIPT>

<SCRIPT language=JavaScript 
src="tty layer - The kernel structures_file/ygIELib9.js"></SCRIPT>

<SCRIPT language=JavaScript>var yviContents='http://us.toto.geo.yahoo.com/toto?s=76001084&l=NE&b=1&t=1057747199';yviR='us';yfiEA(0);</SCRIPT>

<SCRIPT language=JavaScript 
src="tty layer - The kernel structures_file/mc.js"></SCRIPT>

<SCRIPT language=JavaScript 
src="tty layer - The kernel structures_file/geov2.js"></SCRIPT>

<SCRIPT language=javascript>geovisit();</SCRIPT>
<NOSCRIPT><IMG height=1 alt=setstats 
src="tty layer - The kernel structures_file/visit.gif" width=1 
border=0></NOSCRIPT> <IMG height=1 alt=1 
src="tty layer - The kernel structures_file/serv.gif" width=1> <!-- w26.geo.scd.yahoo.com compressed/chunked Wed Jul  9 03:39:59 PDT 2003 --></CODE></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -