Tuesday, 19 May 2020

C++ compiler setup on windows os machine

Step 1) Install mingw64 compiler

There are two ways to install this compiler.
A) Download mingw64 installer from http://mingw-w64.org/doku.php/download . Select MingW-W64-builds 
It will download installer, and run that file. Chose correct settings during setup like 32bit/64bit configuration.

B) If you are facing any issue with type A, then one can directly download mingw64.7z file.
Once downloaded, extract the .7z file onto your PC using 7-zip and extract to a folder such as C:\MinGW64.

You don't have to put it in 'Program Files' like the installer does.

Step 2) Once installation is over then set windows path.
Open control panel, search "env", select edit system settings. Now, under system variables
select "path" and select edit option. Now, add new entry "C:\<path to mingw64>\bin" and move it up little bit, and just below system32 paths.
Click ok to all.

Step 3) Check if C++ compiler installation is successful
Now, open terminal, and run "g++ --version". If you see mingw related info then installation is success.

Note: if you still have trouble downloading the compiler, click on the 'Problems Downloading?' button on the next screen so you can try to download it from different site around the world.

============================================================
Codelite IDE setup

Download Codelite IDE from: https://codelite.org/

Open codelite IDE, select "Run the setup wizard" under "help" section. Map/scan for already installed c++ compiler "mingw64" and setup this path.

Create workspace with C++ type.

Create Project with below options:
  Category: console
  Type: Simple executable (g++)
  Compiler: Mingw
  Debugger: GNU gdb debugger
  Build system: Default

Update project configuration as
Linker option : -static
Compiler options (add): -Wall; -std=c++17;
--------------------------------------------------------------------
To build & Run: Select "Run" under "build" section
===============================================================

Friday, 7 September 2018

Program to demonstrate using O_DIRECT option in file operations and writev() call

Program

/* Below program showcases the use of O_DIRECT file option. Also, demonstrates writev() use */

#include <iostream>
#include <fcntl.h>    /* For O_RDWR */
#include <unistd.h>   /* For open(), creat() */
#include <string.h>   /* For strlen() */
#include <malloc.h>   /* For memalign() */
#include <sys/uio.h>  /* For struct iovec */
#include <stdint.h>   /* For datatypes */

#define O_DIRECT_ENABLE 1
using namespace std;

int main(int argc, char *argv[])
{
        if (argc != 3) {
            cout << "run: ./<prog_binary_name> <input_file_name> <outputFileName>"<<endl;
            return 0;
        }

        int fd_out, fd_in, ret;
#if O_DIRECT_ENABLE
        fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC | O_APPEND | O_DIRECT, S_IRWXG | S_IRWXU);
        fd_in = open(argv[1], O_RDONLY | O_DIRECT);
#else
        fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, S_IRWXG | S_IRWXU);
        fd_in = open(argv[1], O_RDONLY);
#endif
        if(!fd_out || !fd_in) {
            cout << "Unable to open one of the given files"<<endl;
            return 0;
        }
        char file_data1[4096];
        char *file_data2 = (char*)memalign(4096, 4096);

        /* Below vector declaration won't compile since aligned_allocator defined in xilinx lib.
        vector<uint8_t, aligned_allocator<uint8_t>>  file_data3(4096);
        read(fd_in, file_data3, 4096);
        int file_data3_len = strlen(file_data2);
        */

        read(fd_in, file_data1, 4096); /* not work with O_DIRECT option, it returns 0 bytes */
        int file_data1_len = strlen(file_data1);

        /* works with O_DIRECT since memalign is used for creating the buffer */
        read(fd_in, file_data2, 4096);
        int file_data2_len = strlen(file_data2);

        cout<<"read_4k_nonMemAlign, read_4k_memAlign: "<<file_data1_len<<", "<<file_data2_len<<endl;

        char *data = (char*)malloc(sizeof(char)* 4096);
        strcpy(data, "salkfalksfjslfnsdlfksdklfnsldkfslkdfskldfjskldngslkdgjsdngslkdgskldglksdglksdglsdglsdgklsdfgdfkg");
        int data_len =  strlen(data);

        char *data2 = (char*)memalign(4096, 4096);
        strcpy(data2, "12345678912345678912345678912345678912345678912345678912345678912345678912345678912345678912345");
        int data2_len =  strlen(data2);

        ret = write(fd_out, data, data_len); /* fails with -1 if O_DIRECT enabled */
        cout<<"data(malloc) write ret: "<<ret<<endl;

        ret = write(fd_out, data2, 4096); /* write() works with O_DIRECT since data buffer is memaligned and given size is 4096 also aligned */
        cout<<"data2(memalign) write ret: "<<ret<<endl;

        ret = lseek(fd_out, data_len, SEEK_SET);
        cout<<"seek ret1: "<<ret<<endl;
        ret = write(fd_out, file_data2, 4096); /* write() works with O_DIRECT since buf is memaligned */
        cout<<"write_ret2: "<<ret<<endl;

        ret = lseek(fd_out, 0, SEEK_CUR);
        cout<<"seek ret2: "<<ret<<endl;

        struct iovec    iov[4];
        iov[0].iov_base = (char *) file_data2;
        iov[0].iov_len  = 4096;
        iov[1].iov_base = (char *) data2;
        iov[1].iov_len  = 4096;//data2_len;
        iov[2].iov_base = (char *) file_data1;
        iov[2].iov_len  = file_data1_len;
        iov[3].iov_base = (char *) data;
        iov[3].iov_len  = data_len;

        int total_len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len + iov[3].iov_len;
        cout<<"total_len: "<<total_len<<" {"<<data_len<<", "<<data2_len<<", "<<file_data1_len<<", "<<file_data2_len<<"}"<<endl;

/*        ret = writev(fd_out, &iov[0], 4); */
        ret = writev(fd_out, &iov[0], 2);
        cout<<"writev ret: "<<ret<<endl; /*writev() works fine when O_DIRECT flag removed in file open option. */
        ret = lseek(fd_out, 4096+data2_len, SEEK_SET);
        cout<<"seek ret: "<<ret<<endl;
        ret = write(fd_out, data, 4096); /* write() works with O_DIRECT since buf is memaligned */
        cout<<"ret: "<<ret<<endl;
        close(fd_out);
        close(fd_in);
        return 0;
}

Program Output

$g++ odirect_writev_prog.cpp -o odirect_writev_prog
$ ./odirect_writev_prog input.txt output_fd.txt
read_4k_nonMemAlign, read_4k_memAlign: 0, 4096
data(malloc) write ret: -1
data2(memalign) write ret: 4096
seek ret1: 96
write_ret2: -1
seek ret2: 96
total_len: 8288 {96, 95, 0, 4096}
writev ret: -1
seek ret: 4191
ret: -1

Tuesday, 31 October 2017

Generate Binary Numbers using Queue data structure

Generate Binary Numbers using Queue data structure

Problem Statement (from geeksforgeeks):

Given a number n, Write a program that generates and prints all binary numbers with decimal values from 1 to n.
Input:
The first line of input contains an integer T denoting the number of test cases.
The first line of each test case is N.

Output:
Print all binary numbers with decimal values from 1 to n in a single line.

Constraints:
1 ≤ T ≤ 100
1 ≤ N ≤ 500

Example:
Input
2
2
5
Output
1 10
1 10 11 100 101

Solution:

/* Generating Binary Numbers of given input using Queue Data structure.
 * Implemented in C language.
 * Used Circular Queue as part of the implementation
 */

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct queue{
    int cap;
    int front, rear;
    int size;
    char array[1000][10];
};

struct queue* createQueue(int n){
    struct queue *q = (struct queue*)malloc(sizeof(struct queue));
    
    q->cap = n;
    q->front = -1;
    q->rear = n - 1;
    q->size = 0;
    return q;
}

int isQueueEmpty(struct queue *q){
    return q->size == 0;
}

int isQueueFull(struct queue *q){
    return q->size == q->cap;
}

void enQueue(struct queue *q, char *ch){
    if (isQueueFull(q))
        return;
    q->rear = (q->rear + 1) % q->cap;
    strcpy (q->array[q->rear], ch);
    q->size += 1;
}

char* deQueue(struct queue *q){
    if (isQueueEmpty(q))
        return NULL;
    q->front = (q->front + 1) % q->cap;
    q->size -= 1;
    return q->array[q->front];
    
}

void printQueue(struct queue *q){
    printf("Queue elements...\n");
    for (int i = 0; i < q->front; i++)
        printf("ele: %s\n", q->array[i]);
}
void toBinary(int n) {
    struct queue *q = createQueue(n);
    
    enQueue(q, "1");
    
    for (int i = 1; i <= n; i++) {
        char d1[10], d2[10];
        strcpy(d1, deQueue(q));
        printf("%s ", d1);
        strcpy(d2, d1);
        strcat(d1, "0");
        strcat(d2, "1");
        enQueue(q, d1);
        enQueue(q, d2);
    }
    printf("\n");
    free(q);
}

int main()
{
    // Note that size of arr[] is considered 100 according to
    // the constraints mentioned in problem statement.
    int arr[100], t, n;
 
    // Input the number of test cases you want to run
    scanf("%d", &t); 
 
    // One by one run for all input test cases
    while (t--)
    {
        // Input the size of the array
        scanf("%d", &n);
        toBinary(n);
    }
    return 0;
}

Friday, 2 September 2016

Python Learning - Notes


I have prepared this document during my Python course from sololearn.com

Thursday, 17 December 2015

Tuesday, 30 September 2014

Open Quiz on basic OS Kernel concepts


Open Quiz on basic OS Kernel concepts

The quiz contains total 17 questions and only one option is correct and clue for the answer is also given.

  1. When does kernel starts loading? (Clue)

  2. When power on the system
    Before Bootloader starts (booting process)
    After Booting process
    When init process start

  3. What is the process id defined for init process (Clue)

  4. 0
    1
    Not defined
    Defined but vary from system to system

  5. Where does executable instructions of any program stored? (Clue)

  6. Text segment
    Stack memory segment
    Heap memory segment
    Block Started by Symbol (BSS) segment

  7. Which one of the followings is not responsibility of the Kernel (Clue)

  8. Process management
    Loading the operating system into memory
    File management
    Device Input/Output control

  9. Which one of the followings is not a device driver type (Clue)

  10. Character device driver
    Integer device driver
    Block device driver
    Network device driver

  11. What is a deferrable function in kernel? (Clue)

  12. Mechanism for supporting delayed execution of functions, used in interrupt handlers
    Used in kernel context to delay the execution of piece of code
    Used to find the behavior of a given function
    It is a function which signals the other function after receiving an interrupt

  13. Which one of the followings is not true about Mutex and Semaphore? (Clue)

  14. Mutex and Semaphore are kernel resources to provide synchronize services
    Mutex and Semaphore provides mutual exclusion property
    Mutex used within in a process and Semaphore can be used across processes
    Mutex and Semaphore both runs in kernel space

  15. Which of the followings memory allocation technique uses Page Table setup for accessing the allocated memory locations? (Clue)

  16. Kzalloc()
    Kcalloc()
    vmalloc()
    Kmalloc()

  17. Select the correct APIs which are used to find the time taken for a function of piece of code in kernel (Clue)
    A) ktime_get()
    B) do_gettimeofday()
    C) get_time()
    D) getnstimeofday()

  18. Only B
    Only C
    A and B and D
    Only A and B

  19. A mechanism that will suspend/block the execution of parent (caller) process (i.e. parent can’t continue its operation) until child terminates and instructs the process manager to destroy the child process and it is called as ____? (Clue)

  20. Synchronous mechanism
    Asynchronous mechanism
    Mutual exclusion
    Work queues

  21. fork() system call is used to create a new process and it returns integer value. Which of the followings is correct? (Clue)
    A) Returns 0 in the child process
    B) Returns process ID of child process in the parent process
    C) Child and Parent process share same address space after fork() call
    D) Copy on write approach is used.

  22. A and B
    Only D
    A, B, C and D
    A, B and D

  23. Identify the child process execution code (Clue)
    pid_t pid = fork();
    if (pid == 0)
    { ___A___
    } else {
    ___B___
    }

  24. A
    B
    A and B
    Syntax is wrong

  25. Which of the followings is not true about Busy Waiting? (Clue)

  26. A process/thread run in a loop by constantly checking the event occurred condition
    There is no overhead of context switching in Busy Waiting
    udelay(), mdelay() and ndelay() are examples of Busy waiting techniques
    A process/thread will be put into wait queue so that CPU can start the execution of the other process.

  27. What is a Memory leak? (Clue)

  28. Memory blocks which are allocated dynamically in heap, but not deallocated by the program
    Free memory block in the memory region
    A memory block which is part of the stack memory
    A memory block which is part of text segment

  29. Identify the macro, which is used to find the starting address of the structure by using its own member variables in kernel (Clue)

  30. container_of()
    base_str_addr()
    start_str_addr()
    None of the above, we don’t have such macro

  31. What is the use of __init macro? (Clue)

  32. Used for module initialization purpose and memory allotted to this function will be freed once this function tasks gets over
    Used for module initialization purpose but memory is not freed
    Used for module initialization purpose and the function will be in memory until system shutdown
    None of the above

  33. Identify the command to load a module into kernel (Clue)

  34. insmod module.ko
    insmod module
    loadmod module.ko
    loadmod module

Tuesday, 5 August 2014

[Operating System] Mutex vs Semaphore

Mutex and semaphore are used for providing mutual exclusion property, and these are Kernel resources to provide synchronization services. 

Now comes to differences:
  1. Mutex job is mainly to provide Mutual Exclusion and Semaphore is mainly used for resource sharing.
  2. Mutex serializes the access to critical section of code i.e. only one process/thread can access this code at a time. (Single Resource Manager)
  3. Semaphore looks like Mutex if the semaphore count/value is equal to 1 since if one thread acquires lock then other thread trying to access the critical section should wait until the 1st thread releases the acquired lock. But, the purpose of using the Mutex and Semaphore is different.
  4. Semaphores are of two types based on this value
     Semaphore value = 1, then binary semaphore Semaphore values > 1 then counting semaphore i.e. it can handle multiple identical resources with its count value.
  5. Mutex is just a lock, whoever acquired it they should release that lock so that next process/thread which is in the queue will get this lock. There is no signal mechanism for Mutex. But, Semaphore can signal the other process/threads by simply increment the semaphore value by 1. So, Semaphores are mainly used for synchronizing the multiple processes/threads.

Mutex
Semaphore
A Locking mechanism used to synchronize access to a resource. Mutex is just a Lock.
A Signaling mechanism and used for message passing mechanism
Only one task can acquire the Mutex and can release it. Mutex maintains ownership info
Lacks of ownership details
Mutex is used within a process by multiple threads
Semaphore can be used across processes
Mutex can be used only in userspace
Semaphore can be used in Kernel space also

What is Critical Section?
Definition: A Critical section is a piece of code that accesses shared resources that must not be concurrently accessed by more than one thread of execution.
So, some Synchronization mechanism are being used to ensure this for ex: Mutex and Semaphores

What is Mutual Exclusion Property?
It is a property to ensure that no two concurrently executing threads/processes are in their critical section at the same time.

What is Synchronization?

Definition: Synchronization is a mechanism to ensure that two concurrently executing threads/processes do not execute specific portion of code/program at the same time. This specific portion of code/program is called as Critical Section.

Reference: Wikipedia and GeeksForGeeks

Sunday, 6 July 2014

[Kernel Programming] Cross compile a module for ARM platform

My initial Kernel Programming posts in this blog contains the following info

  • how to write a module,
  • how to compile a module using a Makefile,
  • how to insert/remove a module into linux platform machine
Please check my previous posts for this information below

Now, I will share the required data for writing a simple module for ARM platform in this post. Please follow below steps for the same. 

[Note: You should have working linux kernel source code, and able to flash this code on any android device for testing this module.]

Step-1: Goto Linux Kernel source directory and set $TOP variable with this path
Example: If kernel source code is present on home directory then
export TOP = $(/home/your-machine-username/kernel_source_dir)

Step-2: Goto kernel folder from $TOP and create a temporary directory there.
Example: 1. cd $TOP/kernel
                2. mkdir test

Step-3: Now, add simple module file in the test directory.
Example: simple.c

#include<linux/module.h> /* Needed by all modules *MUST* */

int init_module(void) {
         printk(KERN_ALERT "1st module program: Module Inserted\n");
         return 0;
 }

 void cleanup_module() {
         printk(KERN_ALERT "1st module program: Module Removed\n");
 }

Step-4: Add Makefile for this module.
Example: Makefile
obj-m += simple.o

Only above one line is enough here.

Step-5: Now, we have two files in the test directory. They are simple.c and Makefile. Goto kernel folder (cd $TOP/kernel)
Step-6: Compile our test module using make command

make -j4 ARCH=arm CROSS_COMPILE=$TOP/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/arm-linux-androideabi- O=$TOP/out/target/product/<product-name>/obj/KERNEL M=$TOP/kernel/test

Options description:

-j4: Describes how many threads GNU compiler will make use of, to compile the module. Normally, the number(just after 'j') should be twice the number of CPU cores available for your pc.

ARCH: Describes the destination platform architecture. The name of the architecture can be found in the $TOP/kernel/arch/ directory.
Example: arm platform: $TOP/kernel/arch/arm
                arm64 platform: $TOP/kernel/arch/arm64

CROSS_COMPILE: Specifies the correct tools path to be used for generating object files and binary files for our test module.

O: Specifies the path to where the generated object files have to go.

M: Path to input module directory to compile the required module.

Step-7: After successful compilation of our test module, we can see simple.ko file get generated in $TOP/kernel/test directory.

Step-8: Now, insert this module into destination platform using insmod command.
If the destination platform is accessed through adb shell then do the following.
  1. sudo adb push $TOP/kernel/test/simple.ko /data
  2. sudo adb shell
  3. su -
  4. cd /data
  5. Insert our test module (simple.ko) using below command
    insmod simple.ko
  6. We can see the output of the insmod using below command
    dmesg
    And observe, "1st module program: Module Inserted" got printed in the log
  7. Use below command for removing our module
    rmmod simple
I hope this data is useful to compile any module for different platform.

References:
https://www.kernel.org/doc/Documentation/kbuild/kbuild.txt


Tuesday, 8 April 2014

[Kernel Programming] Allocation of memory in Kernel

Allocation of memory in Kernel


kmalloc()kzalloc()kcalloc()vmalloc()
Allocates contiguous physical blocks of memory in byte-sized chunksAllocates contiguous physical blocks of memoryAllocates memory for an arraysame as kmalloc, except it allocates memory that is only virtually contiguous
Memory is not set to zeroMemory is set to zeroMemory is set to zerounderling physical memory can be discontiguous
void * kmalloc (size_t size, int flags)void * kzalloc (size_t size, int flags)void * kcalloc  (size_t n, size_t size, unsigned int __nocast flags);void * vmalloc (unsigned long size)
Depends on the flag used, it may sleepDepends on the flag used, it may sleepDepends on the flag used, it may sleepCan sleep, so don’t use it in interrupt context
Can allocate upto 4MBytesSame as kmallocNeed to check ?Can obtain very large regions of memory
Simple and fastSimple, preferable and fastSimple and fastSlow compare to kmalloc


Vmalloc(): Slower and not advisable if memory requirement is less. Because,
  1. Makes non-contiguous physical memory to continuous virtual memory
  2. Setting up the page table entries
  3. Pages obtained from vmalloc() must be mapped to their individual pages since physical memory is not contiguous
  4. Results in much greater TLB, performance is affected.

Note: malloc() function also works in same manner. i.e. allocated memory in continuous in virtual address space of the processor, but there is no guarantee that they are contiguous in the physical address space (physical RAM)

Flag: controls the behavior of memory allocation and divided into 3 groups
–Action modifiers: How to allocate memory. Ex: can sleep or not
–Zone modifiers: Where the request should be satisfied. (ex: DMA buffers)
–Types: types of allocation


FLAG TypeAction ModifierZone Modifier
GFP_KERNEL(__GFP_WAIT | __GFP_IO | __GFP_FS) -NA-
GFP_ATOMIC__GFP_HIGH -NA-
GFP_DMA__GFP_DMA


GFP_ATOMIC:  Allocation is High priority and does not sleep. This flag will  be used in Interrupt handlers, bottom halves where kernel should not sleep
GFP_KERNEL: Allocation will be Normal priority and can be used in process context, and safe to sleep

Action Modifiers and Zone Modifiers:

__GFP_HIGH: The kernel can access emergency pools.
__GFP_WAIT: The kernel can sleep
__GFP_IO: The kernel can start disk I/O
__GFP_FS: The kernel can start filesystem I/O
__GFP_DMA: Allocate only DMA-capable memory

References:
Third Edition of Linux Device Drivers, by Jonathan Corbet

Monday, 16 December 2013

[C Programming] Function Pointers basics in C

Function Pointers

Definition

Function pointers are pointers, which points to the address of a function. Function pointers are variables only, so it will be declared and defined like other variable.

Syntax

<data_type> (*function_pointer_name) (variable data_type list) = NULL; /* defining function pointer and initializes to NULL */

The signature of this function pointer should match with the signature of function which address is stored in this pointer.

Sample code

float doMath (float a, float b) {
 /*
    desired code
 */
return result;
}

int main() {
float (*math_pointer) (float, float) = NULL;

math_pointer = &doMath; /* pointer to function doMath() */

output = math_pointer (10.5, 11.1);
/*
   desired code
*/
return 0;
}


Usage

  1. To replace switch/if conditional statements
  2. To implement late-binding (runtime binding) (C++ scenario)
  3. To implement callbacks

Example for Usage-1

#include<stdio.h>

float addition (float a, float b) {
 return a + b;
}

float subtraction (float a, float b) {
 return a - b;
}

float multiplication (float a, float b) {
 return a * b;
}

void select (float a, float b, char opCode) {
float result;
switch(opCode)
{
 case '+': result = addition(a, b); break;
 case '-': result = subtraction(a, b); break;
 case '*': result = multiplication (a, b); break;
}
printf("Result: %f\n", result);
}

/* Replace the above switch statement with function pointer */
void select_function_pointer (float a, float b, float (*math_pointer)(float, float)) {
float result = math_pointer(a, b); /* Calling function using function pointer */
printf("Result: %f\n", result);
}

void main()
{
  float a, b;
   
  select(10, 15, '+');
  select_function_pointer (10, 15, &addition); /* Passing function as an address argument */
}


Array of Function Pointers

Since the Function pointer is a variable, we can define array of function pointer using below syntax.


Syntax-I
tyepdef <data_type> function_pointer_name (argument data_type list);
function_pointer_name array_fun_pointer [10] = {NULL};

Syntax-II
<data_type> (*array_fun_pointer[10])(argument data_type list) = {NULL};

array_fun_pointer [0] = &function1;
.
.
Calling function using function pointer
(*array_fun_pointer[0]) (arguments); or
array_fun_pointer[0](arguments);


Implementation of Callbacks using Function Pointers

It is a bit more complex syntax. Try to understand the callback mechanism in C by using below sample code:

void insert_array (int *array, size_t size, int (*getNextValue) (void))
{
     for (int i = 0; i < size; i++)
        array[i] = getNextValue();
}

int getNextRandomValue()
{
   return rand();
}

int main()
{
   int a[10];
   insert_array(a, 10, &getNextRandomValue);
}

Here, the function insert_array() takes the 3rd argument as the function address using function pointer getNextValue. And, the callback function is getNextRandomValue(), returns random value. The function insert_array() calls this callback function using function pointer getNextValue for inserting the values into the array.

The similar explanation can be found here (from Stackoverflow)

You might also like

Related Posts Plugin for WordPress, Blogger...