[go: up one dir, main page]

0% found this document useful (0 votes)
45 views61 pages

Set1 Processes and Threads

Processes are the executable instantiations of programs that run in memory. The OS represents each process using a process control block that stores the process's state and execution information. Processes can be in different states like ready, running, blocked, and each state represents what the process is currently doing. Context switching involves saving a process's state before switching to another process and restoring its state when switching back.

Uploaded by

hamza.nayef
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views61 pages

Set1 Processes and Threads

Processes are the executable instantiations of programs that run in memory. The OS represents each process using a process control block that stores the process's state and execution information. Processes can be in different states like ready, running, blocked, and each state represents what the process is currently doing. Context switching involves saving a process's state before switching to another process and restoring its state when switching back.

Uploaded by

hamza.nayef
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

Processes

2
Dr. Suleiman Abu Kharmeh
Processes
• Definition
• Creation
• Management
• PCB
• States
• Interaction with the OS
• Threads
• Process and thread scheduling
3
Dr. Suleiman Abu Kharmeh
Process Management
• This lecture begins a series of topics on processes, and
threads.
– this is perhaps the most important part of the class
• Today: processes and process management
– what are the OS units of execution?
– how are they represented inside the OS?
– how is the CPU scheduled across processes?
– what are the possible execution states of a process?

4
Dr. Suleiman Abu Kharmeh
Running Programs
• One basic function of an OS is to execute and
manage code (programs) dynamically, e.g.:
– A command issued at a command line terminal
– An icon double clicked from the desktop
– Jobs/tasks run as part of a batch system
(sequential execution of many commands)

• A process is an execution instant of a program

5
Dr. Suleiman Abu Kharmeh
Programs and Processes

Process
The running
instantiation of a
program, stored in
RAM

Program One-to-many
An executable relationship
file in long-term between program
storage and processes
6
Dr. Suleiman Abu Kharmeh
What’s in a Process?
• A process consists of (at least):
– an address space
– the code for the running program
– the data for the running program
– an execution stack and stack pointer (SP)
• traces state of procedure calls made
– the program counter (PC), indicating the next instruction
– a set of general-purpose processor registers and their values
– a set of OS resources
• open files, network connections, sound channels, …
• The process is a container for all of this state
– a process is named by a process ID (PID)
• just an integer (actually, typically a short)

7
Dr. Suleiman Abu Kharmeh
A process’s address space
0xFFFFFFFF
stack
(dynamic allocated mem)
SP

address space heap


(dynamic allocated mem)
static data
(data segment)
code PC/IP
0x00000000 (text segment)

8
Dr. Suleiman Abu Kharmeh
The Program Loader
• OS functionality that loads programs
into memory, creates processes
Memory
– Places segments into memory
ESP
– Loads necessary dynamic libraries Stack

– Performs relocation
– Allocates the initial stack frame
– Sets EIP to the program’s entry point

Heap

.data
EIP .text

9
Dr. Suleiman Abu Kharmeh
Single-Process Address Apace
• The stack is used for local variables and
Memory
function calls
– Grows downwards Stack
• Heap is allocated dynamically
(malloc/new)
– Grows upwards
• When the stack and heap meet, there is
no more memory left in the process
Heap
– Process will probably crash
.data
• Static data and global variables are fixed .text
at compile time 10
Dr. Suleiman Abu Kharmeh
Process states
• Each process has an execution state, which
indicates what it is currently doing
– ready: waiting to be assigned to CPU
• could run, but another process has the CPU
– running: executing on the CPU
• is the process that currently controls the CPU
• how many processes can be running simultaneously?
– Waiting/blocked: waiting for an event, e.g. I/O completion
• cannot make progress until event happens
• As a process executes, it moves from state to state
– UNIX: run ps, STAT column shows current state
• In which state a process spends most of the time?
• Other process states: New, Terminated. 11
Dr. Suleiman Abu Kharmeh
Process states and state transitions
exit
terminated
running

dispatch / interrupt
schedule (unschedule)

create ready trap or exception


new
(I/O, page fault,
etc.)
interrupt
(I/O complete)

blocked You can create


and destroy
processes!
12
Dr. Suleiman Abu Kharmeh
Process data structures
• How does the OS represent a process in the kernel?
– at any time, there are many processes, each in its own
particular state
– the OS data structure that represents each is called the
process control block (PCB)
• PCB contains all info about the process
– OS keeps all of a process’ hardware execution state in the
PCB when the process isn’t running
• PC
• SP
• registers
– when process is unscheduled, the state of the hardware is
transferred out into the PCB

13
Dr. Suleiman Abu Kharmeh
PCB
• The PCB is a data structure with many, many fields:
– process ID (PID)
– execution state
– program counter, stack pointer, registers
– memory management info
– UNIX username of owner
– scheduling priority
– accounting info
– pointers into state queues
• In linux:
– defined in task_struct (include/linux/sched.h)
– over 95 fields and 350 lines of code.

14
Dr. Suleiman Abu Kharmeh
PCBs and Hardware State
• When a process is running, its hardware state is inside the CPU
– PC, SP, registers
– CPU contains current values
• When the OS stops running a process (puts it in the waiting/ready
state), it saves the registers’ values in the PCB
– when the OS puts the process in the running state, it loads the hardware
registers from the values in that process’ PCB
• The act of switching the CPU from one process to another is called a
context switch
– timesharing systems may do 1000s of switches per second
• On a 2.6GHz CPU, results in 2.6MHz per process, 2.6 Million
instruction per process assuming 1 instruction per cycle
– The context switch itself takes about 1 microseconds on today’s hardware
• On a 2.6GHz CPU, assuming 1 instruction per cycle, this
translates to 2600 instructions per 1 microsecond.

16
Dr. Suleiman Abu Kharmeh
Context Switching
• Context switching
– Saves state of a process before a switching to another process
– Restores original process state when switching back

• Simple concept, but:


– How do you save the state of a process?
– How do you stop execution of a process?
– How do you restart the execution of process that has been
switched out?

17
Dr. Suleiman Abu Kharmeh
Threads
• So far, process has a single thread of execution
• Consider having multiple program counters per
process
– Multiple locations can execute at once
• Multiple threads of control -> threads
• Must then have storage for thread details,
multiple program counters in PCB
• Explore in detail later

Dr. Suleiman Abu Kharmeh


UNIX Process Management
(Selected System Calls)
• fork() – system call to create a copy of the current process, and
start it running
– No arguments!
pid_t fork(void);

• exec() – system call to change the program being run by the


current process
int execv(const char *path_to_prog, char *const argv[]);

• wait() – system call to wait for a process to finish


pid_t waitpid(pid_t pid, int *status, int options);

• signal() – system call to send a notification to another process


int kill(pid_t pid, int sig);

19
Dr. Suleiman Abu Kharmeh
Process creation (fork system call)
• One process can create another process
– creator is called the parent
– created process is called the child
– UNIX: do ps, look for PPID field
• ps axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm

– what creates the first process, and when?


• Try pstree command, check the root of the tree.

• when child is created, parent may either wait for


it to finish, or it may continue in parallel, or both!

20
Dr. Suleiman Abu Kharmeh
UNIX process creation
• UNIX process creation through fork()
system call
– creates and initializes a new PCB
– creates a new address space
– initializes new address space with a copy of the entire
contents of the address space of the parent
– initializes kernel resources of new process with resources
of parent (e.g. open files)
– places new PCB on the ready queue
• the fork() system call returns twice
– once into the parent, and once into the child
– In the parent, it returns the child’s PID
– In the child, it returns 0 21
Dr. Suleiman Abu Kharmeh
Parent similar, but different Child
PCB in key ways PCB

Parent Child address


address space space
identical
(code, static (code, static
copy
data, heap, (with sole data, heap,
stack) exception stack)
of PID
argument
on the top
of the
stack)

22
Dr. Suleiman Abu Kharmeh
testfork – use of fork( )
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)


{
char *name = argv[0];
int fork_return = fork();
if (fork_return != 0) {
printf("My child is %d\n", fork_return);
return 0; // = exit(0) = abort()
} else {
printf("Child of %s is %d\n", name, fork_return);
return 0;
}
}

23
Dr. Suleiman Abu Kharmeh
testfork output
CMD% gcc -o testfork testfork.c
CMD% ./testfork
My child is 486
Child of testfork is 0
CMD% ./testfork
Child of testfork is 0
My child is 571

24
Dr. Suleiman Abu Kharmeh
Fork and exec
• So how do we start a new program, instead of
just forking the old program?
– the exec() system call!
• exec(‘program’, …)
– stops the current process
– loads ‘program’ into the address space
– initializes hardware context, args for new program
– places PCB onto ready queue
– note: does not create a new process!

25
Dr. Suleiman Abu Kharmeh
Starting New Programs
• Exec System Call:
– Many versions of exec() are used from the program in C (Linux),
for example:
• int execv(const char *prog, char *const argv[]);
– Check privileges and file type of prog
– Loads program at path prog into address space
• Replacing previous contents!
• Execution starts at main()
– Initializes context – e.g. passes arguments
• *argv
– Place PCB on ready queue
– Preserves, pipes, open files, privileges, etc.
• Running a new program in Unix/Linux from C:
– fork() followed by exec()
– Creates a new process as clone of previous one
– First thing that clone does is to replace itself with new program
• What does it mean for exec to return?

Dr. Suleiman Abu Kharmeh


Strating new Programs
time0 time1 time2

Child Process

pid = fork();
if (pid == 0) main() {
exec(…); …
else }
wait(pid);
pid = 0

pid = fork(); pid = fork();


if (pid == 0) if (pid == 0)
exec(…); exec(…);
else pid = 9418 else
wait(pid); wait(pid);

Original Process Parent Process 27


Dr. Suleiman Abu Kharmeh
Linux: wait vs waitpid
• The waitpid(pid, NULL, 0) system
call suspends execution of the calling process
until a child specified by pid argument has
changed state:
– On error, -1 is returned.

• The wait() system call suspends execution of the


calling process until one of its children terminates. The
call wait(NULL) is equivalent to waitpid(-1, NULL, 0);
– returns the process ID of the terminated child; on
error, -1 is returned.

28
Dr. Suleiman Abu Kharmeh
Process Termination
• Typically, a process will call waitpid(pid, …) until
its child process(es) complete
– wait(NULL) waits for one of the children to finish.
– If you want to wait for all children to finish:
• while(wait(NULL) != -1);
• abort() can be used to immediately end the
current process (similar to exit system call)
– noreturn void abort(void);
• How can we immediately terminate a child
process?
– kill(pid, SIGKILL);

29
Dr. Suleiman Abu Kharmeh
Fork + Exec
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>

int main(int argc, char **argv)


{
char *argvNew[5];
int pid;

if ((pid = fork()) < 0) {


printf( "Fork error\n“);
exit(1);
} else if (pid == 0) { /* child process */
argvNew[0] = "/bin/ls";
argvNew[1] = "-l";
argvNew[2] = NULL;
if (execv(argvNew[0], argvNew) < 0) {
printf( "Execve error\n“);
exit(1);
}
} else { /* parent */
waitpid(pid, NULL, 0); /* wait for the child to finish */
}
}

Dr. Suleiman Abu Kharmeh


UNIX shells/terminal
// Need to provide an implementation of the get_next_command function.
int main(int argc, char **argv)
{
while (1) {
char **cmd = get_next_command();
int child_pid = fork();
if (child_pid == 0) {
if(execv(cmd[0], cmd) < 0)
printf("ERROR: exec failed!");
} else {
waitpid(child_pid, NULL, 0);
}
}
}

31
Dr. Suleiman Abu Kharmeh
Cooperating Processes
• Concurrent Processes can be
– Independent processes
» cannot affect or be affected by the execution of another
process.
– Cooperating processes
» can affect or be affected by the execution of another process.
• Advantages of process cooperation:
» Information sharing
» Computation speedup
» Modularity
» Convenience(e.g. editing, printing, compiling)
• Concurrent execution requires
» process communication and process synchronization

Dr. Suleiman Abu Kharmeh


Interprocess Communication (IPC)

Proc 1 Proc 2 Proc 3

• Separate address space isolates processes


– High Creation/Memory Overhead; (Relatively) High Context-Switch Overhead
• Mechanism for processes to communicate and synchronize actions.

– Via shared memory - Accomplished by mapping addresses to common DRAM


• Read and Write through memory
– Via Messaging system - processes communicate without resorting to shared
variables.
• send() and receive() messages
• Can be used over the network!

– Messaging system and shared memory not mutually exclusive


• can be used simultaneously within a single OS or a single process.

Dr. Suleiman Abu Kharmeh


Shared Memory Communication
Code Data 2 Code
Data Stack 1 Data
Heap Heap 1 Heap
Stack Code 1 Stack
Shared Stack 2 Shared
Prog/Proc 1 Data 1 Prog/Proc 2
Virtual Heap 2 Virtual
Address Code 2 Address
Space 1 Shared Space 2
• Communication occurs by “simply” reading/writing to shared address
page
– Really low overhead communication
– Introduces complex synchronization problems

Dr. Suleiman Abu Kharmeh


Examples of IPC Systems
• Shared Memory
1. Process first creates shared memory segment
int shm_fd = shm_open(“my_shared”, O_CREAT | O_RDWR, 0666);
• Also used to open an existing segment
2. Set the size of the object:
• ftruncate(shm_fd, SIZE);
• // e.g. SIZE is 4096 opening a 4KB shared memory
3. Use mmap() to memory-map a file pointer to the shared
memory object
• Reading and writing to shared memory is done by using the pointer
returned by mmap().
• char *var = (char *) mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

4. Use shm_unlink to remove/delete the shared memory from the operating


system
• shm_unlink(“my_shared”);

Dr. Suleiman Abu Kharmeh


Examples of IPC Systems

• Check the manual pages for shm_open:


– Need to include additional libraries in your project
– Need to link with “-lrt”: Just pass this option to GCC
on the command line, for example:
• gcc sender.c -o sender -lrt
36
Dr. Suleiman Abu Kharmeh
#include <sys/mman.h>
#include
#include
#include
<sys/stat.h>
<fcntl.h>
<stdio.h>
IPC Producer
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
const int SIZE = 4096; /* the size (in bytes) of shared memory object */
const char *name = "OS"; /* name of the shared memory object */
const char *message_0 = "Hello"; /* strings written to shared memory */
const char *message_1 = "World!";

int fd; /* shared memory file descriptor */


char *ptr; /* pointer to shared memory object */

fd = shm_open(name, O_CREAT | O_RDWR, 0666); /* create the shared memory object */

/* configure the size of the shared memory object */


ftruncate(fd, SIZE);

/* memory map the shared memory object */


ptr = (char *) mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

sprintf(ptr,"%s", message_0); /* write to the shared memory object */


ptr += strlen(message_0);
sprintf(ptr,"%s", message_1);
ptr += strlen(message_1);

return 0;
}
Dr. Suleiman Abu Kharmeh
#include <sys/mman.h>
IPC Consumer
#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>

int main() {

const int SIZE = 4096; /* the size (in bytes) of shared memory object */
const char *name = "OS"; /* name of the shared memory object */
int fd; /* shared memory file descriptor */
char *ptr; /* pointer to shared memory object */

/* open the shared memory object */


fd = shm_open(name, O_RDONLY, 0666);

/* memory map the shared memory object */


ptr = (char *) mmap(0, SIZE, PROT_READ, MAP_SHARED, fd, 0);

printf("%s\n", ptr); /* read from the shared memory object */

shm_unlink(name); /* remove the shared memory object */

return 0;
}

Dr. Suleiman Abu Kharmeh


IPC – Message Passing
• Processes communicate with each other
without resorting to shared variables
• IPC facility provides two operations:
– send(message)
– receive(message)
• The message size is either fixed or variable

• Fixed vs. Variable size message


– Fixed message size - straightforward physical implementation,
programming task is difficult due to fragmentation
– Variable message size - simpler programming, more complex
physical implementation.
Dr. Suleiman Abu Kharmeh
Message Passing (Cont.)
• If processes P and Q wish to communicate, they
need to:
– Establish a communication link between them
– Exchange messages via send/receive
• Implementation issues:
– How are links established?
– Can a link be associated with more than two
processes?
– How many links can there be between every pair of
communicating processes?
– What is the capacity of a link?
– Is the size of a message that the link can
accommodate fixed or variable?
– Is a link unidirectional or bi-directional?

Dr. Suleiman Abu Kharmeh


More IPC options
• Pipes
– Unnamed: seize to exist after the process is
terminated
• Check the “pipe” system call in Linux
• Figure 3.21 and Figure 3.22 in the book.
– Named: exist after the process is terminated:
• Check the “mkfifo” system call in Linux.
• Works very similar to a file, where you can use all file
system calls: open, read, write, close…

Dr. Suleiman Abu Kharmeh


Foreground vs background process
• A process that connects to the terminal is called a
foreground job.
– A job is said to be in the foreground because it can communicate with
the user via the screen and the keyboard.
• A process that disconnects from the terminal and
cannot communicate with the user is called a
background job.
– If the background job requires interaction with the user, it will stop
and wait until establishing a connection to the terminal.
• You can start a process/command in the background
by adding & at the end of command. For example:
– gedit &
42
Dr. Suleiman Abu Kharmeh
Threads & Concurrency

44
Dr. Suleiman Abu Kharmeh
Processes and Parallel Programming
• A process includes many things:
– an address space (all the code and data pages)
• protection boundary
– OS resources (e.g., open files) and accounting info
– hardware execution state (PC, SP, regs)
• Creating a new process is costly, because of all the data
structures that must be allocated/initialized
 creating address space and copying old process

• Inter-process communication is costly, since it must usually


go through the OS
 overhead of system calls to do communication
• Thus doing parallel programs by having multiple processes that
communicate between them is costly

45
Dr. Suleiman Abu Kharmeh
Processes and Parallel Programing (2)
• Imagine a web server, which forks off copies of itself to
handle multiple simultaneous tasks
– or, imagine we have any parallel program on a
multiprocessor
• To execute these, we need to:
– create several processes that execute in parallel
– cause each to map to the same address space to share data
• see the shm_open
• have the OS schedule them in parallel
• multiprogramming or true parallel processing on an SMP:
shared-memory symmetric multiprocessing
• This is inefficient
– space: PCB, page tables –discussed later-, etc.
– time: creating OS structures, fork and copy addr space, etc.

46
Dr. Suleiman Abu Kharmeh
Can we do better?
• What’s similar in these processes?
– they all share the same code and data (address space)
– they all share the same privileges
– they all share the same resources (files, sockets, etc.)
• What’s different?
– each has its own hardware execution state
• PC, registers, stack pointer, and stack
• Key idea:
– a process (address space, etc.)
– a “thread of control” is a minimal execution state (PC, SP, …etc)
• this execution state is usually called a thread, or sometimes, a
lightweight process

47
Dr. Suleiman Abu Kharmeh
Thread Design Space

older
MS/DOS UNIXes

address one thread/process one thread/process


space one process many processes

thread
Java Mach, NT,
Chorus,
many threads/process many threads/process Linux, …
one process many processes

48
Dr. Suleiman Abu Kharmeh
(old) Process address space
0xFFFFFFFF stack
(dynamic allocated mem)
SP

address space heap


(dynamic allocated mem)
static data
(data segment)
code
PC
0x00000000 (text segment)

49
Dr. Suleiman Abu Kharmeh
(new) Address space with threads
thread 1 stack
SP (T1)
0xFFFFFFFF
thread 2 stack
SP SP (T2)

thread 3 stack
SP (T3)
address space
heap
(dynamic allocated mem)
static data
(data segment)
0x00000000 PC PC (T2)
code
PC (T1)
(text segment) PC (T3)
50
Dr. Suleiman Abu Kharmeh
Threads and processes
• Most modern OS’s (Mach, Chorus, NT, modern Unix)
therefore support two entities:
– the process, which defines the address space and general
process attributes (such as open files, etc.)
– the thread, which defines a sequential execution stream within
a process
• A thread is bound to a single process
– processes, however, can have multiple threads executing within
them
– sharing data between threads is cheap: all see same address
space
• Threads become the unit of scheduling
– processes are just containers in which threads execute

51
Dr. Suleiman Abu Kharmeh
Process/Thread Separation
• Separating threads and processes makes it easier to
support multi-threaded applications
– creating concurrency does not require creating new
processes
• Reasons to create programs with multiple threads:
– improving program structure (the Java argument)
• and potentially the performance
– handling concurrent events (e.g., web servers)
– building parallel programs (e.g., raytracer)
• So, multithreading is useful even on a uniprocessor
– even though only one thread can run at a time

52
Dr. Suleiman Abu Kharmeh
Types of Threads
• User-level threads
• Kernel-supported threads
• Hybrid approach implements both user-level
and kernel-supported threads.

Dr. Suleiman Abu Kharmeh


User Threads: many-to-one
• Supported above the kernel, via a set of library calls at the user
level.
• Thread management done by user-level threads library
– User program provides scheduler and thread package
• May have several user threads per kernel thread
• User threads may be scheduled non-premptively relative to each other
(only switch on yield(), i.e. leave the CPU)
– Advantages
• Cheap, Fast: Threads do not need to call OS and cause interrupts to kernel
– Disadvantage: system call/blocking IO from any thread can block the
entire process; solving this requires coordination between the kernel
and the user-level thread manager
• Example thread libraries:
– Early versions of Java threads

Dr. Suleiman Abu Kharmeh


Kernel Threads: one-to-one

• Supported by the Kernel


– Kernel is responsible for thread management.
– Every thread can run or block independently
– One process may have several threads waiting on different things

• Downside of kernel threads: a bit expensive


– Need to make a crossing into kernel mode to schedule

• Examples
– Linux and Windows operating systems

Dr. Suleiman Abu Kharmeh


Hybrid approach: Coordinating K/L and U/L Threads (Many-to-Many)
• Another possibility:
– use both K/L and U/L threads in a single system
– can associate a user-level thread with a kernel-level thread
– or, can multiplex user-level threads on top of kernel threads
• “scheduler activations”
– a research paper from UW with huge effect on industry*
– each process can request one or more kernel threads
• process is given responsibility for mapping user-level threads onto kernel
threads
• kernel promises to notify user-level before it suspends or destroys a kernel
thread
– this is a middle ground between kernel level threads (1:1), and user
level thread (N:1)  N:M
• map N user level threads to M kernel level threads.

Thomas Anderson, Brian Bershad, Edward Lazowska, and Henry Levy.


Scheduler Activations: Effective Kernel Support for the User-Level management of Parallelism.
ACM Trans. on Computer Systems 10(1), February 1992, pp. 53-79.

56
Dr. Suleiman Abu Kharmeh
Kernel thread vs user-level threads
• Who is responsible for creating/managing threads?
– Two answers, in general:
• the OS (kernel threads)
– thread creation and management requires system calls
• the user-level process (user-level threads)
– a library linked into the program manages the threads
– thread creation and management requires procedure calls
• Why is user-level thread management possible?
– threads share the same address space
• therefore the thread manager doesn’t need to manipulate
address spaces
– threads only differ in hardware contexts (roughly)
• PC, SP, registers
• these can be manipulated by the user-level process itself!
57
Dr. Suleiman Abu Kharmeh
Processes vs. Threads
• Threads are better if:
– You need to create new ones quickly, on-the-fly
– You need to share lots of state/data

• Processes are better if:


– You want protection
• One process that crashes or freezes doesn’t impact the
others
– You need high security
• Only way to move state is through well-defined,
sanitized/protected message passing interface
58
Dr. Suleiman Abu Kharmeh
Linux Threads
• In the kernel, threads are just tasks
– Remember the task_struct from earlier?
• New threads created using the clone() API
– Sort of like fork()
– Creates a new child task that copies the address space
pointers (Heap, Data) of the parent
• Same code, same data, same environment, etc.
• New stack is allocated (SP)
• No memory needs to be copied (unlike fork())
• For more information, check the clone man page:
– https://man7.org/linux/man-pages/man2/clone.2.html

59
Dr. Suleiman Abu Kharmeh
Pthread
• POSIX.1 specifies a set of interfaces (functions, header
files) for threaded programming commonly known as
Pthreads. A single process can contain multiple threads,
all of which are executing the same program.
• It is a widely used Linux library.
• You must compile with the –pthread option to GCC.
• For more information check the man page:
– https://man7.org/linux/man-pages/man7/pthreads.7.html

60
Dr. Suleiman Abu Kharmeh
Pthread API
• pthread_create() – create a new thread (similar to fork for processes)
– Create independent threads each of which will execute a function
• pthread_exit() – exit the current thread (similar to exit or abort for
processes)
• pthread_join() – wait for another thread to exit (similar to wait/waitpid for
processes)
– Wait till threads are complete before main continues.
– If we do not “join”, then the main process might execute an “exit” which
will terminate the process and all threads before the threads have
completed.

• Pthreads/POSIX also contains a full range of synchronization primitives

61
Dr. Suleiman Abu Kharmeh
#include <stdio.h>
Pthread Basic Example:
#include <stdlib.h>
#include <pthread.h>

void *print_message_function( void *ptr )


{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}
void main()
{
pthread_t thread1, thread2;
char *message1 = "Thread 1";
char *message2 = "Thread 2";
int iret1, iret2;

iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);


iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);

// check that iret1 == 0 and iret2 == 0, i.e. pthread_create function finished creating the threads successfully.
printf("Thread 1 returns: %d\n", iret1);
printf("Thread 2 returns: %d\n", iret2);

pthread_join( thread1, NULL);


pthread_join( thread2, NULL);

exit(0);
}
62
Dr. Suleiman Abu Kharmeh
Thread Oddities
• What happens if you fork() a process that has
multiple threads?
– You get a child process with exactly one thread
– Whichever thread called fork() survives
• What happens if you run exec() in a multi-
threaded process?
– All but one threads are killed
– exec() gets run normally (*unless exec fails)

63
Dr. Suleiman Abu Kharmeh
Summary
• You really want multiple threads per address space
• Kernel threads are much more efficient than processes,
but they’re still not cheap
– all operations require a kernel call and parameter validation
• User-level threads are:
– really fast/cheap
– great for common-case operations
• creation, synchronization, destruction
– can suffer in uncommon cases due to kernel obliviousness
• I/O
• preemption of a lock-holder
• Scheduler activations are an answer
– pretty subtle though (can map user threads over kernel
threads)
64
Dr. Suleiman Abu Kharmeh

You might also like