<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://homeostasis.scs.carleton.ca/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ssarazin</id>
	<title>Soma-notes - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://homeostasis.scs.carleton.ca/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ssarazin"/>
	<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php/Special:Contributions/Ssarazin"/>
	<updated>2026-05-12T22:15:45Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_15&amp;diff=21192</id>
		<title>Operating Systems 2017F Lecture 15</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_15&amp;diff=21192"/>
		<updated>2017-11-12T18:57:35Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
The video from the lecture given on Nov. 7, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec15-07Nov2017.mp4 is now available].  Unfortunately, the video cut out halfway through; [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec15-07Nov2017-audio.m4a audio is also available] however.&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
===In Class===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Lecture 15&lt;br /&gt;
----------&lt;br /&gt;
&lt;br /&gt;
What&#039;s a filesystem?&lt;br /&gt;
 - persistent data structure organized around fixed allocation units (blocks)&lt;br /&gt;
 - maps hierarchical names (keys) to values&lt;br /&gt;
 - provide a file-like API (open, read, write, close, etc)&lt;br /&gt;
&lt;br /&gt;
What does it mean to &amp;quot;make&amp;quot; a filesystem?&lt;br /&gt;
 - initialize the data structure&lt;br /&gt;
 - &amp;quot;formatting&amp;quot; a disk&lt;br /&gt;
&lt;br /&gt;
Physical versus logical size of a file&lt;br /&gt;
 - logical: the &amp;quot;size&amp;quot; your program sees when accessing the file&lt;br /&gt;
 - physical: how much space the file takes up on disk&lt;br /&gt;
&lt;br /&gt;
Physical is in terms of blocks - fixed units of storage allocation&lt;br /&gt;
 - ext4 has 4k blocks&lt;br /&gt;
 - default for many command line utilities is 1k blocks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Kernel programming&lt;br /&gt;
 - you may destroy the system you are working on AT ANY TIME&lt;br /&gt;
 - HAVE GOOD BACKUPS&lt;br /&gt;
 - rsync is your friend&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Kernel modules&lt;br /&gt;
 - way of splitting up kernel functionality so everything doesn&#039;t have to load&lt;br /&gt;
   at boot&lt;br /&gt;
    - code loaded as part of the initial boot image is hard to get rid of at&lt;br /&gt;
      runtime&lt;br /&gt;
 - why do we need modules? why not processes?&lt;br /&gt;
   - no new mechanisms&lt;br /&gt;
   - increased security (restricted access)&lt;br /&gt;
   - &amp;quot;microkernel&amp;quot; approach&lt;br /&gt;
   - instead of code talking in supervisor mode, processes do IPC&lt;br /&gt;
      - filesystems&lt;br /&gt;
      - drivers&lt;br /&gt;
      - networking&lt;br /&gt;
   - minix, QNX, GNU hurd&lt;br /&gt;
 - Linux is a &amp;quot;monolithic&amp;quot; kernel.  Why?&lt;br /&gt;
   - performance: context switches are expensive&lt;br /&gt;
     - techniques to make microkernels fast can be adopted by&lt;br /&gt;
       monolithic kernels to make them even faster&lt;br /&gt;
   - security benefit is illusory&lt;br /&gt;
     - if you control the filesystem process, you already own everything&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Additional===&lt;br /&gt;
&lt;br /&gt;
--&amp;gt; Core kernel functionality is implemented via modules&lt;br /&gt;
--&amp;gt; use ls mod to see modules that are loaded&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;What is a monolithic kernel?&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt; a type of OS architecture where the entire OS is working in kernel space&lt;br /&gt;
--&amp;gt; can dynamically load/unload modules at runtime&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;make localmodconfig:&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt; takes output of ls mod and configures your kernel&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ones.c program:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;/dev/ones:&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt; permissions are read only&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;file_operations ones_fops():&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt; defines what happens when you open a file, read from it, release tells you what happens when you&#039;re done with it (not the same thing as close)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ones_read():&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt; len is the number of bytes to read&lt;br /&gt;
--&amp;gt; offset tells you where you are in the file&lt;br /&gt;
--&amp;gt; put_user() takes care of whatever needs to be done to write into that process properly&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ones_release:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Why are we using printk instead of printf?&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt; printf is not yet defined (ie. C library is not available in the kernel)&lt;br /&gt;
--&amp;gt; kernel doesn&#039;t depend on any libraries, all code belongs to the kernel itself&lt;br /&gt;
--&amp;gt; printk is the kernel&#039;s own implementation of printf (outputs to the kernel log --&amp;gt; /var/log/kern.log)&lt;br /&gt;
&lt;br /&gt;
vfs = virtual filesystem layer&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;How do we limit access to user space processes?&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt; Do a permission check&lt;br /&gt;
&lt;br /&gt;
--&amp;gt; kernels need to be updated regularly to correct bugs that make the kernel vulnerable to programs trying to gain access to important user space processes&lt;br /&gt;
--&amp;gt; unlikely() = tells you that this branch is not likely to be taken, optimize the current path&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vfs_read:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;file-&amp;gt;f_op-&amp;gt;read:&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt; this is how our read function will be called&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== From the Text Book (Filesystem Implementation) ===&lt;br /&gt;
&lt;br /&gt;
VSFS	&lt;br /&gt;
- Illustrates the a typical Unix file system using vsfs (Very Simple File System).&lt;br /&gt;
- Introduces some of the basic on-disk structures, access methods, and various policies&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
The mental model of File Systems&lt;br /&gt;
*Want to answer these questions:&lt;br /&gt;
**What on-disk structures store the file system&#039;s data and metadata?&lt;br /&gt;
**What happens when a process opens a file?&lt;br /&gt;
**Which on-disk structures are accessed during a read or write?&lt;br /&gt;
&lt;br /&gt;
*The file system is pure software that implements:&lt;br /&gt;
**a data-structure to organize its data and metadata.&lt;br /&gt;
**access methods - how it maps the calls made by a process (open(), read(), write()) onto its structures&lt;br /&gt;
&lt;br /&gt;
Data structure&lt;br /&gt;
*A file system divides the hard disk into blocks, a common sized block is 4KB.&lt;br /&gt;
*The majority of the blocks hold user data and their inodes&lt;br /&gt;
*Two bitmaps, one of the inode table and the other for the user data blocks track usage&lt;br /&gt;
*Finally, a superblock contains information about the filesystem -- how many inodes, datablocks, and type of filesystem&lt;br /&gt;
&lt;br /&gt;
Mounting the filesystem&lt;br /&gt;
*The operating system reads the superblock and then attaches the volume to the filesystem tree&lt;br /&gt;
&lt;br /&gt;
File Organization&lt;br /&gt;
*inode (index node) number indexes into the inode table to find the desired block of inodes.  Once the inode is retrieved all of the corresponding file information is known.  Some metadata include: uid (who owns it), size (how many bytes are in the file), gid (which group does the file belong to), blocks ( how many blocks have been allocated to this file) etc…&lt;br /&gt;
*inode&#039;s refer to data blocks using a multi-level index.  Direct pointers and indirect pointers.  Direct pointers reference data blocks and indirect pointers reference pointers to data blocks.  Adding levels of pointers allows the inode to reference very large files&lt;br /&gt;
&lt;br /&gt;
Directory Organization&lt;br /&gt;
*A directory is a list of pairs (entry name, inode number).  The entry name is the string representing the directory.&lt;br /&gt;
*&#039;dot&#039; is the current directory and &#039;dot-dot&#039; is the parent directory&lt;br /&gt;
*Directories are stored in a file system the same way regular files are - they have an inode.  Only directories are marked as such in the inode type field.&lt;br /&gt;
&lt;br /&gt;
Free Space Management&lt;br /&gt;
*When a file is created the file system searches the inode bitmap and allocates a free inode to the new file.&lt;br /&gt;
*The filesystem uses a pre-allocation policy to allocate data blocks for a new file.  It tries to contiguous blocks thus improving performance.&lt;br /&gt;
&lt;br /&gt;
Reading and Writing a file&lt;br /&gt;
*Open: the filesystem traverses the pathname and locates the inode for the file.  It starts at the root directory (this is known to the filesystem when it is mounted) and traverses the pathname for the file&#039;s inode.  Once the permissions have been verified a file descriptor to the file is returned to the user.  Note that several reads happen during open in order to find the correct inode number.&lt;br /&gt;
*Read: The filesystem starts at file offset 0 which it gets from the inode.  It updates memory with the file contents and moves the file offset such that the next read knows where to begin.  Disk IO is accessed as needed.&lt;br /&gt;
*Close:  The file descriptor is deallocated.&lt;br /&gt;
*Writing: Each write to a file generates five I/O&#039;s: one to read the data bitmap, one to write the bitmap, two more to read and then write the inode and finally one to write to the data block.&lt;br /&gt;
&lt;br /&gt;
Caching and Buffering&lt;br /&gt;
*Caching is used to eliminate disk IO for future accesses of popular files.  Popular files are loaded into virtual memory so that future accesses do not have to go through the process of reading from disk.&lt;br /&gt;
*Write buffering is used by the filesystem as a way of minimizing the number of disk accesses.  The system builds a buffer of write&#039;s and schedules them minimizing IO.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Talk:Operating_Systems_2017F_Lecture_14&amp;diff=21162</id>
		<title>Talk:Operating Systems 2017F Lecture 14</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Talk:Operating_Systems_2017F_Lecture_14&amp;diff=21162"/>
		<updated>2017-10-28T21:39:06Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* Review Notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_14&amp;diff=21161</id>
		<title>Operating Systems 2017F Lecture 14</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_14&amp;diff=21161"/>
		<updated>2017-10-28T21:38:46Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: Created page with &amp;quot;==Review Notes==  Definitions:   - OS: A resource Manager that abstracts the hardware so that applications can get easy access to it.  The OS facilitates resource sharing amon...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Review Notes==&lt;br /&gt;
&lt;br /&gt;
Definitions:&lt;br /&gt;
&lt;br /&gt;
 - OS: A resource Manager that abstracts the hardware so that applications can get easy access to it.  The OS facilitates resource sharing among concurrent programs.&lt;br /&gt;
 - Kernel: The first program to launch when the computer boots.  The kernel has absolute power over the hardware; it manages and controls access to these resources.&lt;br /&gt;
 - Process: A running program.  It has one or more threads and address space.&lt;br /&gt;
 - Thread: A function that runs in the same memory space as other functions.&lt;br /&gt;
 - Memory: A contiguous array of bytes.  Modern systems virtualize memory, mapping it to physical memory so it can be shared among processes.&lt;br /&gt;
 - Interrupts: A mechanism used by the kernel that interrupts the CPU when other tasks are higher priority.&lt;br /&gt;
 - Signals: Inter-process communications.  A mechanism used by the kernel and processes to communicate with one another.&lt;br /&gt;
 - System Call: Specialized functions used by programs to request more resources from the kernel.&lt;br /&gt;
 - File: A hierarchical name with a value mapping (Key/Value pair)&lt;br /&gt;
 - Shell: Another program that is used to send system calls to the kernel or launch other programs.&lt;br /&gt;
 - File system: A set of files grouped together with a common hierarchical root.&lt;br /&gt;
 - Fragmentation: Variable sized memory allocation.&lt;br /&gt;
 - Internal Fragmentation: Space wasted in an allocation.&lt;br /&gt;
 - Concurrency: More than one thing happening at a time.&lt;br /&gt;
 - Atomic Variables: Variables that guarantee a strict ordering of operations.&lt;br /&gt;
 - Segmentation: Managing memory without paging.&lt;br /&gt;
 - Segments: A variable sized block of memory that can be placed in different parts of the address space.&lt;br /&gt;
 - Segfault: When a virtual address does not have a corresponding physical address.&lt;br /&gt;
 - mmap: The virtual address range corresponds to the contents of a file or RAM.&lt;br /&gt;
 - Concurrency: More than one thing is happening at the same time.&lt;br /&gt;
&lt;br /&gt;
Creating a process:&lt;br /&gt;
* fork() creates a process and execve() loads the binary to the new process.&lt;br /&gt;
** returns a process id&lt;br /&gt;
*** pid &amp;gt; 0, parent process&lt;br /&gt;
*** pid &amp;lt; 0, error&lt;br /&gt;
*** pid = 0, child process&lt;br /&gt;
&lt;br /&gt;
* When a parent does not deal with its child processes they become zombies&lt;br /&gt;
* If a parent dies before its children they become orphans that are re-parented by the OS&lt;br /&gt;
&lt;br /&gt;
* wait()&lt;br /&gt;
** suspends the current process until one, some, or all of its children have terminated&lt;br /&gt;
** wait() can be called anytime to check on the status of children&lt;br /&gt;
&lt;br /&gt;
IO redirection:&lt;br /&gt;
* &amp;gt;, direct to stdout&lt;br /&gt;
* &amp;lt;, direct to stdin&lt;br /&gt;
* |, connect the output of one process to the input of another process&lt;br /&gt;
* when a process starts it is given file descriptors to stdout, stdin, and stderr&lt;br /&gt;
&lt;br /&gt;
Inodes:&lt;br /&gt;
* Contain information about the blocks corresponding to the contents of a file on disk, its owner, and the file access permissions.&lt;br /&gt;
* A filename points to an inode&lt;br /&gt;
* The inode count represents all of the files and folders on disk&lt;br /&gt;
* Hard links create another name to the same inode number&lt;br /&gt;
** Only point to files within the same file system&lt;br /&gt;
* Symbolic links are files with their own inode&lt;br /&gt;
** Can point to files in other partitions or file systems&lt;br /&gt;
&lt;br /&gt;
Virtual Memory:&lt;br /&gt;
* Every process receives a memory map with virtual addresses that correspond to physical addresses.&lt;br /&gt;
&lt;br /&gt;
Memory Allocation Challenges:&lt;br /&gt;
* Need to have a contiguous address range&lt;br /&gt;
* Data Structures can not be moved once allocated&lt;br /&gt;
* Memory is constantly allocated and deallocated&lt;br /&gt;
&lt;br /&gt;
Solution to these challenges:&lt;br /&gt;
* Use fixed size chunks that can be stored anywhere&lt;br /&gt;
** Called a page in memory or a block on disk&lt;br /&gt;
** Sizes are always a power of 2 because addresses are indexed in bits&lt;br /&gt;
** The benefit: it removes the limitations on array sizes.&lt;br /&gt;
** Use a table to map virtual memory to physical memory -- called a page table&lt;br /&gt;
** In a 32 bit system: the top 20 bits are the page locations and the lower 12 bits are the page offset&lt;br /&gt;
&lt;br /&gt;
Concurrency:&lt;br /&gt;
* Challenge: keeping the shared state consistent; want deterministic behavior from concurrent computations&lt;br /&gt;
* Solution: Need mechanisms that bypass the memory hierarchy.&lt;br /&gt;
** Use filesystem locking primitives -&amp;gt; atomic variables -&amp;gt; semaphores&lt;br /&gt;
** Use signals to synchronize the shared state&lt;br /&gt;
&lt;br /&gt;
Segmentation:&lt;br /&gt;
* The physical address can be found by adding the segment register to the offset.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Talk:Operating_Systems_2017F_Lecture_14&amp;diff=21160</id>
		<title>Talk:Operating Systems 2017F Lecture 14</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Talk:Operating_Systems_2017F_Lecture_14&amp;diff=21160"/>
		<updated>2017-10-28T21:35:42Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: Created page with &amp;quot;==Review Notes==  Definitions:   - OS: A resource Manager that abstracts the hardware so that applications can get easy access to it.  The OS facilitates resource sharing amon...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Review Notes==&lt;br /&gt;
&lt;br /&gt;
Definitions:&lt;br /&gt;
&lt;br /&gt;
 - OS: A resource Manager that abstracts the hardware so that applications can get easy access to it.  The OS facilitates resource sharing among concurrent programs.&lt;br /&gt;
 - Kernel: The first program to launch when the computer boots.  The kernel has absolute power over the hardware; it manages and controls access to these resources.&lt;br /&gt;
 - Process: A running program.  It has one or more threads and address space.&lt;br /&gt;
 - Thread: A function that runs in the same memory space as other functions.&lt;br /&gt;
 - Memory: A contiguous array of bytes.  Modern systems virtualize memory, mapping it to physical memory so it can be shared among processes.&lt;br /&gt;
 - Interrupts: A mechanism used by the kernel that interrupts the CPU when other tasks are higher priority.&lt;br /&gt;
 - Signals: Inter-process communications.  A mechanism used by the kernel and processes to communicate with one another.&lt;br /&gt;
 - System Call: Specialized functions used by programs to request more resources from the kernel.&lt;br /&gt;
 - File: A hierarchical name with a value mapping (Key/Value pair)&lt;br /&gt;
 - Shell: Another program that is used to send system calls to the kernel or launch other programs.&lt;br /&gt;
 - File system: A set of files grouped together with a common hierarchical root.&lt;br /&gt;
 - Fragmentation: Variable sized memory allocation.&lt;br /&gt;
 - Internal Fragmentation: Space wasted in an allocation.&lt;br /&gt;
 - Concurrency: More than one thing happening at a time.&lt;br /&gt;
 - Atomic Variables: Variables that guarantee a strict ordering of operations.&lt;br /&gt;
 - Segmentation: Managing memory without paging.&lt;br /&gt;
 - Segments: A variable sized block of memory that can be placed in different parts of the address space.&lt;br /&gt;
 - Segfault: When a virtual address does not have a corresponding physical address.&lt;br /&gt;
 - mmap: The virtual address range corresponds to the contents of a file or RAM.&lt;br /&gt;
 - Concurrency: More than one thing is happening at the same time.&lt;br /&gt;
&lt;br /&gt;
Creating a process:&lt;br /&gt;
* fork() creates a process and execve() loads the binary to the new process.&lt;br /&gt;
** returns a process id&lt;br /&gt;
*** pid &amp;gt; 0, parent process&lt;br /&gt;
*** pid &amp;lt; 0, error&lt;br /&gt;
*** pid = 0, child process&lt;br /&gt;
&lt;br /&gt;
* When a parent does not deal with its child processes they become zombies&lt;br /&gt;
* If a parent dies before its children they become orphans that are re-parented by the OS&lt;br /&gt;
&lt;br /&gt;
* wait()&lt;br /&gt;
** suspends the current process until one, some, or all of its children have terminated&lt;br /&gt;
** wait() can be called anytime to check on the status of children&lt;br /&gt;
&lt;br /&gt;
IO redirection:&lt;br /&gt;
* &amp;gt;, direct to stdout&lt;br /&gt;
* &amp;lt;, direct to stdin&lt;br /&gt;
* |, connect the output of one process to the input of another process&lt;br /&gt;
* when a process starts it is given file descriptors to stdout, stdin, and stderr&lt;br /&gt;
&lt;br /&gt;
Inodes:&lt;br /&gt;
* Contain information about the blocks corresponding to the contents of a file on disk, its owner, and the file access permissions.&lt;br /&gt;
* A filename points to an inode&lt;br /&gt;
* The inode count represents all of the files and folders on disk&lt;br /&gt;
* Hard links create another name to the same inode number&lt;br /&gt;
** Only point to files within the same file system&lt;br /&gt;
* Symbolic links are files with their own inode&lt;br /&gt;
** Can point to files in other partitions or file systems&lt;br /&gt;
&lt;br /&gt;
Virtual Memory:&lt;br /&gt;
* Every process receives a memory map with virtual addresses that correspond to physical addresses.&lt;br /&gt;
&lt;br /&gt;
Memory Allocation Challenges:&lt;br /&gt;
* Need to have a contiguous address range&lt;br /&gt;
* Data Structures can not be moved once allocated&lt;br /&gt;
* Memory is constantly allocated and deallocated&lt;br /&gt;
&lt;br /&gt;
Solution to these challenges:&lt;br /&gt;
* Use fixed size chunks that can be stored anywhere&lt;br /&gt;
** Called a page in memory or a block on disk&lt;br /&gt;
** Sizes are always a power of 2 because addresses are indexed in bits&lt;br /&gt;
** The benefit: it removes the limitations on array sizes.&lt;br /&gt;
** Use a table to map virtual memory to physical memory -- called a page table&lt;br /&gt;
** In a 32 bit system: the top 20 bits are the page locations and the lower 12 bits are the page offset&lt;br /&gt;
&lt;br /&gt;
Concurrency:&lt;br /&gt;
* Challenge: keeping the shared state consistent; want deterministic behavior from concurrent computations&lt;br /&gt;
* Solution: Need mechanisms that bypass the memory hierarchy.&lt;br /&gt;
** Use filesystem locking primitives -&amp;gt; atomic variables -&amp;gt; semaphores&lt;br /&gt;
** Use signals to synchronize the shared state&lt;br /&gt;
&lt;br /&gt;
Segmentation:&lt;br /&gt;
* The physical address can be found by adding the segment register to the offset.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21084</id>
		<title>Operating Systems 2017F Lecture 3</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21084"/>
		<updated>2017-10-05T00:47:32Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* Adding the execve() system call to the mix */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 14, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec03-14Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec03/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
====Commands ====&lt;br /&gt;
*-wall: show all warning&lt;br /&gt;
*less: allow screen navigation, hit q to quit&lt;br /&gt;
&lt;br /&gt;
==== What is fork? ====&lt;br /&gt;
* Fork creates a new program but contains the same code (call the clone system call) and only argv[] and envp[] passed on to the new born program&lt;br /&gt;
&lt;br /&gt;
 - More on creating a process using fork().&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
  int child;&lt;br /&gt;
  int status;&lt;br /&gt;
  pid_t retval;&lt;br /&gt;
        &lt;br /&gt;
  child = fork();&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
  if (child == 0) {&lt;br /&gt;
  /* We&#039;re the child */&lt;br /&gt;
    sleep(3);&lt;br /&gt;
    printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
  /* We&#039;re the parent */&lt;br /&gt;
    retval = wait(&amp;amp;status);&lt;br /&gt;
    printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
            (int) retval, WEXITSTATUS(status));&lt;br /&gt;
  }&lt;br /&gt;
        &lt;br /&gt;
  return 42;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 - sleep(int)&lt;br /&gt;
   - causes the current process to do nothing for the specified number of seconds.&lt;br /&gt;
&lt;br /&gt;
 - pid_t = fork(void)&lt;br /&gt;
   - fork creates a clone of the parent process&lt;br /&gt;
   - pid is 0 when the child process is running and &amp;gt;0 when the parent process is running.  Both processes will return from the system call to fork().&lt;br /&gt;
&lt;br /&gt;
 - pid_t = wait(int * status)&lt;br /&gt;
   - this system call is equivalent to pid_t = waitpid(-1, &amp;amp;status, 0)&lt;br /&gt;
   - the wait system call suspends the current process until one of its children has terminated.&lt;br /&gt;
   - pid_t specifies which child to wait for.  Various options are available that define how to wait.&lt;br /&gt;
   - int* status holds the status of the wait system call.  There are various macros that define what the status can be.&lt;br /&gt;
&lt;br /&gt;
 - &#039;&#039;&#039;What happens when the newline character is removed from the printf statement?&#039;&#039;&#039;&lt;br /&gt;
   - printf holds the output in a buffer until it receives a newline character.  The result is the output does not print when expected. &lt;br /&gt;
   - The kernel is doing things as it is told, so the c library is at fault.&lt;br /&gt;
   - We could get the expected output if we bypass the c library using a system call: &amp;quot;write&amp;quot;&lt;br /&gt;
   - running an &amp;quot;strace&amp;quot; on the executable will show us the order in which the processes were run to help debug the problem.&lt;br /&gt;
	&lt;br /&gt;
 - &#039;&#039;&#039;What happens in the conditional?&#039;&#039;&#039;&lt;br /&gt;
   - When the parent process calls fork(), a child process is created and begins executing at the fork() statement.  The OS returns a value from fork() which indicates which process &lt;br /&gt;
     is currently running.&lt;br /&gt;
   - If fork() returns zero then the child sleeps for 3 seconds before printing.  The sleep system call forces the child process to do nothing for 3 seconds.&lt;br /&gt;
   - if fork() returns anything else, it is assumed to be the parent process.  In this case the wait() system call is run by the parent which causes the parent process to wait for its &lt;br /&gt;
     child to finish; then the printf executes and prints the child process id and its return value from main.  The macro WEXITSTATUS retrieves 42.&lt;br /&gt;
&lt;br /&gt;
==== What Happen to the child process after the parent process died? ====&lt;br /&gt;
*Every child process must have a currently running parent. When the parent process die, kernel collect the dead body(return value) and re-parent the process &lt;br /&gt;
* In the demo showed in class, “system d user” became its new parent&lt;br /&gt;
**Use command &amp;quot;Pstree&amp;quot; to show process hierarchy&lt;br /&gt;
* Every process must have a valid process parent.  Use &amp;quot;pstree&amp;quot; to see the tree structure&lt;br /&gt;
* When a parent dies before a child &amp;quot;init&amp;quot; will adopt every orphan on the system&lt;br /&gt;
&lt;br /&gt;
==== What is zombie process? ====&lt;br /&gt;
*When a process die it become &#039;zombie&#039; (s = sleep, z = zombie)&lt;br /&gt;
*We can use wait to be a &#039;good&#039; parent&lt;br /&gt;
&lt;br /&gt;
==== How to load a new binary manually====&lt;br /&gt;
*Use the execve command.&lt;br /&gt;
**We can fork child process to handle dangerous task (“Suicide Squad”), or handle all incoming request&lt;br /&gt;
&lt;br /&gt;
==== Manipulating environment variables====&lt;br /&gt;
*argc tells the number of argument in command line, while argv[] contains the actual command obtained in the command line&lt;br /&gt;
&lt;br /&gt;
=== Adding the execve() system call to the mix ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
   int child;&lt;br /&gt;
   int status;&lt;br /&gt;
   pid_t retval;&lt;br /&gt;
   int i;&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;You called me with %d arguments.\n&amp;quot;, argc);&lt;br /&gt;
        &lt;br /&gt;
   for (i=0; i&amp;lt;argc; i++) {&lt;br /&gt;
     printf(&amp;quot;Arg %d: %s\n&amp;quot;, i, argv[i]);&lt;br /&gt;
   }&lt;br /&gt;
        &lt;br /&gt;
   child = fork();&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
   if (child == 0) {&lt;br /&gt;
   /* We&#039;re the child */&lt;br /&gt;
                &lt;br /&gt;
     execve(&amp;quot;/bin/ls&amp;quot;, argv, envp);&lt;br /&gt;
     sleep(3);&lt;br /&gt;
     printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
   /* We&#039;re the parent */&lt;br /&gt;
      retval = wait(&amp;amp;status);&lt;br /&gt;
      printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
             (int) retval, WEXITSTATUS(status));&lt;br /&gt;
   }&lt;br /&gt;
        &lt;br /&gt;
   return 42;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 - int execve(const char *filename, char *const argv[],  char *const envp[])&lt;br /&gt;
   - this system call executes the program pointed to by filename&lt;br /&gt;
   - The child process becomes independent from its parent -- a new program&lt;br /&gt;
   - argv[] is an array of strings passed to the new program.  The values are loaded into the array by execve not the kernel.&lt;br /&gt;
   - envp[] is an array of strings of the form key=value which are passed as environment to the new program&lt;br /&gt;
&lt;br /&gt;
 - What happens when the if statement executes&lt;br /&gt;
   - execve creates a new program -- an independent process and passes arguments to the &amp;quot;ls&amp;quot; program.&lt;br /&gt;
   - execve stops the new process after it has completed.&lt;br /&gt;
&lt;br /&gt;
 - Some interesting points about main(int argc, char* argv[], char* envp[])&lt;br /&gt;
   - Notice that the size of the arrays are not defined.  We have to use argc to get this information.  Not good programming practice but is &lt;br /&gt;
     accepted because it is grandfathered from the early days of the c language.&lt;br /&gt;
   - arg[0] is always the name of the program.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21083</id>
		<title>Operating Systems 2017F Lecture 3</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21083"/>
		<updated>2017-10-05T00:46:48Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* What is fork? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 14, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec03-14Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec03/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
====Commands ====&lt;br /&gt;
*-wall: show all warning&lt;br /&gt;
*less: allow screen navigation, hit q to quit&lt;br /&gt;
&lt;br /&gt;
==== What is fork? ====&lt;br /&gt;
* Fork creates a new program but contains the same code (call the clone system call) and only argv[] and envp[] passed on to the new born program&lt;br /&gt;
&lt;br /&gt;
 - More on creating a process using fork().&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
  int child;&lt;br /&gt;
  int status;&lt;br /&gt;
  pid_t retval;&lt;br /&gt;
        &lt;br /&gt;
  child = fork();&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
  if (child == 0) {&lt;br /&gt;
  /* We&#039;re the child */&lt;br /&gt;
    sleep(3);&lt;br /&gt;
    printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
  /* We&#039;re the parent */&lt;br /&gt;
    retval = wait(&amp;amp;status);&lt;br /&gt;
    printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
            (int) retval, WEXITSTATUS(status));&lt;br /&gt;
  }&lt;br /&gt;
        &lt;br /&gt;
  return 42;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 - sleep(int)&lt;br /&gt;
   - causes the current process to do nothing for the specified number of seconds.&lt;br /&gt;
&lt;br /&gt;
 - pid_t = fork(void)&lt;br /&gt;
   - fork creates a clone of the parent process&lt;br /&gt;
   - pid is 0 when the child process is running and &amp;gt;0 when the parent process is running.  Both processes will return from the system call to fork().&lt;br /&gt;
&lt;br /&gt;
 - pid_t = wait(int * status)&lt;br /&gt;
   - this system call is equivalent to pid_t = waitpid(-1, &amp;amp;status, 0)&lt;br /&gt;
   - the wait system call suspends the current process until one of its children has terminated.&lt;br /&gt;
   - pid_t specifies which child to wait for.  Various options are available that define how to wait.&lt;br /&gt;
   - int* status holds the status of the wait system call.  There are various macros that define what the status can be.&lt;br /&gt;
&lt;br /&gt;
 - &#039;&#039;&#039;What happens when the newline character is removed from the printf statement?&#039;&#039;&#039;&lt;br /&gt;
   - printf holds the output in a buffer until it receives a newline character.  The result is the output does not print when expected. &lt;br /&gt;
   - The kernel is doing things as it is told, so the c library is at fault.&lt;br /&gt;
   - We could get the expected output if we bypass the c library using a system call: &amp;quot;write&amp;quot;&lt;br /&gt;
   - running an &amp;quot;strace&amp;quot; on the executable will show us the order in which the processes were run to help debug the problem.&lt;br /&gt;
	&lt;br /&gt;
 - &#039;&#039;&#039;What happens in the conditional?&#039;&#039;&#039;&lt;br /&gt;
   - When the parent process calls fork(), a child process is created and begins executing at the fork() statement.  The OS returns a value from fork() which indicates which process &lt;br /&gt;
     is currently running.&lt;br /&gt;
   - If fork() returns zero then the child sleeps for 3 seconds before printing.  The sleep system call forces the child process to do nothing for 3 seconds.&lt;br /&gt;
   - if fork() returns anything else, it is assumed to be the parent process.  In this case the wait() system call is run by the parent which causes the parent process to wait for its &lt;br /&gt;
     child to finish; then the printf executes and prints the child process id and its return value from main.  The macro WEXITSTATUS retrieves 42.&lt;br /&gt;
&lt;br /&gt;
==== What Happen to the child process after the parent process died? ====&lt;br /&gt;
*Every child process must have a currently running parent. When the parent process die, kernel collect the dead body(return value) and re-parent the process &lt;br /&gt;
* In the demo showed in class, “system d user” became its new parent&lt;br /&gt;
**Use command &amp;quot;Pstree&amp;quot; to show process hierarchy&lt;br /&gt;
* Every process must have a valid process parent.  Use &amp;quot;pstree&amp;quot; to see the tree structure&lt;br /&gt;
* When a parent dies before a child &amp;quot;init&amp;quot; will adopt every orphan on the system&lt;br /&gt;
&lt;br /&gt;
==== What is zombie process? ====&lt;br /&gt;
*When a process die it become &#039;zombie&#039; (s = sleep, z = zombie)&lt;br /&gt;
*We can use wait to be a &#039;good&#039; parent&lt;br /&gt;
&lt;br /&gt;
==== How to load a new binary manually====&lt;br /&gt;
*Use the execve command.&lt;br /&gt;
**We can fork child process to handle dangerous task (“Suicide Squad”), or handle all incoming request&lt;br /&gt;
&lt;br /&gt;
==== Manipulating environment variables====&lt;br /&gt;
*argc tells the number of argument in command line, while argv[] contains the actual command obtained in the command line&lt;br /&gt;
&lt;br /&gt;
=== Adding the execve() system call to the mix ===&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
   int child;&lt;br /&gt;
   int status;&lt;br /&gt;
   pid_t retval;&lt;br /&gt;
   int i;&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;You called me with %d arguments.\n&amp;quot;, argc);&lt;br /&gt;
        &lt;br /&gt;
   for (i=0; i&amp;lt;argc; i++) {&lt;br /&gt;
     printf(&amp;quot;Arg %d: %s\n&amp;quot;, i, argv[i]);&lt;br /&gt;
   }&lt;br /&gt;
        &lt;br /&gt;
   child = fork();&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
   if (child == 0) {&lt;br /&gt;
   /* We&#039;re the child */&lt;br /&gt;
                &lt;br /&gt;
     execve(&amp;quot;/bin/ls&amp;quot;, argv, envp);&lt;br /&gt;
     sleep(3);&lt;br /&gt;
     printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
   /* We&#039;re the parent */&lt;br /&gt;
      retval = wait(&amp;amp;status);&lt;br /&gt;
      printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
             (int) retval, WEXITSTATUS(status));&lt;br /&gt;
   }&lt;br /&gt;
        &lt;br /&gt;
   return 42;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 - int execve(const char *filename, char *const argv[],  char *const envp[])&lt;br /&gt;
   - this system call executes the program pointed to by filename&lt;br /&gt;
   - The child process becomes independent from its parent -- a new program&lt;br /&gt;
   - argv[] is an array of strings passed to the new program.  The values are loaded into the array by execve not the kernel.&lt;br /&gt;
   - envp[] is an array of strings of the form key=value which are passed as environment to the new program&lt;br /&gt;
&lt;br /&gt;
 - What happens when the if statement executes&lt;br /&gt;
   - execve creates a new program -- an independent process and passes arguments to the &amp;quot;ls&amp;quot; program.&lt;br /&gt;
   - execve stops the new process after it has completed.&lt;br /&gt;
&lt;br /&gt;
 - Some interesting points about main(int argc, char* argv[], char* envp[])&lt;br /&gt;
   - Notice that the size of the arrays are not defined.  We have to use argc to get this information.  Not good programming practice but is &lt;br /&gt;
     accepted because it is grandfathered from the early days of the c language.&lt;br /&gt;
   - arg[0] is always the name of the program.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_5&amp;diff=21082</id>
		<title>Operating Systems 2017F Lecture 5</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_5&amp;diff=21082"/>
		<updated>2017-10-05T00:44:18Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* Notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 21, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec05-21Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec05/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
====IO Redirection====&lt;br /&gt;
*The &amp;gt; operator output to a location&lt;br /&gt;
**Eg. Ls &amp;gt; foo.txt&lt;br /&gt;
&lt;br /&gt;
*The | operator connect the output of the 1st program to the input of the 2nd program&lt;br /&gt;
**Eg. Shuf foo.txt | shuf &amp;gt; shuf2.txt (pipe operater connect output of shuf foo.txt to input of shuf then output to shuf2.txt)&lt;br /&gt;
&lt;br /&gt;
*File usually comes with standard input (0), standard output(1),standard error(error message, port 2). This defined when program started&lt;br /&gt;
**Ls foo &amp;gt; test.txt 2 &amp;gt;error.txt: redirect error message (port 2) of foo to error.txt&lt;br /&gt;
*Ls foo&amp;gt;&amp;amp; all.txt: redirect everything to output file&lt;br /&gt;
**Bc -l: This command bring up the calculater&lt;br /&gt;
*The convention is 3 file descriptors are available once the system boots.  They can be accessed by a shell and used to send data in both directions.&lt;br /&gt;
**file descriptor 0 is stdin&lt;br /&gt;
**file descriptor 1 is stdout&lt;br /&gt;
**file descriptor 2 is stderr&lt;br /&gt;
*redirections is accomplished using the &amp;gt; (redirect to) or &amp;lt; (redirect from)&lt;br /&gt;
**example: ls &amp;gt; foo.txt creates a file called foo.txt and puts the result of ls in it&lt;br /&gt;
**example: ls foo &amp;gt; test.txt 2&amp;gt; errors.txt will generate errors because ls won&#039;t be able to find foo.  In this case nothing will be put into test.txt instead the resulting error will be sent to errors.txt. 2&amp;gt; is the convention for selecting file descriptor 2.&lt;br /&gt;
*using &amp;gt;&amp;amp; will merge stdout and stderr&lt;br /&gt;
*The pipe | operator&lt;br /&gt;
**This operator allows us to join output from one process sending the data to another process.&lt;br /&gt;
**example: seq 1 100 num.txt | shuf &amp;gt; shuf2.txt&lt;br /&gt;
***The result is the sequence of numbers from 1 to 100 are put in num.txt then sent to shuf to be &amp;quot;shuffled&amp;quot; and finally redirected to shuf2.txt&lt;br /&gt;
&lt;br /&gt;
====Manipulating environment variables====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(int argc, char *argv[], char *envp[]){&lt;br /&gt;
While (envp[i] != NULL) {&lt;br /&gt;
     If (strcmp(“User=“, envp[i], 5){&lt;br /&gt;
         printf(“%s\n”, envp[i]);&lt;br /&gt;
	 char *username = envp[i] +5;  //pointer arithmetic &lt;br /&gt;
     }&lt;br /&gt;
     I++;&lt;br /&gt;
}&lt;br /&gt;
printf (“%s\n”, username);&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Getopt: a better way to find environmental variable&lt;br /&gt;
*&#039;&#039;&#039;How many are there?&#039;&#039;&#039;&lt;br /&gt;
**arg c tells us how many are in argv[] not envp[]&lt;br /&gt;
**we can look at all of the environment variables using env in the shell -- There are a lot!&lt;br /&gt;
**Accessing argv[] and envp[] from a c programming can be accomplished using the unistd.h library&lt;br /&gt;
***getopt for manipulating argv[]&lt;br /&gt;
***getenv for manipulating envp[]&lt;br /&gt;
&lt;br /&gt;
====Signals====&lt;br /&gt;
*Kill: send a signal to destroy a program&lt;br /&gt;
**Kill -stop 5617(This stop a progam)  and   Kill -cont 5617(resume a program)&lt;br /&gt;
**Sigkill, sigterm (ctrl+c),  sigstop (ctrl+z), sigpipe (when | died), sighup (when close terminal window)&lt;br /&gt;
**Sigchild(when a child process terminated),&lt;br /&gt;
*Signals allow us to communicate with other processes through the kernel.  The signal is a way to alert other processes that some event has happened giving the process some time to react.&lt;br /&gt;
**for example the kill command sends a signal that can suspend or terminate a running process&lt;br /&gt;
***kill -STOP pid or kill - CONT pid&lt;br /&gt;
**use man 7 signal to see the list of available signals&lt;br /&gt;
***SIGHUP: tells the process that the modem has just hung-up&lt;br /&gt;
***SIGCHLD: is a signal that gets sent when a child process terminates&lt;br /&gt;
***SIGUSR1: is a user defined signal&lt;br /&gt;
*sigaction() is a programming tool that allows us to interact with signals&lt;br /&gt;
**It is a structure that contains function pointers -- we have to define these functions in our code&lt;br /&gt;
&lt;br /&gt;
*Implementing a shell&lt;br /&gt;
**What is the best strategy for reading and understanding code?&lt;br /&gt;
***Start with main or where execution starts.  Most often we won&#039;t have a main, just a large body of code.&lt;br /&gt;
***temporarily ignore variable definitions until they are required&lt;br /&gt;
***Notice the different kinds of control structures and conditionals and start reviewing the code here.  Examine the code line by line.&lt;br /&gt;
*Example of a shell program.  What happens in the code?&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #define BUFFER_SIZE 1&amp;lt;&amp;lt;16&lt;br /&gt;
 #define ARR_SIZE 1&amp;lt;&amp;lt;16&lt;br /&gt;
	&lt;br /&gt;
 void parse_args(char *buffer, char** args, &lt;br /&gt;
      size_t args_size, size_t *nargs)&lt;br /&gt;
 {&lt;br /&gt;
   char *buf_args[args_size]; /* You need C99 */&lt;br /&gt;
   char **cp;&lt;br /&gt;
   char *wbuf;&lt;br /&gt;
   size_t i, j;&lt;br /&gt;
	    &lt;br /&gt;
   wbuf=buffer;&lt;br /&gt;
   buf_args[0]=buffer; &lt;br /&gt;
   args[0] =buffer;&lt;br /&gt;
	    &lt;br /&gt;
   for(cp=buf_args; (*cp=strsep(&amp;amp;wbuf, &amp;quot; \n\t&amp;quot;)) != NULL ;){&lt;br /&gt;
     if ((*cp != &#039;\0&#039;) &amp;amp;&amp;amp; (++cp &amp;gt;= &amp;amp;buf_args[args_size]))&lt;br /&gt;
       break;&lt;br /&gt;
    }&lt;br /&gt;
	    &lt;br /&gt;
    for (j=i=0; buf_args[i]!=NULL; i++){&lt;br /&gt;
      if(strlen(buf_args[i])&amp;gt;0)&lt;br /&gt;
        args[j++]=buf_args[i];&lt;br /&gt;
    }&lt;br /&gt;
	    &lt;br /&gt;
    *nargs=j;&lt;br /&gt;
    args[j]=NULL;&lt;br /&gt;
 } &lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
 int main(int argc, char *argv[], char *envp[]){&lt;br /&gt;
   char buffer[BUFFER_SIZE];&lt;br /&gt;
   char *args[ARR_SIZE];&lt;br /&gt;
	&lt;br /&gt;
   int *ret_status;&lt;br /&gt;
   size_t nargs;&lt;br /&gt;
   pid_t pid;&lt;br /&gt;
	    &lt;br /&gt;
   while(1){&lt;br /&gt;
     printf(&amp;quot;$ &amp;quot;);&lt;br /&gt;
     fgets(buffer, BUFFER_SIZE, stdin);&lt;br /&gt;
     parse_args(buffer, args, ARR_SIZE, &amp;amp;nargs); &lt;br /&gt;
	&lt;br /&gt;
     if (nargs==0) continue;&lt;br /&gt;
       if (!strcmp(args[0], &amp;quot;exit&amp;quot; )) exit(0);       &lt;br /&gt;
         pid = fork();&lt;br /&gt;
         if (pid){&lt;br /&gt;
           printf(&amp;quot;Waiting for child (%d)\n&amp;quot;, pid);&lt;br /&gt;
           pid = wait(ret_status);&lt;br /&gt;
           printf(&amp;quot;Child (%d) finished\n&amp;quot;, pid);&lt;br /&gt;
         } else {&lt;br /&gt;
           if( execvp(args[0], args)) {&lt;br /&gt;
             puts(strerror(errno));&lt;br /&gt;
             exit(127);&lt;br /&gt;
           }&lt;br /&gt;
       }&lt;br /&gt;
     }    &lt;br /&gt;
     return 0;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Start in main at the infinite while loop&lt;br /&gt;
**printf prints the shell prompt&lt;br /&gt;
**parse-args takes the command line arguments it receives from fgets and places these values in the args[] array.  it  also returns the total number of arguments received via nargs.  At     this point understanding all of the details as to how this function works is not necessary.  To get the full picture we would have to examine the code&#039;s fine details which takes time.&lt;br /&gt;
*After the aguments have been parsed, check to see if there are arguments to work with and is the argument exit.  If no arguments are entered then jump to the start of the loop; if the   argument is &#039;exit&#039; then quit the program.&lt;br /&gt;
**The conditional is where all of the work gets done.  Any argument other than &#039;none&#039; or &#039;exit&#039; cause a fork().  A child process is cloned and the parent is made to wait until the child   process finishes.  The execvp runs the program requested using the entered argument.  An example would be &#039;ls&#039;; in this case the child process would run the ls program.&lt;br /&gt;
***If the argument is not understood then an error results and is printed stdout and the child process terminates.  Note that the error string is printed from errno.&lt;br /&gt;
*1 &amp;lt;&amp;lt; 16 is interesting.  it is a left shift operator that computes 65536.  The most significant bit in a 16 bit number is set to 1.  It&#039;s the same as saying 2^16.  Defining this statement in a preprocessor definition means that it runs prior to compilation possibly saving some time.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_5&amp;diff=21081</id>
		<title>Operating Systems 2017F Lecture 5</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_5&amp;diff=21081"/>
		<updated>2017-10-05T00:28:08Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* Signals */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 21, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec05-21Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec05/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
====IO Redirection====&lt;br /&gt;
*The &amp;gt; operator output to a location&lt;br /&gt;
**Eg. Ls &amp;gt; foo.txt&lt;br /&gt;
&lt;br /&gt;
*The | operator connect the output of the 1st program to the input of the 2nd program&lt;br /&gt;
**Eg. Shuf foo.txt | shuf &amp;gt; shuf2.txt (pipe operater connect output of shuf foo.txt to input of shuf then output to shuf2.txt)&lt;br /&gt;
&lt;br /&gt;
*File usually comes with standard input (0), standard output(1),standard error(error message, port 2). This defined when program started&lt;br /&gt;
**Ls foo &amp;gt; test.txt 2 &amp;gt;error.txt: redirect error message (port 2) of foo to error.txt&lt;br /&gt;
*Ls foo&amp;gt;&amp;amp; all.txt: redirect everything to output file&lt;br /&gt;
**Bc -l: This command bring up the calculater&lt;br /&gt;
*The convention is 3 file descriptors are available once the system boots.  They can be accessed by a shell and used to send data in both directions.&lt;br /&gt;
**file descriptor 0 is stdin&lt;br /&gt;
**file descriptor 1 is stdout&lt;br /&gt;
**file descriptor 2 is stderr&lt;br /&gt;
*redirections is accomplished using the &amp;gt; (redirect to) or &amp;lt; (redirect from)&lt;br /&gt;
**example: ls &amp;gt; foo.txt creates a file called foo.txt and puts the result of ls in it&lt;br /&gt;
**example: ls foo &amp;gt; test.txt 2&amp;gt; errors.txt will generate errors because ls won&#039;t be able to find foo.  In this case nothing will be put into test.txt instead the resulting error will be sent to errors.txt. 2&amp;gt; is the convention for selecting file descriptor 2.&lt;br /&gt;
*using &amp;gt;&amp;amp; will merge stdout and stderr&lt;br /&gt;
*The pipe | operator&lt;br /&gt;
**This operator allows us to join output from one process sending the data to another process.&lt;br /&gt;
**example: seq 1 100 num.txt | shuf &amp;gt; shuf2.txt&lt;br /&gt;
***The result is the sequence of numbers from 1 to 100 are put in num.txt then sent to shuf to be &amp;quot;shuffled&amp;quot; and finally redirected to shuf2.txt&lt;br /&gt;
&lt;br /&gt;
====Manipulating environment variables====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(int argc, char *argv[], char *envp[]){&lt;br /&gt;
While (envp[i] != NULL) {&lt;br /&gt;
     If (strcmp(“User=“, envp[i], 5){&lt;br /&gt;
         printf(“%s\n”, envp[i]);&lt;br /&gt;
	 char *username = envp[i] +5;  //pointer arithmetic &lt;br /&gt;
     }&lt;br /&gt;
     I++;&lt;br /&gt;
}&lt;br /&gt;
printf (“%s\n”, username);&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Getopt: a better way to find environmental variable&lt;br /&gt;
*&#039;&#039;&#039;How many are there?&#039;&#039;&#039;&lt;br /&gt;
**arg c tells us how many are in argv[] not envp[]&lt;br /&gt;
**we can look at all of the environment variables using env in the shell -- There are a lot!&lt;br /&gt;
**Accessing argv[] and envp[] from a c programming can be accomplished using the unistd.h library&lt;br /&gt;
***getopt for manipulating argv[]&lt;br /&gt;
***getenv for manipulating envp[]&lt;br /&gt;
&lt;br /&gt;
====Signals====&lt;br /&gt;
*Kill: send a signal to destroy a program&lt;br /&gt;
**Kill -stop 5617(This stop a progam)  and   Kill -cont 5617(resume a program)&lt;br /&gt;
**Sigkill, sigterm (ctrl+c),  sigstop (ctrl+z), sigpipe (when | died), sighup (when close terminal window)&lt;br /&gt;
**Sigchild(when a child process terminated),&lt;br /&gt;
*Signals allow us to communicate with other processes through the kernel.  The signal is a way to alert other processes that some event has happened giving the process some time to react.&lt;br /&gt;
**for example the kill command sends a signal that can suspend or terminate a running process&lt;br /&gt;
***kill -STOP pid or kill - CONT pid&lt;br /&gt;
**use man 7 signal to see the list of available signals&lt;br /&gt;
***SIGHUP: tells the process that the modem has just hung-up&lt;br /&gt;
***SIGCHLD: is a signal that gets sent when a child process terminates&lt;br /&gt;
***SIGUSR1: is a user defined signal&lt;br /&gt;
*sigaction() is a programming tool that allows us to interact with signals&lt;br /&gt;
**It is a structure that contains function pointers -- we have to define these functions in our code&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_5&amp;diff=21080</id>
		<title>Operating Systems 2017F Lecture 5</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_5&amp;diff=21080"/>
		<updated>2017-10-05T00:26:19Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* Manipulating environment variables */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 21, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec05-21Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec05/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
====IO Redirection====&lt;br /&gt;
*The &amp;gt; operator output to a location&lt;br /&gt;
**Eg. Ls &amp;gt; foo.txt&lt;br /&gt;
&lt;br /&gt;
*The | operator connect the output of the 1st program to the input of the 2nd program&lt;br /&gt;
**Eg. Shuf foo.txt | shuf &amp;gt; shuf2.txt (pipe operater connect output of shuf foo.txt to input of shuf then output to shuf2.txt)&lt;br /&gt;
&lt;br /&gt;
*File usually comes with standard input (0), standard output(1),standard error(error message, port 2). This defined when program started&lt;br /&gt;
**Ls foo &amp;gt; test.txt 2 &amp;gt;error.txt: redirect error message (port 2) of foo to error.txt&lt;br /&gt;
*Ls foo&amp;gt;&amp;amp; all.txt: redirect everything to output file&lt;br /&gt;
**Bc -l: This command bring up the calculater&lt;br /&gt;
*The convention is 3 file descriptors are available once the system boots.  They can be accessed by a shell and used to send data in both directions.&lt;br /&gt;
**file descriptor 0 is stdin&lt;br /&gt;
**file descriptor 1 is stdout&lt;br /&gt;
**file descriptor 2 is stderr&lt;br /&gt;
*redirections is accomplished using the &amp;gt; (redirect to) or &amp;lt; (redirect from)&lt;br /&gt;
**example: ls &amp;gt; foo.txt creates a file called foo.txt and puts the result of ls in it&lt;br /&gt;
**example: ls foo &amp;gt; test.txt 2&amp;gt; errors.txt will generate errors because ls won&#039;t be able to find foo.  In this case nothing will be put into test.txt instead the resulting error will be sent to errors.txt. 2&amp;gt; is the convention for selecting file descriptor 2.&lt;br /&gt;
*using &amp;gt;&amp;amp; will merge stdout and stderr&lt;br /&gt;
*The pipe | operator&lt;br /&gt;
**This operator allows us to join output from one process sending the data to another process.&lt;br /&gt;
**example: seq 1 100 num.txt | shuf &amp;gt; shuf2.txt&lt;br /&gt;
***The result is the sequence of numbers from 1 to 100 are put in num.txt then sent to shuf to be &amp;quot;shuffled&amp;quot; and finally redirected to shuf2.txt&lt;br /&gt;
&lt;br /&gt;
====Manipulating environment variables====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(int argc, char *argv[], char *envp[]){&lt;br /&gt;
While (envp[i] != NULL) {&lt;br /&gt;
     If (strcmp(“User=“, envp[i], 5){&lt;br /&gt;
         printf(“%s\n”, envp[i]);&lt;br /&gt;
	 char *username = envp[i] +5;  //pointer arithmetic &lt;br /&gt;
     }&lt;br /&gt;
     I++;&lt;br /&gt;
}&lt;br /&gt;
printf (“%s\n”, username);&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Getopt: a better way to find environmental variable&lt;br /&gt;
*&#039;&#039;&#039;How many are there?&#039;&#039;&#039;&lt;br /&gt;
**arg c tells us how many are in argv[] not envp[]&lt;br /&gt;
**we can look at all of the environment variables using env in the shell -- There are a lot!&lt;br /&gt;
**Accessing argv[] and envp[] from a c programming can be accomplished using the unistd.h library&lt;br /&gt;
***getopt for manipulating argv[]&lt;br /&gt;
***getenv for manipulating envp[]&lt;br /&gt;
&lt;br /&gt;
====Signals====&lt;br /&gt;
*Kill: send a signal to destroy a program&lt;br /&gt;
**Kill -stop 5617(This stop a progam)  and   Kill -cont 5617(resume a program)&lt;br /&gt;
**Sigkill, sigterm (ctrl+c),  sigstop (ctrl+z), sigpipe (when | died), sighup (when close terminal window)&lt;br /&gt;
**Sigchild(when a child process terminated),&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_5&amp;diff=21079</id>
		<title>Operating Systems 2017F Lecture 5</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_5&amp;diff=21079"/>
		<updated>2017-10-05T00:23:54Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* IO Redirection */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 21, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec05-21Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec05/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
====IO Redirection====&lt;br /&gt;
*The &amp;gt; operator output to a location&lt;br /&gt;
**Eg. Ls &amp;gt; foo.txt&lt;br /&gt;
&lt;br /&gt;
*The | operator connect the output of the 1st program to the input of the 2nd program&lt;br /&gt;
**Eg. Shuf foo.txt | shuf &amp;gt; shuf2.txt (pipe operater connect output of shuf foo.txt to input of shuf then output to shuf2.txt)&lt;br /&gt;
&lt;br /&gt;
*File usually comes with standard input (0), standard output(1),standard error(error message, port 2). This defined when program started&lt;br /&gt;
**Ls foo &amp;gt; test.txt 2 &amp;gt;error.txt: redirect error message (port 2) of foo to error.txt&lt;br /&gt;
*Ls foo&amp;gt;&amp;amp; all.txt: redirect everything to output file&lt;br /&gt;
**Bc -l: This command bring up the calculater&lt;br /&gt;
*The convention is 3 file descriptors are available once the system boots.  They can be accessed by a shell and used to send data in both directions.&lt;br /&gt;
**file descriptor 0 is stdin&lt;br /&gt;
**file descriptor 1 is stdout&lt;br /&gt;
**file descriptor 2 is stderr&lt;br /&gt;
*redirections is accomplished using the &amp;gt; (redirect to) or &amp;lt; (redirect from)&lt;br /&gt;
**example: ls &amp;gt; foo.txt creates a file called foo.txt and puts the result of ls in it&lt;br /&gt;
**example: ls foo &amp;gt; test.txt 2&amp;gt; errors.txt will generate errors because ls won&#039;t be able to find foo.  In this case nothing will be put into test.txt instead the resulting error will be sent to errors.txt. 2&amp;gt; is the convention for selecting file descriptor 2.&lt;br /&gt;
*using &amp;gt;&amp;amp; will merge stdout and stderr&lt;br /&gt;
*The pipe | operator&lt;br /&gt;
**This operator allows us to join output from one process sending the data to another process.&lt;br /&gt;
**example: seq 1 100 num.txt | shuf &amp;gt; shuf2.txt&lt;br /&gt;
***The result is the sequence of numbers from 1 to 100 are put in num.txt then sent to shuf to be &amp;quot;shuffled&amp;quot; and finally redirected to shuf2.txt&lt;br /&gt;
&lt;br /&gt;
====Manipulating environment variables====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(int argc, char *argv[], char *envp[]){&lt;br /&gt;
While (envp[i] != NULL) {&lt;br /&gt;
     If (strcmp(“User=“, envp[i], 5){&lt;br /&gt;
         printf(“%s\n”, envp[i]);&lt;br /&gt;
	 char *username = envp[i] +5;  //pointer arithmetic &lt;br /&gt;
     }&lt;br /&gt;
     I++;&lt;br /&gt;
}&lt;br /&gt;
printf (“%s\n”, username);&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Getopt: a better way to find environmental variable&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Signals====&lt;br /&gt;
*Kill: send a signal to destroy a program&lt;br /&gt;
**Kill -stop 5617(This stop a progam)  and   Kill -cont 5617(resume a program)&lt;br /&gt;
**Sigkill, sigterm (ctrl+c),  sigstop (ctrl+z), sigpipe (when | died), sighup (when close terminal window)&lt;br /&gt;
**Sigchild(when a child process terminated),&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_4&amp;diff=21078</id>
		<title>Operating Systems 2017F Lecture 4</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_4&amp;diff=21078"/>
		<updated>2017-10-05T00:19:46Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 19, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec04-19Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
 - The textbook&lt;br /&gt;
   - Is just for reference as supporting material.  The class lectures will not follow the text.&lt;br /&gt;
&lt;br /&gt;
 - Some concepts from the tutorial&lt;br /&gt;
   - Running an ltrace on a statically compiled program prints an error.  The error just explains that the file was not dynamically compiled &amp;quot;couldn&#039;t find .dynsym&amp;quot;&lt;br /&gt;
   - What is obj code?&lt;br /&gt;
     - machine code.  It is important to have a good mental picture of what is happening.  Notice that addresses are unique for each process.&lt;br /&gt;
   - The point is that the system is not clean, it is complicated and not well understood.&lt;br /&gt;
&lt;br /&gt;
 - How to build a Linux machine using virtualbox and an iso image (concepts)&lt;br /&gt;
   - iso: international organization for standardization for optical disk media&lt;br /&gt;
     - it&#039;s a cd or dvd&lt;br /&gt;
   - The VM uses a dynamically allocated hard drive.  It is a file that has a filesystem and it grows and shrinks as needed.&lt;br /&gt;
   - Hard drive partition: Creates memory segments on the disk that is used to store different types of data.&lt;br /&gt;
   - Memory swapping: The processor uses hard disk space when it runs out of RAM.&lt;br /&gt;
&lt;br /&gt;
 - Things about linux&lt;br /&gt;
   - &#039;&#039;&#039;Why is the kernel split?&#039;&#039;&#039;&lt;br /&gt;
     - So the various hardware modules can be added to the system when the hardware is installed&lt;br /&gt;
     - We can see the modules using ls mod or cd /sys/proc&lt;br /&gt;
   - Environment Variables&lt;br /&gt;
     - TERM or USER for example.  They are capitalized by convention.  The significance is that these variables belong to a process (like a shell).  &lt;br /&gt;
     - Child processes inherit the environment variables from the parent; envp[] stores the values of these variables.&lt;br /&gt;
 - Things that can be done in a shell&lt;br /&gt;
   - We can run programming commands directly in the shell&lt;br /&gt;
     - things like loops and conditionals&lt;br /&gt;
     - $ defines a variable&lt;br /&gt;
     - echo is the shell&#039;s version of printf&lt;br /&gt;
 - ssh&lt;br /&gt;
   - used to access remote machines using a secure shell&lt;br /&gt;
   - The ssh uses a file that stores authorized keys.  If a user has a key for the remote terminal then they do not require a password.&lt;br /&gt;
   - certificates&lt;br /&gt;
     - used by websites to maintain security&lt;br /&gt;
     - A secure website encrypts the data so it can&#039;t be viewed by hackers.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21077</id>
		<title>Operating Systems 2017F Lecture 3</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21077"/>
		<updated>2017-10-05T00:11:59Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* Notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 14, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec03-14Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec03/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
====Commands ====&lt;br /&gt;
*-wall: show all warning&lt;br /&gt;
*less: allow screen navigation, hit q to quit&lt;br /&gt;
&lt;br /&gt;
==== What is fork? ====&lt;br /&gt;
* Fork creates a new program but contains the same code (call the clone system call) and only argv[] and envp[] passed on to the new born program&lt;br /&gt;
&lt;br /&gt;
 - More on creating a process using fork().&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
  int child;&lt;br /&gt;
  int status;&lt;br /&gt;
  pid_t retval;&lt;br /&gt;
        &lt;br /&gt;
  child = fork();&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
  if (child == 0) {&lt;br /&gt;
  /* We&#039;re the child */&lt;br /&gt;
    sleep(3);&lt;br /&gt;
    printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
  /* We&#039;re the parent */&lt;br /&gt;
    retval = wait(&amp;amp;status);&lt;br /&gt;
    printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
            (int) retval, WEXITSTATUS(status));&lt;br /&gt;
  }&lt;br /&gt;
        &lt;br /&gt;
  return 42;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
 - sleep(int)&lt;br /&gt;
   - causes the current process to do nothing for the specified number of seconds.&lt;br /&gt;
&lt;br /&gt;
 - pid_t = fork(void)&lt;br /&gt;
   - fork creates a clone of the parent process&lt;br /&gt;
   - pid is 0 when the child process is running and &amp;gt;0 when the parent process is running.  Both processes will return from the system call to fork().&lt;br /&gt;
&lt;br /&gt;
 - pid_t = wait(int * status)&lt;br /&gt;
   - this system call is equivalent to pid_t = waitpid(-1, &amp;amp;status, 0)&lt;br /&gt;
   - the wait system call suspends the current process until one of its children has terminated.&lt;br /&gt;
   - pid_t specifies which child to wait for.  Various options are available that define how to wait.&lt;br /&gt;
   - int* status holds the status of the wait system call.  There are various macros that define what the status can be.&lt;br /&gt;
&lt;br /&gt;
 - &#039;&#039;&#039;What happens when the newline character is removed from the printf statement?&#039;&#039;&#039;&lt;br /&gt;
   - printf holds the output in a buffer until it receives a newline character.  The result is the output does not print when expected. &lt;br /&gt;
   - The kernel is doing things as it is told, so the c library is at fault.&lt;br /&gt;
   - We could get the expected output if we bypass the c library using a system call: &amp;quot;write&amp;quot;&lt;br /&gt;
   - running an &amp;quot;strace&amp;quot; on the executable will show us the order in which the processes were run to help debug the problem.&lt;br /&gt;
	&lt;br /&gt;
 - &#039;&#039;&#039;What happens in the conditional?&#039;&#039;&#039;&lt;br /&gt;
   - When the parent process calls fork(), a child process is created and begins executing at the fork() statement.  The OS returns a value from fork() which indicates which process &lt;br /&gt;
     is currently running.&lt;br /&gt;
   - If fork() returns zero then the child sleeps for 3 seconds before printing.  The sleep system call forces the child process to do nothing for 3 seconds.&lt;br /&gt;
   - if fork() returns anything else, it is assumed to be the parent process.  In this case the wait() system call is run by the parent which causes the parent process to wait for its &lt;br /&gt;
     child to finish; then the printf executes and prints the child process id and its return value from main.  The macro WEXITSTATUS retrieves 42.&lt;br /&gt;
&lt;br /&gt;
==== What Happen to the child process after the parent process died? ====&lt;br /&gt;
*Every child process must have a currently running parent. When the parent process die, kernel collect the dead body(return value) and re-parent the process &lt;br /&gt;
* In the demo showed in class, “system d user” became its new parent&lt;br /&gt;
**Use command &amp;quot;Pstree&amp;quot; to show process hierarchy&lt;br /&gt;
* Every process must have a valid process parent.  Use &amp;quot;pstree&amp;quot; to see the tree structure&lt;br /&gt;
* When a parent dies before a child &amp;quot;init&amp;quot; will adopt every orphan on the system&lt;br /&gt;
&lt;br /&gt;
==== What is zombie process? ====&lt;br /&gt;
*When a process die it become &#039;zombie&#039; (s = sleep, z = zombie)&lt;br /&gt;
*We can use wait to be a &#039;good&#039; parent&lt;br /&gt;
&lt;br /&gt;
==== How to load a new binary manually====&lt;br /&gt;
*Use the execve command.&lt;br /&gt;
**We can fork child process to handle dangerous task (“Suicide Squad”), or handle all incoming request&lt;br /&gt;
&lt;br /&gt;
==== Manipulating environment variables====&lt;br /&gt;
*argc tells the number of argument in command line, while argv[] contains the actual command obtained in the command line&lt;br /&gt;
&lt;br /&gt;
=== Adding the execve() system call to the mix ===&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
   int child;&lt;br /&gt;
   int status;&lt;br /&gt;
   pid_t retval;&lt;br /&gt;
   int i;&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;You called me with %d arguments.\n&amp;quot;, argc);&lt;br /&gt;
        &lt;br /&gt;
   for (i=0; i&amp;lt;argc; i++) {&lt;br /&gt;
     printf(&amp;quot;Arg %d: %s\n&amp;quot;, i, argv[i]);&lt;br /&gt;
   }&lt;br /&gt;
        &lt;br /&gt;
   child = fork();&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
   if (child == 0) {&lt;br /&gt;
   /* We&#039;re the child */&lt;br /&gt;
                &lt;br /&gt;
     execve(&amp;quot;/bin/ls&amp;quot;, argv, envp);&lt;br /&gt;
     sleep(3);&lt;br /&gt;
     printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
   } else {&lt;br /&gt;
   /* We&#039;re the parent */&lt;br /&gt;
      retval = wait(&amp;amp;status);&lt;br /&gt;
      printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
             (int) retval, WEXITSTATUS(status));&lt;br /&gt;
   }&lt;br /&gt;
        &lt;br /&gt;
   return 42;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 - int execve(const char *filename, char *const argv[],  char *const envp[])&lt;br /&gt;
   - this system call executes the program pointed to by filename&lt;br /&gt;
   - The child process becomes independent from its parent -- a new program&lt;br /&gt;
   - argv[] is an array of strings passed to the new program.  The values are loaded into the array by execve not the kernel.&lt;br /&gt;
   - envp[] is an array of strings of the form key=value which are passed as environment to the new program&lt;br /&gt;
&lt;br /&gt;
 - What happens when the if statement executes&lt;br /&gt;
   - execve creates a new program -- an independent process and passes arguments to the &amp;quot;ls&amp;quot; program.&lt;br /&gt;
   - execve stops the new process after it has completed.&lt;br /&gt;
&lt;br /&gt;
 - Some interesting points about main(int argc, char* argv[], char* envp[])&lt;br /&gt;
   - Notice that the size of the arrays are not defined.  We have to use argc to get this information.  Not good programming practice but is &lt;br /&gt;
     accepted because it is grandfathered from the early days of the c language.&lt;br /&gt;
   - arg[0] is always the name of the program.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21076</id>
		<title>Operating Systems 2017F Lecture 3</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21076"/>
		<updated>2017-10-05T00:04:38Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* What Happen to the child process after the parent process died? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 14, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec03-14Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec03/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
====Commands ====&lt;br /&gt;
*-wall: show all warning&lt;br /&gt;
*less: allow screen navigation, hit q to quit&lt;br /&gt;
&lt;br /&gt;
==== What is fork? ====&lt;br /&gt;
* Fork creates a new program but contains the same code (call the clone system call) and only argv[] and envp[] passed on to the new born program&lt;br /&gt;
&lt;br /&gt;
 - More on creating a process using fork().&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
  int child;&lt;br /&gt;
  int status;&lt;br /&gt;
  pid_t retval;&lt;br /&gt;
        &lt;br /&gt;
  child = fork();&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
  if (child == 0) {&lt;br /&gt;
  /* We&#039;re the child */&lt;br /&gt;
    sleep(3);&lt;br /&gt;
    printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
  /* We&#039;re the parent */&lt;br /&gt;
    retval = wait(&amp;amp;status);&lt;br /&gt;
    printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
            (int) retval, WEXITSTATUS(status));&lt;br /&gt;
  }&lt;br /&gt;
        &lt;br /&gt;
  return 42;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
 - sleep(int)&lt;br /&gt;
   - causes the current process to do nothing for the specified number of seconds.&lt;br /&gt;
&lt;br /&gt;
 - pid_t = fork(void)&lt;br /&gt;
   - fork creates a clone of the parent process&lt;br /&gt;
   - pid is 0 when the child process is running and &amp;gt;0 when the parent process is running.  Both processes will return from the system call to fork().&lt;br /&gt;
&lt;br /&gt;
 - pid_t = wait(int * status)&lt;br /&gt;
   - this system call is equivalent to pid_t = waitpid(-1, &amp;amp;status, 0)&lt;br /&gt;
   - the wait system call suspends the current process until one of its children has terminated.&lt;br /&gt;
   - pid_t specifies which child to wait for.  Various options are available that define how to wait.&lt;br /&gt;
   - int* status holds the status of the wait system call.  There are various macros that define what the status can be.&lt;br /&gt;
&lt;br /&gt;
 - &#039;&#039;&#039;What happens when the newline character is removed from the printf statement?&#039;&#039;&#039;&lt;br /&gt;
   - printf holds the output in a buffer until it receives a newline character.  The result is the output does not print when expected. &lt;br /&gt;
   - The kernel is doing things as it is told, so the c library is at fault.&lt;br /&gt;
   - We could get the expected output if we bypass the c library using a system call: &amp;quot;write&amp;quot;&lt;br /&gt;
   - running an &amp;quot;strace&amp;quot; on the executable will show us the order in which the processes were run to help debug the problem.&lt;br /&gt;
	&lt;br /&gt;
 - &#039;&#039;&#039;What happens in the conditional?&#039;&#039;&#039;&lt;br /&gt;
   - When the parent process calls fork(), a child process is created and begins executing at the fork() statement.  The OS returns a value from fork() which indicates which process &lt;br /&gt;
     is currently running.&lt;br /&gt;
   - If fork() returns zero then the child sleeps for 3 seconds before printing.  The sleep system call forces the child process to do nothing for 3 seconds.&lt;br /&gt;
   - if fork() returns anything else, it is assumed to be the parent process.  In this case the wait() system call is run by the parent which causes the parent process to wait for its &lt;br /&gt;
     child to finish; then the printf executes and prints the child process id and its return value from main.  The macro WEXITSTATUS retrieves 42.&lt;br /&gt;
&lt;br /&gt;
==== What Happen to the child process after the parent process died? ====&lt;br /&gt;
*Every child process must have a currently running parent. When the parent process die, kernel collect the dead body(return value) and re-parent the process &lt;br /&gt;
* In the demo showed in class, “system d user” became its new parent&lt;br /&gt;
**Use command &amp;quot;Pstree&amp;quot; to show process hierarchy&lt;br /&gt;
* Every process must have a valid process parent.  Use &amp;quot;pstree&amp;quot; to see the tree structure&lt;br /&gt;
* When a parent dies before a child &amp;quot;init&amp;quot; will adopt every orphan on the system&lt;br /&gt;
&lt;br /&gt;
==== What is zombie process? ====&lt;br /&gt;
*When a process die it become &#039;zombie&#039; (s = sleep, z = zombie)&lt;br /&gt;
*We can use wait to be a &#039;good&#039; parent&lt;br /&gt;
&lt;br /&gt;
==== How to load a new binary manually====&lt;br /&gt;
*Use the execve command.&lt;br /&gt;
**We can fork child process to handle dangerous task (“Suicide Squad”), or handle all incoming request&lt;br /&gt;
&lt;br /&gt;
==== Manipulating environment variables====&lt;br /&gt;
*argc tells the number of argument in command line, while argv[] contains the actual command obtained in the command line&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21075</id>
		<title>Operating Systems 2017F Lecture 3</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21075"/>
		<updated>2017-10-05T00:03:10Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* What is fork? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 14, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec03-14Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec03/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
====Commands ====&lt;br /&gt;
*-wall: show all warning&lt;br /&gt;
*less: allow screen navigation, hit q to quit&lt;br /&gt;
&lt;br /&gt;
==== What is fork? ====&lt;br /&gt;
* Fork creates a new program but contains the same code (call the clone system call) and only argv[] and envp[] passed on to the new born program&lt;br /&gt;
&lt;br /&gt;
 - More on creating a process using fork().&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
  int child;&lt;br /&gt;
  int status;&lt;br /&gt;
  pid_t retval;&lt;br /&gt;
        &lt;br /&gt;
  child = fork();&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
  if (child == 0) {&lt;br /&gt;
  /* We&#039;re the child */&lt;br /&gt;
    sleep(3);&lt;br /&gt;
    printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
  /* We&#039;re the parent */&lt;br /&gt;
    retval = wait(&amp;amp;status);&lt;br /&gt;
    printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
            (int) retval, WEXITSTATUS(status));&lt;br /&gt;
  }&lt;br /&gt;
        &lt;br /&gt;
  return 42;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
 - sleep(int)&lt;br /&gt;
   - causes the current process to do nothing for the specified number of seconds.&lt;br /&gt;
&lt;br /&gt;
 - pid_t = fork(void)&lt;br /&gt;
   - fork creates a clone of the parent process&lt;br /&gt;
   - pid is 0 when the child process is running and &amp;gt;0 when the parent process is running.  Both processes will return from the system call to fork().&lt;br /&gt;
&lt;br /&gt;
 - pid_t = wait(int * status)&lt;br /&gt;
   - this system call is equivalent to pid_t = waitpid(-1, &amp;amp;status, 0)&lt;br /&gt;
   - the wait system call suspends the current process until one of its children has terminated.&lt;br /&gt;
   - pid_t specifies which child to wait for.  Various options are available that define how to wait.&lt;br /&gt;
   - int* status holds the status of the wait system call.  There are various macros that define what the status can be.&lt;br /&gt;
&lt;br /&gt;
 - &#039;&#039;&#039;What happens when the newline character is removed from the printf statement?&#039;&#039;&#039;&lt;br /&gt;
   - printf holds the output in a buffer until it receives a newline character.  The result is the output does not print when expected. &lt;br /&gt;
   - The kernel is doing things as it is told, so the c library is at fault.&lt;br /&gt;
   - We could get the expected output if we bypass the c library using a system call: &amp;quot;write&amp;quot;&lt;br /&gt;
   - running an &amp;quot;strace&amp;quot; on the executable will show us the order in which the processes were run to help debug the problem.&lt;br /&gt;
	&lt;br /&gt;
 - &#039;&#039;&#039;What happens in the conditional?&#039;&#039;&#039;&lt;br /&gt;
   - When the parent process calls fork(), a child process is created and begins executing at the fork() statement.  The OS returns a value from fork() which indicates which process &lt;br /&gt;
     is currently running.&lt;br /&gt;
   - If fork() returns zero then the child sleeps for 3 seconds before printing.  The sleep system call forces the child process to do nothing for 3 seconds.&lt;br /&gt;
   - if fork() returns anything else, it is assumed to be the parent process.  In this case the wait() system call is run by the parent which causes the parent process to wait for its &lt;br /&gt;
     child to finish; then the printf executes and prints the child process id and its return value from main.  The macro WEXITSTATUS retrieves 42.&lt;br /&gt;
&lt;br /&gt;
==== What Happen to the child process after the parent process died? ====&lt;br /&gt;
*Every child process must have a currently running parent. When the parent process die, kernel collect the dead body(return value) and re-parent the process &lt;br /&gt;
* In the demo showed in class, “system d user” became its new parent&lt;br /&gt;
**Use command &amp;quot;Pstree&amp;quot; to show process hierarchy&lt;br /&gt;
&lt;br /&gt;
==== What is zombie process? ====&lt;br /&gt;
*When a process die it become &#039;zombie&#039; (s = sleep, z = zombie)&lt;br /&gt;
*We can use wait to be a &#039;good&#039; parent&lt;br /&gt;
&lt;br /&gt;
==== How to load a new binary manually====&lt;br /&gt;
*Use the execve command.&lt;br /&gt;
**We can fork child process to handle dangerous task (“Suicide Squad”), or handle all incoming request&lt;br /&gt;
&lt;br /&gt;
==== Manipulating environment variables====&lt;br /&gt;
*argc tells the number of argument in command line, while argv[] contains the actual command obtained in the command line&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21074</id>
		<title>Operating Systems 2017F Lecture 3</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_3&amp;diff=21074"/>
		<updated>2017-10-05T00:01:09Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: /* What is fork? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 14, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec03-14Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec03/ here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
====Commands ====&lt;br /&gt;
*-wall: show all warning&lt;br /&gt;
*less: allow screen navigation, hit q to quit&lt;br /&gt;
&lt;br /&gt;
==== What is fork? ====&lt;br /&gt;
* Fork creates a new program but contains the same code (call the clone system call) and only argv[] and envp[] passed on to the new born program&lt;br /&gt;
&lt;br /&gt;
 - More on creating a process using fork().&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[], char* envp[]) {&lt;br /&gt;
  int child;&lt;br /&gt;
  int status;&lt;br /&gt;
  pid_t retval;&lt;br /&gt;
        &lt;br /&gt;
  child = fork();&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Hello!  I am %d, my parent is %d.\n&amp;quot;,&lt;br /&gt;
          getpid(), getppid());&lt;br /&gt;
&lt;br /&gt;
  if (child == 0) {&lt;br /&gt;
  /* We&#039;re the child */&lt;br /&gt;
    sleep(3);&lt;br /&gt;
    printf(&amp;quot;Child all done!\n&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
  /* We&#039;re the parent */&lt;br /&gt;
    retval = wait(&amp;amp;status);&lt;br /&gt;
    printf(&amp;quot;Parent all done!  Child %d returned %d.\n&amp;quot;,&lt;br /&gt;
            (int) retval, WEXITSTATUS(status));&lt;br /&gt;
  }&lt;br /&gt;
        &lt;br /&gt;
  return 42;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
 - sleep(int)&lt;br /&gt;
   - causes the current process to do nothing for the specified number of seconds.&lt;br /&gt;
&lt;br /&gt;
 - pid_t = fork(void)&lt;br /&gt;
   - fork creates a clone of the parent process&lt;br /&gt;
   - pid is 0 when the child process is running and &amp;gt;0 when the parent process is running.  Both processes will return from the system call to fork().&lt;br /&gt;
&lt;br /&gt;
 - pid_t = wait(int * status)&lt;br /&gt;
   - this system call is equivalent to pid_t = waitpid(-1, &amp;amp;status, 0)&lt;br /&gt;
   - the wait system call suspends the current process until one of its children has terminated.&lt;br /&gt;
   - pid_t specifies which child to wait for.  Various options are available that define how to wait.&lt;br /&gt;
   - int* status holds the status of the wait system call.  There are various macros that define what the status can be.&lt;br /&gt;
&lt;br /&gt;
 - &#039;&#039;&#039;What happens when the newline character is removed from the printf statement?&#039;&#039;&#039;&lt;br /&gt;
   - printf holds the output in a buffer until it receives a newline character.  The result is the output does not print when expected. &lt;br /&gt;
   - The kernel is doing things as it is told, so the c library is at fault.&lt;br /&gt;
   - We could get the expected output if we bypass the c library using a system call: &amp;quot;write&amp;quot;&lt;br /&gt;
   - running an &amp;quot;strace&amp;quot; on the executable will show us the order in which the processes were run to help debug the problem.&lt;br /&gt;
	&lt;br /&gt;
 - &#039;&#039;&#039;What happens in the conditional?&#039;&#039;&#039;&lt;br /&gt;
   - When the parent process calls fork(), a child process is created and begins executing at the fork() statement.  The OS returns a value from fork() which indicates which process is &lt;br /&gt;
     currently running.&lt;br /&gt;
   - If fork() returns zero then the child sleeps for 3 seconds before printing.  The sleep system call forces the child process to do nothing for 3 seconds.&lt;br /&gt;
   - if fork() returns anything else, it is assumed to be the parent process.  In this case the wait() system call is run by the parent which causes the parent process to wait for its child   &lt;br /&gt;
     to finish; then the printf executes and prints the child process id and its return value from main.  The macro WEXITSTATUS retrieves 42.&lt;br /&gt;
&lt;br /&gt;
==== What Happen to the child process after the parent process died? ====&lt;br /&gt;
*Every child process must have a currently running parent. When the parent process die, kernel collect the dead body(return value) and re-parent the process &lt;br /&gt;
* In the demo showed in class, “system d user” became its new parent&lt;br /&gt;
**Use command &amp;quot;Pstree&amp;quot; to show process hierarchy&lt;br /&gt;
&lt;br /&gt;
==== What is zombie process? ====&lt;br /&gt;
*When a process die it become &#039;zombie&#039; (s = sleep, z = zombie)&lt;br /&gt;
*We can use wait to be a &#039;good&#039; parent&lt;br /&gt;
&lt;br /&gt;
==== How to load a new binary manually====&lt;br /&gt;
*Use the execve command.&lt;br /&gt;
**We can fork child process to handle dangerous task (“Suicide Squad”), or handle all incoming request&lt;br /&gt;
&lt;br /&gt;
==== Manipulating environment variables====&lt;br /&gt;
*argc tells the number of argument in command line, while argv[] contains the actual command obtained in the command line&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_2&amp;diff=21068</id>
		<title>Operating Systems 2017F Lecture 2</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2017F_Lecture_2&amp;diff=21068"/>
		<updated>2017-10-04T01:54:08Z</updated>

		<summary type="html">&lt;p&gt;Ssarazin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video from the lecture given on September 12, 2017 [http://homeostasis.scs.carleton.ca/~soma/os-2017f/lectures/comp3000-2017f-lec02-12Sep2017.mp4 is now available].&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
Code and files from the lecture (captured as they were at the end) are available [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/lec02/ here].&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
&#039;&#039;&#039;What is a file?&#039;&#039;&#039;&lt;br /&gt;
  - A hierarchical name with a value mapping, accessed using the API &amp;quot;open, read, close, seek&amp;quot; (roughly).  Open and close are used for efficiency; read and write do all of the work.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Why is Unix and Linux interchangeable?&#039;&#039;&#039;&lt;br /&gt;
  - Linux is a variant of the Unix, it contains the Unix kernel with custom built layers on top.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;What is the architecture of the Unix kernel?&#039;&#039;&#039;&lt;br /&gt;
  - A system of hierarchical files that represent all of the different hardware devices&lt;br /&gt;
    for example: writing to stdout or reading from stdin.  These are the computer monitor and keyborad file descriptors.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;How do we add new devices to the system?&#039;&#039;&#039;&lt;br /&gt;
  - We tell the operating system to mount the new device.  The operating system responds with a file descriptor for the new device.  Accessing the device means writing to its file.&lt;br /&gt;
  - There are many files that represent a device.  We can trace these files by calling the command &amp;quot;lspci&amp;quot; which gets the PCI bus hardware device info from the kernel.  Using the   &lt;br /&gt;
    command &amp;quot;strace lspci&amp;quot; we can trace all of the system calls performed by lspci.  Now we know exactly which files make up each device on the PCI bus. &lt;br /&gt;
  - file descriptors like /dev or /sys are conduits to the kernel.  The kernel then performs operations on the hardware.&lt;br /&gt;
&lt;br /&gt;
The key point(s):  The kernel abstracts the hardware by assigning file descriptors for every device.  A program can gain information about the device using system calls to the kernel.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Virtualizing Memory&#039;&#039;&#039;&lt;br /&gt;
  - Hard disks file descriptors appear as:&lt;br /&gt;
    - /dev/sda -&amp;gt; unencrypted drive&lt;br /&gt;
    - /dev/mapper… -&amp;gt; encrypted drive&lt;br /&gt;
  - We can see the filesystem using the &amp;quot;df&amp;quot; command or view the size of files using &amp;quot;df.&amp;quot;&lt;br /&gt;
  - Why are some of the files showing a size of 0 bytes?&lt;br /&gt;
    - When memory is virtualized, the kernel builds the file system as it goes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Processes&#039;&#039;&#039;&lt;br /&gt;
  - &#039;&#039;&#039;What is a Process?&#039;&#039;&#039;&lt;br /&gt;
    - A running program&lt;br /&gt;
    - Just like the devices, every process gets a directory in the files system &amp;quot;/proc&amp;quot;&lt;br /&gt;
    - To view running process use the command &amp;quot;ps&amp;quot;&lt;br /&gt;
      - To stop a running process use the command &amp;quot;Kill &amp;lt;process id&amp;gt;&amp;quot;&lt;br /&gt;
  - &#039;&#039;&#039;What happens when multiple processes are created?&#039;&#039;&#039;&lt;br /&gt;
    - The operating system shares the resources between the processes using time sharing -- also called virtualizing the resources.&lt;br /&gt;
  - &#039;&#039;&#039;What is a shell in Linux?&#039;&#039;&#039;&lt;br /&gt;
    - Just another program that can access the operating system and run other programs&lt;br /&gt;
    - A shell can run multiple programs (processes), only control returns to the shell after the process has finished.  To give the shell priority use the &amp;quot;&amp;amp;&amp;quot; to send the current process to &lt;br /&gt;
      the background.  This idea demonstrates how the CPU is virtualized because it is being shared by the shell and the running process.  The concept was demonstrated using xclock.&lt;br /&gt;
      - Use the &amp;quot;jobs&amp;quot; command to see which processes are running&lt;br /&gt;
      - Use the &amp;quot;ps aux&amp;quot; command to view the full command line of all running processes.&lt;br /&gt;
      - Use the &amp;quot;getpid()&amp;quot; function call in a c program to find the process id for the current process.&lt;br /&gt;
      - Use the &amp;quot;getppid()&amp;quot; function call in a c program to find the parents process id for the current process.&lt;br /&gt;
  - &#039;&#039;&#039;How do I make a process?&#039;&#039;&#039;&lt;br /&gt;
    - by copying the current process&lt;br /&gt;
    - fork(): a system call the clones the currently running process.  The new process (child) begins executing from the statement that contained the call to fork().&lt;br /&gt;
    - fork() returns zero it means the child process is running.&lt;br /&gt;
    - fork() returns &amp;gt; 0 it means the parent process is running.&lt;br /&gt;
    - fork() returns &amp;lt; 0 it means the fork() failed.&lt;br /&gt;
&lt;br /&gt;
Using fork() in a c program&lt;br /&gt;
&lt;br /&gt;
/* hello-world.c */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  fork();&lt;br /&gt;
  fork();&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Hello world! I&#039;m %d.  My parent is %d\n&amp;quot;, getpid(), getppid());&lt;br /&gt;
  return 42;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;What does the program do?&#039;&#039;&#039;&lt;br /&gt;
  - The first call to fork() clones a child process running the hello-world program.  The child begins operating as if it just called fork().  Only the value returned from fork() &lt;br /&gt;
    is different for the child than the parent.  The child process returns a zero.&lt;br /&gt;
  - Now there are two processes running concurrently, executing the same code.  A parent process and a child process.&lt;br /&gt;
  - The parent process calls fork() again creating another child process, and the first child process also creates a child process.  Now there are 4 processes running concurrently.&lt;br /&gt;
  - All 4 processes will print their process id and their parent&#039;s process id.&lt;br /&gt;
  - finally a return value of 42 is delivered to the parent of each process as it exits.&lt;br /&gt;
  - Important: The order of execution for each process is not deterministic.  We do not know which process will run next because the operating system decides.&lt;/div&gt;</summary>
		<author><name>Ssarazin</name></author>
	</entry>
</feed>