Networking - C Threads in Linux

in #networking7 years ago (edited)

    After talking about Processes here we will today talk about Threads also. I will first start out with what Threads are getting into the differences with Processes and finish of with the implementation in C Linux. So, without further do let's get started!


Linux Threads:

    Each Process in Linux has at least 1 Thread that is the main thread. When creating a new Thread constant variables, open files and signal handlers  are being used in a common memory address for all threads. In Processes each new Process has a copy from everything as you might remember and so we don't have common memory, but we can do this in another way that we will talk about another time! 

    Threads get also scheduled, but using the Thread Scheduler. In different circumstances and operation systems threads or processes will be preferable. What is the best for each Application depends on the process and thread switching time of the operation system and also on the time that the operation systems takes to create a new process or thread. We will discuss all that later on when we get into different kinds of Servers! 

    The Library-API that we will use in Linux for creating and managing Threads is called pthread.h. This library contains everything that we need. So, let's get into the implementation part now!

Implementation of pthreads in C (Linux):

Creating a Thread:

    The function that does the same as fork() in processes, but for pthreads is called pthread_create(). So, we use pthread_create(&thread, &attributes, function, arguments) to create a new thread that will be stored in thread, has specific attributes that we mostly set to NULL, runs a specific function with the specified arguments/parameters.

This looks like that in Code:

// in main
pthread_t pthread;
int arg = 5;
pthread_create(&pthread, NULL, thread_function, (void*)&arg);
// function thread runs
void *thread_function(void *arg){
    val = *(int*)arg;
    printf("%d", arg);
}


    Don't be scared by the weird syntax in the argument. Me myself always copy paste it from a example programm I have, that looks similar to this one :)


Waiting for thread to finish:

    Another important function that is even more important than in Processes in Threads, is the function that makes the main process or any process/thread that created a child thread wait for the thread to finish. In Processes we called wait or waitpid. In Threads we use pthread_join(thread, result).

So, let's expand our previous Code making the main process wait for the thread to finish:

// in main
pthread_t pthread;
int arg = 5;
pthread_create(&pthread, NULL, thread_function, (void*)&arg);
void* result;
result = pthread_join(pthread, NULL);
if(result != 0){
    printf("thread join failed!\n");
}
// function thread runs
void *thread_function(void *arg){
    val = *(int*)arg;
    printf("%d", arg);
}

    

    I put NULL inside of the return value, just to show you that you don't have to get a return value. But, you could also get a return value.


Exiting a Thread:

     Lastly, there is also pthread_exit(return_val) that is for terminating a thread on a given point of Code. We can get this return value with the pthread_join function to make our thread feedback information to the process that created it.

So, the thread may send back a string like that:

pthread_exit("My name is Jeff!");

And then the process can print this out like that:

void *thread_result;
pthread_join(pthread, &thread_result);
printf("%s\n", (char *)thread_result);


Multiple Threads:

    That way we actually talked about everything. You can now create a thread and pass arguments to it, and also exit a thread with a return value that gets passed to the process that waits for it. The only thing left are multiple Threads, but I guess you can do it easily. 

     Here's how you create and wait for multiple threads without arguments and return values and using the same function:

// include stdio and pthread libraries
#define N 10
int main{
    int i;
    pthread_t = threads[N];
    // create threads
    for(i = 0; i < N; i++){
        pthread_create(&threads[i], NULL, example, NULL);
    }
    printf("successfully created threads\n");
    // wait for threads
    for(i = 0; i < N; i++){
        pthread_join(threads[i], NULL);
    }
    printf("threads finished\n");
}
void *example(){
    sleep(1 + rand()%3); // random sleep
    printf("I am a thread!\n);
}


    Lastly, I wanted to tell you that compiling the Code in the Terminal now needs also another argument. You will have to include the pthread library. This can be done this way:

gcc -o output_name code.c -lpthread


And this is actually it for today! Hope you enjoyed it!

Next time we will get into the Synchronization of Processes and Threads.

Until next time...Bye!

Sort:  

Nice tutorial, and if you don't mind... I would like to say that maybe including a practical example for demonstration purpose will enhance the readability a lot.

Thanks for you feedback.
Well I mostly tend to start off with the basics and later on we will also get into Examples don't worry :)

Thanks @drifter1. You made me easy to understand my Real-time OS subject. But I want to clarify last example coding. Is it all threads sequentially run after another? And what happens at rand()?

It's "Random" how threads will run on the CPU.
To make it even easier to see that this exact thing happens I put a random sleep timer for each thread to be run so that they don't quit directly...
Of course thread 0 will be "made" much faster then thread N-1, but which thread will start running the example() code is random, cause the "timing" of the CPU is not so sequential at all.
Even if you have an 4Core/8Thread i7 (like me) you will see that 8 threads will not run in this exact order or even at the same time, but thread 7 might even print out a message before thread 0...

Thanks @drifter1 for detailed explanation. Could you please tell me what happens below. I think I confused with thread joining.

for(i = 0; i < N; i++){
pthread_join(threads[i], NULL);
}

Haha of course...
When a process or thread runs the main process/thread that created it must finish after it.
For threads we use the function pthread_join() with an important parameter being the thread_id (the number which represents the thread in the Operating system).
So, because we have N threads and because the id's are stored in an array, we have a for loop so that the main process/thread waits for all of them :)

Congratulations @drifter1! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Coin Marketplace

STEEM 0.20
TRX 0.14
JST 0.030
BTC 63718.61
ETH 3390.60
USDT 1.00
SBD 2.62