0% found this document useful (0 votes)
10 views15 pages

Unix Unit4 Part A

This document discusses the process environment in C programming, focusing on the main function, command-line arguments, memory layout, and process termination methods. It explains how the main function is executed, the role of the startup routine, and various functions like exit, _exit, and atexit for terminating processes. Additionally, it covers the use of environment variables and the interaction of longjmp and setjmp with the stack.

Uploaded by

pranavhm2692003
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)
10 views15 pages

Unix Unit4 Part A

This document discusses the process environment in C programming, focusing on the main function, command-line arguments, memory layout, and process termination methods. It explains how the main function is executed, the role of the startup routine, and various functions like exit, _exit, and atexit for terminating processes. Additionally, it covers the use of environment variables and the interaction of longjmp and setjmp with the stack.

Uploaded by

pranavhm2692003
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

7

Process Environment

7.1 Introduction

Before looking at the process control primitives in the next chapter, we need to
the environment of a single process. In this chapter, we'll see how the examine
main
called when the program is executed, how command-line arguments are passed function is
to the
new program, what the typical memory layout looks like, how to allocate additional
memory, how the process can use environment variables, and various ways for the
process to terminate. Additionally, we'll look at the longjmp and setjmp functions
and their interaction with the stack. We finish the chapter by
limits of a examining the resource
process.

7.2 main Function


ACprogram starts execution with a function called main. The prototype for the main
function is
int main( int argc, char *argv[]);
where argc is the number of command-line arguments, and argv is an array of pointers
to the arguments. We describe these arguments in Section 7.4.
When a Cprogram is executed by the kernel-by one of the exec functions, which
we describe in Section 8.10--a special start-up routine is called before the main
function is called. The executable program file specifies this routine as the starting
address for the program; this is set up by the link editor when it is invoked by the C
compiler. This start-up routine takes values from the kernel-the command-line
arguments and the environment-and sets things up so that the main function is called
as shown earlier.

197
POSIX.1. specified
by _exit
is
13 C,
w
IS0 specifed
by are Exit and exit that headersis different the for reason The
status exit the print $?
echo $
world hello, Section
8.5. process,
interminating the parent
of the and
./[Link] $ chilae the processes,
as
such other functions
on three these effect
of discuss
helloc . gcc $ the We'l
returns: function main the that time status); (int exit VOid
at register
thecontents of
and stack the contents thdepending
e on exit
codes, different
random. <unistd.
h> #include
get likely
to we different
are systems, program
on same compile
the we If
in the run and compile we When status); Exit(int void
iscode exit the that see we7.1,Figure program
status);exit(int void
program ClassicC Figure
7.1 <stdlib.
h> #include
kernel. the returns
to
world\n") ; "hello, print£ ( processing
tha and cleanup certain performs which exit, immediately,
and kernel
return
teto which _Exit,normally:_exit
and program terminatea functions Three
main()
Functions Exit
<stdio.
h> #include
example. world" "hello, classic 7.1
the isFigure program
in The argv))? (argC, (main exit
Example ike look could main callanguage)
to l the assembly coded
in often C(it
is coded
in
the called.
If function
is exit returns,
the function main the
thatroutine
i wrso itstart-up
en mentioned thatroutine start-up
we The
is previous
also section the in
furnction. main the from 12. andChapters1l threads
in
threads
until
dwe three the ignore we'l now, For
return(0); specific
to methodstermination
is requestcancellation thread
ato last thResponse
e of 8.
same the 11.5
>and13(Sections
aS aof
signal Receipt 7.
exit(0);
10.(Section
2)
10.1(Section
7) abort Calling 6.
same the with
Thus value.
Returning Abnormal
to function
is main the from value integer an ways: three termination
occurs
in
exít calling equivalent
exitpthread Calling 5.
function exit the a or
tocall statement thread last the from 11.5(Section
)
return explicit without
an reached function
was main the ofend thundefined
e if was
start ifromts thread of
last the Return 4.
standard. of
0 the version
ISC 1999 is
the with new behavior This 11.5)(Section routine
status the
exitHistorically, and or_Exit _exit Calling 3.
main
process
0. is the statusof exit return), the implicit (an end" the off1"falls status exit exit Calling 2.
type return thHowever,
e if undefined. process of
the without
integer anmain is of is
integet returrn
an declared to notfunction
is main the (c) value, main from Return 1.
the
or return ofany a (a) If
(b)
status, exit without
an functions is these status.
return does
| aastatus
of main exit examine the to way provideacalled shells System UNIX Most All i ways:
process. argument, integer single functions exit three Section eight
which
we
expect
a 5.5 termination Normal terminate. process
to afor ways are There
exit the call to flushed betodataoutput buffered causes
all this I/Othatstandard
file). the (written library: Termination Process
open al called function fclose theHistorically, 7.3
from Recall streans. clean performeda for always is function
theshutdown
of has exit the
Soction
73
Environment Process
Termínation Process 198
199
7.2). Figure shown
in (not signal terminated registered. was ittimes
as many called
as function
is registration.
Each
arily bealso proces
can exit),A calling implicitly
(by explicitly
or aby ner theu order
of reverse functions
in these calls function exit The value. returna
alled, is
Exit _exit
or terminate
if isvoluntarily canprocess
waay only The alled. expectedto not isarguments
and any passed not is
called,
it function this When
nctionsis exec the of
one ifkernel
is the executed
by be
program
can waay only lne atexit. argument
to thefunction
as address
aof the pass we
that declaration
says This
error nonzero
on OK, Returns:
if 0
terminates howit andstarted program
is HowaC [Link]
2 (void);) (*func) (void atexit int
<stdlib.h> #include
function. atexit tcalling
he registered
by are handlers
and exit called arThese
e exit.
kernel automatically
calledby are functions
that 32
least register
at cprocess
an aC,
1SO With
Function atexit
status. exit its fetch then complete,
and process
to the for
exec executed,
wait program
be to causea canprocess any how se well chapter, next the In
used. are
routine warning
onadditional unless warnings compiler extraneous these enmit doesn't usually
Exit start-up C com. GNUC the that Notwarrings.
e their verbosity
of the in
varycompilers Different
cleanup or returm) not
(does
I/standard
0 erim exit POSDX.1.
exit
c": ISo both specified
by definition the isthat since integer, returning
an as
main show
ter this integer.
In signed supposed
a beto main
is type
of return the sincewarnings,
process user I
function return) not(does
function othergenerate can and programming
text), (especially
ain right look doesn't
rerum main
Exit, retur ingbut Duñ compiler the ofrid gets This exit. calling continue and int, instead
of void,
exit exit
handler exit
call

retum) retu not (does utlityto grepSystasSmaienm's declare to


solution
is Another program. froma exit tocalls locate
al
exit exiti nsteadreturn UNIX the using from prevents
us this doing But main. from exit
retut
One use towhile,
is a
annoying
after become whichwarnings, these around
the maiisn from exit an t
that know don'compilers these that
prreotburlwneaymisareturn.
The as
asame
handler exit functions
Exit,
program. lint(1);
instead the compilers
and some from warnings needless produces
of exit ofuse the and integer returning
an as of
main declaration The
user
Or
exitr we endreaches "control something
like message warning
enablwoule d function.
then n nonvoid of
al flag), -Wall the (withcompiler the from warningsecommended
terminate. can wwa antrmeinliger. were
to However,
weif away. would
go message declaration,
the this add to
were
functions. to
declared
[Link]
extThiesnsian explicitly not function
is in ma the tvpe the
of because printed
Figure O 1999
ISC the enable when warning compiler
we the Note
waysIt various the and started program is aCsummarizes 7.2 handlers exit
family of exec how installed fclose)
all
the ofany calprogram ls the cleared
if be wil
any specifying
that standard
by O extends
ISC the open all 0
POSIX.1 streams. ISO With status exit the print $?
echo $
(via closes then handlers
and C world hello,
exit the calls first exit POSIX.1, and
platform,
./[Link] $
[Link] illustrated
in as given supported
aby handlers numberof maximum int defaults
to type return warninq: nello.C:4:
determine
the toused befunction exit (see more
support hello.c -std=c99
can sysconf
chang code extensions 1SOC 1999 gocs enable
ementations
often handlers,
but The 2.15). Pigure 1S0C
gcc $
exit 32least support
at systems requires
that exit. see
the that extensions,
we compiler ISCOC 1999 theenable
(hapter w
weNoif
handlers. exit theseprovide did
ANSI predate thatSystems 1989. Standard
in ANSIC appeared
the notin4.3BSD, handlers
first andSVR3, exias tsuchThese C,
Environment Process
Termination Process
20
201
environ
the call We'l string. end the bytes
75. Figure like look could strings,iteach fiof at null the explicitly
show we Here
veconsisted
ofenvironment the example,
if For main. from return
exit call don't we
that Note times. "ead,
we
**environ; char extern two called is ittwice,
so registered ndler
is
,
eut first the 7.3Figure registered.
In is timite each for once called handler
contained pointers environ: variable global is exit
is array
of the address of null-terminatedC
The string. the in
containing
the pointer each withpointers, character address
aof handler exit second
argument
the list, array
of anenvironment
islist handler exit first
the Like environment
list. passed
an
program also handler exit first
is Each done ismain
./[Link] $
Environment
List 75 yields 7.3Figure program
in Executing
the
it+) NULL; argv[i)
!= 0; =(i for handlers exitExample
of 7.3Figure
argument-processing
loop
as thealternatively
code 1us oke
This pointer. null argc]
ais argv[ POSDK. }
that 1 and SOC bothguaranteed
by .[Link] handler\n"); exit"second printf(
argv[3]: (void
my_exit2
)
foo
TESTargv(2]: void static
argl argv[1
]:
"/echoarg argv[0]:
\n")ihandler printf("first
exit
./echoarg
argl $
have echoarg,
we executable thIname
e foo progranm
andTEST this
compile we If my_exiti(void)
void static
output standard arguments
tocommand-line al Echo Eirure
7.4 return(0);
(0) ;exit done\n"); "main
is printf(
i]); argv [ printf(" my_exiti"); register "cant err_sys (
command-line
args* i,
$s\n", " %d]: "argv[ (i for (my_exitl (atexit if
all echo /* argc; < i 0; =
0) != ) err_sys
(
1++) my_exitl"); register "can
't
int (my__exitl) (atexit if
i; 0) !=
(int mainint
argc, my_exitz" register err_sys("cant
*argvLD) Char ); (atexit
(my 1f
!=
0) exit2)
#include
(VOid ) main
"apue.h"
that Note int
argument. zeroth the
proOgTa The
output standard the echodoesnt program 1echo(1) normal inTam EraMple (void) i exit2 my
void static
arguments
to comnand-line its echoes
al [Link]
4 (void)i exitl my
void Static
"apue.h" #include
system
chapterS- earlier shells.
aTguments function. demonstrates
7.3Figure program
in The
fromexamples the many
of in
this seenalready have We atexit the the
ofuse
When
UNDA the operation
of normal the of
part newprogamthe to a Example
commarnd-line pass can exec Thisprogram.
is
Command-Line hapter
the does thatprOcess
Argumentsexecuted,
the is
Environment Process
202
Environment
List
203
204
Process Environment Memory Layout of a C Program 205
tion
Z6

Initialized data segment, usuallycalled simply the data segment, containing


variables that are specifically initialized in the prograrn. For example, the C
environment
declaration
envionment environment maxcOunt = 99:
pointer list
strings int

environ: HOME=/home/sar\o appearingoutside any function causes this variable to be stored lin the initialized
withits initial value.
PATH=: /bin:/usr/bin datasegment
Uninitialized data segment, often called the bss
SHELL=/bin/bash\n segment,
ancient assembler operator that stood for "block started by symbol." Data an
named after in
+USER=sar\0
segmentis initialized by the kernel to arithmetic 0 or null before the
LOGNAME=sar\0 this
program starts executing. The Cdeclaration pointers
NULL
long sum[ 1000]:
appearing outside any function causes this variable to be stored in the
Figure 7.5 Environment consisting of five C character strings ninitialized data segment.
Stack, where automatic variables are stored, along with information that is saved
environment list, and each time a function is called. Each time a function is called, the address of
environment pointer, the array of pointers the the strings they where to return to and certain information about the caller's environment, such
to the environment strings.
By convention, the environment consists of Weme of the machine registers, are saved on the stack. The newly called
function then allocates room on the stack for its automatic and temporary
name=value variables. This is how recursive furnctions in Ccan work. Each time a recursive
names are entirely function calls itself, a new stack frame is used, so one set of variables doesn't
strings, as shown in Figure 7.5. Most predefined uppercase, but this interfere with the variables from another instance of the function.
is only a convention.
Historically, most UNIX systems have provided a third argument to the main Heap, where dynamic memory allocation usually takes place. Historically, the
function that is the address of the environment list: heap has been located between the uninitialized data and the stack.
int main ( int argc, char *argv[], char *envp U):
Eeure 7.6 showslooks;
the typical arrangement of these segments. This is alogical picture of
Because ISO Cspecifies that the main function be written with two arguments, how a program there no requirement that a given implementation arrange its
is
because this third argument provides no benefit over the global variable e memoryinthis fashion. Nevertheless, this gives us a typical arrangement to describe.
POSIX.1 specifies that environ should be used instead of the (possible) th Wh Linux on a 32-bit Intel X86 processor, the text segment starts at location
argument. Access to specific environment variables is normally through the gete nw08048000, and the bottom of the stack starts just below 0xC0000000. (The stack
and putenv functions, described in Section 7.9, instead of through the enviv ornws from higher-numbered addresses to lower-numbered addresses on this particular
variable. But togo through the entire environment, the environ pointer must be se architecture.) The unused virtual address space between the top of the heap and the top
of the stack is large.

7.6 Memory Layout of a C Program Several more segment types exist in an [Link], containing the symbol table, debugging
information, linkage tables for dynamic shared libraries, and the like. These additional
Historically, a Cprogram has been composed of the following pieces: sections don't get loaded as part of the program's image executed by a process.

Text segment, consisting of the machine instructions that the CPU executs Note from Figure 7.6 that the contents of the uninitialized data segment are not
Usually, the text segment is sharable so that only a single copy needs to be n stored in the program file on disk, because the kernel sets the contents to 0 before the
memory for frequently executed programs,such as text editors, the Ccompilet program starts runing. The only portions of the program that need to be saved in the
the shells, and so on. Also, the text segment is often read-only, to prevent a program file are the text segment and the initialized data.
program from accidentally modifying its instructions.
206 Memory Allocation 207
Process Environment
o r t oZ
n 8

the oige differences,


the
-was
examnple
of following executable ile-the classic
first created without shared libraries:
hello.c
program--
an .c
-static hello1 prevent goc from using shared libraries
high address command-line arguments
and environment variables go 1 [Link]
-rWXr-Kr-x
1 8ar 879443 Sep 2 10:39 a.0ut
stack s size [Link]
data bss dec hez filename
text 11272 805175
6128 c4937 [Link]
787775
compile this program to use shared libraries, the text and data sizes of the
we
executable
If ileare greatly decreased:
$ gcchello1.e gcc defaults to use shared libraries
heap [Link]
-rWXr-XE-X
l 1 sar 8378 Sep 2
$ ls 10:39 [Link]
uninitialized data initialized to $ s1ze [Link]
(bss) zero by exec data bss dec hex
text £ilename
504 16 1696 6a0 [Link]
initialized data read from 1176
program file
text by exec
low address Memory Allocation

Figure 7.6 Typical memory arrangement 18 specifiesthree functions for memory allocation:
1SOC
malloc, which allocates a specified number of bytes of memory. The initial
The size(1) command reports the sizes (in bytes) of the text. 1.
value of the memory is indeterminate.
segments. For example: data, and bs calloc, which allocates space for a specified number of objects of a specified
2. 0 bits
size. The space is initialized to all
$ size /usr/bin/cc /bin/sh
text data bss dec hex filename
346919 3576 6680 357175 57337 /usr/bin/cc realloc, which increases or decreases the size of a previously allocated area.
3.
102134 1776 11272 115182 lclee /bin/sh When the size increases, it may involve moving the previously allocated area
The fourth and fifth columns are the total of the three sizes, displayed in decimal.. somewhere else, to provide the additional room at the end. Also, when the size
increases, the initial value of the space between the old contents and the end of
hexadecimal, respectively. indeterminate.
the new area is
#include <stdlib.h>
7.7 Shared Libraries
void *malloc ( size_t size) ;
Most UNIX systems today support shared libraries. Arnold (1986] describes an earl
implementation under System V, and Gingell et al. [1987] describe a difere void *calloc (size_t nobj, sizet size);
implementation under SunOS. Shared libraries remove the common library routins void *realloc (void *ptr, sizet newsize ) ;
from the executable file, instead maintaining a single copy of the library routing Allthree return: non-null pointer if OK, NULL On error
somewhere in memory that all processes reference. This reduces the size of each
executable file but may add some runtime overhead, either when the program is first void free (void *ptr);
executed or the first time each shared library function is called. Another advantage of
shared libraries is that library functions can be replaced with new versions without The pointer returned by the three allocation functions is guaranteed to be suitably
having to relink edit every program that uses the library (assuming that the number and aligned so that it can be used for any data object. For example, if the most restrictive
type of arguments haven't changed). alignment requiremnent on a particular system requires that doubles must start at
Different systems provide different ways for a program to say that it wants to use or memory locations that are multiples of 8, then all pointers returned by these three
not use the shared libraries. Options for the cc(1) and ld(1) commands are typical. As functions would be so aligned.
Process Environment
objects can be unrelated to the code corrupting them, making it even
These source of the
Because the three alloc functions return a generic void
difficultto find the
objects.
errors that can be fatal are corruption.
possible freeing a block that was already freed and
#include <stdlib.h> (to obtain the function prototypes),
to cast the Ponter returned by these functions when we assign it to a
different type. The default noturn value for undeclared functhons is int.
we do
not peoxiplntri,tly more
Other
functions.
with a pointer that was not obtained from one of
free
calling If a process calls malloc but forgets to call £ree, its
continuallyincrease:his is called leakage. If we do not call
the three alloc
memory usage w
hide an error on systems
free to return unused
process's,address space will slowly increase until
without the Proper function declaration could return thesizeof aperformance no free space is lert.
thiswhere ase)he s
of type int differs from the size of afunction's value (a pointer in can degrade from excess
ptr to be deallocat
space,
this time, paging overhead.
The free causes the space pointed to byand
function can be allocat
During memory allocation errors are difficult to track down, some
systems provide
space is usually put intoa pool of available memory
to one of the three alloc functions.
Tahliaster fre a
in
Because
of
these hunctions that do additional error checking every time one of the three
functions or free is called. These versions of the functions are often specifhea
versions
change the size of a previously
Ihe realloc function Jets us area's size.) For example, if wo allocated area. alloc,
including a
special library for the link editor. There are also
compile with special flags to publicly available
most common usage is to increase

realloc. If
an
we fill in at runtime but later
find
Dl2 elenments in an arrav that there is room beyond the end of that thel existing
alweocateneedrOOm(h hy
SOurces that youcan enable additional runtime checking-
FreeBSD, Mac OS X. and Linux support additional debugging through the setting of
room, we can call additional
simply allocates this
then realloc area at regon o n
environment variables. In addition, options can be passed to the FreeBSD library through the
the requested
returns the space,
same pointer that we passed it. But if there isn't room,
512-elemernt.
realloc ihe end and asrmbolic link /etc/malloc. con f
copies the existing array to the
another area that is large enough, Because
the pointer to the new area.
frees the old area, and returns into this area. Exercise 4.16 and
the area ma new area AlternateMemory. Allocators
we shouldn't have any
pointers
handle a pathname of any
Figure
length.
Figure C3mayShowmoehe replacements for malloc and free are available. Some systems already include
use of realloc with getcwd to arrays
an example that uses realloc to avoidrealloc
with fixed, compile-time
size of
c'
1721 Showe Many providing alternative memory allocator implementations. Other systems
Note that the final argument to
the new
special case, if ptr is a
the reginulon, not th
libraries
provide onlythe standard allocator, leaving it up to software developers to download
difference between the old and new sizes. As a alternatives,:if desired.
We discuss some of the alternatives here.
realloc behaves like malloc and allocates a region of the specified newsize pointe,
we
Older versions of these routines allowed us to realloc a block that had
last call to malloc, real loc, or calloc. This trick dates
back to
Version 7and freed since te Jibmalloc
search strategy of malloc to perform storage compaction. Solaris still supports exploited ta SVR4-based systems, such as Solaris, include the libmalloc library, which provides a
but many other platforms do not. This feature is deprecated and should not be iuedthis featue interfaces matching the ISO C memory allocation functions. The libmalloc
set of
mallopt, afunction that allows a process to set certain variables that
libraryincludes
operation of the storage allocator. Afunction called mallinfo is also
The allocation routines are usually implemented with the sbrk(2) system call n. control the
system call expands (or contracts) the heap of the process. (Refer to Figure 76 statistics on the memory allocato.
available to provide
sample implementation of malloc and free is given in Section 8.7 of
Ritchie [1988). Kernighan and
Although sbrk can expand or contract the memory of a process, most versions of PMalloc
malloc and free never decrease their memory size. The space that we fre t. fno961 describes a memory allocator that allows processes to allocate memory using
available for a later allocation, but the freed space is not usually returned to the kemel Aifferent techniques for different regions of memory. In addition to the functions
instead, that space is kept in the malloc pool. snecificto vmalloc, the library provides emulations of the ISO C memory allocation
Most implementations allocate more space than requested and use the additional functions.
space for record keeping-thesize of the block, a pointer to the next allocated blok.
and the like. As a consequence, writing past the end or before the start of an allocated quick-fit
area could overwrite this record-keeping information in another block. These types of
errors are often catastrophic, but difficult to find, because the error may not show up Historically, the standard malloc algorithm used either a best-fit or a first-fit memory
untilmuch later. allocation strategy. Quick-fit is faster than either, but tends to use more memory.
Writing past the end or before the beginning of a dynamically allocated buffer can Weinstock and Wulf (1988) describe the algorithm, which isbuffers
based on
on different
splitting free
up
corrupt more than internal record-keeping information. The memory before and after a memory into buffers of various sizes and maintaining unused
dynamically allocated buffer can potentially be used for other dynamically allocated lists, depending on the buffer sizes. Most modern allocators are based on quick-fit.
Environment Variables 211
210
Process Environment o nZ

function returns a pointer to the value of a name=palue string. We should


jemalloc hapte thatthis
Note use
environ
getenvto
always directly.
fetch aspecific value from the environ ment. instead of accessing
environment variables are defined by POSIX.1 in the Single UNIX
The jemalloc implementation of the mallocdesigned
family of hbrary functions :
memory allocator in FreeBSD to scale well
Sorme whereas others are defined only if the XSI option is
supported. Figure 7.7
multithreaded applications
8.0. It was
running on multiprocessor systems.
Evans
when ushe edde a w Specification,
the
lists
environment variables defined by the Single ÚNIX Specification and notes
implementations support the variables,. Any environment variable defined by
the implementation andevaluates its performance. which marked with ; otherwise, it is part of the XSI option.
implemerntation-dependent Many additional
POSIX.1is environment variables are used in the four implemerntations
TCMalloc described,
inthisbook. Note that ISO Cdoesn't define any environment variables.
TCMalloc was designed as a replacement memory for the malloc family of
provide high performance, scalability, and efficiency. It usSes
functions
releasinighreabdufleors t
buffers from and FreeBSD Linux Mac 0S X Solaris
locking overhead when allocating POSIX.1
cachesto avoid 10.6.8 Description
checker and a heap profiler built in to
8.0 3.2.0 10
memory usage. The TCMalloc library is aid
has a hearp in Variable
andcache.
the It alsodynamic
analyzing
source from Google. It is briefly
described by Ghemawat and
available
I Menage (2005). debugin COLUMNS
DATEMSK
HOME
XSI
terminal width
getdate(3) template file pathname
home directory
name of locale
alloca Function LANG name of locale

One additional function is also worth


mentioning. The function alloca LCALL name of locale for collation
however, instead of allocating memory from the has LCCOLLATE
name of locale for character classification
calling sequence as malloc;
memory is allocated from the stack frame
of the current function. The the heap, be LCCTYPE
LCMESSAGES name of locale for messages

we don't have to free the space; it goes away


automatically when the advantage
eisi that LC MONETARY
name of locale for monetary editing

The alloca function increases the size of the stack frame. The functioangereturns
disadvant
to increase the size of is that
LCNUMERIC
name of locale for numeric editing
name of locale for date/ time formatting
some systems can't support alloca, if it's impossible many
C TIME terminal height
frame after the function has been called. Nevertheless, the
software packages Usestackit INES
LOGNAME
login narme
and implementations exist for a wide variety of systems. MSGVERB
XSI Emtnsg(3) message components to process
NLSPATH sequence of templates for message catalogs
Alfour platforms discussed in this text provide the alloca function. PATH
list of path prefixes to search for executable file
absolute pathname of current working directory
|PWD name of user's preferred shell
SHELL
7.9 Environment Variables TERM
terminal type
TMPDIR pathname of directory for creating temporary files
As we mentioned earlier, the environment strings are usually of the form time zone information
name=value
Figure 7.7 Environment variables defined in the Single UNIX Specification
The UNIX kernel never looks at these strings; their interpretation is up to the vatio.
applications. The shells, for example, use numerous environment variables. Soma
such as HOME and USER, are set automatically at login; others are left for us to set. N In addition to fetching the value of an environment variable, sometimes we may
normally set environment variables in a shell start-up fle to control the shell's actions want to set an environment variable. We may want to change the value of an existing
If we set the environment variable MAILPATH, for example, it tells the Bourne shel variable or add a new variable to the environment. (In the next chapter, we'l see that
GNU Bourne-again shell, and Korn shell where to look for mail. we can affect the environment of only the current process and any child processes that
ISO C defines a function that we can use to fetch values from the environment, but
this standard says that the contents of the environment are implementation defined. we invoke. We cannot affect the environment of the parent process, which is often a
#include <stdlib.h>
shell. Nevertheless, it is still useful to be able to modify the environment list.)
Unfortunately, not allsystems support this capability. Figure 78 shows the functions
char *getenv(const char *name); that are supported by the various standards and implementations.
Returns: pointer to value associated with name, NULL if not found
212
Process Environment
G t oZ
n In
8etjmp and longimp Functions 213

and SO can't expand upward; it can't be


Function ISOc POSIX. 1
FreeBSD Linux Mac OS X
procesS
frames
below it can't be moved, expanded downward, because all the
geteny
8.0 3.2.0 10.6.8 Solaris
10
stack

If we're modifying an existing name:


putenv 1. of the new
XS If the size value is less than
setenv a.
value, we can just copy the or equal to the size of the
unsetenv new stringover the old existing
cleareny of the
h If the size obtain new value is larger than string.
the
malloc to room
for the old One, however, we must
Figure 7.8 Support for various environment list functions and then replace new string,
the old pointer in the copy the new stringgto this area,
nointer to this allocated area. environment list for name with the
The clearenv function is not part of the Single UNX Specification. It is we're adding
2. Ifmalloc
a new
name, its more
name=valuecomplicated.
entries from the environment list. used to o to allocate room for the First, we have to call
remo string and copy the string to this
The prototypes for the middle three functions listed in Figure 7.8 are area.
if it's the
#include <stdlib. h> first time we've added a new
a.
to obtain room for a new list of name, we have to call malloc
int putenv (char *str) ; pointers. We
this new area ana store a pointer to Copy the old environment list
Returns: 0if
the
bis list of ponters. We also store a null name=value string at the end of
int setenv (const char *name, const char *value, int rewrite.
:OK,nonzero on eourse. Finally, We set environ to point topointer at the end of this list, of
this new list of pointers. Note
Erom Figure 7.6 that if the original environment list was contained above the
int unsetenv(const char *name) ; f the stack, as is
common, then
the heap. But most of the pointers in we have moved this list of pointers to
Both return: 0if OK, -1 this list still point to
The operation of these three functions is as follows:
on error above the top of the stack. name=value strings
b
TE #his isn't the first time we've added new strings to the
The putenv function takes a string of the form name=value
andrenmove then we know that we've already environment list,
environnment list. If name already exists, its old definition is first places it in the Ne iMst call realloc to allocate allocated room for the list on the heap, so
room for one more pointer. The pointer to
The setenv function sets nanme to value. If name already she neW name=value string is stored at the end of the list (on top of the
environment, then (a) if rewrite is nonzero, the existing definition forexists
nameinie the previous null pointer), followed by a null pointer.
removed; or (b) if rewrite is 0, an existing definition for name is not rem
name is not set to the new value, and no error oCcurs.
The unseteny function removes any definition of name. It is not
such a definition does not exist.
an ero . 110 setjmp and 1longjmp Functions
. can't goto a label that's in another function. Instead, we must use the
Note the difference between putenv and setenv. Whereas setenv must setjmp
allocate memo. dlongjmp functions to perform this type of branching. As welsee, these two
create the name=value string from its arguments, putenv is free to place the
directly into the environment. Indeed, many implementations do exactly this, string passed th hnctions are useful for handling error conditions that occur in a deeply nested function
an error to pass putenv a string allocated on the stack, since the so it would he
memory would be reusei cal.
after we return from the current function. Consider the skeleton in Figure 79. It consists of a main loop that reads lines from
It is interesting to examine how these functions must operate when standard input and calls the function do_line to process each line. This function then
modifying the calls gettoken to fetch the next token from the input line. The first token of a line is
environment list. Recall Figure 7.6: the environment list-the array of pointers to the assumed to be a command of some form, and a switch statement selects each
actual name=value strings--and the environment strings are typically stored at the top command. For the single command shown, the function cmd add is called.
of a process's memory space, above the stack. Deleting a string is simple; we just find
the pointer in the environment list and move all subsequent pointers The skeleton in Figure 7.9 is typical for programs that read commands, determine
down one. But the command type, and then call functions to process each command. Figure 7.10
adding a string or modifying an existing string is more difficult. The space at the top
the stack cannot be expanded, because it is often at the top of the address space of theaf
shows what the stack could look like after cmd add has been called.
214
Process Environment set jmp and longimp Functions 215
ton
ZIn

#include "apue.h"
(hapt
bottom of stack
|higheraddress
#define TOK ADD 5
stack frame
Void for main
do_ line(char *);
void cmd add(void);
int get token (void); stack frame
int for do line

main(void) stack frame


for cmd add
char line (MAXLINE ] ; direction of
!= NULL) stack growth
while (fgets (1line, MAXLINE, stdin) lower address
do line (line) ;
exit (0): Figure 7.10 Stack frames after cmd add has been called
/* global pointer for get_token() */
char *tok ptr; Storagefor the automatic variables is within the stack frame for each function. The
void line is in the stack frame for main, the integer cmd is in the stack frame tor
do line ( char *ptr) /* process one line of input */ do_line,
array and the integer token is in the stack frame for cmd add.
{ we've said, this type of arrangement of the stack is typical, but not required.
int cmd; As have to grow toward lower memory addresses. On systems that don't
Stacks do not
tok ptr = ptr; have built-in hardware support for stacks, a C implementation might use alinked list
while ((cmd = get token () ) > 0) { frames.
switch (cmd) { /* one case for each command */ foritsstack problem that's often encountered with programs like the one shown in
The coding to handle
case TOK ADD:
Figure 7.9 is
how nonfatal errors. For example, if the cmd add function
cmd _add () ; encounters an error-say, an invalid number-it might want to print an error message,
break;
rest of the input line, and return to the main function to read the next input
ignorethe
when we're deeply nested numerous levels down from the ma in function, this
line. But
to do in C. (In this example, the cmd_add function is only two levels down
is difficult but
void from main, it's not uncommon to be five or more levels down from the point to
cmd add (void) ohich we want to return.) It becomes messy if we have to code each function with a
specialIreeturn value that tells it to return one level.
int token; The solution tothis problem is to use a nonlocal goto: the setjmp and longjmp
token = get token();
unction's. The adjective "nonlocal" indicates that we're not doing a normal Cgoto
/* rest of processing for this command */ statement within a function; instead, we're branching back through the call frames to a
function that is in the call path of the current function.
int #include <setjmp.h>
get_token (void)
{ int setjmp( jmp_buf env);
/* fetch next token from line pointed to by tok ptr */
) Returns: 0 if called directly, nonzero if returning from a call to longjmp
Figure 7.9 Typical program skeleton for command processing void longjmp(jmp buf env, int val) ;
217
216 Process Environment 8et jmp and longjmp Functions

executed, we call setjmp, which


mainis records whatever information it needs
We call When variable 4mpbuffer and returns 0. We then call do line, which calis
is in the main setjmp fromInthe location that we want to return to, wewhich in
0because
the
in and eaume that an error of some form is the call to
the stack looks like that in Figure detected. Before causes the
function. this case, set jmp returns type
the call to
setjmp, the argument env is of the specialinformation
some form of array that is capable of holding all the
calleThid s direct
jmp buf. it
to
cmd
add,
cmd
add
1ongjmpin"unwOund"
7.10. But longjmp
backto the main function, throwing away the stack frames tor
required darteastorype
t o be
,
stack do 1ine (Figure 7.12). Calling longjmp causes the setimp in main to
status of the stack to the state when we call longjmp. Normally, thbe to add, and
it returns with
another function. env cmd butthis time a value of 1(the second argument for
longjmp)-
500l variable,since we'll need to reference it fromcmd_add
When we encounter an error-say, in thethat we usedfunction-w varmabl return,

with two arguments. The first is the same env in a call


to call bottom of stack

msetp. )mTp,helongisandecond
from set s
value higher address
Second, val, is a nonzem value that becomes the return
dgumernt allows us to use more than one longjmp tor each setjmp, cjFor stack frame
of 1and also call longjmo fr
could longjmp from cmd add with a valreturn
for main

With a val of 2. In the ma in function, the


value from set jmp isfrom
the
eitherget
we can test this value. if we
cmd add or get token.
want, and determine whether

7.11 shows both the main


longjmandp10r2was,and
Let's return to the example. Figure get_ token, haven't
functions. (The other two functions, do line and
#include "apue.h"
#include <set jmp. h>
changed.) direction of
stack growth
lower address

#define TOK ADD 5


Figure 7.12 Stack frame after longjmp has been called
jmp_buf jmpbuffer;
int
main (void)
and Volatile Variables
Automatic, Register,
char line [MAXLINE ];
what the stack looks like after calling longjmp. The next question is, "What
if (setjmp(jmpbuffer) 1= 0) We've seen
printf ("error"): are the states of the automatic variables and register variables in the main function?"
to main as a result of the longjmp, do these variables have values
while (fgets (line, MAXLINE, stdin) != NULL) When we return
do line(line) ; corresponding to those when the setjmp was previously called (i.e., are their values
exit(0); rolled back), or are their values left alone so that their values are whatever they were
when do line was called (which caused cmd _add to be called, which caused
longjmp to be called)? Unfortunately, the answer is "It depends." Most
imnlementations do not try to rol back these automatic variables and register variables,
void
cmd_add (void)
hut the standards say only that their values are indeterminate. If you have an automatic
variable that you don't want rolled back, define it with the volatile attribute.
int token; Variables that are declared as global or static are left alone when longjmp is executed.
token = get token ( );
if (token <0) /* an error has occurred */
longjmp(jmpbuffer, 1); Example
/* rest of processing for this command */
}
The program in Figure 7.13 demonstrates the different behavior that can be seen with
Figure 7.11 Example of set jmp and longjmp automatic, global, register, static, and volatile variables after calling 1longjmp.
218
Process Environment Bet jmp and longjmp Functions 219
on
ZO

compile nd test the prOgran in Figure


the results are differemt:
optimizations,
we
7.13, with and without compiler
#include "apue.h" I f $ gec testjmp.e
compile without any
#include <set jmp.h> $ . / a .Out optimization
static void f1(int, int, int, int)7 in fl()#
static void f2(void); globval = 95, autoval = 96,
after longjmp:
regival = 97,
volaval = 98, statval = 99
static jmp buf jmpbuffer; globval = 95, autoval = 96, regival = 97, volaval = 98. statval = 3
static int globval; gec
-0 testjmp.c compile with fulloptimization
int $$ ./[Link]

main(void) in f l( ): = 95, auutoval


globval - 96 r regival 97,, volaval = 98., statval = 99
after longjmp:
int autoval; autova1 2, regival = 3,
register int regival; Globval = 95, volaval = 98, statval 2
volatile int volaval;
thatthe
optimizations don't affect the global, static. and volatile variables; their
static int statval; Note afterthe longjmp are the last values that they assumed. The
values setjmp(3) marnual
system states that variables stored in memory will have values as of
l; autoval = 2; regival = 3; volaval = 4; the
globval statval = on one
page the longjmp, whereas variables in the
CPU and floating-point registers are
if (set jmp ( jmpbuffer ) != 0) { of
restoredto their values
time when setjmp was called. This is indeed what we see when we
printf ("after longjmp:\n");
printf("globval = %d, autoval = %d, regival = %d, " programin Figure 7.13. Without optimization, all five variables are stored in
" volaval = %d, statval = %d\n",
Iunthe hint
register is ignored for regival). When we enable optimization,
memory (the
globval, autoval, regival, volaval, statval): both autovaland regival go into registers, even though the former wasn't declared
register,andthevolatile variable stays in memory. The
exit(0):
important thing to realize
this example is that you must use the volatile attribute if you're writing
with
portable code that uses nonlocal jumps. Anything else can change from one system to
* Change variables after setjmp, but before longjmp.
thenext.
Some printf format strings in Figure 7.13 are longer than will fit comfortably for
*/
globval = 95; autoval = 96; regival = 97; volaval = 98; programmingtext. Instead of
statval = 99: making multiple calls to printf, we rely on
display in a concatenation feature, where the
ISO C'sstring sequence
fl(autoval, regival, volaval, statval); /* never returns */
exit (0); "stringl1" "string2"
} isequivalentto
static void "stringlstring2 "
fl(int i, int i, int k, int l)

printf ("in £1() :\n") ; Well returm to these two functions,setjmp and longjmp, in Chapter 10when we
printf("globval = %d, autoval = td, regival = td, " kouss signal handlers and their signal versions: sigset jmp and siglongjmp.
volaval = td, statval = $d\n", globval, i, j, k, l);
f2();
Varlables
Potentlal Problem with Automatic
static void
f2 (void) Having looked at the way stack frames are usually handled, it is worth looking at a
potential error in dealing with automatic variables. The basic rule is that an automatic
longjmp(jmpbuffer, 1); variable can never be referenced after the function that declared it returns. Numerous
warnings about this can be found throughout the UNIX System manuals.
Figure 7.14 shows a function called open data that opens a standard I/0 stream
Figure 7.13 Effect of longjmp on various types of variables
and sets the buffering for the stream.
220
Process Environment getrlimit and setrlimit Functions 221

govern the changing of the resource limit,.


rules
#include <stdio.h>
Three
A process can change its soft limit to a value less than or egual to limit.
FILE * its hard
A process can lower its hard limit to a value greater than or equal to its soft
1.
open data (void) This lowering of the hard limit is
limit. irreversible
superuser process can raise a hard limit.
for normal users.
FILE *fp; Only a
char setvbuf makes this
databuf [ BUFS IZ ] ; /*
the stdio specified|by the constant
infinitelimit isargument RLIM INPINITY.

1f
(( tp = fopen( " datafile", "r"))
return (NULL);
(setvbuf(fp, databuf, IOLBF,
= NULL)

BUFSIZ) = 0)
buf er An
The
which
resOurce
limits
implementation.
takes on one of the following
are defined by the values. Figure 7.15 shows
Single UNDX Specification and supported by each
return (NULL);
/* error */ The maximum size in bytes of a process's total
return(fp);
memory. This affects the sbrk function (Section 1.11)available
RLIMITAS
and the
Figure 7.14 Incorrect usage of an automatic variable mmap function (Section 14.8).
RLIMITCORE The maximum size in bytes of a core file. A limit of 0
the creation of a core file. prevents
The problem is that whern open data returns, the space it used on the
standardstack
used by the stack frame for the next function that is called. But the wil RLIMITCPU The maximum amount of CPU time in seconds. When the
will still be using that portion of memory for its stream buffer. Chaos is
To correct this problem, the array databuf needs to be allocatedfrom globalsure
either statically (staticor extern) or dynamically (one of the alloc functioe
to
I/Ofbmeramryory, RLIMIT_DATA
soft limit is exceeded, the SIGKCPU signal is sent to the
process.
The maximum size in bytes of the data segment: the sum of
the initialized data, uninitialized data, and heap from
7.11 getrlimit and setrlimit Functions Figure 7.6.
RLIMIT FSIZE The maximum size in bytes of a fle that may be created.
Every process has a set of resource limits, some of which can be queried andi When the soft limit is exceeded, the process is sent the
the getrlimit and setrlimit functions. changed by SIGXFSz signal.
#include <sys/resource.h> RIIMIT_ MEMLOCK The maximum amount of memory in bytes that a process can
lock into memory using mlock(2).
int getrlimit(int resource, struct rlimit *rlptr);
RLIMIT MSGQUEUE The maximum amount of memory in bytes that a process can
int setrlimit(int esource, const struct rlimit *rlptr): allocate for POSIX message queues.
Both return: 0if OK, -l on error RLIMIT NICE The limit to which a process's nice value (Section 8.16) can be
raised to affect its scheduling priority.
These two functions are defined the XSI option in the Single UNIX Specification. The RLIMIT NOFILE The maximum number of open files per process. Changing
resource limits for a process are normally established by process 0 when the system i this limit affects the value returned by the sysconf function
initialized and then inherited by each successive process. Each implementation has its ou for its _sC _OPEN MAX argument (Section 2.5.4). See
way of tuning the various limits.
Figure 2.17 also.
Each call to these two functions specifies asingle resource and a pointer to the RLIMIT NPROC The maximum number of child processes per real user ID.
following structure: Changing this limit affects the value returned for
struct rlimit { SC CHILD MAX by the sysconf function (Section 2.5.4).
rlim t rlim cur; /* soft limit: current limit *} RLIMIT NPTS The maximum number of pseudo terminals (Chapter 19) that
rlim t rlin max; /* hard limit: maximum value for rlim cur */ a user can have open at one time.
222 Process Environment getrlimit and setrlimit Functions 223

inplermentatios,we have
conditionally included the resource names that differ. Note
RLIMIT RSS systems define rlim _t to be an
Maximum resident set size (RSS) in unsígned long long
loong. This definition can even change on the same system, instead
of an
physical memory is low, the kernel bytes. some

depending
processes that exceed their RSS. akes unslgned
whether we compile the program to support 64-bit files. Some limits apply to file size,on
that

RLIMIT SBSIZE The maximum size in bytes of


socket
buffers that a
memory the
rlim_t type has to be large enough to represent a file
compilerwarnings that use the wrong format specification, we first size
copylimit. To into
the limit avoida
consume at any given time.
sO
64-bit
integersothat we have to deal with only one
user format.
RLIMIT _SIGPENDING The maximnum number of signals that Can can
enforced by the sigqueue be fur #include "apue.h"
process. This limit is
(Section 10.20). qucued or #include cSys/resource. h>

RLIMIT STACK The maximum size in bytes of the stack, See funchn #define doit(name pr limits (#name, name)

RLIMIT SWAP The maximum amount


Consume.
of swap space in bytes
[Link] can
a static
void 1imits (char t, int):

RLIMIT VMEM This is asynonym for RLIMIT_ AS. main


i n t (vOid)

#1fdef RIIMIT AS
FreeBSD Linux Mac OS X doit(RLIMIT_AS);
Limit XSI 8.0 3.2.0 10.6.8 Solaris
10 #endif
RLIMIT AS doit (RLIMIT CORE):
RLIMIT CORE doit(RIIMIT CPU):
RLIMIT CPU doit (RLIMIT DATA):
RLIMIT_ DATA doit(RIIMIT_FSIZE):
RLIMIT FSIZE
RLIMIT MEMLOCK RIIMIT MEMLOCK
RLIMIT MSGQUEUE #ifdef
doit (RLIMIT MEMLOCK):
RLIMIT NICE
RLIMIT NOFILE #endif
RLIMIT NPROC 41fdef RLIMIT MSGQUEUE
RLIMIT NPTS
RLIMIT_RSS doit (RILIMIT_ MSsGQUEUE );
RLIMIT SBSIZE #endif
RLIMIT SIGPENDING #ifdef RLIMIT NICE
RLIMIT STACK
RLIMIT SWAP doit (RLIMIT NICE) ;
RLIMIT VMEM #endif

doit (RLIMIT NOF ILE);


Figure 7.15 Support for resource limits
#ifdef RLIMIT NPROC
The resource limits affect the calling process and are inherited by any of its children doit (RLIMIT NPROC );
This means that the setting of resource limits needs to be built into the shells to affectall #endif
our future processes. Indeed, the Bourne shell, the GNU Bourne-again shell, and the #ifdef RLIMIT NPTS
Korn shell have the built-in ulimit command, and the C shell has the built-in limit doit (RLIMIT_ NPTS) ;
command. (The umask and chdir functions also have to be handled as shell built-ins) #endif

#ifdef RLIMIT RSS


Example
doit (RLIMIT RSS) ;
#endif
The program in Figure 7.16 prints out the current soft limit and hard limit for all the
resource limits supported on the system. To compile this program on all the variousS #ifdef RLIMIT SBSIZE
doit (RLIMIT SBSIZE);
224 Summary 225
Process Environment
G t i oZ
n 13

this program under FreeBSD gives us the following output:


#endif Running
$ ./[Link]
#ifdef RLIMIT SIGPENDING RLIMIT AS (infinite) (infinite)
doit (RLIMIT SIGPENDING): RLIMIT CORE (infinite) (infinite)
#endif RLIMIT CPU (infinite) (infinite)
RLIMIT_DATA 536870912 536870912
doit(RLIMIT STACK) ; (infiníte)
RLIMIT FSIZE
RLIMIT_MEMLOCK
(infinite)
#ifdef RLIMIT SWAP ( infinite) (infinite)
RLIMIT_NOFILE 3520 3520
doit (RLIMIT SWAP); 1760
#endif RLIMIT_NPROc 1760
RLIMIT_NPTS (infinite) (int inite)
#ifdef RLIMIT VMEM RLIMIT RSS (infinite) (infinite)
doit(RLIMIT VMEM) ; RLIMIT_SBSIZE (infinite) (infinite)
67108864
#endif RLIMIT STACK 67108864
RLIMIT SWAP (infinite) ( infinite)
exit (0); RLIMIT_VMEM (infinite) (infinite)
us thefollowing results:
Solarisgives
static void
resource)
pr limits (char *name, int s .[Link]
RLIMIT AS (infinite) (infinite)
struct rlimit limit; (infinite) ( infinite)
RIIMITCORE
unsigned long long lim;
RLIMIT CPU (infinite) (infinite)
if (getrlimit (resource, &limit) < 0) RLIMIT DATA (infinite) (infinite)
err_sys ("getrlimit error for $s", name ) ; RLIMIT FSIZE (infinite) (infinite)
printf( "$-14s ", name) ; RLIMIT NOFILE 256 65536
if ([Link] cur == RLIM_ INFINITY) { RLIMIT STACK 8388608 (infinite)
printf(" (infinite) "); RLIMIT VMEM (infinite) (infinite)
} else {
lim = [Link] cur;
discussion of resource limits, after we've covered signals.
Exercise 10.11 continues the
printf( "%10lld " lim) ;
}
if ([Link] max = RLIM INFINITY) {
printf("(infinite) ");
}else { 7.12 Summary
lim = [Link] max;
TInderstanding the environment of a C program within a UNDX system's environment is
print£("$10lld", lim) ; UNIX System. In this
} aprerequisite to understanding the process control features of the
and how it's
putchar( (int) ' \n'): hanter. we've looked at how a process is started, how it can terminate,
} and an environment. Although both the argument list and the
passed an argument list that passes both from the
environment are uninterpreted by the kernel, it is the kernel
Figure 7.16 Print the current resource limits
caller of exec to the new process. seen how a
We've also examined the typical memory layout of a Cprogram and
Note that we've used the ISO Cstring-creation operator (#) in the doit worthwhile to look in detail at
macro, to process can dynamically allocate and free memory. It is
generate the string value for each resource name. When we say
the functions available for manipulating the environment, since they involve memory
doit (RLIMIT_CORE) ; allocation. The functions set jmp and longjmp were presented, providing a way to
perform nonlocal branching within a process. We finished the chapter by describing the
the C preprocessor expands this into
pr limits ("RLIMIT CcORE", RLIMIT CORE);
resource limits that various implementations provide.

You might also like