Process Control Block , Process Descriptor in Linux and task_struct? - linux

I am having trouble understanding the difference between a Process Control Block and Process Descriptor in Linux?
I have seen both of these structures referred to as a task_struct, and the terms seem to be used interchangeably - what is the difference between the two?
Many thanks for your help!

Neither of those terms ("Process Control Block" or "Process Descriptor") are considered "terms of art" in Linux kernel development. Of course, there is no official Linux kernel glossary so people are free to call things whatever makes sense to them.
In contrast, however, task_struct is a specific C structure that is used by the linux kernel to maintain state about a task. A task in Linux corresponds roughly to a thread.
Each user process has at least one thread so each process maps to one or more task_structs. More particularly, a process is one or more tasks that happen to share certain resources -- file descriptors, address space / memory map, signal handling, process and process group IDs, etc. Each thread in a process has its own individual version of certain other resources: registers/execution context, scheduling parameters, and so forth.
It's quite common for a process to have only a single thread. In that case, you could consider a process to be represented by a single task_struct.

Related

How are threads made?

I was reading up on threads and as I understand it, they are a set of values for an execution context. From what I understand, a thread is comprised of values (registers, PC, stack, etc.) that allow a CPU to continue running a set of instructions.
However, my question is: how are these threads made? I hear some of my professors throw around the word thread as a way to break up a process into multiple (mostly) independent parts of code (ie. multithreading). How does this work? Is there another section of memory that stores specifically what a thread can run, as well as it's state?
First of all you have to understand that operating systems vary greatly in their general working as well as in their implementations of seemingly identical functions.
so don't go into these kind of questions thinking that if one operating system does something in some way then other operating systems would do that in similar manner.
Now to your question
how are these threads made?
I will answer it using Linux as an example. When creating a new process Linux lets you specify which data structures (file descriptors, IO context etc) new process would share with its parent process. you can do this using the clone system call.
you can see in the documentation of clone that it takes some parameters specifying the sharing properties.
Now you can call a task_struct thread if it shares all sharable data structures with its parent ( because this property is consistent with the conventional definition of a thread). and if it shares none then you would call it a process.
But as far as Linux is concerned there is no notion of a thread or a process, all you have is a task_struct which may share certain resources with its parent.

How an OS figures out an identity of a thread calling the GetCurrentThreadId()?

I'm trying to understand how an OS figures out what thread is a current one (for example, when the thread calls gettid() or GetCurrentThreadId()). Since a process address space is shared between all threads, keeping a thread id there is not an option. It must be something unique to each thread (i.e. stored in its context). If I was an OS developer, I would store it in some internal CPU register readable only in kernel mode. I googled a lot but haven't found any similar question (as if it was super obvious).
So how is it implemented in real operating systems like Linux or Windows?
You are looking for Thread Control Block(TCB).
It is a data structure that holds information about threads.
A light reading material can be found here about the topic:
https://www.cs.duke.edu/courses/fall09/cps110/slides/threads2.3.ppt
But I would recommend getting a copy of Modern Operating Systems by Andrew S. Tanenbaum if you are interested in OS.
Chapter 2 Section 2.2 Threads:
Implementing Threads in User Space - "When threads are managed in user space, each process needs its own private
thread table to keep track of the threads in that process."
Implementing threads in the Kernel - "The kernel has a thread table that keeps track
of all the threads in the system."
Just an edit you might also want to read "SCHEDULING". In a general manner you can say kernel decides which thread/process should be using the CPU.Thus kernel knows which thread/process made a system call. I am not going into detail because it depends on which OS we are talking about.
I believe this has already been very well explained in this question: how kernel distinguishes between thread and process
If you want to find out more, you can also google for the kernel task structure and see what info is stored about each type of processes running in the user space
The answer to your question is entirely system specific. However, most processors know nothing about threads. They only support processes. Threads are generally implemented by created separate processes that share the same address space.
When you do a system service call to get a thread ID it is going to be implemented in the same general fashion as system service to get the process id. Imagine how a get process ID function could work in a system that does not support threads. And to keep it simple, let's assume a single processor.
You are going to have some kind of data structure to represent the current process and the kernel is going to have some means of identifying the current process (e.g. a pointer in the kernel address space to that process). On some processors there is a current task register that points to a structure defined by the processor specification. An operating system can usually add its own data to the end of this structure.
So now I want to upgrade this operating system to support threads. To that I must have a data structure that describes the thread. In that structures I have a pointer to a structure that defines the process.
Then get thread ID works the same way get process ID worked before. But now Get Process ID has an additional step that I have to translate the thread to the process to get its id (which may even be included in the thread block).

threads and LWP in Linux

Is this sentence correct: "All threads in Linux are LWP but not all LWP are threads". Actually, I try to understand thread realisation in Linux. pthread_create call clone syscall, but in man clone, I didn't find any reference to LWP.
So, does Linux have LWP at all?
From this blog you can find your answer http://www.thegeekstuff.com/2013/11/linux-process-and-threads/
Threads in Linux are nothing but a flow of execution of the process. A
process containing multiple execution flows is known as multi-threaded
process.
For a non multi-threaded process there is only execution flow that is
the main execution flow and hence it is also known as single threaded
process. For Linux kernel , there is no concept of thread. Each thread
is viewed by kernel as a separate process but these processes are
somewhat different from other normal processes. I will explain the
difference in following paragraphs.
Threads are often mixed with the term Light Weight Processes or LWPs.
The reason dates back to those times when Linux supported threads at
user level only. This means that even a multi-threaded application was
viewed by kernel as a single process only. This posed big challenges
for the library that managed these user level threads because it had
to take care of cases that a thread execution did not hinder if any
other thread issued a blocking call.
Later on the implementation changed and processes were attached to
each thread so that kernel can take care of them. But, as discussed
earlier, Linux kernel does not see them as threads, each thread is
viewed as a process inside kernel. These processes are known as light
weight processes.
The main difference between a light weight process (LWP) and a normal
process is that LWPs share the same address space and other resources like
open files etc. As some resources are shared so these processes are
considered to be light weight as compared to other normal processes
and hence the name light weight processes.
So, effectively we can say that threads and light weight processes are
the same. It’s just that thread is a term that is used at user level while
light weight process is a term used at kernel level.
From implementation point of view, threads are created using functions
exposed by POSIX compliant pthread library in Linux. Internally, the
clone() function is used to create a normal as well as a light weight
process. This means that to create a normal process fork() is used
that further calls clone() with appropriate arguments while to create
a thread or LWP, a function from pthread library calls clone() with
relevant flags. So, the main difference is generated by using
different flags that can be passed to clone() function.
Read more about fork() and clone() on their respective man pages.

When is clone() and fork better than pthreads?

I am beginner in this area.
I have studied fork(), vfork(), clone() and pthreads.
I have noticed that pthread_create() will create a thread, which is less overhead than creating a new process with fork(). Additionally the thread will share file descriptors, memory, etc with parent process.
But when is fork() and clone() better than pthreads? Can you please explain it to me by giving real world example?
Thanks in Advance.
clone(2) is a Linux specific syscall mostly used to implement threads (in particular, it is used for pthread_create). With various arguments, clone can also have a fork(2)-like behavior. Very few people directly use clone, using the pthread library is more portable. You probably need to directly call clone(2) syscall only if you are implementing your own thread library - a competitor to Posix-threads - and this is very tricky (in particular because locking may require using futex(2) syscall in machine-tuned assembly-coded routines, see futex(7)). You don't want to directly use clone or futex because the pthreads are much simpler to use.
(The other pthread functions require some book-keeping to be done internally in libpthread.so after a clone during a pthread_create)
As Jonathon answered, processes have their own address space and file descriptor set. And a process can execute a new executable program with the execve syscall which basically initialize the address space, the stack and registers for starting a new program (but the file descriptors may be kept, unless using close-on-exec flag, e.g. thru O_CLOEXEC for open).
On Unix-like systems, all processes (except the very first process, usuallyinit, of pid 1) are created by fork (or variants like vfork; you could, but don't want to, use clone in such way as it behaves like fork).
(technically, on Linux, there are some few weird exceptions which you can ignore, notably kernel processes or threads and some rare kernel-initiated starting of processes like /sbin/hotplug ....)
The fork and execve syscalls are central to Unix process creation (with waitpid and related syscalls).
A multi-threaded process has several threads (usually created by pthread_create) all sharing the same address space and file descriptors. You use threads when you want to work in parallel on the same data within the same address space, but then you should care about synchronization and locking. Read a pthread tutorial for more.
I suggest you to read a good Unix programming book like Advanced Unix Programming and/or the (freely available) Advanced Linux Programming
The strength and weakness of fork (and company) is that they create a new process that's a clone of the existing process.
This is a weakness because, as you pointed out, creating a new process has a fair amount of overhead. It also means communication between the processes has to be done via some "approved" channel (pipes, sockets, files, shared-memory region, etc.)
This is a strength because it provides (much) greater isolation between the parent and the child. If, for example, a child process crashes, you can kill it and start another fairly easily. By contrast, if a child thread dies, killing it is problematic at best -- it's impossible to be certain what resources that thread held exclusively, so you can't clean up after it. Likewise, since all the threads in a process share a common address space, one thread that ran into a problem could overwrite data being used by all the other threads, so just killing that one thread wouldn't necessarily be enough to clean up the mess.
In other words, using threads is a little bit of a gamble. As long as your code is all clean, you can gain some efficiency by using multiple threads in a single process. Using multiple processes adds a bit of overhead, but can make your code quite a bit more robust, because it limits the damage a single problem can cause, and makes it much easy to shut down and replace a process if it does run into a major problem.
As far as concrete examples go, Apache might be a pretty good one. It will use multiple threads per process, but to limit the damage in case of problems (among other things), it limits the number of threads per process, and can/will spawn several separate processes running concurrently as well. On a decent server you might have, for example, 8 processes with 8 threads each. The large number of threads helps it service a large number of clients in a mostly I/O bound task, and breaking it up into processes means if a problem does arise, it doesn't suddenly become completely un-responsive, and can shut down and restart a process without losing a lot.
These are totally different things. fork() creates a new process. pthread_create() creates a new thread, which runs under the context of the same process.
Thread share the same virtual address space, memory (for good or for bad), set of open file descriptors, among other things.
Processes are (essentially) totally separate from each other and cannot modify each other.
You should read this question:
What is the difference between a process and a thread?
As for an example, if I am your shell (eg. bash), when you enter a command like ls, I am going to fork() a new process, and then exec() the ls executable. (And then I wait() on the child process, but that's getting out of scope.) This happens in an entire different address space, and if ls blows up, I don't care, because I am still executing in my own process.
On the other hand, say I am a math program, and I have been asked to multiply two 100x100 matrices. We know that matrix multiplication is an Embarrassingly Parallel problem. So, I have the matrices in memory. I spawn of N threads, who each operate on the same source matrices, putting their results in the appropriate location in the result matrix. Remember, these operate in the context of the same process, so I need to make sure they are not stamping on each other's data. If N is 8 and I have an eight-core CPU, I can effectively calculate each part of the matrix simultaneously.
Process creation mechanism on unix using fork() (and family) is very efficient.
Morever , most unix system doesnot support kernel level threads i.e thread is not entity recognized by kernel. Hence thread on such system cannot get benefit of CPU scheduling at kernel level. pthread library does that which is not kerenl rather some process itself.
Also on such system pthreads are implemented using vfork() and as light weight process only.
So using threading has no point except portability on such system.
As per my understanding Sun-solaris and windows has kernel level thread and linux family doesn't support kernel threads.
with processes pipes and unix doamin sockets are very efficient IPC without synchronization issues.
I hope it clears why and when thread should be used practically.

Thread control block in linux

What is the structure used for saving thread state like PC, SP and registers during thread context switch in linux? The equivalent of TCB in freebsd. If possible please point to the source file here.
Note that PCB itself is not enough, as we have PC, SP etc. per thread not per process.
It's actually task_struct. In Linux, a task can be a thread, a process, or something in between. A thread is just the name you give to a task that shares most things (VMA's, file descriptors, etc...) with other tasks.
This is much in line with the idea that a thread is just a particular kind of process, and can be handled via the same functions, etc... Plan 9's rfork() and Linux's clone() allow to create a process with a customizable level of sharing, so you end up using the same machinery to create processes and threads.
Perhaps you want setcontext and friends (but your code won't be very portable, and tricky to get right)?
Or are you talking from inside the kernel? Then perhaps task_struct could be what you look for??

Resources