Google Ads

June 29, 2015

Linux C/C++ fork () Example

If you ever wanted to do multiple tasks at the same time in your C/C++ program then Linux fork () system call function is for you. When your C/C++ compiled binary program begins execution, it creates a main process in which all the program instructions are executed. In Linux every program you run will create one or more processes. Inside each process the program instructions will be executed sequentially. Which means inside one process without completing one task the program will not be able to do another task and that is where fork () function comes in handy. The fork () function will let you create a new process which is a exact copy of the main process but completely independent and run alongside the main process. For example, if you are copying a file in the main process then the new process created by fork () can be used to update the user interface for the copy operation. 

Things to remember about processes are:

  • Processes are one of the building blocks for multitasking in Linux
  • Each process has it's own unique id provided by the Linux kernel by which the process can be tracked for different purposes
  • Processes can run independently to each other, therefore closing or terminating one process does not effect the other processes
  • Any process will have their own memory space, therefore variables from stack and heap from one process are not accessible by other processes
Now, lets build a simple C program to see how fork () can be utilized

In the program we call the main process as parent process    , and the new process created from inside main process as child process. This naming convention for processes is very typical, since one process can create another new process by using fork().

We build a simple program where, parent process counts to 10 while at the same time child process counts to 20. After finishing counting the parent process waits for the child process to end.

Code:


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

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main (int argc, char *argv[])
{
    pid_t child_id;
   
    child_id = fork ();
   
    if (child_id == -1) {
        printf ("Creating new process by fork() failed!\n");
        return 1;
    }
    else if (child_id == 0) {
        /* code block for child process */
        int count;
        for (count = 1; count < 10; count++) {
            printf ("Child counting: %d\n", count);
            sleep (1);
        }
        _exit (0);
    }
    else {
        /* code block for parent process */
        int child_exit_status;
        int count;
        printf ("Child process id: %d\n", child_id);
        for (count = 1; count < 5; count++) {
            printf ("Parent counting: %d\n", count);
            sleep (1);
        }
        printf ("Waiting for child to end\n");
        wait (&child_exit_status);
        printf ("Child exited with %d\n", child_exit_status);
    }

    return EXIT_SUCCESS;
}
The above code should print the following output in the terminal:


Child process id: 7225
Child counting: 1
Parent counting: 1
Parent counting: 2
Child counting: 2
Child counting: 3
Parent counting: 3
Child counting: 4
Parent counting: 4
Child counting: 5
Waiting for child to end
Child counting: 6
Child counting: 7
Child counting: 8
Child counting: 9
Child exited with 0


Now, let's go through the most important elements in the code:

We need to include unistd.h for the fork function. The other two header files types.h and wait.h are required by the wait () function. First, we create a variable of type pid_t for storing child process id which will be returned by the fork () function. The fork function returns -1 if the function can not create a new process and if successful fork() returns 0 to the child process and the process id of created process (child) to the parent process (main process). Therefore, inside the child process the value for child_id would be 0 and it would be child process id inside parent (main) process. Inside the child process block the _exit function is used to terminate the child process. The sleep function inside the for loop blocks will suspend the respective execution for specified amount of seconds given in the parameters, in our case it is one second. And finally the wait function will suspend the parent (main) process until state of one of the child processes changes, in our case when the child process exits. And finally, the exit status of the child process is retrieved by using the wait function which is stored in the child_exit_status variable.

Hopefully, this tutorial helped you learn basic about processes.
 

Download the fork() example source file and test it by yourself:

fork.c

June 20, 2015

Install Ralink RT3290 Wi-Fi driver on Ubuntu based distributions

Note: Ubuntu 17.10 has a builtin driver (rt2800pci) which performs good and usable. 

Ralink. RT3290 is a PCIe device which combines 802.11bgn Wi-Fi and Bluetooth 3.0 devices in a single chip. Currently, Linux kernel has experimental support for RT3290 wireless through the module named rt2800pci. The state of this module is such that in many circumstances you will have very weak wireless signals.


Ubuntu 15.04 comes with Linux kernel version 3.19 and the problem of weak RT3290 wireless signals is still prevalent since by default Ubuntu 15.04 will be using Linux kernel rt2800pci module. However, there is a official driver available for Linux from MediaTek for Ralink RT3290 STA wireless device. This driver will fix weak signal and many other problems on Ubuntu 15.04 based distributions. To install this driver simply download the following file and after extracting the file in the Home directory of your Ubuntu, follow the instructions in the ReadMe file inside the extracted RT3290 folder (You may need to shutdown computer and boot again to get it working). 


RT3290 Linux Driver (Ubuntu 15.04)


After installing the driver hopefully you will have better wireless experience in your Ubuntu system :)


For fedora users, please try the following:


RT3290 Linux Driver


*Updated package for latest Ubuntu based distributions (tested against Ubuntu 17.04). Also suitable for Ubuntu 15.04 based distributions:


RT3290 Linux Driver (Ubuntu 16.04 or latest)



*If you update Linux kernel then you will have to run the following commands from the RT3290_u16 directory to compile and install the driver for new kernel:


./compile.sh

sudo ./install.sh

*If you do not see Wi-Fi network, you may need to activate it manually by executing the following command from RT3290_u16 folder or reboot computer:


sudo ./activate-net-rt



*If you are able to see WIFI interface but can not connect to any WIFI network then you should try wicd Network manager instead of default network manager for connecting to WIFI networks. To do that, on Ubuntu first install wicd network manger by entering following command in the terminal:


sudo apt-get install wicd


and then remove default gnome network manager of Ubuntu by entering following command:


sudo apt-get remove network-manager-gnome


Finally, restart computer and use Wicd Network Manger to connect to WIFI networks.


Cheers