clone()
syscall with the CLONE_THREAD
flag, then that's again just a new "task" to the kernel/scheduler! The only real difference between a "process" and a "thread" is that, when a new "thread" is created, then the corresponding "task" is placed in the same "thread group" as the calling "process" (task), and that it shares the same memory space with its sibling "threads", i.e. the "tasks" belonging to the same "thread group".read()
syscall blocks or not, that does not really have anything to do with multi-threading. Instead, a file descriptor (FD) can be opened in "blocking" or "non-blocking" mode. If the FD was opened in "blocking" mode, then the read()
syscall will block until some data becomes available for reading, if no data is available for reading at the moment. While the read()
syscall is blocked, the corresponding task (process or thread) is removed from the scheduler's "ready" queue and is put to a separate "I/O waiting" queue, so the no CPU time gets wasted. As soon as some data becomes available for reading, the task is again inserted into the scheduler's "ready" queue and, eventually, will be able to proceed. Conversely, if the FD was opened in "non-blocking" mode, then the read()
syscall will either immediately return some data, or, if no data is available for reading at the moment, it will immediately fail, with an EAGAIN
or EWOULDBLOCK
error code.poll()
or epoll()
syscall to monitor your file descriptors and only start the I/O operation when the file descriptor is "ready" for the desired type of I/O operation. Note that, if poll()
signals that a file descriptor is "ready", then this guarantees that the subsequent (blocking) I/O operation will not block.
clone()
syscall with specific flags to create a new thread, whereas FreeBSD has a thr_new()
syscall and Windows would use the CreateThread()
function. User-space libraries, such as PThreads, are just an additional abstraction layer on top of the OS-specific "low-level" API, which makes managing threads much easier and more portable. Originally, PThreads was created to have a "standardized" threading API across various variants of the Unix operating systems, but nowadays ports are available for Linux, Windows and some other OS. Internally, those user-space threading libraries still use the "low-level" API of the underlying OS! Programming languages with built-in threading support, such as <std::thread>
in C++, <threads.h>
in C11, or std::thread
in Rust, either build on top of the system's "low-level" API or they wrap the PThreads library.boost::fibers
or GNU Portable Threads. Be aware that "fibers" do not benefit from multiple processors (CPU cores), because the kernel/scheduler can not distribute "fibers" across multiple processors, because the OS usually is not even aware of their existence.create threads in the userspace, and the kernel is not aware about this and view it as a single process only, unaware of how many threads are inside. |
clone()
syscall:Before the 2.6 version of the Linux kernel, processes were the schedulable entities, and there were no special facilities for threads [in the kernel]. However, it did have a system call — clone — which creates a copy of the calling process where the copy shares the address space of the caller. The LinuxThreads project used this system call to provide kernel-level threads. Unfortunately, it only partially complied with POSIX, particularly in the areas of signal handling, scheduling, and inter-process synchronization primitives. |
modern operating systems 4th edition” by Tananbuam (sic) |
The operating system implements a scheduler which gives each process a time quantum to use the CPU. |
getpid()
, is in fact the TGID. Of course, you can also still have a "process" with only a single "thread", which is really just a "task" that is alone it its thread group. Anyways, the scheduler is always scheduling individual tasks (i.e. "threads").std::thread
, for managing the "threads" (instead of directly messing with the OS' "low-level" API), but that is mainly for having a simpler API. And for portability between different OS!
*Note: This post refers to UNIX systems |
As pointed out before, "processes" and "threads" are user-space concepts |
If specific then consider 'Understanding Linux Kernel' by Daniel Plerre |
With Windows, processes and threads are dealt with by the kernel (kernel32.dll). |
kernel32.dll
, gdi32.dll
, user32.dll
and so on are the user-space libraries that provide the Win32 API. The names are "historic".ntdll.dll
is a user-space library that provides the Native API, i.e. the "syscall" interface to the NT kernel. Normally this is library is not linked directly to the applications, but instead it gets called indirectly via the Win32 API libraries that the applications are supposed to use.ntoskrnl.exe
is the actual Windows NT kernel image.Not that it really matters your link lists different authors for the 3E Linux kernel book. |
On Amazon US there are newer Linux kernel books available |