blog/public/2023/11/kernel-process-creation/index.html

315 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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, Process creation | Morgan&#39;s Blog</title>
<meta name="keywords" content="">
<meta name="description" content="Linux Kernel #3">
<meta name="author" content="Me">
<link rel="canonical" href="http://blog.morgan.kr/2023/11/kernel-process-creation/">
<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&#43;DeuBXAn3YbvT7g5oJtOhMJuAhTM=" rel="preload stylesheet" as="style">
<script defer crossorigin="anonymous" src="/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js" integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG&#43;9vmJ0cTS&#43;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, Process creation" />
<meta property="og:description" content="Linux Kernel #3" />
<meta property="og:type" content="article" />
<meta property="og:url" content="http://blog.morgan.kr/2023/11/kernel-process-creation/" /><meta property="article:section" content="posts" />
<meta property="article:published_time" content="2023-11-26T07:44:51+00:00" />
<meta property="article:modified_time" content="2023-11-26T07:44:51+00:00" /><meta property="og:site_name" content="Morgan&#39;s Blog" />
<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Kernel, Process creation"/>
<meta name="twitter:description" content="Linux Kernel #3"/>
<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, Process creation",
"item": "http://blog.morgan.kr/2023/11/kernel-process-creation/"
}
]
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Kernel, Process creation",
"name": "Kernel, Process creation",
"description": "Linux Kernel #3",
"keywords": [
],
"articleBody": "static int init(void * unused) { lock_kernel(); do_basic_setup(); /* * Ok, we have completed the initial bootup, and * we're essentially up and running. Get rid of the * initmem segments and start the user-mode stuff.. */ free_initmem(); unlock_kernel(); if (open(\"/dev/console\", O_RDWR, 0) \u003c 0) printk(\"Warning: unable to open an initial console.\\n\"); (void) dup(0); (void) dup(0); /* * We try each of these until one succeeds. * * The Bourne shell can be used instead of init if we are * trying to recover a really broken machine. */ if (execute_command) execve(execute_command,argv_init,envp_init); execve(\"/sbin/init\",argv_init,envp_init); execve(\"/etc/init\",argv_init,envp_init); execve(\"/bin/init\",argv_init,envp_init); execve(\"/bin/sh\",argv_init,envp_init); panic(\"No init found. Try passing init= option to kernel.\"); } In this init/main.c, after basic kernel initialization things, open(\"/dev/console\") and two dup(0) opens three file descriptor 0, 1, 2 as stdin, stdout, stderr. Later when execve() or fork() happens, it simply copies calling processs task_struct as process context, so all file descriptors are also passed down as-is.\nAll processes file descriptor 0, 1, 2 originates to inits file descriptor.\nIf calling process opens PTY or TTY, which is common when we opens new terminal to run a process, it is also passed down to exec/forked process.\n",
"wordCount" : "192",
"inLanguage": "en",
"datePublished": "2023-11-26T07:44:51.449Z",
"dateModified": "2023-11-26T07:44:51.449Z",
"author":{
"@type": "Person",
"name": "Me"
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "http://blog.morgan.kr/2023/11/kernel-process-creation/"
},
"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, Process creation
</h1>
<div class="post-description">
Linux Kernel #3
</div>
<div class="post-meta"><span title='2023-11-26 07:44:51.449 &#43;0000 UTC'>
Nov 26, 2023
</span>
</div>
</header>
<div class="post-divider"></div>
<div class="post-content"><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">init</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">unused</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">lock_kernel</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> <span class="nf">do_basic_setup</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Ok, we have completed the initial bootup, and
</span></span></span><span class="line"><span class="cl"><span class="cm"> * we&#39;re essentially up and running. Get rid of the
</span></span></span><span class="line"><span class="cl"><span class="cm"> * initmem segments and start the user-mode stuff..
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"> <span class="nf">free_initmem</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> <span class="nf">unlock_kernel</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">open</span><span class="p">(</span><span class="s">&#34;/dev/console&#34;</span><span class="p">,</span> <span class="n">O_RDWR</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printk</span><span class="p">(</span><span class="s">&#34;Warning: unable to open an initial console.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="nf">dup</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="nf">dup</span><span class="p">(</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="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm"> * We try each of these until one succeeds.
</span></span></span><span class="line"><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="cl"><span class="cm"> * The Bourne shell can be used instead of init if we are
</span></span></span><span class="line"><span class="cl"><span class="cm"> * trying to recover a really broken machine.
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</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">execute_command</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nf">execve</span><span class="p">(</span><span class="n">execute_command</span><span class="p">,</span><span class="n">argv_init</span><span class="p">,</span><span class="n">envp_init</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="nf">execve</span><span class="p">(</span><span class="s">&#34;/sbin/init&#34;</span><span class="p">,</span><span class="n">argv_init</span><span class="p">,</span><span class="n">envp_init</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="nf">execve</span><span class="p">(</span><span class="s">&#34;/etc/init&#34;</span><span class="p">,</span><span class="n">argv_init</span><span class="p">,</span><span class="n">envp_init</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="nf">execve</span><span class="p">(</span><span class="s">&#34;/bin/init&#34;</span><span class="p">,</span><span class="n">argv_init</span><span class="p">,</span><span class="n">envp_init</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="nf">execve</span><span class="p">(</span><span class="s">&#34;/bin/sh&#34;</span><span class="p">,</span><span class="n">argv_init</span><span class="p">,</span><span class="n">envp_init</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">&#34;No init found. Try passing init= option to kernel.&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>In this <code>init/main.c</code>, after basic kernel initialization things, <code>open(&quot;/dev/console&quot;)</code> and two <code>dup(0)</code> opens three file descriptor 0, 1, 2 as stdin, stdout, stderr. Later when <code>execve()</code> or <code>fork()</code> happens, it simply copies calling process&rsquo;s <code>task_struct</code> as process context, so all file descriptors are also passed down as-is.</p>
<p>All processes&rsquo; file descriptor 0, 1, 2 originates to <code>init</code>&rsquo;s file descriptor.</p>
<p>If calling process opens PTY or TTY, which is common when we opens new terminal to run a process, it is also passed down to exec/forked process.</p>
</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;">&copy;</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>