Showing posts with label Linux. Show all posts
Showing posts with label Linux. Show all posts

Tuesday, December 8, 2020

How I backup my files

Backups are important. You never know when you will lose your files! A good backup tool and a good backup procedure are essential in today's digital world.

I've been using Unison as my 'backup' solution for a while now,  though it is more of a file synchronization tool. It allows me to efficiently replicate my Documents folder (which is about 20GB) across my Linux devices. Fortunately, Linux is my main OS.

I use a desktop in the office, a laptop at home, and a laptop I carry with me. I also have an external drive at home as extra backup storage which contains a VeryCrypt volume. My Documents folder contains essential files only.  It does not contain media files like photos, mp3s, and videos.

Recently, I purchased a storage volume from Digital Ocean to use as extra backup storage in the cloud,  which I also sync using Unison. This will allow me to access my files anywhere and in Windows. I don't want Google to see my files in the meantime.

I make sure to sync my office desktop, my cloud backup, and my laptop before I leave the office. When I arrive home, I sync my laptop with my home laptop. I only sync my external storage on weekends.

All I can say is Unison made my life easier and you should give it a try.

Monday, March 9, 2020

Count the number of downloads of publications

I make my publications public. I was curious about the download count of the papers so I wrote a bash script. My site is using Nginx as the web server software thus I can process the access logs which contain the HTTP requests. So as of writing this post and from Feb 23, 2020, the following are the download counts.

     21 /publications/pabico-pitj2008-perceived.pdf
     14 /publications/tolentino-iwcfu2012-disaster.pdf
     13 /publications/raquel-iwcfu2012-parallel.pdf
     12 /publications/hermocilla-ncite2016-osv-mpi.pdf
     11 /publications/escamos-acrs2015-comparison.pdf
     10 /publications/aluning-ncite2010-terra.pdf
      9 /publications/silapan-iwcfu2012-using.pdf
      8 /publications/lara-ncite2017-exploring.pdf
      8 /publications/duldulao-ncite2011-an.pdf
      7 /publications/lactuan-pitj2011-a.pdf
      7 /publications/hermocilla-pitj2009-ics-os.pdf
      7 /publications/cabigting-iwcfu2012-eucalyptus.pdf
      7 /publications/borja-iwcfu2012-squigis.pdf
      7 /publications/aguila-ncite2015-sustainable.pdf
      5 /publications/lactuan-ncite2011-a.pdf
      5 /publications/hermocilla-ncite2014-p2c.pdf
      5 /publications/carpio-pcsc2017-skylab.pdf
      4 /publications/hermocilla-model2009-a.pdf
      4 /publications/escamos-acrs2016-bertud.pdf
      3 /publications/manzano-sfrc2013-squidler.pdf
      3 /publications/macasaet-iwcfu2012-a.pdf
      3 /publications/eclarin-ncite2014-dgrav.pdf
      3 /publications/bulalacao-sfrc2015-is.pdf
      3 /publications/aguinaldo-iwcfu2012-automatic.pdf


The one-liner below does the trick.
Loading or something, this is just text to display while the browser pulls the gist....

Wednesday, October 30, 2019

Using VBoxManage to run BioLinux, headless


1. Import the appliance

$ vboxmanage import bio-linux-8-latest.ova

2. Check if the VM was imported

$ vboxmanage list vms
$ vboxmanage showvminfo "Bio-Linux-8.0.7" | less

3. Modify the VM to use bridged network connection

$ vboxmanage modifyvm "Bio-Linux-8.0.7" --nic1 bridged --bridgeadapter1 eno1

4.  Start the VM in headless mode

$ vboxmanage startvm "Bio-Linux-8.0.7" --type headless

5. Check if the VM is running

$ vboxmanage list runningvms

6. Get the assigned IP address to the VM

$ vboxmanage guestproperty enumerate {`VBoxManage list runningvms | awk -F"{" '{print $2}'` | grep IP | awk -F"," '{print $2}' | awk '{print $2}'

7. Hard shutdown of the VM

$ vboxmanage controlvm "Bio-Linux-8.0.7" poweroff

8. Use SSH to connect to the VM

Thursday, September 5, 2019

Introduction to debugging C programs using GDB


Instead of just reading the code, a debugger such as GDB, can be used to find errors in C programs. GDB is available in linux distributions.

Example code, prod.c :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>

int mul(int x, int y){
   int prod;
   int i;

   prod=0;
   for (i=0;i<y;i++){
      prod=prod+x;
   }
   return prod;
}

int main(){
   int a=4;
   int b=3;

   printf("The product of %d and %d is %d\n",a,b,mul(a,b));
   
   return 0;

} 

The following are the typical activities when debugging C programs:

1.  Create the executable with debug information

$ gcc -g -o prod.exe prod.c

For assembly language programs:

$ nasm -g -F dwarf -felf64 prod.asm
$ ld -o prod.exe prod.o


2.  Load the program in GDB

$ gdb prod.exe

3. View the source code listing

(gdb) list
 
4. Set a breakpoint

(gdb) b * main

5. Execute until breakpoint

(gdb) r

6. Execute next line

(gdb) n

7. View current line being executed

(gdb) frame

8. Step into a function

(gdb) s

9. View local variables

(gdb) info locals

10. Print variables

(gdb) print a

11. Set new values for variables

(gdb) set variable a=5

12. Continue execution until next breakpoint

(gdb) c

13. Quit

(gdb) quit

Tuesday, April 17, 2018

Memory and Linux Processes

Physical Memory and Virtual Memory

The CPU of the computer is responsible for executing instructions (machine code). These instructions, as well as the data used by these instructions, should be placed in the physical memory (which is on the actual memory chip).  Each byte in the physical memory is accessed through a physical address. The physical address is placed in the memory address register (MAR) when writing or reading to/from memory. The size of the MAR and address bus determine the range of addresses that can be used. For example, if MAR is 32 bits, then addresses from 0 to 0xFFFFFFFF (up to 4GB) can be accessed.

Image result for Memory Address Register image
(https://archive.cnx.org/contents/6876272b-9b8f-463c-848b-1d388dccf776@1/module-5)


Modern computer architectures however provide a virtual or logical memory view to the CPU. The CPU accesses each byte through a virtual or logical address. The range of virtual addresses is usually the same as the range of the physical addresses, although the actual amount of physical memory may be less or more than the addressable range.

Virtual addresses must eventually be translated to physical addresses to access instructions and data from the physical memory. This translation/mapping is technically called address binding. The translation is performed by the Memory Management Unit (MMU) hardware component. Schemes such as segmentation and/or paging are often used to support different features and needs, such as protection . The operating system also performs some operations related to this address translation by invoking specialized CPU instructions.


(https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/MMU_principle_updated.png/325px-MMU_principle_updated.png)


Application programmers need only to concern themselves with the virtual memory. Kernel developers, however, need to be concerned with both virtual and physical memory as part of implementing the memory management component of the operating system.

Having a virtual memory view provides flexibility, especially in multiprogramming and timesharing operating systems. It allows a process to "believe" that it has exclusive and full access to the entire physical memory, even though it does not. Also, virtual memory allows processes to access code and data that are in secondary storage (disk) as if they are in physical memory through a scheme called swapping.

Process Memory Map in Linux (Ubuntu 16.04 x86_64, GCC 5.4.0)

When writing C programs, variables are used to hold data and functions are used to implement operations. The variables and functions have names, which are symbolic. In compiler design, names are generally called symbols. Consider a payroll program, the variable named age can be used to hold the age of an employee. Also, the function named compute_salary can be used to perform the operation of computing the salary of an employee.

When a C program is compiled and linked, the variables and functions are converted to memory locations/addresses(in virtual memory) and machine code(object code) respectively.  Variable names and function names become memory addresses and are stored in a symbol table. The result of this conversion is stored in an executable file (aka program binary image). The executable file is what is usually run. Executable file format is usually dependent on the operating system. In Linux for example, ELF is the standard format for executable files.

Running a program actually means the loader reading the executable file and creating a process for it. When the executable file is loaded by the operating system for execution, for example via the exec() system call in Linux, the operating system allocates a portion of memory in an area dedicated for user processes.  The data and instructions are read from the executable file and placed in the allocated memory in locations which are also specified(in the symbol table) from  the executable file. Again, it is emphasized that the memory locations being referred to here is in virtual memory. Once the data and instructions are in memory, a new process control block(PCB) is created representing the process. The allocated memory becomes the process' memory map or address space and is usually a field in the PCB. The process is then scheduled for execution.

A process' memory map is divided into sections which serve different purposes. A typical memory map is shown below. The text section for instructions, the data section for initialized data, the bss section for uninitialized data, the stack section for function calls (and traditionally, parameters), and the heap section for dynamically allocated memory (via the function malloc()). Some of these sections are already defined during the compilation and linking process. Although it appears below that the memory is contiguous in virtual memory, it may not be the case in the corresponding physical memory.

(https://www.hackerearth.com/practice/notes/memory-layout-of-c-program/)
The example C program below will illustrate in what section of a process' memory map the different symbols are placed. Download binding.c, create an object file and executable file [1]. Run the executable several times and observe which variables change in address. The variables are so named to show in which section they will reside.

Compile time (output is object file):
$ gcc -fno-common -c -o binding.o binding.c

Link time (output is executable file):
$ gcc -fno-common -o binding.exe binding.c

Run time (a process is created) :
$ ./binding.exe

Next, examine the symbol table of the object file and the executable file. The first column refers to the assigned address and the fourth column refers to the assigned section.
$ objdump -t binding.o 
$ objdump -t binding.exe

Compare the entries for some of the symbols in the object file and executable file. Which file contains an address for the symbol, the object file or the executable file?
$ objdump -t binding.o | grep data_global_initialized_nonzero
$ objdump -t binding.exe | grep data_global_initialized_nonzero 

$ objdump -t binding.o | grep -w bss_global
$ objdump -t binding.exe | grep -w bss_global

$ objdump -t binding.o | grep -w text_func
$ objdump -t binding.exe | grep -w text_func

Can the symbols that start with stack_ and those stored in the heap be found?No. The stack section and heap section are allocated at run time.

Let us look where each of the sections start in memory and the symbols in each section.
$ objdump -t binding.exe | grep -w .text
$ objdump -t binding.exe | grep -w .data
$ objdump -t binding.exe | grep -w .bss

We will now use GDB to examine the process address space at run time. GDB will allow us to examine the state of the execution by allowing us to run one instruction at a time. (Try to compare the addresses at link time and at run time. Are they the same?)
$ gdb ./binding.exe
(gdb) set disassembly-flavor intel
(gdb) b main+99
(gdb) r
(gdb) disas main
(gdb) info proc mapping
   
Study the memory map. Notice that there is no heap section yet. This is because no call to malloc() has been made yet.
(gdb) ni +6
(gdb) disas main
(gdb) info proc mapping

The heap section is now present. Let us look for the variables in the sections.
(gdb) find 0x601000,+0x1000,"JACH_IN_DATA"
(gdb) find 0x601000,+0x1000,"JACH_IN_BSS"
(gdb) find 0x602000,+0x21000,"JACH_IN_HEAP"
(gdb) find 0x7ffffffde000,+0x21000,"JACH_IN_STACK_LOCAL"

How about the parameter?Is it in the stack?
(gdb) find 0x7ffffffde000,+0x21000,"JACH_IN_STACK_PARAM"

The string is not in the stack! It is in the text section! Traditionally however, parameters are pushed to the stack.
(gdb) find 0x400000,+0x1000,"JACH_IN_STACK_PARAM"

Finally, run the process to completion.
(gdb) c
(gdb) quit 

Conclusion

This post discussed some concepts in memory management in relation to C programs and Linux processes.

Figure 1. Sample Memory Map (no heap section yet)