390 lines
38 KiB
HTML
390 lines
38 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en" dir="auto">
|
||
|
||
<head><meta charset="utf-8">
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||
<meta name="robots" content="index, follow">
|
||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||
<title>Kernel, PTY and TTY | Morgan's Blog</title>
|
||
<meta name="keywords" content="">
|
||
<meta name="description" content="Linux Kernel #4">
|
||
<meta name="author" content="Me">
|
||
<link rel="canonical" href="http://blog.morgan.kr/2023/11/kernel-pty-and-tty/">
|
||
|
||
<script type="text/javascript">
|
||
let vh = window.innerHeight * 0.01;
|
||
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
||
</script>
|
||
<link crossorigin="anonymous" href="/assets/css/stylesheet.dde9171333af37b8e856933e0deb815c09f761bbd3ee0e6826d3a1309b808533.css" integrity="sha256-3ekXEzOvN7joVpM+DeuBXAn3YbvT7g5oJtOhMJuAhTM=" rel="preload stylesheet" as="style">
|
||
<script defer crossorigin="anonymous" src="/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js" integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA="
|
||
onload="hljs.initHighlightingOnLoad();"></script>
|
||
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
|
||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" onload="renderMathInElement(document.body);"></script>
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function() {
|
||
renderMathInElement(document.body, {
|
||
delimiters: [
|
||
{left: "$$", right: "$$", display: true},
|
||
{left: "$", right: "$", display: false}
|
||
]
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<link rel="icon" href="https://blog.morgan.kr/favicon.ico">
|
||
|
||
<meta name="theme-color" content="#2e2e33">
|
||
<meta name="msapplication-TileColor" content="#2e2e33">
|
||
<noscript>
|
||
<style>
|
||
#theme-toggle,
|
||
.top-link {
|
||
display: none;
|
||
}
|
||
|
||
</style>
|
||
</noscript><meta property="og:title" content="Kernel, PTY and TTY" />
|
||
<meta property="og:description" content="Linux Kernel #4" />
|
||
<meta property="og:type" content="article" />
|
||
<meta property="og:url" content="http://blog.morgan.kr/2023/11/kernel-pty-and-tty/" /><meta property="article:section" content="posts" />
|
||
<meta property="article:published_time" content="2023-11-26T10:47:11+00:00" />
|
||
<meta property="article:modified_time" content="2023-11-26T10:47:11+00:00" /><meta property="og:site_name" content="Morgan's Blog" />
|
||
|
||
<meta name="twitter:card" content="summary"/>
|
||
<meta name="twitter:title" content="Kernel, PTY and TTY"/>
|
||
<meta name="twitter:description" content="Linux Kernel #4"/>
|
||
|
||
|
||
<script type="application/ld+json">
|
||
{
|
||
"@context": "https://schema.org",
|
||
"@type": "BreadcrumbList",
|
||
"itemListElement": [,
|
||
{
|
||
"@type": "ListItem",
|
||
"position": 2 ,
|
||
"name": "Posts",
|
||
"item": "http://blog.morgan.kr/posts/"
|
||
},
|
||
{
|
||
"@type": "ListItem",
|
||
"position": 3 ,
|
||
"name": "Kernel, PTY and TTY",
|
||
"item": "http://blog.morgan.kr/2023/11/kernel-pty-and-tty/"
|
||
}
|
||
]
|
||
}
|
||
</script>
|
||
<script type="application/ld+json">
|
||
{
|
||
"@context": "https://schema.org",
|
||
"@type": "BlogPosting",
|
||
"headline": "Kernel, PTY and TTY",
|
||
"name": "Kernel, PTY and TTY",
|
||
"description": "Linux Kernel #4",
|
||
"keywords": [
|
||
|
||
],
|
||
"articleBody": "PTY (Pseudo-TTY), TTY (TeleTYpewriter). TTY The term TTY originates from the early days of computing when teletype machines were used as the main way for hci. As technology evolved, the physical teletype machines were replaced with virtual terminals or screens, and TTY is used as interface for text-based communication between a user and the system. TTYs can be hardware-based, like a console, or software-based, commonly known as virtual consoles or terminals (e.g., /dev/tty1, /dev/tty2, etc.).\nPTY A PTY is a Pseudo Terminal, which is a software emulation of a TTY. It allows for the creation of a terminal interface without the need for any actual terminal hardware. A PTY is typically used for providing terminal functionality to processes whose input and output are not directly connected to a physical terminal. PTY is used when you open a terminal window in GUI or SSH. It is used for bridge for real-TTY emulation and dealing with user-facing end of TTY.\nTTY can be thought as two parts. IO, and TTY driver inside of kernel. When process is created, it is attched to some kind of IO device like TTY device as stdout/stdin/stderr. Just like writing to files via file descriptors, outputing and inputing act of process is a wrapper for read() and write() to “0, 1, 2” file descriptors. What printf actually does is fprintf(stdout, ...), in libc.\nJust like in TTY, PTY acts simmilarly, just that it doesnt have actual “hardware” and matching driver, it just differently handles it.\nPTY also has two ends: the master end and the slave end. The master end is used by a terminal emulator, like xterm or GNOME Terminal, to control the terminal session. The slave end provides the interface that emulates the physical terminal, where programs like shells (bash, zsh, …) read input from and write output to, as if they were interacting with a real TTY.\nPTY and TTY When we open new terminal emulator with shell and check shell’s /proc/{pid}/fd/, we can see 0, 1, 2 is a symlink to some /dev/pts/{id}. If we put data (char data) to /dev/tty0 as write(), in kernel (because write is also syscall), data is forwarded to driver code, and then driver transforms and sends char data to TTY as some kind of electronic signal. In case of PTY, it is just same but now instead of driver, kernel just forwards data to other end, /dev/pty#, and master process (like terminal emulator) handles that data just like kernel driver, but now it just makes display image out of it (GUI), or sends it to web socket (SSH).\nstatic int pty_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { struct tty_struct *to = tty-\u003elink; int\tc=0, n; char\t*temp_buffer; if (!to || tty-\u003estopped) return 0; if (from_user) { down(\u0026tty-\u003eflip.pty_sem); temp_buffer = \u0026tty-\u003eflip.char_buf[0]; while (count \u003e 0) { /* check space so we don't copy needlessly */ n = MIN(count, to-\u003eldisc.receive_room(to)); if (!n) break; n = MIN(n, PTY_BUF_SIZE); n -= copy_from_user(temp_buffer, buf, n); if (!n) { if (!c) c = -EFAULT; break; } /* check again in case the buffer filled up */ n = MIN(n, to-\u003eldisc.receive_room(to)); if (!n) break; buf += n; c += n; count -= n; to-\u003eldisc.receive_buf(to, temp_buffer, 0, n); } up(\u0026tty-\u003eflip.pty_sem); } else { c = MIN(count, to-\u003eldisc.receive_room(to)); to-\u003eldisc.receive_buf(to, buf, 0, c); } return c; } static int pty_open(struct tty_struct *tty, struct file * filp) { int\tretval; int\tline; struct\tpty_struct *pty; retval = -ENODEV; if (!tty || !tty-\u003elink) goto out; line = MINOR(tty-\u003edevice) - tty-\u003edriver.minor_start; if ((line \u003c 0) || (line \u003e= NR_PTYS)) goto out; pty = (struct pty_struct *)(tty-\u003edriver.driver_state) + line; tty-\u003edriver_data = pty; retval = -EIO; if (test_bit(TTY_OTHER_CLOSED, \u0026tty-\u003eflags)) goto out; if (test_bit(TTY_PTY_LOCK, \u0026tty-\u003elink-\u003eflags)) goto out; if (tty-\u003elink-\u003ecount != 1) goto out; clear_bit(TTY_OTHER_CLOSED, \u0026tty-\u003elink-\u003eflags); wake_up_interruptible(\u0026pty-\u003eopen_wait); set_bit(TTY_THROTTLED, \u0026tty-\u003eflags); retval = 0; out: return retval; } int __init pty_init(void) { int i; memset(\u0026dev_tty_driver, 0, sizeof(struct tty_driver)); dev_tty_driver.magic = TTY_DRIVER_MAGIC; dev_tty_driver.driver_name = \"/dev/tty\"; dev_tty_driver.name = dev_tty_driver.driver_name + 5; dev_tty_driver.name_base = 0; dev_tty_driver.major = TTYAUX_MAJOR; dev_tty_driver.minor_start = 0; dev_tty_driver.num = 1; dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM; dev_tty_driver.subtype = SYSTEM_TYPE_TTY; if (tty_register_driver(\u0026dev_tty_driver)) panic(\"Couldn't register /dev/tty driver\\n\"); dev_syscons_driver = dev_tty_driver; dev_syscons_driver.driver_name = \"/dev/console\"; dev_syscons_driver.name = dev_syscons_driver.driver_name + 5; dev_syscons_driver.major = TTYAUX_MAJOR; dev_syscons_driver.minor_start = 1; dev_syscons_driver.type = TTY_DRIVER_TYPE_SYSTEM; dev_syscons_driver.subtype = SYSTEM_TYPE_SYSCONS; if (tty_register_driver(\u0026dev_syscons_driver)) panic(\"Couldn't register /dev/console driver\\n\"); ... } ",
|
||
"wordCount" : "714",
|
||
"inLanguage": "en",
|
||
"datePublished": "2023-11-26T10:47:11.631Z",
|
||
"dateModified": "2023-11-26T10:47:11.631Z",
|
||
"author":{
|
||
"@type": "Person",
|
||
"name": "Me"
|
||
},
|
||
"mainEntityOfPage": {
|
||
"@type": "WebPage",
|
||
"@id": "http://blog.morgan.kr/2023/11/kernel-pty-and-tty/"
|
||
},
|
||
"publisher": {
|
||
"@type": "Organization",
|
||
"name": "Morgan's Blog",
|
||
"logo": {
|
||
"@type": "ImageObject",
|
||
"url": "https://blog.morgan.kr/favicon.ico"
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
</head>
|
||
|
||
<body class=" dark" id="top"><header class="header">
|
||
</header>
|
||
<script>
|
||
if (localStorage.getItem("pref-theme") === "light") {
|
||
document.body.classList.remove('dark')
|
||
document.getElementById('main-logo').src = "\/favicon-inv.png";
|
||
}
|
||
|
||
</script>
|
||
<main class="main">
|
||
|
||
<article class="post-single">
|
||
|
||
<header class="post-header">
|
||
<h1 class="post-title">
|
||
Kernel, PTY and TTY
|
||
</h1>
|
||
<div class="post-description">
|
||
Linux Kernel #4
|
||
</div>
|
||
|
||
<div class="post-meta"><span title='2023-11-26 10:47:11.631 +0000 UTC'>
|
||
Nov 26, 2023
|
||
</span>
|
||
</div>
|
||
</header>
|
||
<div class="post-divider"></div>
|
||
<div class="post-content"><h2 id="pty-pseudo-tty-tty-teletypewriter">PTY (Pseudo-TTY), TTY (TeleTYpewriter).<a hidden class="anchor" aria-hidden="true" href="#pty-pseudo-tty-tty-teletypewriter">#</a></h2>
|
||
<h3 id="tty">TTY<a hidden class="anchor" aria-hidden="true" href="#tty">#</a></h3>
|
||
<p>The term TTY originates from the early days of computing when teletype machines were used as the main way for hci. As technology evolved, the physical teletype machines were replaced with virtual terminals or screens, and TTY is used as interface for text-based communication between a user and the system. TTYs can be hardware-based, like a console, or software-based, commonly known as virtual consoles or terminals (e.g., /dev/tty1, /dev/tty2, etc.).</p>
|
||
<h3 id="pty">PTY<a hidden class="anchor" aria-hidden="true" href="#pty">#</a></h3>
|
||
<p>A PTY is a Pseudo Terminal, which is a software emulation of a TTY. It allows for the creation of a terminal interface without the need for any actual terminal hardware. A PTY is typically used for providing terminal functionality to processes whose input and output are not directly connected to a physical terminal.
|
||
PTY is used when you open a terminal window in GUI or SSH. It is used for bridge for real-TTY emulation and dealing with user-facing end of TTY.</p>
|
||
<p>TTY can be thought as two parts. IO, and TTY driver inside of kernel. When process is created, it is attched to some kind of IO device like TTY device as stdout/stdin/stderr. Just like writing to files via file descriptors, outputing and inputing act of process is a wrapper for <code>read()</code> and <code>write()</code> to “0, 1, 2” file descriptors. What <code>printf</code> actually does is <code>fprintf(stdout, ...)</code>, in libc.</p>
|
||
<p>Just like in TTY, PTY acts simmilarly, just that it doesnt have actual “hardware” and matching driver, it just differently handles it.</p>
|
||
<p>PTY also has two ends: the master end and the slave end. The master end is used by a terminal emulator, like xterm or GNOME Terminal, to control the terminal session. The slave end provides the interface that emulates the physical terminal, where programs like shells (bash, zsh, …) read input from and write output to, as if they were interacting with a real TTY.</p>
|
||
<h3 id="pty-and-tty">PTY and TTY<a hidden class="anchor" aria-hidden="true" href="#pty-and-tty">#</a></h3>
|
||
<p>When we open new terminal emulator with shell and check shell’s <code>/proc/{pid}/fd/</code>, we can see 0, 1, 2 is a symlink to some <code>/dev/pts/{id}</code>. If we put data (char data) to /dev/tty0 as <code>write()</code>, in kernel (because write is also syscall), data is forwarded to driver code, and then driver transforms and sends char data to TTY as some kind of electronic signal. In case of PTY, it is just same but now instead of driver, kernel just forwards data to other end, <code>/dev/pty#</code>, and master process (like terminal emulator) handles that data just like kernel driver, but now it just makes display image out of it (GUI), or sends it to web socket (SSH).</p>
|
||
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">pty_write</span><span class="p">(</span><span class="k">struct</span> <span class="n">tty_struct</span> <span class="o">*</span> <span class="n">tty</span><span class="p">,</span> <span class="kt">int</span> <span class="n">from_user</span><span class="p">,</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">int</span> <span class="n">count</span><span class="p">)</span>
|
||
</span></span><span class="line"><span class="cl"><span class="p">{</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">tty_struct</span> <span class="o">*</span><span class="n">to</span> <span class="o">=</span> <span class="n">tty</span><span class="o">-></span><span class="n">link</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">c</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">*</span><span class="n">temp_buffer</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">to</span> <span class="o">||</span> <span class="n">tty</span><span class="o">-></span><span class="n">stopped</span><span class="p">)</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">from_user</span><span class="p">)</span> <span class="p">{</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="nf">down</span><span class="p">(</span><span class="o">&</span><span class="n">tty</span><span class="o">-></span><span class="n">flip</span><span class="p">.</span><span class="n">pty_sem</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">temp_buffer</span> <span class="o">=</span> <span class="o">&</span><span class="n">tty</span><span class="o">-></span><span class="n">flip</span><span class="p">.</span><span class="n">char_buf</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">while</span> <span class="p">(</span><span class="n">count</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="cm">/* check space so we don't copy needlessly */</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">MIN</span><span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">to</span><span class="o">-></span><span class="n">ldisc</span><span class="p">.</span><span class="nf">receive_room</span><span class="p">(</span><span class="n">to</span><span class="p">));</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">n</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">MIN</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">PTY_BUF_SIZE</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">-=</span> <span class="nf">copy_from_user</span><span class="p">(</span><span class="n">temp_buffer</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">c</span><span class="p">)</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="o">-</span><span class="n">EFAULT</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">break</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="cm">/* check again in case the buffer filled up */</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">n</span> <span class="o">=</span> <span class="nf">MIN</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">to</span><span class="o">-></span><span class="n">ldisc</span><span class="p">.</span><span class="nf">receive_room</span><span class="p">(</span><span class="n">to</span><span class="p">));</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">n</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">buf</span> <span class="o">+=</span> <span class="n">n</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">+=</span> <span class="n">n</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">count</span> <span class="o">-=</span> <span class="n">n</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">to</span><span class="o">-></span><span class="n">ldisc</span><span class="p">.</span><span class="nf">receive_buf</span><span class="p">(</span><span class="n">to</span><span class="p">,</span> <span class="n">temp_buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="nf">up</span><span class="p">(</span><span class="o">&</span><span class="n">tty</span><span class="o">-></span><span class="n">flip</span><span class="p">.</span><span class="n">pty_sem</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="nf">MIN</span><span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">to</span><span class="o">-></span><span class="n">ldisc</span><span class="p">.</span><span class="nf">receive_room</span><span class="p">(</span><span class="n">to</span><span class="p">));</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">to</span><span class="o">-></span><span class="n">ldisc</span><span class="p">.</span><span class="nf">receive_buf</span><span class="p">(</span><span class="n">to</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">c</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">c</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"><span class="p">}</span>
|
||
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">pty_open</span><span class="p">(</span><span class="k">struct</span> <span class="n">tty_struct</span> <span class="o">*</span><span class="n">tty</span><span class="p">,</span> <span class="k">struct</span> <span class="n">file</span> <span class="o">*</span> <span class="n">filp</span><span class="p">)</span>
|
||
</span></span><span class="line"><span class="cl"><span class="p">{</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">retval</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">line</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="n">pty_struct</span> <span class="o">*</span><span class="n">pty</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="n">retval</span> <span class="o">=</span> <span class="o">-</span><span class="n">ENODEV</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">tty</span> <span class="o">||</span> <span class="o">!</span><span class="n">tty</span><span class="o">-></span><span class="n">link</span><span class="p">)</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">line</span> <span class="o">=</span> <span class="nf">MINOR</span><span class="p">(</span><span class="n">tty</span><span class="o">-></span><span class="n">device</span><span class="p">)</span> <span class="o">-</span> <span class="n">tty</span><span class="o">-></span><span class="n">driver</span><span class="p">.</span><span class="n">minor_start</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">((</span><span class="n">line</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">line</span> <span class="o">>=</span> <span class="n">NR_PTYS</span><span class="p">))</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">pty</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">pty_struct</span> <span class="o">*</span><span class="p">)(</span><span class="n">tty</span><span class="o">-></span><span class="n">driver</span><span class="p">.</span><span class="n">driver_state</span><span class="p">)</span> <span class="o">+</span> <span class="n">line</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">tty</span><span class="o">-></span><span class="n">driver_data</span> <span class="o">=</span> <span class="n">pty</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="n">retval</span> <span class="o">=</span> <span class="o">-</span><span class="n">EIO</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">test_bit</span><span class="p">(</span><span class="n">TTY_OTHER_CLOSED</span><span class="p">,</span> <span class="o">&</span><span class="n">tty</span><span class="o">-></span><span class="n">flags</span><span class="p">))</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">test_bit</span><span class="p">(</span><span class="n">TTY_PTY_LOCK</span><span class="p">,</span> <span class="o">&</span><span class="n">tty</span><span class="o">-></span><span class="n">link</span><span class="o">-></span><span class="n">flags</span><span class="p">))</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">tty</span><span class="o">-></span><span class="n">link</span><span class="o">-></span><span class="n">count</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="nf">clear_bit</span><span class="p">(</span><span class="n">TTY_OTHER_CLOSED</span><span class="p">,</span> <span class="o">&</span><span class="n">tty</span><span class="o">-></span><span class="n">link</span><span class="o">-></span><span class="n">flags</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="nf">wake_up_interruptible</span><span class="p">(</span><span class="o">&</span><span class="n">pty</span><span class="o">-></span><span class="n">open_wait</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="nf">set_bit</span><span class="p">(</span><span class="n">TTY_THROTTLED</span><span class="p">,</span> <span class="o">&</span><span class="n">tty</span><span class="o">-></span><span class="n">flags</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">retval</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"><span class="nl">out</span><span class="p">:</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">retval</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"><span class="p">}</span>
|
||
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">__init</span> <span class="nf">pty_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
|
||
</span></span><span class="line"><span class="cl"><span class="p">{</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="nf">memset</span><span class="p">(</span><span class="o">&</span><span class="n">dev_tty_driver</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">tty_driver</span><span class="p">));</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">magic</span> <span class="o">=</span> <span class="n">TTY_DRIVER_MAGIC</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">driver_name</span> <span class="o">=</span> <span class="s">"/dev/tty"</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">driver_name</span> <span class="o">+</span> <span class="mi">5</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">name_base</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">major</span> <span class="o">=</span> <span class="n">TTYAUX_MAJOR</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">minor_start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">num</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">TTY_DRIVER_TYPE_SYSTEM</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_tty_driver</span><span class="p">.</span><span class="n">subtype</span> <span class="o">=</span> <span class="n">SYSTEM_TYPE_TTY</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">tty_register_driver</span><span class="p">(</span><span class="o">&</span><span class="n">dev_tty_driver</span><span class="p">))</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="nf">panic</span><span class="p">(</span><span class="s">"Couldn't register /dev/tty driver</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_syscons_driver</span> <span class="o">=</span> <span class="n">dev_tty_driver</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_syscons_driver</span><span class="p">.</span><span class="n">driver_name</span> <span class="o">=</span> <span class="s">"/dev/console"</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_syscons_driver</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">dev_syscons_driver</span><span class="p">.</span><span class="n">driver_name</span> <span class="o">+</span> <span class="mi">5</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_syscons_driver</span><span class="p">.</span><span class="n">major</span> <span class="o">=</span> <span class="n">TTYAUX_MAJOR</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_syscons_driver</span><span class="p">.</span><span class="n">minor_start</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_syscons_driver</span><span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">TTY_DRIVER_TYPE_SYSTEM</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="n">dev_syscons_driver</span><span class="p">.</span><span class="n">subtype</span> <span class="o">=</span> <span class="n">SYSTEM_TYPE_SYSCONS</span><span class="p">;</span>
|
||
</span></span><span class="line"><span class="cl">
|
||
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nf">tty_register_driver</span><span class="p">(</span><span class="o">&</span><span class="n">dev_syscons_driver</span><span class="p">))</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="nf">panic</span><span class="p">(</span><span class="s">"Couldn't register /dev/console driver</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
|
||
</span></span><span class="line"><span class="cl"> <span class="p">...</span>
|
||
</span></span><span class="line"><span class="cl"><span class="p">}</span>
|
||
</span></span></code></pre></div>
|
||
|
||
</div>
|
||
|
||
<footer class="post-footer">
|
||
<ul class="post-tags">
|
||
</ul>
|
||
<nav class="pag-back">
|
||
<a href="#back" onclick="window.history.back()">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" focusable="false" style="pointer-events: none; display: block; width: 100%; height: 100%;fill: var(--primary);stroke: var(--primary);" stroke-width="1"><polygon points="11.65,3.50 3.80,11.35 11.65,19.20 12.36,18.50 5.71,11.85 20.15,11.85 20.15,10.85 5.71,10.85 12.36,4.20"></polygon></svg>
|
||
</a>
|
||
</nav>
|
||
<br/>
|
||
</footer>
|
||
</article>
|
||
</main>
|
||
|
||
<footer class="footer">
|
||
<a href="/admin/" style="text-decoration: none;">©</a> <span><a href="http://blog.morgan.kr">Morgan</a> · PaperMod</span>
|
||
<br/>
|
||
<span style="">Ver.11081623 </span>
|
||
<a href="#" id="theme-toggle">Toggle Dark Mode</a>
|
||
</footer>
|
||
<button id="top-link" class="top-link" onclick="window.scrollTo({top: 0, behavior: 'smooth'})">
|
||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" focusable="false" style="pointer-events: none; display: block; width: 100%; height: 100%;" fill="currentColor" stroke="white" stroke-width="1"><polygon points="19.35,11.5 11.5,3.65 3.65,11.5 4.35,12.21 11,5.56 11,20 12,20 12,5.56 18.65,12.21"></polygon></svg>
|
||
</button>
|
||
|
||
<script>
|
||
let menu = document.getElementById('menu')
|
||
if (menu) {
|
||
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
|
||
menu.onscroll = function () {
|
||
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
|
||
}
|
||
}
|
||
|
||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||
anchor.addEventListener("click", function (e) {
|
||
e.preventDefault();
|
||
var id = this.getAttribute("href").substr(1);
|
||
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
|
||
behavior: "smooth"
|
||
});
|
||
} else {
|
||
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
|
||
}
|
||
if (id === "top") {
|
||
history.replaceState(null, null, " ");
|
||
} else {
|
||
history.pushState(null, null, `#${id}`);
|
||
}
|
||
});
|
||
});
|
||
|
||
</script>
|
||
<script>
|
||
var mybutton = document.getElementById("top-link");
|
||
window.onscroll = function () {
|
||
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
|
||
mybutton.style.visibility = "visible";
|
||
mybutton.style.opacity = "1";
|
||
} else {
|
||
mybutton.style.visibility = "hidden";
|
||
mybutton.style.opacity = "0";
|
||
}
|
||
};
|
||
|
||
</script>
|
||
<script>
|
||
document.getElementById("theme-toggle").addEventListener("click", () => {
|
||
if (document.body.className.includes("dark")) {
|
||
document.body.classList.remove('dark');
|
||
localStorage.setItem("pref-theme", 'light');
|
||
document.getElementById('main-logo').src = "\/favicon-inv.png";
|
||
|
||
} else {
|
||
document.body.classList.add('dark');
|
||
localStorage.setItem("pref-theme", 'dark');
|
||
document.getElementById('main-logo').src = "\/favicon.png";
|
||
|
||
}
|
||
})
|
||
|
||
</script>
|
||
<script>
|
||
document.querySelectorAll('pre > code').forEach((codeblock) => {
|
||
const container = codeblock.parentNode.parentNode;
|
||
|
||
const copybutton = document.createElement('button');
|
||
copybutton.classList.add('copy-code');
|
||
copybutton.innerHTML = 'copy';
|
||
|
||
function copyingDone() {
|
||
copybutton.innerHTML = 'copied!';
|
||
setTimeout(() => {
|
||
copybutton.innerHTML = 'copy';
|
||
}, 2000);
|
||
}
|
||
|
||
copybutton.addEventListener('click', (cb) => {
|
||
if ('clipboard' in navigator) {
|
||
navigator.clipboard.writeText(codeblock.textContent);
|
||
copyingDone();
|
||
return;
|
||
}
|
||
|
||
const range = document.createRange();
|
||
range.selectNodeContents(codeblock);
|
||
const selection = window.getSelection();
|
||
selection.removeAllRanges();
|
||
selection.addRange(range);
|
||
try {
|
||
document.execCommand('copy');
|
||
copyingDone();
|
||
} catch (e) { };
|
||
selection.removeRange(range);
|
||
});
|
||
|
||
if (container.classList.contains("highlight")) {
|
||
container.appendChild(copybutton);
|
||
} else if (container.parentNode.firstChild == container) {
|
||
|
||
} else if (codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName == "TABLE") {
|
||
|
||
codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(copybutton);
|
||
} else {
|
||
|
||
codeblock.parentNode.appendChild(copybutton);
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|