Operating System Concepts

Category: Programming
Author: Abraham Silberschatz, Peter B. Galvin, Greg Gagne
3.8
All Stack Overflow 7
This Month Stack Overflow 3

Comments

by anonymous   2019-07-21

There are two ways to create threads:

synchronous threading - the parent creates one (or more) child threads and then must wait for each child to terminate. Synchronous threading is often referred to as the fork-join model.

asynchronous threading - the parent and child run concurrently/independently of one another. Multithreaded servers typically follow this model.

resource - http://www.amazon.com/Operating-System-Concepts-Abraham-Silberschatz/dp/0470128720

by anonymous   2019-07-21

The fork() might seem a little confusing at first, but its actually pretty simple. What it does is copy the current process into a new process in another memory location (copy everything, its data, code, current instruction, ...).

So we started with a process with pid = 5079, when we got to the fork call, a child process with pid = 5080 was created, and it has the same code of the parent process.

 // Parent Process //                    // Child Process //
 #include<stdio.h>                       #include<stdio.h> 
 #include<unistd.h>                      #include<unistd.h>
 #include<stdlib.h>                      #include<stdlib.h>
 int main()                              int main()
 {                                       {
    printf("\...                            printf("\...
    pid_t pid1=fork();                      pid_t pid1=fork(); 
    printf("\nPI...    //Next line//        printf("\nPI...    //Next line//
    pid_t pid2=fork();                      pid_t pid2=fork();
    printf("\nPID:=...                      printf("\nPID:=...
    pid_t pid3=fork();                      pid_t pid3=fork();
    printf("\nPID:=...                      printf("\nPID:=...
    return 0;                               return 0;
 }                                        }

before we continue following the code, the return value of the fork call is as follows: inside the process that called the fork(), the return value is the pid of the child process (pid1 variable in Parent Process = 5080), and inside the child process, the output is 0 (pid1 variable in Child Process = 0).

So the print statement after the fork will be executed by the Parent Process and the Child Process with different getpid() value and different pid1 values, the parent has getpid() = 5079, and pid1 = child's pid = 5080 (you can see this in the third line of the output). The child will make its own print statement, with getpid() = 5080 and pid1 = 0, you can see this in the 8th line of the output, but why the 8th line!!!

The operating system schedules the process, that is, it decides which process the CPU will work on and for how long. so it seems that the OS decided that the parent process (pid = 5079) should run for a little longer, and left the child process (pid = 5080) waiting for the CPU to execute its instructions.

So process 5079 went on with the next fork, creating a new child process with pid = 5081. Then it printed what we expect in the third line, then it went on to the last fork creating process 5082, printing what we would expect in the forth line, then terminating (process 5079 terminated, leaving 5080,5081,5082 waiting, and Adopted by the OS, they need to have a parent, but this isn't important to the output).

Now that 5079 terminated, we have 3 processes waiting in the memory for the CPU to work them. The operating system must decide which process to run, and it seems to have choose the process that is closest to terminate, which is process 5082, let's look at the remaining instructions for each process:

  // process 5082 //      // process 5081 //     // process 5080 //
  printf("\nP...          printf("\nP...         printf("\nP...
  return 0;               pid_t pid3=fork();     pid_t pid2=fork();
                          printf("\nP...         printf("\nP...
                          return 0;              pid_t pid3=fork();
                                                 printf("\nP...
                                                 return 0;

Why is this the remaining code? any process created by a fork in some other process will start executing after that fork statement like we have seen earlier. so process 5082 printed line 5 then terminated (its value of pid3 = 0 because it is a child of 5079). After terminating of 5082, 5081 took the CPU, and it printed line 6, then created process 5085 as we can see in line 6 (why not 5083 in order? maybe the OS created some process during the execution of your code).

after printing line 6 process 5081 has terminated. Now we have 5080, and 5085 in the memory. you should now be able to follow the pattern, 5080 was selected to run, creating 5086 and 5087 then terminating. then 5085 ran, followed by 5087, which only had the print statement in the end, both then terminated, and we were left with 5086 which printed, made the last fork creating 5088, then terminated as did 5088 after its print.

Operating systems is a fascinating field, its fun to go beyond the system calls, if you are interested in this I would recommend this book, it is what I studied in college: https://www.amazon.com/Operating-System-Concepts-Abraham-Silberschatz/dp/0470128720

by acomjean   2018-11-10
For those that don't know.. Tannenbaum wrote the book on Operating Systems... Well a book. I think his OS Minix[2] is in there. Its on every intel CPU, but I think that was news to Tannenbaum.

This argument was at its root a "theory" vs. "getting it done" now argument. I think thats why it resonates.

[1]https://www.amazon.com/Modern-Operating-Systems-Andrew-Tanen... [2]https://www.amazon.com/Operating-System-Concepts-Abraham-Sil...

by anonymous   2017-08-20

In general, at process termination, all resources allocated by this process are freed by operating system. (see 3.3.2 Operating System Concepts by Abraham Silberschatz , Peter B. Galvin, Greg Gagne http://www.amazon.com/Operating-System-Concepts-Abraham-Silberschatz/dp/0470128720)

The kill command does not "kill" process, but sends signal to it. If the signal is SIGKILL (kill -9 PID) you can do nothing. Process is killed unconditionally. If signal is SIGTERM (default), you can serve it or ignore it. See: http://en.wikipedia.org/wiki/Unix_signal

by anonymous   2017-08-20

In short, here's how a system call works:

  • First, the user application program sets up the arguments for the system call.
  • After the arguments are all set up, the program executes the "system call" instruction.
  • This instruction causes an exception: an event that causes the processor to jump to a new address and start executing the code there.

  • The instructions at the new address save your user program's state, figure out what system call you want, call the function in the kernel that implements that system call, restores your user program state, and returns control back to the user program.

A visual explanation of a user application invoking the open() system call:

enter image description here

It should be noted that the system call interface (it serves as the link to system calls made available by the operating system) invokes intended system call in OS kernel and returns status of the system call and any return values. The caller need know nothing about how the system call is implemented or what it does during execution.
Another example: A C program invoking printf() library call, which calls write() system call

enter image description here

For more detailed explanation read section 1.5.1 in CH-1 and Section 2.3 in CH-2 from Operating System Concepts.

by anonymous   2017-08-20

Memory is a storage space where instructions and data, regarding programs, are stored. Buffer and stack both are the small section of the memory.

Buffer stores data temporarily while execution of the program.

Operating System Concepts (8th ED):

A buffer is memory area that stores data being transferred between two devices or between a device and an application.

On the other hand, a stack is a container of objects that are inserted and removed according to the last-in first-out (LIFO) principle. In the pushdown stacks only two operations are allowed: push the item into the stack, and pop the item out of the stack. A stack is a limited access data structure - elements can be added and removed from the stack only at the top. push adds an item to the top of the stack, pop removes the item from the top.