<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>INFO-0940 Operating Systems Archives - Tom Barbette</title>
	<atom:link href="https://perso.uclouvain.be/tom.barbette/category/courses/os/feed/" rel="self" type="application/rss+xml" />
	<link>https://perso.uclouvain.be/tom.barbette/category/courses/os/</link>
	<description></description>
	<lastBuildDate>Thu, 25 Jan 2018 14:52:20 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://perso.uclouvain.be/tom.barbette/wp-content/uploads/2022/04/cropped-logo-uclouvain-2021-barbette-32x32.png</url>
	<title>INFO-0940 Operating Systems Archives - Tom Barbette</title>
	<link>https://perso.uclouvain.be/tom.barbette/category/courses/os/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Warm up !</title>
		<link>https://perso.uclouvain.be/tom.barbette/warm-up/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Thu, 25 Jan 2018 14:52:20 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=734</guid>

					<description><![CDATA[<p>Hello 2017-2018 students ! A first warm-up with a video from Mark Handley about Spectre and Meltdown vulnerabilities. Also, a very good introduction to a lot of things discussed in the course ! https://www.youtube.com/watch?v=m66EAgRMmi8 &#160;</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/warm-up/">Warm up !</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Hello 2017-2018 students !</p>
<p>A first warm-up with a video from Mark Handley about Spectre and Meltdown vulnerabilities.</p>
<p>Also, a very good introduction to a lot of things discussed in the course !</p>
<p><a href="https://www.youtube.com/watch?v=m66EAgRMmi8">https://www.youtube.com/watch?v=m66EAgRMmi8</a></p>
<p>&nbsp;</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/warm-up/">Warm up !</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Fork &#038; Exec system calls to implement a shell</title>
		<link>https://perso.uclouvain.be/tom.barbette/fork-exec-system-calls-to-implement-a-shell/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Fri, 10 Feb 2017 19:53:07 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=672</guid>

					<description><![CDATA[<p>A shell, typically parse a command, then fork (duplicates itself). The duplicated process replaces itself using Execvp by the program described in the command The other process wait for the duplicated one to exit using waitpid. When that happens it prints the prompt again, ready for the next one to come. And the whole thing &#8230; </p>
<p class="link-more"><a href="https://perso.uclouvain.be/tom.barbette/fork-exec-system-calls-to-implement-a-shell/" class="more-link">Continue reading<span class="screen-reader-text"> "Fork &#038; Exec system calls to implement a shell"</span></a></p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/fork-exec-system-calls-to-implement-a-shell/">Fork &#038; Exec system calls to implement a shell</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>A shell, typically parse a command, then fork (duplicates itself).</p>
<p>The duplicated process replaces itself using Execvp by the program described in the command</p>
<p>The other process wait for the duplicated one to exit using waitpid. When that happens it prints the prompt again, ready for the next one to come. And the whole thing restarts again.</p>
<p>Not a very hard life.</p>
<p>Here are the important parts of the manpages of the 3 functions :</p>
<p><strong>Fork</strong></p>
<p>NAME<br />
fork &#8211; create a child process</p>
<p>SYNOPSIS<br />
#include &lt;unistd.h&gt;</p>
<p>pid_t fork(void);</p>
<p>DESCRIPTION<br />
fork() creates a new process by duplicating the calling process. The<br />
new process is referred to as the child process. The calling process<br />
is referred to as the parent process.</p>
<p>The child process and the parent process run in separate memory spaces.<br />
At the time of fork() both memory spaces have the same content.</p>
<p>RETURN VALUE<br />
On success, the PID of the child process is returned in the parent, and<br />
0 is returned in the child. On failure, -1 is returned in the parent,<br />
no child process is created, and errno is set appropriately.</p>
<p><strong>Execvp</strong></p>
<p>EXEC(3) Linux Programmer&#8217;s Manual EXEC(3)</p>
<p>NAME<br />
execvp &#8211; execute a file</p>
<p>SYNOPSIS<br />
#include &lt;unistd.h&gt;<br />
int execvp(const char *file, char *const argv[]);</p>
<p>DESCRIPTION</p>
<p>The execvp() function replaces the current process image with<br />
a new process image.</p>
<p>The initial argument for this function is the name of a file that is<br />
to be executed.</p>
<p>The const char *arg can be thought of as arg0, arg1, &#8230;, argn.<br />
Together they describe a list of one or more pointers to null-termi‐<br />
nated strings that represent the argument list available to the exe‐<br />
cuted program. The first argument, by convention, should point to the<br />
filename associated with the file being executed. The list of argu‐<br />
ments must be terminated by a null pointer, and, since these are vari‐<br />
adic functions, this pointer must be cast (char *) NULL.</p>
<p>RETURN VALUE<br />
The exec() functions return only if an error has occurred. The return<br />
value is -1, and errno is set to indicate the error.</p>
<p><strong>waitpid</strong></p>
<p>NAME<br />
waitpid &#8211; wait for process to change state</p>
<p>SYNOPSIS</p>
<p>pid_t waitpid(pid_t pid, int *status, int options);</p>
<p>DESCRIPTION</p>
<p>The waitpid() system call suspends execution of the calling process<br />
until a child specified by pid argument has changed state. By default,<br />
waitpid() waits only for terminated children.</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/fork-exec-system-calls-to-implement-a-shell/">Fork &#038; Exec system calls to implement a shell</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to find the mkdir syscall</title>
		<link>https://perso.uclouvain.be/tom.barbette/how-to-find-the-mkdir-syscall/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Mon, 29 Feb 2016 09:44:54 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=577</guid>

					<description><![CDATA[<p>The first question to ask yourself is probably what the mkdir syscall does? Obviously, it will create a new dir (thanks captain!) but is it only one piece of code for the whole kernel? If I ask, the answer is no. First, there is one syscall entry per achitecture, so searching about mkdir in the &#8230; </p>
<p class="link-more"><a href="https://perso.uclouvain.be/tom.barbette/how-to-find-the-mkdir-syscall/" class="more-link">Continue reading<span class="screen-reader-text"> "How to find the mkdir syscall"</span></a></p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/how-to-find-the-mkdir-syscall/">How to find the mkdir syscall</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The first question to ask yourself is probably what the mkdir syscall does?</p>
<p>Obviously, it will create a new dir (thanks captain!) but is it only one piece of code for the whole kernel?</p>
<p>If I ask, the answer is no. First, there is one syscall entry per achitecture, so searching about mkdir in the arch will already show a lot entries.</p>
<p>But what&#8217;s a dir? Something which contains one or multiple files? Yes but no. Conceptually, the main purpose of the directory is to give names to files and allow to address them. If the name of the file was in the file structure, how to access it? Without folder you would only have an array of files without names&#8230; But I&#8217;m getting away from the question (just giving you an exam answer by the way&#8230;)</p>
<p>The dir, in practice is implemented differently in all file systems. So there is one different mkdir function per file system, and there is a lot of FS in the linux kernel&#8230; How the kernel knows which one to use? It uses something much like net_device_ops for a network device (OS 2015-2016), md_personality for an md array (OS 2014-2015) or sched_class for a scheduler (OS 2013-2014) : a structure of function pointers that the kernel can follow to accomplish some actions.</p>
<p>So a &#8220;grep -Ri mkdir&#8221; on the top level of the kernel will give you way too much results&#8230;</p>
<p>If you look at the syscall table, you&#8217;ll find that we often talk about sys_something, so searching for sys_mkdir could be a good idea&#8230;</p>
<p>Could be&#8230; Because you won&#8217;t find it. Why? You should remember half of my slides, or what I said in class, or &#8230; Well, that smells the macro&#8230; Cscope does not support them well, Eclipse does. But Eclipse can only resolve a macro usage, not search in reverse from the macro declarations (as far as I know).</p>
<p>Time to show your regular expression skills ! (You could also search for the macro defining the syscall directly&#8230;). We should have something called syscall and mkdir in the same line&#8230; So let&#8217;s search for sys [something] mkdir, or the reverse :</p>
<p>grep &#8211;exclude &#8220;*.o&#8221; -RiE &#8220;sys.*mkdir|mkdir.*sys&#8221;</p>
<p>&#8211;exclude *.o allows to avoid searching object files, R do the search recursively, i case insensitive, E use regular expressions.</p>
<p>That stills give too much results. Looking quickly through, you could add &#8211;exclude Documentation and arch as those two won&#8217;t contain the actual implementation. Another way is to search only in the fs folder, as we can think that the syscall implementation is something about file systems&#8230; Even if it will call a per-fs function.</p>
<p>Let&#8217;s do the later :</p>
<pre>cd fs
grep --exclude "*.o" -RiE "sys.*mkdir|mkdir.*sys"
sysv/namei.c:static int sysv_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode)
sysv/namei.c: .mkdir = sysv_mkdir,
Fichier binaire sysv/sysv.ko correspondant
tracefs/inode.c:static int tracefs_syscall_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode)
tracefs/inode.c: .mkdir = tracefs_syscall_mkdir,
proc/root.c: proc_mkdir("sysvipc", NULL);
proc/proc_sysctl.c: proc_sys_root = proc_mkdir("sys", NULL);
namei.c:SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
namei.c:SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
namei.c: return sys_mkdirat(AT_FDCWD, pathname, mode);
btrfs/ioctl.c: * sys_mkdirat and vfs_mkdir, but we only do a single component lookup</pre>
<p>And it&#8217;s right in front of you <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> The number to use at the end of the macro is quite obvious&#8230; But google can help you if you don&#8217;t find what it means.</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/how-to-find-the-mkdir-syscall/">How to find the mkdir syscall</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>A reminder about variable size structures</title>
		<link>https://perso.uclouvain.be/tom.barbette/a-reminder-about-variable-size-structures/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Mon, 27 Apr 2015 14:57:44 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=489</guid>

					<description><![CDATA[<p>Variable-size structures are helpful, because you can allocate a structure containing an array of an unkown (at compile time) size at the end. For example, a &#8220;nuda_conf&#8221; structure containing informations about an MD Array and a &#8220;dev_info&#8221; structure per disks. The number of disks is unknown at compile time, so the only solution is to &#8230; </p>
<p class="link-more"><a href="https://perso.uclouvain.be/tom.barbette/a-reminder-about-variable-size-structures/" class="more-link">Continue reading<span class="screen-reader-text"> "A reminder about variable size structures"</span></a></p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/a-reminder-about-variable-size-structures/">A reminder about variable size structures</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Variable-size structures are helpful, because you can allocate a structure containing an array of an unkown (at compile time) size at the end. For example, a &#8220;nuda_conf&#8221; structure containing informations about an MD Array and a &#8220;dev_info&#8221; structure per disks. The number of disks is unknown at compile time, so the only solution is to use a kalloc/vmalloc. The classical solution is to do :</p>
<p>[code lang=&#8221;c&#8221;]</p>
<pre>struct dev_info {
int whatever;
struct rdev* rdev;
}

struct nuda_conf {
char* name;
int whotever;
struct dev_info disks*
}

...

struct nuda_conf* conf;
conf = kzalloc(sizeof(struct nuda_conf));
conf-&gt;disks = kzalloc(sizeof(struct dev_info) * NUMER_OF_DISKS);</pre>
<p>[/code]</p>
<p>But variable-size structures allows to do only one allocation :</p>
<p>[code lang=&#8221;c&#8221;]</p>
<pre>struct nuda_conf {
char* name;
int whotever;
struct dev_info disks[0];
}

struct nuda_conf* conf;

conf = kzalloc(sizeof(struct nuda_conf) + sizeof(struct dev_info) * NUMBER_OF_DISKS);</pre>
<p>[/code]</p>
<p>This will allocate the memory for the char* and the int of nuda_conf, and the memory for a number of &#8220;dev_info&#8221;. To access them, one can do <em>conf-&gt;disks[N] </em>where N is the disk index.</p>
<p><strong>But, this is limited to one variable-size array. </strong>If you do :</p>
<p>[code lang=&#8221;c&#8221;]</p>
<pre>struct nuda_conf {
char* name;
int whotever;
struct dev_info disks[0];
struct indirection_line indirection_table[0];
}</pre>
<p>[/code]</p>
<p>The &#8220;indirection_table&#8221; and the &#8220;disks&#8221; pointer will point to the same location ! Even if you allocate size for both ! The solution is either to use a classical pointer as in the first example, or handle the memory access yourself :</p>
<p>[code lang=&#8221;c&#8221;]</p>
<pre>struct nuda_conf {
char* name;
int whotever;
}
...
conf = kzalloc (sizeof(struct nuda_conf) + sizeof(struct dev_info) * NUMBER_OF_DISKS + sizeof(struct indirection_line)*NUMBER_OF_CHUNKS);
struct dev_info* disks = (struct dev_info*)(conf + 1);
struct indirection_line* indirection_table = (struct dev_info*)(disks + NUMBER_OF_DISKS);</pre>
<p>[/code]</p>
<p>But there is no interest in doing so, and both disks and indirection_table pointers have to be manually computed each time you need them&#8230; The use for that is really really really specific (dynamic metadata in packets for example).</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/a-reminder-about-variable-size-structures/">A reminder about variable size structures</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>sysfs entries</title>
		<link>https://perso.uclouvain.be/tom.barbette/sysfs-entries/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Sat, 21 Mar 2015 13:42:47 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=438</guid>

					<description><![CDATA[<p>Entries in the /sys folder are represented by &#8220;struct kobject&#8220;. A kobject is &#8230; a kernel object. So it can be anything. Regarding the /sys system, kobject can be more or less thinked as a &#8220;folder&#8221; of /sys. To obtain the &#8220;kobject&#8221; entry for /sys of an md device, one can do &#38;disk_to_dev(mddev-&#62;gendisk)-&#62;kobj. This object will &#8230; </p>
<p class="link-more"><a href="https://perso.uclouvain.be/tom.barbette/sysfs-entries/" class="more-link">Continue reading<span class="screen-reader-text"> "sysfs entries"</span></a></p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/sysfs-entries/">sysfs entries</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Entries in the <em>/sys</em> folder are represented by &#8220;<em>struct kobject</em>&#8220;.</p>
<p>A <em>kobject</em> is &#8230; a kernel object. So it can be anything. Regarding the /sys system, <em>kobject</em> can be more or less thinked as a &#8220;folder&#8221; of /sys. To obtain the &#8220;kobject&#8221; entry for /sys of an md device, one can do<em> &amp;disk_to_dev(mddev-&gt;gendisk)-&gt;kobj</em>. This object will handle the &#8220;folder&#8221; <em>/sys/block/md/mdX/</em> where X is the number of the md device.</p>
<p>To initialize your own <em>kobject</em> and add it as a child of the <em>kobject</em> of the <em>mddev</em>, one can use <em>kobject_init_and_add(yourobject, &amp;yourobect_type,</em><br />
<em> &amp;disk_to_dev(mddev-&gt;gendisk)-&gt;kobj, &#8220;%s&#8221;, &#8220;foldername&#8221;)</em>; In practice this will create a folder named &#8220;foldername&#8221; in /sys/block/md/mdX/.</p>
<p>&#8220;<em>yourobject</em>&#8221; should be a pointer to your <em>kobject</em>. It must be persistent, allocated with <em>kmalloc</em> or something like that and not in your function stack, even if you don&#8217;t plan to modify it. As <em>kobject</em> are more or less anything, you have to describe your <em>kobject</em> by passing to <em>kobject_init_and_add</em> a <em>struct kobj_type</em></p>
<p><em>static struct kobj_type myobject_ktype = {</em><br />
<em> .release = release_function,</em><br />
<em> .sysfs_ops = &amp;myobject_sysfs_ops,</em><br />
<em>}; </em></p>
<p><em>release</em> is the function which will be called when it&#8217;s time to destroy your kobject, while <em>sysfs_ops is a struct sys_ops</em>. We&#8217;ll come back to them later.</p>
<p>The &#8220;files&#8221; in your sys folder are represented by<em> struct attribute</em>. You have two choices here. Either the files in your folder do not change, and you add all the attribute as the &#8220;default list&#8221;of attributesof your kobject <strong>before the kobject initialisation </strong> , or you start with an empty kobject (or with some default files in the list but not all) and you add some files <strong>after kobject initialization</strong> using <em>sysfs_create_file(yourobject, attr);</em> where attr is a pointer to the attribute that you want to add. We&#8217;ll consider that all files are known in advance and we&#8217;ll put everything in the &#8220;default&#8221; list.</p>
<p>The &#8220;default&#8221; list is more a default array and is referenced via  <em>yourobject_ktype.default_attr .</em> It is a pointer to the array of pointer to attributes. Yes, re-read that sentence twice <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> It means you&#8217;ll give an array of pointer to attributes and not an array of attributes.</p>
<p><em>struct attribute **all_attrs;<br />
all_attrs =  kzalloc(sizeof(struct attribute *) * number_of_files);<br />
<em>attrs =  kzalloc(sizeof(struct attribute) * number_of_files);</em><br />
</em><em>[fill attrs]<br />
for (i = 0; i &lt; number_of_files;i++)<br />
all_attrs[i] = &amp;attrs[i];<br />
</em><em>yourobject_ktype.default_attrs =<em>all_attrs</em>;</em></p>
<p>If we look at struct attributes it contains :</p>
<p><em>struct attribute {</em><br />
<em> const char *name;</em><br />
<em> mode_t mode;</em><br />
<em>};</em></p>
<p>You should find by yourself how to initialize the attrs. Note that name is a char pointer, and in noway can store character themselves. So you need to allocate somewhere all the names of your attributes, and obviously not on your function stack&#8230;</p>
<p>Now, let&#8217;s go back to the <em><em>myobject_sysfs_ops</em></em> which describes how to read and write to these attributes</p>
<p>The main two functions in the sys_ops are <em>show</em> an <em>store</em></p>
<p><em>static const struct sysfs_ops <em>myobject_sysfs_ops</em> = {</em><br />
<em> .show = myobject_attr_show,</em><br />
<em> .store = myobject_attr_store,</em><br />
<em>};</em></p>
<p>These two functions will be called when any kobject attr is read or written in your kobject entry. Let&#8217;s see the show function :</p>
<p><em>static ssize_t</em><br />
<em>myobject_attr_show(struct kobject *kobj, struct attribute *attr, char *page)</em><br />
<em>{}</em></p>
<p>kobj is the pointer to your kobject, the attr is the attribute the user is trying to read and the page is a pointer to a space where you should print the content which was trying to be read.</p>
<p>The function <em>container_of()</em> is very usefull and often used in this case. Let&#8217;s say your kobject is stored in another structure, that we will call &#8220;struct conf&#8221; in our example. To recover the conf storing the kobject, one can do :</p>
<p><em>struct conf* conf = container_of(kobj, struct conf, kobj);</em></p>
<p>And you can use the attribute name to find what to write in the page.</p>
<p><strong>This should be sufficient for most usage, using some tricks to respond according the attribute name.</strong></p>
<p>If the treatment need to be specific according to the attribute/file, or if you absolutely need to store some data with each attribute, you have to allocate another bigger structure which contains the struct attr, this explains by the way why you give pointer to attributes and not an array of attributes to the ktype, because attributes could be scattered inside an array of a bigger structure. As an exemple, here the per-file structure of the md driver :</p>
<p><em>struct md_sysfs_entry {</em><br />
<em> struct attribute attr;</em><br />
<em> ssize_t (*show)(struct mddev *, char *);</em><br />
<em> ssize_t (*store)(struct mddev *, const char *, size_t);</em><br />
<em>};</em></p>
<p>The default_attributes cointains pointers to all the md_sysfs_entry-&gt;attr. And the show function of the kobject use cointainer_of() to find the md_sysfs_entry containing the attr. Then it calls the specific show and store functions of the md_sysfs_entry instead of doing something similar for all attributes.</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/sysfs-entries/">sysfs entries</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Why does my kernel version have a &#8220;+&#8221; at the end?</title>
		<link>https://perso.uclouvain.be/tom.barbette/why-does-my-kernel-version-have-a-at-the-end/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Fri, 27 Feb 2015 17:42:06 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=420</guid>

					<description><![CDATA[<p>If you use GIT, the kernel make system will append a &#8220;+&#8221; at the end of your kernel version. So some commands to install your kernel should be different like &#8220;update-initramfs -k 3.2.66+ -u&#8221; and of course, uname will show 3.2.66+</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/why-does-my-kernel-version-have-a-at-the-end/">Why does my kernel version have a &#8220;+&#8221; at the end?</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>If you use GIT, the kernel make system will append a &#8220;+&#8221; at the end of your kernel version. So some commands to install your kernel should be different like &#8220;update-initramfs -k <strong>3.2.66+</strong> -u&#8221; and of course, uname will show 3.2.66+</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/why-does-my-kernel-version-have-a-at-the-end/">Why does my kernel version have a &#8220;+&#8221; at the end?</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Understanding sleeping mechanism in Linux Kernel</title>
		<link>https://perso.uclouvain.be/tom.barbette/understanding-sleeping-mechanism-in-linux-kernel/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Thu, 10 Apr 2014 11:40:47 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<category><![CDATA[Unix]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=301</guid>

					<description><![CDATA[<p>The students of INFO-0940 were asked to remove a task from it&#8217;s current scheduler class when calling a new syscall and put it back when we call again that syscall. The question is : what to do if the task is currently sleeping? Cause the timer will expire at one moment and maybe put back &#8230; </p>
<p class="link-more"><a href="https://perso.uclouvain.be/tom.barbette/understanding-sleeping-mechanism-in-linux-kernel/" class="more-link">Continue reading<span class="screen-reader-text"> "Understanding sleeping mechanism in Linux Kernel"</span></a></p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/understanding-sleeping-mechanism-in-linux-kernel/">Understanding sleeping mechanism in Linux Kernel</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The students of INFO-0940 were asked to remove a task from it&#8217;s current scheduler class when calling a new syscall and put it back when we call again that syscall. The question is : what to do if the task is currently sleeping? Cause the timer will expire at one moment and maybe put back the state to TASK_RUNNING and run the task which should haven&#8217;t been able to run again. So either it expires after the processus is back in its previous scheduler, and that&#8217;s okay as it will reset it in a runnable state. Or it expires while it&#8217;s still removed, and that&#8217;s a problem as it will put it back in its previous state (or not, depending on how the syscall is implemented).<br />
Warning : this post is just the result of a quick look. More to give you some ideas and basis for understanding the sleeping mechanism.</p>
<p>&nbsp;</p>
<p>So we should try to understand how sleep works.</p>
<p>&nbsp;</p>
<p>Let&#8217;s look at the nanosleep syscall (which is called when you user sleep() or usleep() functions in C).</p>
<pre class="prettyprint linenums">SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
		struct timespec __user *, rmtp)
{
	struct timespec tu;

	if (copy_from_user(&amp;tu, rqtp, sizeof(tu)))
		return -EFAULT;

	if (!timespec_valid(&amp;tu))
		return -EINVAL;

	return hrtimer_nanosleep(&amp;tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
}</pre>
<p>It copies the userspace data, check that the time is valid and call hrtimer_nanosleep.</p>
<pre class="prettyprint linenums">long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
		       const enum hrtimer_mode mode, const clockid_t clockid)
{
	struct restart_block *restart;
	struct hrtimer_sleeper t;
	int ret = 0;
	unsigned long slack;

	slack = current-&gt;timer_slack_ns;
	if (rt_task(current))
		slack = 0;

	hrtimer_init_on_stack(&amp;t.timer, clockid, mode);
	hrtimer_set_expires_range_ns(&amp;t.timer, timespec_to_ktime(*rqtp), slack);
	if (do_nanosleep(&amp;t, mode))
		goto out;

	/* Absolute timers do not update the rmtp value and restart: */
	if (mode == HRTIMER_MODE_ABS) {
		ret = -ERESTARTNOHAND;
		goto out;
	}

	if (rmtp) {
		ret = update_rmtp(&amp;t.timer, rmtp);
		if (ret &lt;= 0)
			goto out;
	}

	restart = &amp;current_thread_info()-&gt;restart_block;
	restart-&gt;fn = hrtimer_nanosleep_restart;
	restart-&gt;nanosleep.clockid = t.timer.base-&gt;clockid;
	restart-&gt;nanosleep.rmtp = rmtp;
	restart-&gt;nanosleep.expires = hrtimer_get_expires_tv64(&amp;t.timer);

	ret = -ERESTART_RESTARTBLOCK;
out:
	destroy_hrtimer_on_stack(&amp;t.timer);
	return ret;
}</pre>
<p>It initialize a timer and call do_nanosleep giving it the timer. After do_nanosleep it will destroy/free the timer structure.</p>
<pre class="prettyprint linenums">static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
{
	hrtimer_init_sleeper(t, current);

	do {
		set_current_state(TASK_INTERRUPTIBLE);
		hrtimer_start_expires(&amp;t-&gt;timer, mode);
		if (!hrtimer_active(&amp;t-&gt;timer))
			t-&gt;task = NULL;

		if (likely(t-&gt;task))
			schedule();

		hrtimer_cancel(&amp;t-&gt;timer);
		mode = HRTIMER_MODE_ABS;

	} while (t-&gt;task &amp;&amp; !signal_pending(current));

	__set_current_state(TASK_RUNNING);

	return t-&gt;task == NULL;
}</pre>
<p>This is the interesting part.</p>
<p>&nbsp;</p>
<p>The first thing done is calling hrtimer_init_sleeper(); which will set parameters of the timer to call the function hrtimer_wakeup when the timer expires, and specify the task to wakeup at that time. hrtimer_wakeup will simply set the task to NULL and call wake_up_process() on that task. We&#8217;ll come back to wake_up_process(task) later.</p>
<p>&nbsp;</p>
<p>We see that after that the state is changed to TASK_INTERRUPTIBLE. Then it starts the timer strictly speaking, and go in schedule().</p>
<p>&nbsp;</p>
<p>Remember that schedule(), before scheduling a new task, will test the state of the current (which is now &#8220;previous&#8221;) task, and if the state is not TASK_RUNNING, it will remove that task from its runqueue (and that is the case as it is in the TASK_INTERRUPTIBLE state).</p>
<p>&nbsp;</p>
<p>Schedule() goes on and start scheduling another task, if there is not, it will run the &#8220;idle&#8221; task.</p>
<p>&nbsp;</p>
<p><span style="line-height: 1.5;">At some point, the timer will expire. The timer rely on an hardware timer which will cause an interrupt, leaving any current task to process the interrupt handler (this is not the schedule() handler and so on !). The interrupt handler for the hardware timer is  hrtimer_interrupt() which will run </span><span style="line-height: 1.5;">hrtimer_wakeup() for all expired timer. As said before, outr timer for the sleeping mechanism will set the timer task as NULL, and call wake_up_process(). But that functions just put back the process in the runqueue and set its state to TASK_RUNNING, not actually scheduling it. The interrupt handler will finish and the CPU will go back to it&#8217;s currently running process (maybe the idle process, running the cpu_idle() function). </span></p>
<p>&nbsp;</p>
<p>That currently running process will eventually finish its processing or be preempted (the normal scheduling mechanism), and the process which was sleeping will re-run again when it will be picked again by pick_next_task().</p>
<p>&nbsp;</p>
<p>But where will this process restart? After the sleep() or usleep() call? No ! Where it was&#8230; in the nanosleep syscall. What does the syscall do after its call to schedule()? Put the state back to TASK_RUNNING and effectively running. That seems obvious as we said before that the syscall is taking care of destroying the timer structure, so it should not restart after the syscall.</p>
<p>&nbsp;</p>
<p>Note that I skipped the part where do_nanosleep() is looping and so on&#8230; I tried usleep(1) and sleep(1), and the loop never happend. I suspect it&#8217;s for very long timers, the kernel would&#8217;nt launch a timer of 1 hour long&#8230; But it&#8217;s just a guess.</p>
<p>&nbsp;</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/understanding-sleeping-mechanism-in-linux-kernel/">Understanding sleeping mechanism in Linux Kernel</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Manual network configuration under ubuntu</title>
		<link>https://perso.uclouvain.be/tom.barbette/manual-network-configuration-under-ubuntu/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Fri, 14 Feb 2014 13:15:47 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[dhclient]]></category>
		<category><![CDATA[ifconfig]]></category>
		<category><![CDATA[ifup]]></category>
		<category><![CDATA[info0940]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[network problem]]></category>
		<category><![CDATA[problem]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=212</guid>

					<description><![CDATA[<p>This procedure is only with cable, not for wifi First check that your interface is up with the command &#8220;sudo ifconfig&#8221; : If like in this screenshot you do not see an interface named &#8220;ethXXX&#8220;, you have to start the interface manually. &#160; To found which of eth0, eth1, &#8230; your network card is, you &#8230; </p>
<p class="link-more"><a href="https://perso.uclouvain.be/tom.barbette/manual-network-configuration-under-ubuntu/" class="more-link">Continue reading<span class="screen-reader-text"> "Manual network configuration under ubuntu"</span></a></p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/manual-network-configuration-under-ubuntu/">Manual network configuration under ubuntu</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>This procedure is only with cable, not for wifi</em></p>
<p>First check that your interface is up with the command &#8220;<em>sudo ifconfig</em>&#8221; :</p>
<p><a href="https://www.tombarbette.be/wp-content/uploads/2014/02/lo.png"><img decoding="async" src="https://www.tombarbette.be/wp-content/uploads/2014/02/lo-300x93.png" alt="lo" width="300" height="93" class="alignnone size-medium wp-image-213" srcset="https://perso.uclouvain.be/tom.barbette/wp-content/uploads/2014/02/lo-300x93.png 300w, https://perso.uclouvain.be/tom.barbette/wp-content/uploads/2014/02/lo.png 577w" sizes="(max-width: 300px) 100vw, 300px" /></a><br />
If like in this screenshot you do not see an interface named &#8220;<em>ethXXX</em>&#8220;, you have to start the interface manually.<br />
&nbsp;<br />
To found which of eth0, eth1, &#8230; your network card is, you can type &#8220;<em>dmesg | grep eth</em>&#8221;</p>
<p><a href="https://www.tombarbette.be/wp-content/uploads/2014/02/dmesg.png"><img decoding="async" src="https://www.tombarbette.be/wp-content/uploads/2014/02/dmesg-300x80.png" alt="dmesg" width="300" height="80" class="alignnone size-medium wp-image-214" srcset="https://perso.uclouvain.be/tom.barbette/wp-content/uploads/2014/02/dmesg-300x80.png 300w, https://perso.uclouvain.be/tom.barbette/wp-content/uploads/2014/02/dmesg.png 718w" sizes="(max-width: 300px) 100vw, 300px" /></a><br />
We see here that the card &#8220;Intel Pro/1000&#8221; takes the &#8220;eth0&#8221; interface name. But it&#8217;s later renamed to &#8220;<em>eth1</em>&#8220;.<br />
&nbsp;<br />
So our interface here is eth1, to bring it up, simply run &#8220;sudo ifconfig eth1 up&#8221;.<br />
<a href="https://www.tombarbette.be/wp-content/uploads/2014/02/eth1up.png"><img decoding="async" src="https://www.tombarbette.be/wp-content/uploads/2014/02/eth1up-300x148.png" alt="eth1up" width="300" height="148" class="alignnone size-medium wp-image-215" srcset="https://perso.uclouvain.be/tom.barbette/wp-content/uploads/2014/02/eth1up-300x148.png 300w, https://perso.uclouvain.be/tom.barbette/wp-content/uploads/2014/02/eth1up.png 636w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>You may not have an IP Adress automatically like in this screenshot. If it&#8217;s the case, simply type &#8220;<em>sudo dhclient eth1</em>&#8221; to get one with DHCP.<br />
&nbsp;<br />
If it doesn&#8217;t work, try to directly ping an IP address like google&#8217;s dns server <em>8.8.8.8</em> with the command &#8220;<em>ping 8.8.8.8</em>&#8220;. If it works, you probably have a nameserver problem. Simply add the line &#8220;<em>nameserver 8.8.8.8</em>&#8221; in /etc/resolv.conf</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/manual-network-configuration-under-ubuntu/">Manual network configuration under ubuntu</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Remove message &#8220;Waiting for network configuration&#8230;&#8221; on ubuntu</title>
		<link>https://perso.uclouvain.be/tom.barbette/remove-message-waiting-for-network-configuration-on-ubuntu/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Fri, 14 Feb 2014 12:41:09 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[info0940]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[problems]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=210</guid>

					<description><![CDATA[<p>On ubuntu, if your system boots without network in failsafe mode, it will wait a long time for network to be available. In many case, this won&#8217;t help much&#8230; Moreover, if you&#8217;re trying to do things like kernel compiling and for some reason you can&#8217;t see the boot log (including this &#8220;Waiting for network configuration&#8221; &#8230; </p>
<p class="link-more"><a href="https://perso.uclouvain.be/tom.barbette/remove-message-waiting-for-network-configuration-on-ubuntu/" class="more-link">Continue reading<span class="screen-reader-text"> "Remove message &#8220;Waiting for network configuration&#8230;&#8221; on ubuntu"</span></a></p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/remove-message-waiting-for-network-configuration-on-ubuntu/">Remove message &#8220;Waiting for network configuration&#8230;&#8221; on ubuntu</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>On ubuntu, if your system boots without network in failsafe mode, it will wait a long time for network to be available. In many case, this won&#8217;t help much&#8230;</p>
<p>Moreover, if you&#8217;re trying to do things like kernel compiling and for some reason you can&#8217;t see the boot log (including this &#8220;Waiting for network configuration&#8221; message), you&#8217;ll have the impression of being stuck with a bad kernel, but in fact it is just waiting 120 seconds&#8230;</p>
<p>Just edit the file <em>sudo vi /etc/init/failsafe.conf</em> and remove all &#8220;sleep&#8221; instructions. The message will be displayed but it won&#8217;t wait any time.</p>
<p>To repair you network problems, you might want to check <a href="https://www.tombarbette.be/vm-and-kernel-compiling-troubleshooting/">this post</a> and <a href="https://www.tombarbette.be/manual-network-configuration-under-ubuntu/">this post</a>.</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/remove-message-waiting-for-network-configuration-on-ubuntu/">Remove message &#8220;Waiting for network configuration&#8230;&#8221; on ubuntu</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ugly things : do not ask password for sudo</title>
		<link>https://perso.uclouvain.be/tom.barbette/ugly-things-do-not-ask-password-for-sudo/</link>
		
		<dc:creator><![CDATA[Tom Barbette]]></dc:creator>
		<pubDate>Mon, 03 Feb 2014 10:53:37 +0000</pubDate>
				<category><![CDATA[INFO-0940 Operating Systems]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[info0940]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[root]]></category>
		<category><![CDATA[sudo]]></category>
		<category><![CDATA[ugly]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[visudo]]></category>
		<guid isPermaLink="false">http://queen.run.montefiore.ulg.ac.be/~barbette/?p=155</guid>

					<description><![CDATA[<p>&#8211;> Ugly but okay in a development virtual machine Launch the command &#8220;sudo visudo&#8221; in a terminal. Add at the end : student ALL=(ALL) NOPASSWD: ALL And student will have no password prompt when using sudo</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/ugly-things-do-not-ask-password-for-sudo/">Ugly things : do not ask password for sudo</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>&#8211;> Ugly but okay in a development virtual machine</p>
<p>Launch the command &#8220;sudo visudo&#8221; in a terminal.</p>
<p>Add at the end :<br />
<code sh>student ALL=(ALL) NOPASSWD: ALL</code></p>
<p>And student will have no password prompt when using sudo</p>
<p>The post <a href="https://perso.uclouvain.be/tom.barbette/ugly-things-do-not-ask-password-for-sudo/">Ugly things : do not ask password for sudo</a> appeared first on <a href="https://perso.uclouvain.be/tom.barbette">Tom Barbette</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
