Networking - C Processes in Linux

    Hello it's a me again! Today as you can see we start out a new Category! In our Networking Series we will talk about everything that you need to know to get starting in Network Programming. I will start off with C getting into the Basics of Linux C Programming starting with Processes, Threads and their Synchronization and ending with Server-Client Socket Communications. After C we will shortly get into how we do such things in Java. Then we could expand later on a little bit more talking about other Languages and how we can use them in Network Programming. 

    Well let's get into the topic of today that is: C Processes, but in Linux. I will first try to explain as shortly as possible how the Linux Processes work and then we will get into the Implementation part that is actually not quite difficult and uses the system call fork(). So, let's get started!


Linux Processes:

    When the Operation System starts System Processes get started and also a process called init. Many of the system processes are deamons that are running in background without the user noticing them. Init is an important process, cause in Linux the Processes form a Tree Structure in form of a parent-child relationship. So, the processes that we run will be childs of the init process and the processes that get called inside of our process will be childs of that process. Pretty useful commands are ps and jobs that give us the current running processes. I will don't talk about signals that les us terminate processes, but will upload them separately! 

    Let's now also get into how Linux is scheduling the processes using the Scheduler. Each Process in Linux has a priority value. Processes with high priority get called more often than the ones with a low priority. We can use ps -l to return the priority of all running processes. Using nice we can set the priority of a processes when calling it and using renice we can set the priority while the process is running.


Compiling and Running C Code in Linux:

    I think it would be a great Idea to tell you how to compile and run C Programs in Linux! It's actually pretty easy and you will get used to it after a long period of time.

To Compile a C Code we use the GCC Compiler using the following command:

gcc -o output_name code_name.c

To run a already compiled file we do:

./output_name

    Following this up with a & we can then run our Code in the Background, but I would suggest you to leave it for now, but if you did run the command kill -INT pid to terminate this process. If you don't have the processid inside of [] than run also jobs to find the pid of your process. I guess you would anyway don't ever create a infinite while loop for a example run, but just to make sure :)


Running Child Processes:

    In C we can run commands that we would normally run inside of the Terminal in Linux using system("command"). This same behavior works also in Windows, where I like using system("cls") that corresponds to system("clear") in Linux and clears up our Console or Terminal.

    To get the pid of our process or the pid of our parent process we use getpid() and getppid(). This functions will become really handy later on in more advanced stuff. 

   Another interesting topic before getting into the main part is the whole exec family. Exec Instructions let us change the Code a Programm is running! I won't get in depth, cause there is a great explanation in Wikipedia.

    Let's now get into the main part. We use the system call fork that creates a copy of our current running process, where the new process will only differentiates by the process id or pid. The fork() call returns the pid of the newly created process and so the parent will have the pid value of it's child and the child will have a value of 0. If we get -1 this means that the fork failed.

So, a simple way of creating a clone of our process is doing this:

int pid;
pid = fork();
if(pid > 0)
    // parent code
else if(pid == 0)
    // child code
else // pid < 0 or pid == -1
    // fork error


We can also write this statement using a switch case, but I prefer using if/else statements!

    You can experiment with that making the parent or child sleep for some seconds using sleep(seconds) and printing messages. Running it a lot of times you will see that the processes are not synchronized and that each call of our function returns a different output combination.

    Something that is very important is waiting for the child to finish. In newer versions the child will become a child of the init process or will be terminated, but it's much better to make the parent wait. This can be done using the system call wait! The call wait(&status) returns the pid of the process that finished and a status that gives us more information about the termination Code. We could for example pass a return value to the parent process after the child has finished calculating something. But, we would have to make multiple waits for each different child process that we have created and so if we want to wait for all the child processes we use wait(NULL) or another call called waitpid(-1, NULL, 0) that wait for all child processes to finish. You can check the Linux Manual here.

    So, let's get into an example you can run to test out if the parent finished after the child. I will use the same structure as before, but make the child process wait for some seconds and also print some messages.

int pid;
pid = fork();
if(pid > 0)
    // parent code
    printf("fork succeeded!\n");
    printf("My pid is %d!\n", getpid());
    wait(NULL);
    printf("Goodbye!\n");
else if(pid == 0)
    // child code
      sleep(2);
    printf("My pid is %d!\n", getpid());
    return 0;
else // pid < 0 or pid == -1
    // fork error

    

As many times as you run this Code now the calls must be pseudo-synchronized, because of the way it is setup.


    To create multiple Processes you simple have to use a while loop and do this stuff over and over storing the pid inside of an array.

The Code looks like this:

int i;
int pid[N];
for(i = 0; i < N; i++){
    pid[i] = fork();
    if(pid[i] > 0){
        // parent continues
        continue;
    }
    else if(pid[i] == 0){
        // child process
    }
    else{
        // error
    }
}
// main parent code


    You can see that this was also not quite difficult! And this is actually it and I hope you enjoyed this post! Next time I think of going into Threads and the differences between those and Processes!

Until next time...Bye!

H2
H3
H4
3 columns
2 columns
1 column
1 Comment
Ecency