quinta-feira, 2 de junho de 2016

Device Drivers


 



 Introduction


This topic is about teaching how to program direct to the linux kernel. We will first explain how to prepare your pc and the basis to start working with the kernel. After we will teach how to overwrite an USB module.

Verifying if your kernel hearder is updated


First, make sure that your kernel header is updated. Open the linux terminal and type the following command.

$ sudo apt-get update
$ sudo apt-get install linux-headers-$(uname -r)

Compiling linux kernel

We will be using some example code as a tutorial.

Setting the modules

1) On the linux terminal, create an hello.c file.

$ nano hello.c


2) Then  copy this code:

#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");

static __init int hello_init(void) {
   printk(KERN_INFO "Hello world!\n");
   return 0;


static __exit void hello_exit(void) {
   printk("Goodbye cruel world!\n");


module_init(hello_init);
module_exit(hello_exit); 

 
Save it with ctrl+x.

3)On the terminal, create a makefile.

$ nano makefile

4) Then copy this code:

obj-m += hello.o
all:
     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 
 

And save it with ctrl+x.

5) Back on the terminal, on the same folder that you saved both hello.c and makefile, compile the module.

$ make

 Trying the example

 

6) On the terminal, enter as the root user.

$ sudo su  

7) Load the module on the kernel with the insmod command.

# insmod hello.ko

8) Unload the module from the kernel with the rmmod command.

# rmmod hello

9) See messages "Hello World!" and "Goodbye cruel world!" in /var/log/message file.

# tail -f /var/log/message

Making an USB driver

We will be making an USB driver using what we learned from the example before.

 

 Setting the modules

1) On the linux terminal, create an hello.c file.

$ nano usb.c


2) Then  copy this code:

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kref.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/mutex.h>

MODULE_LICENSE("Dual BSD/GPL");


#define VENDOR_ID    0x2341
#define PRODUCT_ID    0x0043
 

static const struct usb_device_id table[] = {
    { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
    { }
};
MODULE_DEVICE_TABLE(usb, table);


static int myprobe(struct usb_interface *interface, const struct usb_device_id *id) {
    printk(KERN_INFO "Probe()\n");
    return 0;
}

static void mydisconnect(struct usb_interface *interface){
    printk(KERN_INFO "Disconnect()\n");
}

static void mydraw_down(struct usb_skel *dev){
    printk(KERN_INFO "DrawDown()\n");
}

static int mysuspend(struct usb_interface *intf, pm_message_t message) {
    printk(KERN_INFO "Suspend()\n");
    return 0;
}

static int myresume(struct usb_interfae *intf){
    printk(KERN_INFO "Resume()\n");
    return 0;
}

static int mypre_reset(struct usb_interfae *intf){
    printk(KERN_INFO "Pre_reset()\n");
    return 0;
}

static int mypost_reset(struct usb_interfae *intf){
    printk(KERN_INFO "Post_reset()\n");
    return 0;
}

static struct usb_driver mydriver = {
    .name =        "mydriver",
    .probe =    myprobe,
    .disconnect =     mydisconnect,
    .suspend =     mysuspend,
    .resume =    myresume,
    .pre_reset =     mypre_reset,
    .post_reset =     mypost_reset,
    .id_table =     table,
    .supports_autosuspend = 1,
};

module_usb_driver(mydriver);


 
Save it with ctrl+x.

3)On the terminal, create a makefile.

$ nano makefile




4) Then copy this code:

obj-m += usb.o
all:
     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 
 

And save it with ctrl+x.

5) Back on the terminal, on the same folder that you saved both hello.c and makefile, compile the module.

$ make

Warning!
Trying this will overwrite the normal USB module that the kernel uses.

 Trying the USB

6) On the terminal, enter as the root user.

$ sudo su  

7) Load the module on the kernel with the insmod command.

# insmod usb.ko


8) See messages in /var/log/message file.

# tail -f /var/log/message

Now try the USB.



quarta-feira, 4 de maio de 2016

Performance Analysis - Paralelism

Preview 

In this research, we’ll talk about difference in performance when the threads are running in different CPU scenarios.

Introduction

This research aims to analyze how much parallelism can make our aplications better.

We'll be using 3 functions whithin 3 analysis methods.

For that, we created a float vector with 100*1000*1000 (100M) elements initialized with random values between -1 and 1.

Function 1: Sum all the vector;
Function 2:  Sum all elements in the form Sin[i] (with i from 0 to n-1);
Function 3: Sum all the elements in the form log[i] (with i from 0 to n-1);

Analysis 1: Calculate the execution time of each function, running as a thread into a single core. 

Analysis 2: For each function, calculate the execution of 2 threads with the same function, each one running in a different core.

Analysis 3: For each function, calculate the execution of 2 threads with the same function in the SAME core.

With the methods presented above, we could measure the executions. We'll calculate the time for the creation and execution of the threads and, to better visualize it, we'll plot graphics using GNU Plot tool.

Installations

 QT

   To program the source code in C++ we're using the QT Creator. QT Creator is a very complete IDE for C++ and it has a lot of libraries and tools for GUI creation, data structures, threads creation and etc.
   First of all, you can download QTCreator (offline version) from the links bellow, or download the online installation tool (https://www.qt.io/download). and it will install the IDE while downloads it.
 We're assuming you're using one of the many linux distributions, so the links above are for Linux and not for windows. For windows users, you must download by using the online tool.
  Navigate, in terminal, to the downloads folder and type the following commands:
    - chmod +x file_name (where file names refers to the downloaded one).
    - ./file_name.run

  Follow the instructions on the screen and you're ready to go. 

Gnuplot

To install Gnuplot, open the software center and search for GnuPlot. After found, select it and it will open it's own page. Scroll down a little bit and select the first two Optional Add-ons:
  • Pipe-oriented frontend to Gnuplot
  • Command-line driven interactive plotting program.
  After selecting both Add-ons, click on install and now you have everything you will need.

Repository

We decide to put the codes on a free online repository, GitHub.



Making it work



Open the GitHub link above and select the "download zip" button. Download it anywhere you want.

Now go to QT, open the file that you've just download, and select the AnaliseCPU.pro file. After that click on the red button that will appear ("Configure Project").
 
On the left panel, there is a icon called "Projects", click on it and uncheck, if it is checked, the "Shadow Build".

Now you only have to go to the down part of the left panel and click on the green triangle/arrow. The program will start to run.

It will show the time that was necessary to create the vector and will start to put the analysis results on a .txt file named output that is created on the same file that you've just donwload.

All results are on this .txt file, but to make it more visible, we will plot a graphic.

Open the terminal, go to the file that has the output.txt, and copy the following commands:

$ gnuplot

$ set title "Performance Analysis"
$ f1 = "#99ffff"; f2 = "#4671d5"; f3 = "#ff0000";
$ set auto x
$ set ylabel 'Time(s)'
$ set yrange [0:11]
$ set style data histogram
$ set style histogram cluster gap 1
$ set style fill solid border -1
$ set boxwidth 0.9
$ set xtic scale 0

$ plot 'output.txt' using 2:xtic(1) ti col fc rgb f1, '' u 3 ti col fc rgb f2, '' u 4 ti col fc rgb f3

 After copying the commands above a bar plot will show up and with this data the analysis will be easier.

Conclusion 

For this research, we used the following systems: 

Notebook with an AMD APU model A8-5550M Quad-Core processor clocked at 2.1GHz and 4GB DDR3 1600 MHz RAM. 

Desktop PC equipped with an Intel Core i7 3770k Quad-Core(HT) processor clocked at 4.2GH'z with 8GB DDR3 1600 MHz Ram.
 AMD A8-5550M 2.1GHz
i7 3770k 4.2GHz


In the plots, we can clearly see that paralelism can improve a lot performance. With a big number of threads running at the same time, processors with multiple cores can manage better and being done quickly. 
It's visible that with a major number of threads in a single core, the execution gets slower. When dividing the threads into other cores, we can push harder and the processor still works inside a good media with 2 cores dividing the threads.
We know too that sum itens is very much easier for a processor than calculating logs, in that case we can see that even in the worst case (analysis 3) we have a small execution time. 
Besides the 3770k is a very much stronger processor, it gains some points based on the intel's HT technology, that shows to operational system a extra "core per core", that means that instead of 4 the OS "sees" 8 cores and can alocate more threads within the same core, this is a virtualization and the performance is not as quite good as two real cores, but the logical swap of threads and operations can make difference in some scenarios. 



sexta-feira, 4 de março de 2016

The difference of the performance between BeagleBone Black and the PC

In this research, we’ll talk about performance of different algorithms in two different computer architectures.


We’ll be using a desktop x86_x64(Intel Core i7 3770k 4.2ghz) and a BeagleBone Black, ARM (Cortex A8, 1ghz).

Introduction



In some cases, computers have lower performance aiming saving energy and preventing overheat. Others are just caused by hardware limitation.

To verify those differences we will test the preformance by saving the time and clocks that are spend when processing the same algorithm in different computers and ploting some graphs using the results as a base.


In this case, we will use the Bubble, Quick and Shell sort algorithms. The vector size will start in 5000 and will increase by 5000 every time the function is called again. The maximum point we're aiming will be 500000.

This experiment is also to show the difference, in practice, of time_t and clock. Time is an absolute measure of time, it's based in the "0 hour of unix". It counts the amount of seconds that has been passed since 1 January 1970, 00h00min. Clock, by the other hand, is a measure of clock ticks from the processor. It can be converted to seconds when divided by CLOCKS_PER_SECOND. It's more acurrate to calculate process times. In a short explanation, Time_t takes ALL the time since the process begin, while clock just take the process time.

We used the codes that are saved into the repository below:


Just a brief explanation of each code:

     -run.sh: 
        The executable file for running an specific code with bubble, quick or shell sort. 
               $ ./run.sh  file*  integer**
                 * file that we wish to execute
                 ** 1 Bubble Sort, 2 Quick Sort, 3 Shell Sort


     -run_all_x86.sh:  

        The executable file for running all the codes into an x86 hardware.
               $ ./run_all_x86.sh 

     -run_arm.sh:  

        The executable file for running all the codes into an arm hardware.
               $ ./run_arm.sh

     -trabalho_time.cpp: 

        The c++ code that measure the time spent on one of the 3 Sorts 10 times, and calculates the average and the standard deviation.
     
     -trabalho_clock.cpp:
        The c++ code that measure the clocks spent on one of the 3 Sorts 10 times, and calculates the average and the standard deviation.

     -gnu_test.cpp:

         The c++ code that receives the files of the the same type of test (time or clock), they need to be write down in an ascending order (..._1 , ..._2 , ..._3), and organize those 3 into another .txt file, whose name will be the 4th argument.
               $ g++ gnu_test.cpp -o gnu
           $ ./gnu file_1, file_2 , file_3, newfilename 

           *The gnu_teste.cpp need to be in the same directory as the results files.

     -others:

        files we wish to execute to test.

Before Starting:

As we will use some arm codes, first we need to install an arm compiler.


Open the terminal on linux and type the following lines:


$ sudo apt-get install libc6-armel-cross

$ sudo apt-get install binutils-arm-linux-gnueabi
$ sudo apt-get install libncurses5-dev

$ sudo apt-get install gcc-arm-linux-gnueabihf

$ sudo apt-get install g++-arm-linux-gnueabihf


To test into the BeagleBone Black:

The files needed for this test are:
    - run.sh
    - run_arm.sh
    - trabalho_clock.cpp
    - trabalho_time.cpp

    - time_arm
    - clock_arm

Let's install the Debian SO to the BeagleBone. For this, you'll need a MicroSD card with, at least, 4GB of memory.

You can download the SO over this link.

When the download's finished, connect the MicroSD in the computer and open the terminal. Go to the diretory where the file was saved and unzip it.

$ unxz <filename>.img.xz

Find the list of devices connected to your PC using
$ df -h
The location is different in each computer, so you must be able to find based in the size and if it's mounted in "/media/...". The name sometimes is very strange but it kinda obeys a pattern (/dev/mmc1cb1p1, for example... MMC is from Memory Card).

Once you're sure about the device name, pay attention and take the lasts digits after the last character (this one included) from it (in our example mmc1cb1p1 we took off p1).
Type:
$sudo dd if=<filename>.img of=<devicelocation> (in our example it would be /dev/mmc1cb1)

WARNING: it WILL take some minutes (~20 / 30). When it's finished, simple unmout the device.
$umount <devicelocation> 

Remove the MicroSD and it's done. Now, you can plug the MicroSD into the Beaglebone. Keep "user button" pressed and plug the BBB into the USB. As soon as the leds start to blink, release the user button.


Connect the BeagleBone into your computer and open the Linux terminal.
Fist check if it is really connected into your computer:
$ ifconfig 

When the connection appears with the IP 192.168.7.2, then it's connected.



Type:

$ ssh debian@192.168.7.2

Now save the directory that contains the downloaded files into the BB.
scp -r "path" debian@192.168.7.2:/debian/home 


Go to the directory that they were saved.


Then type:

$ make all
$ chmod +x run.sh
$ chmod +x run_arm.sh
$ ./run_arm.sh

After every step is finished, all the results will be saved into a .txt on the "saidas" directory that was automatically created. 


To test into the PC:


The files needed for this test are:
    - run.sh
    - run_all_x86.sh
    - trabalho_clock.cpp
    - trabalho_time.cpp

    - time_x86
    - clock_x86


After downloading the codes from the repository, open the terminal from Linux and go to the directory that they were saved.

Then type:
$ make all
$ chmod +x run.sh
$ chmod +x run_all_x86.sh
$ ./run_all_x86.sh

After every step is finished, all the results will be saved into a .txt on the "saidas" directory that was automatically created.

Get the data and create a graph using Gnuplot:

  The file needed for this part:

    - gnu_test.cpp

First download the file above into the 'saidas' directory that was created before.


Open linux terminal em go to the 'saidas' directory, then type:

$ g++ gnu_test.cpp -o gnu
$ ./gnu file_1, file_2 , file_3, newfilename

For example: 


$./xxxxxxx time_x86_1, time_x86_2, time_x86_3, pc_time

After doing this for every kind of test, type in the terminal:

$ sudo apt-get install gnuplot


after the dowload is finished, type:


$ gnuplot 


gnuplot> set title ’titleName’

gnuplot> set  xlabel 'vector length'; set ylabel 'ordinateName'
gnuplot> set key box title ’Sorting Functions’


gnuplot>  plot 'newfilename.txt' using 1:2:3 with yerrorbars title 'Quick STD'

gnuplot>  rep 'newfilename.txt' using 1:2 with lines title 'Quick Sort'

gnuplot>  rep 'newfilename.txt' using 1:4:5 with yerrorbars title 'shell STD'

gnuplot>  rep 'newfilename.txt' using 1:4 with lines title 'Shell Sort'

gnuplot>  rep 'newfilename.txt' using 1:6:7 with yerrorbars title 'Bubble STD'

gnuplot>  rep 'newfilename.txt' using 1:6 with lines title 'Bubble Sort'

Following the example before:


$ gnuplot 

gnuplot> set title ’PC - Time’

gnuplot> set  xlabel 'vector length'; set ylabel 'Time'
gnuplot> set key box title ’Sorting Functions’


gnuplot>  plot 'pc_time.txt' using 1:2:3 with yerrorbars title 'Quick STD'

gnuplot>  rep 'pc_time.txt' using 1:2 with lines title 'Quick Sort'

gnuplot>  rep 'pc_time.txt' using 1:4:5 with yerrorbars title 'Shell STD'

gnuplot>  rep 'pc_time.txt' using 1:4 with lines title 'Shell Sort'

gnuplot>  rep 'pc_time.txt' using 1:6:7 with yerrorbars title 'Bubble STD'

gnuplot>  rep 'pc_time.txt' using 1:6 with lines title 'Bubble Sort'
Then, click on the down arrow on the top left of the plot screen(on the left side of an green circular arrow), and select "Export to PDF" saving wherever you want. We will save into the 'saidas' directory. 
 
Results:


 - BeagleBone Black with Time:

 

  - BeagleBone Black with Clock:

 

 - PC with Time:


  
 - PC with Clock:
 

 

Conclusion:


After analysing the results, with the Shell and Quick Sort the performance difference does not appear much, but with the Bubble Sort it is very clear that the BeagleBone performance is very low compared to the PC. This can be verified by the difference in the growing rate.