Write a short program in C.
Write a short C program that checks whether a number is a power of 2. Try to write a program that will perform the test most efficiently.
If you make any assumptions please specify them. Make sure that the syntax is correct.

done. please check the power.c file

IP Networks.
The following network is given:

A -------------                                B ----------
    10.10.10.10 \                               20.20.20.20 \
                 \------------|                              \---------|
                 |            |        |-----------|         |         |
                 |    switch  |--------|   router  |---------|  switch |
  10.10.10.11----|            |        |-----------|         |         |---20.20.20.21
                 --------------                              -----------


Station A (10.10.10.10) wants to send an IP packet to Station B (20.20.20.20.20). Station A knowns only as the IP address of station B.

Describe the steps and types of messages that will go through the network for the package to go from A to B.

I don't know TCP/IP in depth, but on high level, station A needs to create a socket with the IP of station B, requesting
connection to some speciffic port. Station B needs to have a server process listening on that port. The messages will be routed
through the first switch into the router, then the second switch into station B. I think A doesn't know the network topology,
but it should have been configured to send the messages to the gateway IP(the router) through DHCP(from the router) or set statically
Then the router which has a routing table will redirect the messages to station B through the switch. I'm not really sure if some more
configurations need to be performed(VLANs, tagging of packets, etc...), because of the different subnets

Operating Systems.
A.    Given are 3 tasks/threads running, each one of them has different priority level.
The lowest priority task performs an infinite loop:

while(1) {
 counter++;
}

One of the higher priority tasks should run. Explain what will cause the task to run and how the transition will be made.

If the higher prioryty tasks both block on some operation, the sceduler will be invoked and
it will start executing the lowest priority task. Every OS tick quant, the sceduler will check if one of
the two blocked tasks are free to proceed(the operation has completed or timeout has been reached)
If that's the case, it will start the highest priority task that is free to run. Please note that the
time needed to switch tasks is the tick quant unless yield is called which will asynchronously invoke the sceduler


B.    Given are two Threads. One thread writes to memory an array of 10 entries and the other thread reads the same array from memory. Can it generate a problem? If yes, how can you solve it?

The problem that may occur is that the thread which reads the array may attempt to read it before it's written to.
To solve the problem, we need to use mutex to block the second task until the whole array is ready. Depending on the
operations performed on the array by the second task, we may better yet use a semaphore and unblock the task on per
element basis. If the first task is dependent on the second, we also need to be careful not to cause deadlock.

Protocols.

A.    Explain in detail how TCP’s protocol reliability is implemented.
I don't know the protocol in detail, but on high level, messages are broken down into packets(the size is dependent on the MTU I think) and numbered.
Then the packets are sent one by one and confirmation from the receiver is returned. If no confirmation is received, the sender attenpts to send the messages again.
TCP also has some features to dinamically adjust the packet size lower than the MTU if there are many dropped packets. This is in order to prevent resending a large
chunk because of a small error. Every packet should also have some error checking, to verify the integrity of the data. CRC I presume.

B.    What protocol: TCP or UDP would you use for VoIP transfer? Explain why.

I'll use User Datagram Protocol, because loosing packets is not critical when we transfer voice or video in real time.
The more critical task is to give the recepient the perception of real time communication with the other side even if there
are some minor glitches. TCP also has bigger overhead which will create bigger load on the network.

Data Structure.

Write a function that implements removal of element from a one-way linked list. You should consider end cases (blank list).

I haven't used singly linked lists myself, but I remember the Linus Torvalds TED talk from 2016 ( https://youtu.be/o8NPllzkFhE?t=861 )
where he described "taste" as a way to simplify the end cases where possible.

https://github.com/mkirchner/linked-list-good-taste - here someone has put up a nice project based on the talk

General.

A.    Variables:
1.    What is the difference between a global and local variable?
Gobal variables can be acessed in the scope of the whole source file, or from other files if redefined with the extern keyword(and not originally defined with the static keyword(if static isn't used, the compiler defines them as extern by default)).
Local variables can be acessed only in the scope they were defined in(until the closing curly braces).
in the bss or data region if static keyword is used
2.    Where are they located in the memory?
The global variables end up as bss or data, whereas the local variables are stored in registers or in the stack(if there are more varibles than the avaliable registers).
Also if we define local variable with the static keyword, it also ends up in the bss or data region. and could be modified ouside the scope if we return a pointer to it.
3.    In what case should you use each one of them?
The general rule is to avoid global variables as much as possible(prevent spaghetti code)
4.    What is the life span of each one of them?
Global variables are initialized with zeroes or data before we end up in main() and live until the process finishes.
Local variables get popped out of the stack when the function returns.
B.    Compare between recursive solution a serial solution – in terms of performance and memory.
The recursive solution may cause stack overflow, but using the stack is faster than using the main memory as a rule of thumb. Also the recursive solution should
end up using more memory? Don't quote me on the last one.
C.    What's the difference between a macro and an INLINE function??
Macros are processed by the preprocessor before the compilation begins(the statements literraly end up in line where used).
for the inline functions, the compiler optimizes the funtion call and return, inserting the generated instructions inline of the caller function.
Please note that inline may not always act the same way and we can also read about the __attribute__((always_inline)) - https://stackoverflow.com/a/48212527 
D.    What is the benefit of using alignment?
The cpu accesses memory in words which depending on the arch may be different sizes(typically 4 or 8 bytes). Accessing memory out of aligment is slower.
E.    How parameters are passed in function calls?
This depends on the ABI, but in most cases there are registers reserved for passing parameters and if there are more parameters than the
reserved registesrs, they end up pushed on the stack
F.    What's the difference between Thread and Process?
Every process has it's own virtual address space and passing data between processes is more complex(we may use Linux pipes (which act as a FIFO)), but if one process segfaults it doesn't affect the others.
Processes can spawn threads which are in the same address space as the father and may use the same global variables.
G.    What is the size of a pointer variable?
The size depends on the architecture of the cpu. Typically 4 or 8 bytes, but note that the modern 64bit x86 CPUs may execute legacy 32bit code. Also the old BIOS standard starts the CPU in legacy 16bit mode
which dates back to the first IBM PCs. Not sure how UEFI handles things.


Linux Shell scripting

I'm not very proficient with scripring to be honest. I can teach myself to solve the questions.
When writing scripts I will try not to use bash as it has features outside of the POSIX standard and also is slower.
ash or dash should be faster and if the script runs it should be closer to the POSIX standard.

A.    What will be the output of the following command:
i.    printf "%d %d\n" 1 2 3 4 5
aparently this statent is like executing three times printf in C with the three pairs of argumens, padding 0 to the last pair:
1 2
3 4
5 0
B.    Write a script that reads a text file, line by line, and prints the line.
please check print_file.sh script
C.    Change the script that prints the file from end to start.
please check print_file_reverse.sh script
this may not be the best way to implement it though
D.    How do I continuously track a log file update?
        I'm using tail -f for that purpose
E.    What command will we use to check whether $a is greater than 12
if [ "$a" -gt 12 ]; then
    ...
fi

