Search

Linux Quiz 1

A quiz on linux Basics

A quiz on linux Basics

This is a quiz on basics of linux, have fun....
  1. What option of "ls" gives the listing according to the modified time

  2. t
    a
    l
    m

  3. In which folder of linux filesystem does ".." and "." point to the same folder

  4. /root
    /
    /bin
    None of the above

  5. The "-p" option of mkdir

  6. Creates a folder in the parent folder
    Creates parent as well as it subfolders at the same time
    Modifies the path of exiting folder
    Removes a folder

  7. Which option in "cat" adds line numbers to everyline in the output

  8. n
    l
    m
    a

  9. The /bin directory generally holds

  10. Softlinks
    Executables
    Hardlinks
    Text files

  11. The output of "pwd" is what kind of path

  12. Relative path
    Absolute Path
    Both
    Depends on folder

  13. Which of the following is not a type of linux shell

  14. crsh
    csh
    bash
    ksh

  15. ----- can change the password of a user

  16. Only the user
    The user and the root
    Only the root
    Any one

  17. The output of the command "tac <filename>" is

  18. The contents of the file in reverse
    Absolute path of the file
    Number of lines in the file
    Permissions of the file

  19. Which command changes the permissions of a file

  20. passwd
    perm
    chmod
    cmod

Feel free to contact me for any queries...

Answers to quiz can be found at : Answers to linux quiz-1

Atomic Variables


With the advent of multiprocessor systems, the requirement of the programs to maintain the synchronization has become mandatory.

In a multiprocessor systems if a program is being executed on multiple processors with data being shared between the processors then the update of data by one one processor might be affected by an update by another processor.

For eg consider the instruction val = val + 1; This is a good example of a read modify write instruction where the processor read the value of "val" modifies it and write it back. In a uniproessor system this poses no problem because the processor will not let go of the memory bus until the instruction is not completely executed.

But in a multiprocessor system, the memory bus might be released after the read and while one processor updates the value another processor can make use of the bus.
If two processors, processor A and processor B reach this instruction at the same time. Assume the value of val is 3 initially.

Processor A reads the value 3 and lets go of the bus
While processor A updates the val processor B also reads val as 3 and lets the go of the bus
Now processor A updates the new value 4 in the val
Then processor B also updates the value of val as 4.

With 2 increments the value of val should have become 5, but it remains at 4 because both the processors were allowed to read the variable before one of them finished the operation on it.

This simultaneous access can be prevented using semaphores and spinlocks but implementing a semaphore or spinlock for one instruction might be an overkill.

There is another solution in linux kernel called atomic variables.

Atomic variables are the ones on whom the read modify write operation is done as one instruction with out any interruption .

In the above example if val was an atomic variable then processor B would have been allowed access to the variable only after processor A has finished the updating the visible, until then the processor A would have held on to the memory bus.

To make use of the atomic variables the variable needs to be declared as of type atomic_t.

The access to the atomic variables is not through the standard instructions but using special functions listed below.

atomic_t *val   Declaration


atomic_read(val): Returns the value of *val
atomic_set(val,i) :  Sets *val to i


atomic_add(i,val):    adds i to *val
atomic_sub(i,val):  Subtracts i from *val
atomic_sub_and_test(i, val) : Subtracts i from *val and returns 1 if the result is zero,


atomic_inc(val) : Adds 1 to *val
atomic_dec(val) :  Subtracts 1 from *val


atomic_dec_and_test(val): Subtracts 1 from *val and returns 1 if the result is zero, otherwise it returns 0
atomic_inc_and_test(val): Adds 1 to *v and returns 1 if the result is zero; 0 otherwise


atomic_add_negative(i, val): Adds i to *val and returns 1 if the result is negative, otherwise it returns 0

atomic_inc_return(val): Adds 1 to *val and returns the new value of *val
atomic_dec_return(val): Subtracts 1 from *val and return the new value of *val
atomic_add_return(i, val) : Adds i to *val and returns the new value of *val
atomic_sub_return(i, val): Subtracts i from *val and return the new value of *val

Let us write a small module using one of the functions and see how it gets implemented at the assembly level.


***********************test_atomic.c **********************
#include<linux/kernel.h>
#include<linux/module.h> 


atomic_t *test; 


int test_init(void) 
{
atomic_set(test,2);
atomic_add(2,test);
}


void test_exit(void)
{
}
module_init(test_init);
module_exit(test_exit);
**************************************************************

Save the above code as test_atomic.c, the makefile required to compile the code will be

*****************Makefile*******************************


ifneq ($(KERNELRELEASE),) 
   obj-m := test_atomic.o
else 


KERNELDIR ?= /lib/modules/$(shell uname -r)/build 


PWD := $(shell pwd)


default: 
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules  
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
endif 
********************************************************

Now compile the code by running the command make

$ make

This should generate the file test_atomic.ko.

To look at the assembly instructions for this code we can use "objdump"  which is a command to read information from object files.

Run the command as follows

$ objdump -d -S test_atomic.ko 

test_atomic.o:     file format elf32-i386




Disassembly of section .text:


00000000 <init_module>:
   0: a1 00 00 00 00       mov    0x0,%eax
   5: c7 00 02 00 00 00     movl   $0x2,(%eax)
   b: a1 00 00 00 00       mov    0x0,%eax
  10: f0 83 00 02           lock addl $0x2,(%eax)   
  14: c3                   ret    


00000015 <cleanup_module>:
  15: c3                   ret    




The lines after <init_module> in the output of the command is the assembly code for the init function we have written.

If we look at the 4th line of the assebly instructions we notice an instruction that starts with the keyword "lock" and then followed by "addl".

This instruction corresponds to the function "atomic_add". The lock keyword makes sure that the memory bus remains locked as long as the variable is not read modified and written back.

Similarly any of the atomic instructions are executed with the lock keyword making sure that the read modify write happens with out any interruptions.



VI editor tips for programmers - 3


In this post we will look at a few settings that are useful while programming.

Syntax coloring 

While typing a program, it is always helpful if various colors are used to higlight different keywords and variables of a program. This
can be acheived by running the command

:syntax on 

While in the command mode in the vi editor.

The screenshots below show the difference.
With out syntax highlighting

With syntax highlighting




Without numbering 





With Numbering and syntax enabled.














Line numbers

A line number can be added to every line in the file by running the command

:set nu
or
:set number

The screenshots below depict the working of this command


VI editor tips for programmers -2

Playing around with line numbers

In the last post, VI editor tips for programmers -1 , we saw how VI editor helps in keeping track of the braces in a program.
In this post let us look at a few tips that relate to line numbers in a program.

Very often a compilation error points out to a line where some thing is wrong for eg :

*****************hello.c****************
#include<stdio.h>
main ()
{
printf("Hello world");
if(1) {
        printf("Hello again"));
        }
else {
        printf("Hello once more");
        }
}
****************************************


If we compile the above program using gcc compiler as follows

$ cc hello.c

We get the error

test.c: In function ‘main’:
test.c:6: error: expected ‘;’ before ‘)’ token
test.c:6: error: expected statement before ‘)’ token

The error thrown also speciifes the line number in which there is possible error. From the above error we know there might be an error in the line no 6.

Now open the file using vi

$ vi test.c 


To go to the sixth line we could either move with the arrow keys looking at the bottom right of the editor for  the line numbers being displayed.
But if the code is too big and error is 100th or the 1000th line then just using arrow keys of pgup, pgdwn keys are not convienient.
To move to any line number in the file directly , go to command mode (by pressing esc)  and type

:"number" 

That is in our case, to go to the 6th line we will have to type

:6 

and press enter. The cursor should automaticlly move to the sixth line.


Another way of doing this is to pass the line number while opening the file itself .

$ vi test.c +6  

The file opens with the cursor directly placed at the sixth line.

Moving with in the file by specific number of lines can also be done with out using the arrow keys.
To move two lines above/before the current line just do the following in the command mode

:-2  

To move by two lines below/after the current line

:+2 

Hope the tips makes programming and debugging much easier.