0% found this document useful (0 votes)
18 views28 pages

CSE203 LP Unit IV

This document covers the concepts of processes, threads, and process management in Linux programming. It explains the definitions of processes and threads, the process ID allocation, the creation and termination of processes using system calls like fork() and exec(), and the handling of process termination signals. Additionally, it discusses the use of atexit() and on_exit() functions for cleanup during process termination.

Uploaded by

Santosh Kumar
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)
18 views28 pages

CSE203 LP Unit IV

This document covers the concepts of processes, threads, and process management in Linux programming. It explains the definitions of processes and threads, the process ID allocation, the creation and termination of processes using system calls like fork() and exec(), and the handling of process termination signals. Additionally, it discusses the use of atexit() and on_exit() functions for cleanup during process termination.

Uploaded by

Santosh Kumar
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/ 28

CSE203 LINUX PROGRAMMING

UNIT – IV

P. Rajendiran
AP / IT / SoC

12/3/2022 1
Programs, Processes, and Threads
 A process is a running program
 A process includes the binary image loaded into
memory, but also much more: an instance of
virtualized memory, kernel resources such as open
files, a security context such as an associated user, and
one or more threads
 A thread is the unit of activity inside of a process. Each
thread has its own virtualized processor, which
includes a stack, processor state such as registers, and
an instruction pointer.

12/3/2022 2
 In a single threaded process, the process is the
thread. There is one instance of virtualized
memory and one virtualized processor
 In a multithreaded process, there are multiple
threads. As the virtualization of memory is
associated with the process, the threads all share
the same memory address space

12/3/2022 3
The Process ID
 Each process is represented by a unique identifier, the
process ID (frequently shortened to pid).
 The pid is guaranteed to be unique at any single point
in time. That is, while at time t+0 there can be only one
process with the pid 770 (if any process at all exists
with such a value), there is no guarantee that at time
t+1 a different process won’t exist with pid 770

12/3/2022 4
 The first process that the kernel executes after
booting the system, called the init process, has the
pid 1.
 Normally, the init process on Linux is the init
program. We use the term “init” to refer to both the
initial process that the kernel runs, and the specific
program used for that purpose.
 Unless the user explicitly tells the kernel what
process to run
 The Linux kernel tries four executables, in the
following order

12/3/2022 5
 1. /sbin/init: The preferred and most likely location for the
init process.
 2. /etc/init: Another likely location for the init process.
 3. /bin/init: A fallback location for the init process.
 4. /bin/sh: The location of the Bourne shell, which the kernel
tries to run if it fails to find an init process.

 If all four processes fail to execute, the Linux kernel halts


the system with a panic

12/3/2022 6
Process ID Allocation
 the kernel imposes a maximum process ID value of 32768.
This is for compatibility with older Unix systems, which
used signed 16-bit types for process IDs.
 System administrators can set the value higher via
/proc/sys/kernel/pid_max, trading a larger pid space for
reduced compatibility.
 The kernel allocates process IDs to processes in a strictly
linear fashion. If pid 17 is the highest number currently
allocated, pid 18 will be allocated next, even if the process
last assigned pid 17 is no longer running when the new
process starts.

12/3/2022 7
 The kernel does not reuse process ID values until it
wraps around from the top—that is, earlier values will
not be reused until the value in proc/ sys/ kernel/
pid_max is allocated
The Process Hierarchy
 The process that spawns a new process is known as the
parent; the new process is known as the child. Every
process is spawned from another process (except, the
init process)

12/3/2022 8
 the process ID is represented by the pid_t type, which
is defined in the header file <sys/types.h>.
Obtaining the Process ID and Parent Process ID
 The getpid() system call returns the process ID of the
invoking process:
 #include <sys/types.h>
 #include <unistd.h>
 pid_t getpid (void);

12/3/2022 9
 The getppid() system call returns the process ID of the
invoking process’s parent:
#include <sys/types.h>
#include <unistd.h>
pid_t getppid (void);

12/3/2022 10
Running a New Process
 The act of loading into memory and executing a
program image is separate from the act of creating a
new process
 system call loads a binary program into memory,
replacing the previous contents of the address space,
and begins execution of the new program. This is
called executing a new program, and the functionality
is provided by the exec family of calls.
 creating a new process is called forking, and this
functionality is provided by the
 fork() system call. Two acts—first a fork to create a
new process, and then an exec to load a new binary
into that process—
12/3/2022 11
The Exec Family of Calls
 There is no single exec function; instead, there is a
family of exec functions built on a single system call
 execl():
#include <unistd.h>
int execl (const char *path, const char *arg, ...);
 A call to execl() replaces the current process image
with a new one by loading into memory the program
pointed at by path
 The parameter arg is the first argument to this
program. The ellipsis signifies a variable number of
arguments

12/3/2022 12
 The list of arguments must be NULL-terminated
 For example, the following code replaces the currently
executing program with /bin/vi:
int ret;
ret = execl ("/bin/vi", "vi", NULL);
if (ret == −1)
perror ("execl");
• Normally, execl() does not return
• On error, however, execl() returns −1 and sets errno
to indicate the problem.

12/3/2022 13
 The rest of the family In addition to execl(), there are
five other members of the exec family:
 #include <unistd.h>
 int execlp (const char *file,
 const char *arg,
 ...);
 int execle (const char *path,
 const char *arg,
 ...,

12/3/2022 14
 char * const envp[]);
 int execv (const char *path, char *const argv[]);
 int execvp (const char *file, char *const argv[]);
 int execve (const char *filename,
 char *const argv[],
 char *const envp[]);
 The p denotes that the user’s full path is searched for
the given file.
 e notes that a new environment is also supplied for the
new process.
 The l and v delineate whether the arguments are
provided via a list or an array (vector)
12/3/2022 15
 The following snippet uses execv() to execute vi, as we
did previously:
 const char *args[] = { "vi", "/home/kidd/hooks.txt",
NULL };
int ret;
ret = execv ("/bin/vi", args);
if (ret == −1)
perror ("execvp");

12/3/2022 16
Error values
 On success, the exec system calls do not return. On
failure, the calls return −1 and set errno to one of the
following values:
 E2BIG - The total number of bytes in the provided
arguments list (arg) or environment (envp) is too
large.
 EACCES - The process lacks search permission for a
component in path; path is not a regular file; the target
file is not marked executable; or the filesystem on
which path or file resides is mounted noexec.

12/3/2022 17
The fork() System Call
 A new process running the same image as the current
one can be created via the fork() system call:
#include <sys/types.h>
#include <unistd.h>
pid_t fork (void);
 The new process is called the “child” of the original
process, which in turn is called the “parent.”
 In the child, a successful invocation of fork()
returns 0.
 In the parent, fork() returns the pid of the child

12/3/2022 18
Example :
pid_t pid;
pid = fork ();
if (pid > 0)
printf ("I am the parent of pid=%d!\n", pid);
else if (!pid)
printf ("I am the child!\n");
else if (pid == −1)
perror ("fork");

12/3/2022 19
 the kernel created copies of all internal data structures
duplicated the process’s page table entries, and then
performed a page-by-page copy of the parent’s address
space into the child’s new address space.
 Unfortunately, this page-by-page copy is time-
consuming
 multiple consumers request read access to their own
copies of a resource, duplicate copies of the resource
need not be made, if not modification is required

12/3/2022 20
 without copy-on-write semantics their address space
and page table entries. In fact, the only work done
during a vfork() is the duplication of internal kernel
data structures.
 Consequently, the child must not modify any memory
in the address space.

12/3/2022 21
Terminating a Process
 #include <stdlib.h>
 void exit (int status);
 This function has no way of returning an error—in
fact, it never returns at all. Therefore, it does not make
sense for any instructions to follow the exit() call.
 The status parameter is used to denote the process’s
exit status
 Before terminating the process, the C library performs
the following shutdown steps, in order:

12/3/2022 22
 1. Call any functions registered with atexit() or on_exit(), in the reverse
order of their registration.
 2. Flush all open standard I/O streams
 3. Remove any temporary files created with the tmpfile() function
 exit() invokes the system call _exit() to let the kernel handle the rest of
the termination process
 #include <unistd.h>
 void _exit (int status);
 Applications can call _exit() directly, but such a move seldom makes
sense: most applications need to do some of the cleanup provided by a
full exit, such as flushing the stdout stream. Note, however, that vfork()
users should call _exit(), and not exit(), after a fork.

12/3/2022 23
 the ISO C99 standard added the _Exit() function,
which has identical behavior to _exit():
#include <stdlib.h>
void _Exit (int status);

Other Ways to Terminate


 A process can also terminate if it is sent a signal
whose default action is to terminate the process.
Such signals include SIGTERM and SIGKILL

12/3/2022 24
atexit()
 the atexit() library call, used to register functions to be
invoked upon process termination
#include <stdlib.h>
int atexit (void (*function)(void));
 Registered functions must not call exit() lest they
begin an endless recursion. If a function needs to
end the termination process early, it should call
_exit()

12/3/2022 25
 on_exit() SunOS 4 defined its own equivalent to
atexit(), and Linux’s glibc supports it:
 #include <stdlib.h>
 int on_exit (void (*function)(int, void *), void
*arg);
 This function works the same as atexit(), but the
registered function’s prototype is different:

 void my_function (int status, void *arg);

12/3/2022 26
SIGCHLD
 When a process terminates, the kernel sends the signal
SIGCHLD to the parent.
 By default, this signal is ignored, and no action is
taken by the parent
 Processes can elect to handle this signal, however, via
the signal() or sigaction() system calls.

12/3/2022 27
End of the 4th Unit

12/3/2022 28

You might also like