Threads Advance in System Administration with Linux
Process Descriptor Handling
Kernel Stack
Pid_hash Table and Chained Lists
PID Hash Table Handling Functions and Macros
Wait Queues
Process Resource Limits
Task State Segment
System Calls
Pthread Operations
POSIX threads on GNU/Linux
Programs on Thread in C
2. Process Descriptor Handling
union thread_union {
struct thread_info thread_info;
unsigned long stack[2048];
};
Two data structures in 8KB.
thread_info structure
Kernel mode process stack
4. Pid_hash Table and Chained Lists
PID is use to search a process descriptor.
Sequential search in the process list is inefficient.
The pid_hash array contains four hash tables and
corresponding filed in the process descriptor.
pid: PIDTYPE_PID.
tgid: PIDTYPE_TGID (thread group leader).
pgrp: PIDTYPE_PGID (group leader).
session: PIDTYPE_SID (session leader).
Chaining is used to handle PID collisions.
5. pid_hash Table
Size of each pidhash table: dependent on the
available memory.
PID is transformed into table index using pid_hashfn
macro.
7. Continue
pids field of the process descriptor: the pid data
structures:
nr: PID number.
pid_chain: links to the previous and the next
elements in the hash chain list.
pid_list: head of the per-PID list (in thread group).
9. PID Hash Table Handling Functions
and Macros
do_each_trask_pid(nr, type, task) : Execute each task.
while_each_trask_pid(nr, type, task) : Execute each task.
find_trask_by_pid_type(type, nr) : Find task by type & id.
find_trask_by_pid(nr) : Find task by id.
attach_pid(task, type, nr) : Add process on task.
detach_pid(task, type) Delete process from task.
next_thread(task) Show next Thread of a task.
10. How Processes are Organized
Processes in TASK_STOPPED, EXIT_ZOMBIE,
EXIT_DEAD: not linked in lists.
Processes in TASK_INTERRUPTABLE,
TASK_UNINTERRUPTABLE: wait queues
Two kinds of sleeping processes are:
Exclusive process.
Non-exclusive process: always woken up by the
kernel when the event occurs.
15. Process Switch
Process switch, task switch, context switch.
Hardware context switch: far jump (in older Linux).
Software context switch: a sequence of mov
instructions.
It allows better control over the validity of data
being loaded.
The amount of time required is about the same.
Performing the Process Switch
Switching the Page Global Directory.
Switching the Kernel Mode stack and the
hardware context.
16. Task State Segment
It is a specific segment architecture to store
hardware contexts with type in x86.
17. Creating Processes
In traditional UNIX, resources owned by parent
process are duplicated.
Very slow and inefficient.
Mechanisms to solve this problem:
Copy on Write: parent and child read the same
physical pages.
Lightweight process: parent and child share per-
process kernel data structures.
vfork() system call: parent and child share the
memory address space.
18. System Calls
clone(fn, arg, flags, child_stack,ptid, ctid): creating
lightweight process
A wrapper function in C library
Uses clone() system call
fork() and vfork() system calls: implemented by
clone() with different parameters.
Each invokes do_fork() function.
19. Kernel Threads
They run only in kernel mode.
They use only linear addresses greater than
PAGE_OFFSET.
kernel_thread(): To create a kernel thread.
Example kernel threads:
Process 0 (swapper process), the ancestor of all
processes.
Process 1 (init process).
Others: keventd, kswapd, kflushd (also bdflush),
kupdated etc.
20. Destroying Processes
exit() library function
Two system calls in Linux 2.6
_exit() system call :Handled by do_exit() function.
exit_group() system call : Handled by do_group_exit()
function.
Process removal
Releasing the process descriptor of a zombie process
by release_task().
23. Pthread Operations
POSIX function Description
pthread_create create a thread
pthread_detach set thread to release resources
pthread_equal test two thread IDs for equality
pthread_exit exit a thread without exiting process
pthread_kill send a signal to a thread
pthread_join wait for a thread
pthread_self find out own thread ID
24. Thread Packages
Kernel thread packages
Implemented and supported at kernel level
User-level thread packages
Implemented at user level
25. POSIX threads on GNU/Linux
GNU/Linux, threads are implemented as processes.
pthread_create to create a new thread.
Linux creates a new process that runs that thread.
A POSIX thread is not the same as a process you
would create with fork.
It shares the same address space and resources as
the original process rather than receiving copies.
Each thread maps to a kernel scheduling entity.
26. POSIX threads on GNU/Linux
Continue
The Linux clone system call is a generalized form of
fork.
pthread_create that allows the caller to specify which
resources are shared between the calling process
and the newly created process.
Clone system call should not ordinarily be used in
programs.
Use fork to create new processes or pthread_create
to create threads.
27. pthread_t identifier
Process created ptherad_t and it is not visible outside.
For instance, send a pthread_kill to a thread of another
process.
More details for Linux:
pthread_self() will get you an identifier that is unique across your
program, but not across your system.
Thread is a system object.
The system is unaware of the identifier POSIX library allocated for
the thread.
Linux identifies threads with PID like number called TID.
These numbers are system-wide.
28. Example Program
#include <pthread.h>
#include <stdio.h>
void *threadex(void *);
int main()
{
pthread_t tid; /* stores the new thread ID */
pthread_create(&tid, NULL, threadex, NULL); /*creates a new thread*/
pthread_join(tid, NULL); /*main thread waits for termination new thread */
return 0; /* exits main thread */
}
void *threadex(void *arg) /*thread subroutine*/
{
int t;
for (t=0; t<10; t++)
fprintf(stderr, "Hello, world of Threads ! n ");
return NULL;
}
29. Creating a thread with pthread
A thread is created with
int pthread_create(
pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg);
The creating process (or thread) must provide a location
for storage of the thread id.
The third parameter is just the name of the function for the
thread to run.
The last parameter (void *arg) is the sole argument
passed to created thread.
30. Example 1: Thread Creation
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 10
void *PrintHelloThread (void *threadid) {
int tid;
tid = (int)threadid;
printf("Hello World of threads : #%d!n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int count, i;
for(i=0; i<NUM_THREADS; i++){
printf("In main: creating thread %dn", i);
count = pthread_create(&threads[i], NULL, PrintHelloThread, (void *)i);
if (count) {
printf("ERROR code is %dn", count);
exit(1);
}
}
pthread_exit(NULL);
}
31. Example 2: Passing Parameters to a
Thread
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 10
void *PrintHelloThread (void *ptr)
{
char *filename;
int t;
filename = (char *) ptr;
while (1)
{
printf("Hello World of threads : %s!n", filename);
for (t=1; t++; t<500);
}
pthread_exit(NULL);
}
32. Example 2: Passing Parameters to a
Thread (Continue)
int main (int argc, char *argv[])
{
pthread_t thread[10];
int err_code, count=0;
char *filename;
printf ("Enter thread name at any time to create threadn");
while (count <= 9) {
filename = (char *) malloc (80*sizeof(char));
scanf ("%s", filename);
printf(“From main- creating threads %dn", count);
err_code = pthread_create(&thread[count], NULL, PrintHelloThread, (void *)filename);
if (err_code){
printf("ERROR code is %dn", err_code);
exit(1);
}
count++;
}
pthread_exit(NULL);
}