0% found this document useful (0 votes)
27 views41 pages

Unix Mod 3

Module-3 of UNIX System Programming covers Unix standardization and implementations, file I/O operations, and the environment of a UNIX process. It discusses the importance of standards like ISO C, IEEE POSIX, and the Single UNIX Specification in ensuring portability and compliance across different UNIX systems. The module also details various UNIX system implementations, including System V, BSD, FreeBSD, Linux, Mac OS X, and Solaris.

Uploaded by

Nayana H.N
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)
27 views41 pages

Unix Mod 3

Module-3 of UNIX System Programming covers Unix standardization and implementations, file I/O operations, and the environment of a UNIX process. It discusses the importance of standards like ISO C, IEEE POSIX, and the Single UNIX Specification in ensuring portability and compliance across different UNIX systems. The module also details various UNIX system implementations, including System V, BSD, FreeBSD, Linux, Mac OS X, and Solaris.

Uploaded by

Nayana H.N
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/ 41

UNIX System Programming Module-3

MODULE-3 Unix Standardization and Implementations, File I/O, Files and


Dictionaries, The Environment of a UNIX Process

Unix Standardization and Implementations: Introduction, Unix Standardization, UNIX System


Implementation.
File I/O: Introduction, File Description, open, create, read, write, close, fcntl functions.
Files and Dictionaries: mkdir and rmdir functions, reading dictionaries, chdir, fchdir and getcwd
functions. Device Special files.
The Environment of a UNIX Process: Introduction, main function, Process Termination,
Command-Line Arguments, Environment List, Memory Layout of a C Program, Shared Libraries,
Memory Allocation, Environment Variables, setjmp and longjmp Functions, getrlimit, setrlimit
Functions.

Dept of CSE, Vemana I.T Page 1 of 41


UNIX System Programming Module-3

3.1 Unix Standardization and Implementations


Introduction
• Much work has gone into standardizing the UNIX programming environment and the C
programming language.
• Although applications have always been quite portable across different versions of the UNIX
operating system, the proliferation of versions and differences during the 1980s led many large
users, such as the U.S. government, to call for standardization.

UNIX Standardization
• ISO C
• In late 1989, ANSI Standard X3.1591989 for the C programming language was approved. This
standard has also been adopted as international standard ISO/IEC 9899:1990.
• ANSI is the American National Standards Institute, the U.S. member in the International
Organization for Standardization (ISO). IEC stands for the International Electrotechnical
Commission.
• The C standard is now maintained and developed by the ISO/IEC international standardization
working group for the C programming language, known as ISO/IEC JTC1/SC22/WG14, or
WG14 for short.
• The intent of the ISO C standard is to provide portability of conforming C programs to a wide
variety of operating systems, not only the UNIX System.
• This standard defines not only the syntax and semantics of the programming language but also
a standard library
• In 1999, the ISO C standard was updated and approved as ISO/IEC 9899:1999, largely to
improve support for applications that perform numerical processing. The changes don't affect
the POSIX standards described in this book, except for the addition of the restrict keyword to
some of the function prototypes. This keyword is used to tell the compiler which pointer
references can be optimized, by indicating that the object to which the pointer refers is accessed
in the function only via that pointer.
• As with most standards, there is a delay between the standard's approval and the modification
of software to conform to it. As each vendor's compilation systems evolve, they add more
support for the latest version of the ISO C standard.
• A summary of the current level of conformance of gcc to the 1999 version of the ISO C standard
is available at http://www.gnu.org/software/gcc/c99status.html.
• The ISO C library can be divided into 24 areas, based on the headers defined by the standard.
Figure 2.1 lists the headers defined by the C standard.

IEEE POSIX
• POSIX is a family of standards developed by the IEEE (Institute of Electrical and Electronics
Engineers). POSIX stands for Portable Operating System Interface. It originally referred only
Dept of CSE, Vemana I.T Page 2 of 41
UNIX System Programming Module-3

to the IEEE Standard 1003.11988 the operating system interface but was later extended to
include many of the standards and draft standards with the 1003 designation, including the shell
and utilities (1003.2).
• This standard defines the services that must be provided by an operating system if it is to be
"POSIX compliant," and has been adopted by most computer vendors. Although the 1003.1
standard is based on the UNIX operating system, the standard is not restricted to UNIX and
UNIX-like systems. Indeed, some vendors supplying proprietary operating systems claim that
these systems have been made POSIX compliant, while still leaving all their proprietary
features in place.
• Because the 1003.1 standard specifies an interface and not an implementation, no distinction is
made between system calls and library functions. All the routines in the standard are called
functions.

IEEE POSIX
• The 2001 version of 1003.1 departed from the prior versions in that it combined several 1003.1
amendments, the 1003.2 standard, and portions of the Single UNIX Specification (SUS),
Version 2 (more on this later). The resulting standard, IEEE Standard 1003.1-2001, includes
the following other standards:
 ISO/IEC 9945-1 (IEEE Standard 1003.1-1996), which includes
 IEEE Standard 1003.1-1990
 IEEE Standard 1003.1b-1993 (real-time extensions)
 IEEE Standard 1003.1c-1995 (pthreads)
 IEEE Standard 1003.1i-1995 (real-time technical corrigenda)
 IEEE P1003.1a draft standard (system interface revision)
 IEEE Standard 1003.1d-1999 (advanced real-time extensions)
 IEEE Standard 1003.1j-2000 (more advanced real-time extensions)
 IEEE Standard 1003.1q-2000 (tracing)
 IEEE Standard 1003.2d-1994 (batch extensions)
 IEEE P1003.2b draft standard (additional utilities)
 Parts of IEEE Standard 1003.1g-2000 (protocol-independent interfaces)
 ISO/IEC 9945-2 (IEEE Standard 1003.2-1993)
 The Base Specifications of the Single UNIX Specification, version 2, which include

IEEE POSIX
 The Base Specifications of the Single UNIX Specification, version 2, which include :
 System Interface Definitions, Issue 5
 Commands and Utilities, Issue 5
 System Interfaces and Headers, Issue 5
 Open Group Technical Standard, Networking Services, Issue 5.2
Dept of CSE, Vemana I.T Page 3 of 41
UNIX System Programming Module-3

 ISO/IEC 9899:1999, Programming Languages - C

The Single UNIX Specification


• The Single UNIX Specification, a superset of the POSIX.1 standard, specifies additional
interfaces that extend the functionality provided by the basic POSIX.1 specification. The
complete set of system interfaces is called the X/Open System Interface (XSI). The
_XOPEN_UNIX symbolic constant identifies interfaces that are part of the XSI extensions to
the base POSIX.1 interfaces.
• The XSI also defines which optional portions of POSIX.1 must be supported for an
implementation to be deemed XSI conforming. These include file synchronization, memory-
mapped files, memory protection, and thread interfaces, and are marked in Figure 2.5 as "SUS
mandatory." Only XSI conforming implementations can be called UNIX systems.
• The Open Group owns the UNIX trademark and uses the Single UNIX Specification to define
the interfaces an implementation must support to call itself a UNIX system. Implementations
must file conformance statements, pass test suites that verify conformance, and license the right
to use the UNIX trademark.

The Single UNIX Specification


• Some of the additional interfaces defined in the XSI are required, whereas others are optional.
The interfaces are divided into option groups based on common functionality, as follows:
• Encryption: denoted by the _XOPEN_CRYPT symbolic constant
• Real-time: denoted by the _XOPEN_REALTIME symbolic constant
• Advanced real-time
• Real-time threads: denoted by the _XOPEN_REALTIME_THREADS symbolic constant
• Advanced real-time threads
• Tracing
• XSI STREAMS: denoted by the _XOPEN_STREAMS symbolic constant
• Legacy: denoted by the _XOPEN_LEGACY symbolic constant

FIPS
• FIPS stands for Federal Information Processing Standard. It was published by the U.S.
government, which used it for the procurement of computer systems.
• FIPS 1511 (April 1989) was based on the IEEE Std. 1003.11988 and a draft of the ANSI C
standard. This was followed by FIPS 1512 (May 1993), which was based on the IEEE Standard
1003.11990. FIPS 1512 required some features that POSIX.1 listed as optional. All these
options have been included as mandatory in POSIX.1-2001.
• The effect of the POSIX.1 FIPS was to require any vendor that wished to sell POSIX.1-
compliant computer systems to the U.S. government to support some of the optional features
of POSIX.1. The POSIX.1 FIPS has since been withdrawn, so we won't consider it further in
this text.
Dept of CSE, Vemana I.T Page 4 of 41
UNIX System Programming Module-3

UNIX System Implementations


• The previous section described ISO C, IEEE POSIX, and the Single UNIX Specification; three
standards created by independent organizations
• Section 1.1 of McKusick et al. [1996] gives a detailed history (and a nice picture) of the UNIX
System family tree. Everything starts from the Sixth Edition (1976) and Seventh Edition (1979)
of the UNIX Time-Sharing System on the PDP-11 (usually called Version 6 and Version 7).
• These were the first releases widely distributed outside of Bell Laboratories. Three branches of
the tree evolved.
1. One at AT&T that led to System III and System V, the so-called commercial versions of the
UNIX System.
2. One at the University of California at Berkeley that led to the 4.xBSD implementations.
3. The research version of the UNIX System, developed at the Computing Science Research
Center of AT&T Bell Laboratories, that led to the UNIX Time-Sharing System 8th Edition, 9th
Edition, and ended with the 10th Edition in 1990.

UNIX System V Release 4


• UNIX System V Release 4 (SVR4) was a product of AT&T's UNIX System Laboratories (USL,
formerly AT&T's UNIX Software Operation).
• SVR4 merged functionality from AT&T UNIX System V Release 3.2 (SVR3.2), the SunOS
operating system from Sun Microsystems, the 4.3BSD release from the University of
California, and the Xenix system from Microsoft into one coherent operating system. The
• SVR4 source code was released in late 1989, with the first end-user copies becoming available
during 1990. SVR4 conformed to both the POSIX 1003.1 standard and the X/Open Portability
Guide, Issue 3 (XPG3).
• AT&T also published the System V Interface Definition (SVID) [AT&T 1989].
• Issue 3 of the SVID specified the functionality that an operating system must offer to
qualify as a conforming implementation of UNIX System V Release 4.
• As with POSIX.1, the SVID specified an interface, not an implementation. No distinction was
made in the SVID between system calls and library functions.

4.4BSD
• The Berkeley Software Distribution (BSD) releases were produced and distributed by
the
Computer Systems Research Group (CSRG) at the University of California at Berkeley.
• 4.2BSD was released in 1983 and 4.3BSD in 1986. Both of these releases ran on the VAX
minicomputer. The next release, 4.3BSD Tahoe in 1988, also ran on a particular minicomputer
called the Tahoe. This was followed in 1990 with the 4.3BSD Reno release; 4.3BSD Reno
supported many of the POSIX.1 features.

Dept of CSE, Vemana I.T Page 5 of 41


UNIX System Programming Module-3

• The original BSD systems contained proprietary AT&T source code and were covered by
AT&T licenses.
• To obtain the source code to the BSD system you had to have a UNIX source license from
AT&T. This changed as more and more of the AT&T source code was replaced over the years
with non-AT&T source code and as many of the new features added to the Berkeley system
were derived from non-AT&T sources.
• In 1989, Berkeley identified much of the non-AT&T source code in the 4.3BSD Tahoe release
and made it publicly available as the BSD Networking Software, Release 1.0. This was
followed in 1991 with Release 2.0 of the BSD Networking Software, which was derived from
the 4.3BSD Reno release.
• The intent was that most, if not all, of the 4.4BSD system would be free of any AT&T license
restrictions, thus making the source code available to all.

FreeBSD
• FreeBSD is based on the 4.4BSD-Lite operating system. The FreeBSD project was formed to
carry on the BSD line after the Computing Science Research Group at the University of
California at Berkeley decided to end its work on the BSD versions of the UNIX operating
system, and the 386BSD project seemed to be neglected for too long.
• All software produced by the FreeBSD project is freely available in both binary and source
forms. The FreeBSD 5.2.1 operating system was one of the four used to test the examples in
this book.
• Several other BSD-based free operating systems are available. The NetBSD project
(http://www.netbsd.org) is similar to the FreeBSD project, with an emphasis on portability
between hardware platforms. The OpenBSD project (http://www.openbsd.org) is similar to
FreeBSD but with an emphasis on security.

Linux
• Linux is an operating system that provides a rich UNIX programming environment, and is
freely available under the GNU Public License. The popularity of Linux is somewhat of a
phenomenon in the computer industry. Linux is distinguished by often being the first operating
system to support new hardware.
• Linux was created in 1991 by Linus Torvalds as a replacement for MINIX. A grass-roots effort
then sprang up, whereby many developers across the world volunteered their time to use and
enhance it.
• The Mandrake 9.2 distribution of Linux was one of the operating systems used to test the
examples in this book. That distribution uses the 2.4.22 version of the Linux operating system
kernel.

Dept of CSE, Vemana I.T Page 6 of 41


UNIX System Programming Module-3

Mac OS X
• Mac OS X is based on entirely different technology than prior versions. The core operating
system is called "Darwin," and is based on a combination of the Mach kernel (Accetta et al.
[1986]) and the FreeBSD operating system. Darwin is managed as an open source project,
similar to FreeBSD and Linux.
• Mac OS X version 10.3 (Darwin 7.4.0) was used as one of the operating systems to test the
examples in this book.

Solaris
• Solaris is the version of the UNIX System developed by Sun Microsystems. It is based on
System V Release 4, with more than ten years of enhancements from the engineers at Sun
Microsystems.
• It is the only commercially successful SVR4 descendant, and is formally certified to be a UNIX
system.
• The Solaris 9 UNIX system was one of the operating systems used to test the examples in this
book.

Dept of CSE, Vemana I.T Page 7 of 41


UNIX System Programming Module-3

3.2 File I/O, Files and Dictionaries

Files are the building blocks of any operating system. When you execute a command in
UNIX, the UNIX kernel f e t c h e s the corresponding executable file from a file system, loads
its instruction text to memory, and creates a process to execute the command on your behalf. In
the course of execution, a process may read from or write to files. All these operations involve
files. Thus, the design of an operating system always begins with an efficient file management
system.

File Types:
A file in a UNIX or POSIX system may be one of the following types:
 regular file
 directory file
 FIFO file
 Character device file
 Block device file
Regular file
 A regular file may be either a text file or a binary file
 These files may be read or written to by users with the appropriate access
permission
 Regular files may be created, browsed through and modified by various means such as
text editors or compilers, and they can be removed by specific system commands
Directory file
 It is like a folder that contains other files, including sub-directory files.
 It provides a means for users to organise their files into some hierarchical
structure based on file relationship or uses.
 Ex: /bin directory contains all system executable programs, such as cat, rm, sort
 A directory may be created in UNIX by the mkdir command
Ex: mkdir /usr/foo/xyz
 A directory may be removed via the rmdir command
Ex: rmdir /usr/foo/xyz
 The content of directory may be displayed by the ls command

Dept of CSE, Vemana I.T Page 8 of 41


UNIX System Programming Module-3

Device file
 A physical device may have both block and character device files representing it for
different access methods.
 An application program may perform read and write operations on a device file and the OS
will automatically invoke an appropriate device driver function to perform the actual data
transfer between the physical device and the application
 An application program in turn may choose to transfer data by either a character based(via
character device file) or block-based(via block device file).
 A device file is created in UNIX via the mknod command
Ex: mknod /dev/cdsk c 115 5
Here , c - character device file
115 - major device number
5 - minor device number
 For block device file, use argument ‘b’ instead of ‘c’.
Major device number: an index to a kernel table that contains the addresses of all device driver
functions known to the system. Whenever a process reads data from or writes data to a device file,
the kernel uses the device file’s major number to select and invoke a device driver function to carry
out actual data transfer with a physical device.
Minor device number: an integer value to be passed as an argument to a device driver function when
it is called. It tells the device driver function what actual physical device is talking to and the I/O
buffering scheme to be used for data transfer.
FIFO file
 It is a special pipe device file which provides a temporary buffer for two or more processes
to communicate by writing data to and reading data from the buffer.
 The size of the buffer is fixed to PIPE_BUF.
 Data in the buffer is accessed in a first-in-first-out manner.
 The buffer is allocated when the first process opens the FIFO file for read or write
 The buffer is discarded when all processes close their references (stream pointers) to the
FIFO file.
 Data stored in a FIFO buffer is temporary.
 A FIFO file may be created via the mkfifo command.
o The following command creates a FIFO file (if it does not exists)
mkfifo /usr/prog/fifo_pipe
Dept of CSE, Vemana I.T Page 9 of 41
UNIX System Programming Module-3

o The following command creates a FIFO file (if it does not exists)
mknod /usr/prog/fifo_pipe
 FIFO files can be removed using rm command.
Symbolic link file
 BSD UNIX & SV4 defines a symbolic link file.
 A symbolic link file contains a path name which references another file in eitherlocal or a
remote file system.
 POSIX.1 does not support symbolic link file type
 A symbolic link may be created in UNIX via the ln command
Ex: ln -s /usr/divya/original /usr/raj/slink
 It is possible to create a symbolic link to reference another symbolic link. rm, mv and chmod
commands will operate only on the symbolic link arguments directly and not on the files that
they reference.
The UNIX and POSIX File Systems:
 Files in UNIX or POSIX systems are stored in tree-like hierarchical file system.
 The root of a file system is the root (“/”) directory.
 The leaf nodes of a file system tree are either empty directory files or other types of files.
 Absolute path name of a file consists of the names of all the directories, starting from the root.
Ex: /usr/divya/a.out
 Relative path name may consist of the “.” and “..” characters. These are references to current
and parent directories respectively.
Ex: ../../.login
denotes .login file which may be found 2 levels up from the current directory
 A file name may not exceed NAME_MAX characters (14 bytes) and the total number of
characters of a path name may not exceed PATH_MAX (1024 bytes).
 POSIX.1 defines _POSIX_NAME_MAX and _POSIX_PATH_MAX in <limits.h>header
 File name can be any of the following character set only.
A to Z a to z 0 to 9
 Path name of a file is called the hardlink.
 A file may be referenced by more than one path name if a user creates one or more hard links
to the file using ln command.
ln /usr/foo/path1 /usr/prog/new/n1
If the –s option is used, then it is a symbolic (soft) link
Dept of CSE, Vemana I.T Page 10 of 41
UNIX System Programming Module-3

 The following files are commonly defined in most UNIX systems

The UNIX and POSIX File Attributes:


 The general file attributes for each file in a file system are:

 In addition to the above attributes, UNIX systems also store the major and minor device
numbers for each device file. All the above attributes are assigned by the kernel to a file
when it is created. The attributes that are constant for any file are:
 File type
 File inode number
 File system ID
 Major and minor device number

Dept of CSE, Vemana I.T Page 11 of 41


UNIX System Programming Module-3

 The other attributes are changed by the following UNIX commands or system calls

open
• This is used to establish a connection between a process and a file i.e. it is used to open an
existing file for data transfer function or else it may be also be used to create a new file.
• The returned value of the open system call is the file descriptor (row number of the file
table), which contains the inode information.
• The prototype of open function is
#include<sys/types.h>
#include<sys/fcntl.h>
int open(const char *pathname, int accessmode, mode_t permission);
open
 If successful, open returns a nonnegative integer representing the open file descriptor.If
unsuccessful, open() returns –1.
 The first argument is the name of the file to be created or opened.
 This may be an absolute pathname or relative pathname.
 If the given pathname is symbolic link, the open function
will resolve the symbolic link reference to a non-symbolic link file to which it
refers.
 The second argument is access modes, which is an integer value that specifies
how actually the file should be accessed by the calling process.
 Generally the access modes are specified in <fcntl.h>. Various access modes are:

Dept of CSE, Vemana I.T Page 12 of 41


UNIX System Programming Module-3

Sl. No Flag Meaning

1 O_RDONLY open for reading file only

2 O_WRONLY open for writing file only

3 O_RDWR opens for reading and writing file

There are other access modes, which are termed as access modifier flags, and one or more of the
following can be specified by bitwise-ORing them with one of the above access mode flags to alter
the access mechanism of the file.

access modifier flags


S.No Flag Meaning

1 O_APPEND Append data to the end of file.

2 O_CREAT Create the file if it doesn’t exist

3 O_EXCL Generate an error if O_CREAT is also specified and the file already
exists.

4 O_TRUNC If file exists discard the file content and set the file size to zero bytes.

5 O_NONBLOCK Specify subsequent read or write on the file should be non-blocking.

6 O_NOCTTY Specify not to use terminal device file as the calling


process control terminal.

• To illustrate the use of the above flags, the following example statement opens a file called
/usr/syed/usp for read and write in append mode:
int fd=open(“/home/UNIX/file1.c”, O_RDWR | O_APPEND|O_CREAT,755);
• If the file is opened in read only, then no other modifier flags can be used.
• If a file is opened in write only or read write, then we are allowed to use any modifier flags
along with them.
• The third argument is used only when a new file is being created.

Dept of CSE, Vemana I.T Page 13 of 41


UNIX System Programming Module-3

To open "sample.txt" in the current working directory for appending or create it, if it
does not exist, with read, write and execute permissions for owner only:
fd = open(“sample.txt", O_WRONLY|O_APPEND|O_CREAT, S_IRWXU); fd = open(“sample.txt",
O_WRONLY|O_APPEND|O_CREAT, 0700);
fd = open(“sample.txt", O_WRONLY|O_CREAT|O_EXCL,
S_IRWXU|S_IROTH|S_IWOTH);
fd = open(“sample.txt", O_WRONLY|O_CREAT|O_EXCL,0706);
fd = open(“sample.txt", O_WRONLY|O_CREAT|O_TRUNC,0706);

creat ( )
• This system call is used to create new regular files.
#include <sys/types.h> #include<unistd.h>
int creat(const char *pathname, mode_t mode);
• Returns: file descriptor opened for write-only if OK, -1 on error.
• The first argument pathname specifies name of the file to be created.
• The second argument mode_t, specifies permission of a file to be accessed by owner group
and others.
• The creat function can be implemented using open function as:
#define creat(path_name, mode)
Dept of CSE, Vemana I.T Page 14 of 41
UNIX System Programming Module-3

open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);

read ( )
The read function fetches a fixed size of block of data from a file referenced by a given file
descriptor.
The prototype of read function is:
#include<sys/types.h> #include<unistd.h>
size_t read(int fdesc, void *buf, size_t nbyte);
 If successful, read returns the no. of bytes actually read, on error it returns –1.
 The first argument is an integer, fdesc that refers to an opened file.
 The second argument, buf is the address of a buffer holding any data read.
 The third argument specifies how many bytes of data are to be read from the file.
 The size_t data type is defined in the <sys/types.h> header and should be the
same as unsigned int.
There are several cases in which the number of bytes actually read is less than the amount requested:
 When readingfrom a regular file, if the end of file is
reached before the requested number of bytes has been read.
 For example, if 30 bytes remain until the end of file and we try to read 100 bytes, read
returns 30. The next time we call read, it will return 0 (end of file).
 When readingfrom a terminal device. Normally, up to one
line is read at a time.
 When reading from a network. Buffering within the network may cause less than the
requested amount to be returned.
 When readingfrom a pipe or FIFO. If the pipe contains
fewer bytes than requested, read will return only what is available.

read ( )- Errors

Tag Description

Non-blocking I/O has been selected using O_NONBLOCK and no data


EAGAIN was immediately available for reading.
EBADF fd is not a valid file descriptor or is not open for reading.

Dept of CSE, Vemana I.T Page 15 of 41


UNIX System Programming Module-3

EFAULT buf is outside your accessible address space.

EINTR The call was interrupted by a signal before any data was read.

EINVAL fd is attached to an object which is unsuitable for reading; or the file was opened
with the O_DIRECT flag, and either the address specified in buf, the value specified
in count, or the current file offset is not suitably aligned.

EIO I/O error. This will happen for example when the process is in a background
process group, tries to read from its controlling tty, and either it is ignoring or
blocking SIGTTIN or its process group is orphaned. It may also occur when there
is a low-level I/O error while reading from a disk or tape.

EISDIR fd refers to a directory.

#include<fcntl.h> int main()


{
int fd,nob;char c[256];
fd=open(“sample”,O_RDONLY);
nob= read(fd,c,sizeof(c));
if(nob!=-1)
printf("%s\n",c); else
perror(“read Error”);
close(fd); return 0;
}

write( )
The write system call is used to write data into a file
The write function puts data to a file in the form of fixed block size referred by a given file.
The prototype of read function is:
#include<sys/types.h> #include<unistd.h>
ssize_t write(int fdesc, const void *buf, size_t size);
 If successful, write returns the number of bytes actually written.
 If unsuccessful, write returns –1.
 The first argument, fdesc is an integer that refers to an opened file.
Dept of CSE, Vemana I.T Page 16 of 41
UNIX System Programming Module-3

 The second argument, buf is the address of a buffer that contains data to be written.
 The third argument, size specifies how many bytes of data are in the buf argument.
 The return value is usually equal to the number of bytes of data successfully written to a
file. (size value)

write( )-Errors
Error Code Description

EAGAIN Non-blocking I/O has been selected using O_NONBLOCK and the write would block.
EBADF fd is not a valid file descriptor or is not open for writing.

EFAULT buf is outside your accessible address space.

EFBIG An attempt was made to write a file that exceeds the implementation-defined
maximum file size or the process’ file size limit, or to write at a position past the
maximum allowed offset.
EINTR The call was interrupted by a signal before any data was written.
EINVAL fd is attached to an object which is unsuitable for writing; or the file was opened with
the O_DIRECT flag, and either the address specified in buf, the value
specified n count, or the current file offset is not suitably aligned.
EIO A low-level I/O error occurred while modifying the inode.

EPIPE fd is connected to a pipe or socket whose reading end is closed. When this happens the
writing process will also receive a SIGPIPE signal. (Thus, the write return value is seen
only if the program catches, blocks or ignores this signal.)

#include<fcntl.h>
int main()
{
int fd,nob;char c[]=“ This is sample text”; fd=open(“sample”,O_WRONLY,|O_CREAT,0777);
nob= write(fd,c,strlen(c));
if(nob!=-1)
printf(“Successfully written to file”);
else
perror(“write Error”);
close(fd);
return 0;
}
close( )
The close system call is used to terminate the connection to a file from a process.
The prototype of the close() is
#include<unistd.h> int close(int fdesc);
 If successful, close returns 0.
 If unsuccessful, close returns –1.

Dept of CSE, Vemana I.T Page 17 of 41


UNIX System Programming Module-3

 The argument fdesc refers to an opened file.


 Close function frees the unused file descriptors so that they can be reused to reference other
files. This is important because a process may open up to OPEN_MAX files at any time and
the close function allows a process to reuse file descriptors to access more than
OPEN_MAX files in the course of its execution.
 The close function de-allocates system resources like file table entry and memory buffer
allocated to hold the read/write.

close( ) – Errors

Tag Description

EBADF fd isn’t a valid open file descriptor.

EINTR The close() call was interrupted by a signal.


EIO An I/O error occurred.

Emulate ‘cp’ UNIX command – cp f1 f2


#include<fcntl.h>
#include<fcntl.h>
int main()
{
int fd1,fd2,nob;
char c;
fd1=open(“f1”,O_RDONLY);
If(fd1!=-1)
{ fd2=open(“f2”,O_WRONLY|_CREAT|O_TRUNC, 0777);
if(fd2!=-1)
{ while(read(fd1,&c,1))
write(fd2,&c,1);
close(fd1);
close(fd2);
}
else
{
perror(“write Error”); close(fd1);
}
} /*if fd1 */ else
perror(“read Error”);
return 0;
}

Dept of CSE, Vemana I.T Page 18 of 41


UNIX System Programming Module-3

fcntl:
The fcntl function helps to query or set access control flags and the close-on-exec flag of any file
descriptor. Users can also use fcntl to assign multiple file descriptors to reference the same file.
Its prototype is:
#include <fcntl.h>
int fcntl (int fdesc ,int cmd, ….);
 fdesc: is an integer file descriptor that refers to an opened file.
 cmd: specifies which operation to perform on a file referenced by the fdesc argument.
 The third argument value, which may be specified after cmd is dependent on the actual cmd
 value.

The possible cmd values are defined in the <fcntl.h> header. These values and their uses are:

 The fcntl function is useful in changing the access control flag of a file descriptor.

For example: After a file is opened for blocking read-write access and the process needs to
change the access to nonblocking and in write-append mode, it can call fcntl on the file’s
descriptor as:
int cur_flags = fcntl(fdesc, FGETFL);
Dept of CSE, Vemana I.T Page 19 of 41
UNIX System Programming Module-3

int rc = fcntl(fdesc, F_SETFL, cur_flag | O_APPEND |O_NONBLOCK);

 The close-on-exec flag of a file descriptor specifies that if the process that owns the descriptor
calls the exec API to execute different program, the fdesc should be closed by the kernel
before the new program runs or not.
 The example reports the close-on-exec flag of a fdesc, sets it to on afterwards:
cout<<fdesc<<”close-on-exec:”<<fcntl(fdesc,F_GETFD)<<endl;
(void)fcntl(fdesc, F_SETFD, 1);
 The fcntl function can also be used to duplicate a fdesc with another fdesc. The results are
two fdesc reference the same file with same access mode and share the same file pointer to
read or write the file. This is useful in the redirection of standard input or output to reference
a file.
Example: Reference standard input of a process to a file called FOO
int fdesc = open(“FOO”, O_RDONLY); //open FOO for read
close(0); //close standard input
if(fcntl(fdesc, F_DUPFD, 0)==-1) perror(“fcntl”); //stdin from FOO
char buf[256];
int rc = read(0,buf,256); //read data from FOO
 The dup and dup2 functions in UNIX perform the same file duplication function as fcntl.
They can be implemented using fcntl as:
#define dup(fdesc) fcntl(fdesc, F_FUPFD,0)
#define dup2(fdesc1,fd2) close(fd2),fcntl(fdesc, F_DUPFD, fd2)
The dup function duplicates a fdesc with the lowest unused fdesc of a calling process.
The dup2 function will duplicate a fdesc using a fd2 fdesc, regardless of whether fd2 is used
to reference another file.
Directory File API’s:
 A Directory file is a record-oriented file, where each record stores a file name and the inode
number of a file that resides in that directory.
 Directories are created with the mkdir API and deleted with the rmdir API.

The prototype of mkdir is #include<sys/stat.h>

#include<unistd.h>

int mkdir(const char *path_name, mode_t mode);

The first argument is the path name of a directory file to be created.

Dept of CSE, Vemana I.T Page 20 of 41


UNIX System Programming Module-3

The second argument mode, specifies the access permission for the owner, groups and others to be
assigned to the file. This function creates a new empty directory.

The entries for “.” and “..” are automatically created.

The specified file access permission, mode, are modified by the file mode creation mask of the
process.

To allow a process to scan directories in a file system independent manner, a directory record is
defined as struct dirent in the <dirent.h> header for UNIX.

Some of the functions that are defined for directory file operations in the above header are

#include<sys/types.h>
#if defined (BSD) && ! _POSIX_SOURCE
#include<sys/dir.h>
typedef struct direct Dirent;
#else
#include<dirent.h>
typedef struct dirent Dirent;
#endif
DIR *opendir(const char *path_name);
Dirent *readdir(DIR *dir_fdesc);
int closedir(DIR *dir_fdesc);
void rewinddir(DIR *dir_fdsec);
The uses of these functions are

Function Use

Opens a directory file for read-only. Returns a file handle dir * for future
opendir
reference of the file.

Reads a record from a directory file referenced by dir-fdesc and


readdir
returns that record information.

Resets the file pointer to the beginning of the directory file referenced by
rewinddir
dir- fdesc. The next call to readdir will read the first record from the file.

Dept of CSE, Vemana I.T Page 21 of 41


UNIX System Programming Module-3

closedir closes a directory


file referenced by
dir-fdesc.

An empty directory is deleted with the rmdir API.


The prototype of rmdir is
#include<unistd.h>
int rmdir (const char * path_name);
If the link count of the directory becomes 0, with the call and no other process has the directory open
then the space occupied by the directory is freed.

UNIX systems have defined additional functions for random access of directory file records.

The following list_dir.C program illustrates the uses of the mkdir, opendir, readdir, closedir
and rmdir APIs:

#include<iostream.h> int main(int agc, char* argv[])


#include<stdio.h>
{
#include<sys/types.h>
#include<unistd.h> Dirent* dp; DIR* dir_fdesc;
#include<string.h> while(--argc>0)
#include<sys/stat.h>
{
#if defined(BSD) &&
!_POSIX_SOURCE if(!(dir_fdesc=opendir(*++argv)))

#include<sys/dir.h> {

typedef struct direct Dirent; if(mkdir(*argv,S_IRWXU | S_IRWXG | S_IRWXO)==-1)

#else perror("opendir"); continue;

#include<dirent.h> }

typedef struct dirent Dirent;


#endif

The following list_dir.C program illustrates the uses of the mkdir, opendir, readdir, closedir
and rmdir APIs:
Dept of CSE, Vemana I.T Page 22 of 41
UNIX System Programming Module-3

Device file APIs


 Device files are used to interface physical device with application programs.

 A process with superuser privileges to create a device file must call the mknod API.

 The user ID and group ID attributes of a device file are assigned in the same manner as for
regular files.

 When a process reads or writes to a device file, the kernel uses the major and minor device
numbers of a file to select a device driver function to carry out the actual data transfer.

 Device file support is implementation dependent. UNIX System defines the mknod API to
create device files.
The prototype of mknod is
#include<sys/stat.h>
#include<unistd.h>
int mknod(const char* path_name, mode_t mode, int device_id);
 The first argument pathname is the pathname of a device file to be created.
 The second argument mode specifies the access permission, for the owner, group and
others, also S_IFCHR or S_IBLK flag to be assigned to the file.
 The third argument device_id contains the major and minor device number.
Example
mknod(“SCS15”,S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO,(15<<8) | 3);
The above function creates a block device file “SCS15”, to which all the three i.e. read, write and
execute permission is granted for user, group and others with major number as 8 and minor
number 3.
Dept of CSE, Vemana I.T Page 23 of 41
UNIX System Programming Module-3

On success mknod API returns 0 , else it returns -1

The following test_mknod.C program illustrates the use of the mknod, open, read, write and close
APIs on a block device file.

#include<iostream.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
int main(int argc, char* argv[])
{
if(argc!=4)
{
cout<<"usage:"<<argv[0]<<"<file><major_no><minor_no>"; return 0;
}
int major=atoi(argv[2];
(void) mknod(argv[1], S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, (major<<8) | minor);
int rc=1,
Int fd=open(argv[1],O_RDW | O_NONBLOCK | O_NOCTTY);
char buf[256]; while(rc && fd!=-1)
if((rc=read(fd,buf,sizeof(buf)))<0) perror("read");
else if(rc)
cout<<buf<<endl; close(fd);
}

FIFO file API’s


 FIFO files are sometimes called named pipes.
 Pipes can be used only between related processes when a common ancestor has created the
pipe.

Dept of CSE, Vemana I.T Page 24 of 41


UNIX System Programming Module-3

 Creating a FIFO is similar to creating a file.


 Indeed the pathname for a FIFO exists in the file system.
The prototype of mkfifo is
#include<sys/types.h>
#include<sys/stat.h>

#include<unistd.h>
int mkfifo(const char *path_name, mode_t mode);
 The first argument pathname is the pathname(filename) of a FIFO file to be created.
 The second argument mode specifies the access permission for user, group and others and
as well as the S_IFIFO flag to indicate that it is a FIFO file.
 On success it returns 0 and on failure it returns –1.

Example
mkfifo(“FIFO5”, S_IFIFO | S_IRWXU | S_IRGRP | S_ROTH);
 The above statement creates a FIFO file “fifo5” with read-write-execute permission for user
and only read permission for group and others.
 Once we have created a FIFO using mkfifo, we open it using open. Indeed, the normal file
I/O functions (read, write, unlink etc) all work with FIFOs. When a process opens a FIFO file
for reading, the kernel will block the process until there is another process that opens the
same file for writing.
 Similarly whenever a process opens a FIFO file write, the kernel will block the process until
another process opens the same FIFO for reading.
 This provides a means for synchronization in order to undergo inter-process
communication. If a particular process tries to write something to a FIFO file that is full, then
that process will be blocked until another process has read data from the FIFO to make space
for the process to write.
 Similarly, if a process attempts to read data from an empty FIFO, the process will be blocked
until another process writes data to the FIFO. From any of the above condition if the process
doesn’t want to get blocked then we should specify O_NONBLOCK in the open call to the
FIFO file.
 If the data is not ready for read/write then open returns –1 instead of process getting blocked.
Dept of CSE, Vemana I.T Page 25 of 41
UNIX System Programming Module-3

 If a process writes to a FIFO file that has no other process attached to it for read, the kernel
will send SIGPIPE signal to the process to notify that it is an illegal operation.

Another method to create FIFO files (not exactly) for inter-process communication is to use
the pipe system call.
FIFO file API’s
The prototype of pipe is
#include <unistd.h>
int pipe(int fds[2]);
Returns 0 on success and –1 on failure.
If the pipe call executes successfully, the process can read from fd[0] and write to fd[1].
A single process with a pipe is not very useful.
Usually a parent process uses pipes to communicate with its children.
The following test_fifo.C example illustrates the use of mkfifo, open, read, write and close APIs
for a FIFO file:
#include<iostream.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<string.h>
#include<errno.h>
int main(int argc,char* argv[])
{
if(argc!=2 && argc!=3)
{
cout<<"usage:"<<argv[0]<<"<file> [<arg>]"; return 0;
}
int fd; char buf[256];
(void) mkfifo(argv[1], S_IFIFO | S_IRWXU | S_IRWXG | S_IRWXO ); if(argc==2)
{
Dept of CSE, Vemana I.T Page 26 of 41
UNIX System Programming Module-3

fd=open(argv[1],O_RDONLY | O_NONBLOCK);
while(read(fd,buf,sizeof(buf))==-1 && errno==EAGAIN)
sleep(1); while(read(fd,buf,sizeof(buf))>0)
cout<<buf<<endl;
}
else
{
fd=open(argv[1],O_WRONLY);
write(fd,argv[2],strlen(argv[2]));
}
close(fd);
}

Dept of CSE, Vemana I.T Page 27 of 41


UNIX System Programming Module-3

3.3 The Environment of a UNIX Process

1) With a neat diagram, explain how a C – program is initiated and various ways it can be
terminated.

ANS: A C program 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.
 argv is an array of pointers to the arguments.
 When a C program is executed by the kernel—by one of the exec functions 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.

Figure summarizes how a C program is started and the various ways it can terminate.

Dept of CSE, Vemana I.T Page 28 of 41


UNIX System Programming Module-3

PROCESS TERMINATION:
There are eight ways for a process to terminate.
1. Normal termination occurs in five ways:
 Return from main
 Calling exit
 Calling _exit or _Exit
 Return of the last thread from its start routine
 Calling pthread_exit from the last thread
2. Abnormal termination occurs in three ways:
 Calling abort
 Receipt of a signal
 Response of the last thread to a cancellation request

Three functions terminate a program normally: _exit and _Exit, which return to the kernel
immediately, and exit, which performs certain cleanup processing and then returns to the
kernel. Thus, the only way a program is executed by the kernel is when one of the exec
functions is called. The only way a process voluntarily terminates is when _exit or _Exit is
called, either explicitly or implicitly (by calling exit). A process can also be involuntarily
terminated by a signal (not shown in Figure).

2) What are the different ways for a process to terminate? Explain exit,_exit, atexit functions
with its prototypes.
ANS: Prototypes: #include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status)
The reason for the different headers is that exit and _Exit are specified by ISO C, whereas _exit
is specified by POSIX.1.
a) exit:
 exit function terminates the process normally, performs certain cleanup
processing and then returns to the kernel.
 the exit function has always performed a clean shutdown of the standard I/O
library: the fclose function is called for all open streams. This causes all
buffered output data to be flushed (written to the file).
Dept of CSE, Vemana I.T Page 29 of 41
UNIX System Programming Module-3

b) exit and _Exit:


 _exit and _Exit functions terminate the process normally and return to the
kernel immediately

All three exit functions expect a single integer argument, called the exit status.
The exit status of the process is undefined if
 Any of these functions is called without an exit status,
 main does a return without a return value, or
 The main function is not declared to return an integer.

Returning an integer value from the main function is equivalent to calling exit with the same
value. Thus exit(0); is the same as return(0); from the main function.

c) atexit Function:
 With ISO C, a process can register up to 32 functions that are automatically
called by exit. These are called exit handlers and are registered by calling the
atexit function.
 Prototype:
#include <stdlib.h>
int atexit(void (*func)(void));
Returns: 0 if OK, nonzero on error
 This declaration says that the address of a function is passed as an argument
toatexit. When this function is called, it is not passed any arguments and is
notexpected to return a value. The exit function calls these functions in reverse
order of their registration. Each function is called as many times as it was
registered.

The following example shows how a process registers for a function using atexit

/* Program name – atexit.c */

#include<stdio.h>
#include<stdlib.h>

void exit_handler1(void)
{
printf(“\n first exit handler “);
}

Dept of CSE, Vemana I.T Page 30 of 41


UNIX System Programming Module-3

void exit_handler2(void)
{
printf(“\n second exit hadler”);
}

int main( )
{
atexit(exit_handler1);
atexit(exit_handler1);
atexit(exit_handler2);
printf(“IN THE MAIN PROGRAMM”);
return 0;
}

Output :
$ cc atexit.c
$ ./a.out
IN THE MAIN PROGRAMM
second exit handler
first exit handler
first exit handler

With ISO C and POSIX.1, exit first calls the exit handlers and then closes (via fclose) all open streams.

3) Write a note on command line arguments.


ANS: When a program is executed, the process that does the exec can pass command-line arguments
to the new program. This is part of the normal operation of the UNIX system shells.
Example
The program below echoes all its command-line arguments to standard output.

/* Program name - echocmd.c */

#include<unistd.h>
#include<stdio.h>

int main(int argc, char *argv[ ])


{
int i;
for (i = 0; i < argc; i++)
printf(“argv[%d]: %s\n”, i, argv[i]);
exit(0);
}

Output :
$ cc echocmd.c
$ ./a.out unix system programming

Dept of CSE, Vemana I.T Page 31 of 41


UNIX System Programming Module-3

argv[0]: ./a.out
argv[1]: unix
argv[2]: system
argv[3]: programming

4) With a neat diagram explain in detail the memory layout of a C program.

ANS: C program has been composed of the following pieces:

a) Text segment,
consists of the machine instructions that the CPU executes. Usually, the text segment is sharable
so that only a single copy needs to be in memory for frequently executed programs, such as text
editors, the C compiler, the shells, and so on. Also, the text segment is often read-only, to prevent
a program from accidentally modifying its instructions.

b) Initialized data segment,


usually called simply the data segment, containing variables that are specifically initialized in the
program. For example, the C declaration
int maxcount = 99;
appearing outside any function causes this variable to be stored in the initialized data segment with
its initial value.

c) Uninitialized data segment,


often called the "bss" segment, named after an ancient assembler operator that stood for "block
started by symbol." Data in this segment is initialized by the kernel to arithmetic 0 or null pointers
before the program starts executing. The C declaration
long sum[1000];
appearing outside any function causes this variable to be stored in the uninitialized data segment.

d) Stack,
where (local variables )automatic variables are stored, along with information that is saved
each time a function is called. Each time a function is called, the address of where to return to and
certain information about the caller's environment, such as some of the machine registers, are
saved on the stack. The newly called function then allocates room on the stack for its automatic
and temporary variables.

Dept of CSE, Vemana I.T Page 32 of 41


UNIX System Programming Module-3

e) Heap,
where dynamic memory allocation usually takes place. Historically, the heap has been located
between the uninitialized data and the stack.

The memory layout of a c program

5) Write an explanatory note on environment variables. Also write a C/C++ program that
outputs the contents of its environment list.
ANS:
 The environment list is an array of character pointers, with each pointer containing the
address of a null-terminated C string called environment variable. The address of the
array of pointers is contained in the global variable environ:
extern char **environ;
 The environment strings are usually of the form:
name=value

The figure shows an environment consisting five strings

Dept of CSE, Vemana I.T Page 33 of 41


UNIX System Programming Module-3

 The shells use numerous environment variables. Some, such as HOME and USER, are
set automatically at login, and others are for us to set. We normally set environment
variables in a shell start-up file to control the shell’s actions.

 The function that is used to fetch the value from the variables is getenv,
The prototype of getenv function:
#include <stdlib.h>
char *getenv(const char *name);
Returns: pointer to value associated with name, NULL if not found.
this function returns a pointer to the value of a name=value string. We should always use
getenv to fetch a specific value from the environment, instead of accessing environ directly.
 The functions that are used to set an environment variable are putenv and setenv.
These functions are used to change the value of an existing variable or add a new
variable to the environment.
The prototypes of these functions:
#include <stdlib.h>
int putenv(char *str);
int setenv(const char *name, const char *value, int rewrite);
All return: 0 if OK, nonzero on error.

The putenv function takes a string of the form name=value and places it in the environment
list. If name already exists, its old definition is first removed.
The setenv function sets name to value. If name already exists in the environment, then
(a) if rewrite is nonzero, the existing definition for name is first removed;
(b) if rewrite is 0, an existing definition for name is not removed, name is not
set to the new value, and no error occurs.
 The function that is used to remove any definition of name is unsetenv,
The prototype of unsetenv function:
#include <stdlib.h>
int unsetenv(const char *name);
Rreturns: 0 if OK, nonzero on error
The unsetenv function removes any definition of name. It is not an error if such a definition
does not exist

Dept of CSE, Vemana I.T Page 34 of 41


UNIX System Programming Module-3

C/C++ program that outputs the contents of its environment list.


#include "apue.h"

int main(int argc, char *argv[])


{
int i;
char **ptr;
extern char **environ;

for (ptr = environ; *ptr != 0; ptr++) /* and all env strings */


printf("%s\n", *ptr);

exit(0);
}

6) Write A Note On Memory Allocation.

ANS: ISO C specifies three functions for memory allocation:

a) malloc, which allocates a specified number of bytes of memory. The initial value of the
memory is indeterminate(garbage value).
b) calloc, which allocates space for a specified number of objects(n) of a specified size(s).
([n*s] bytes). The space is initialized to all 0 bits.
c) realloc, which increases or decreases the size of a previously allocated area. When the
size increases, it may involve moving the previously allocated area 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 the new area is indeterminate.
 For example, if we allocate room for 512 elements in an array that we
fill in at runtime but find that we need room for more than 512 elements,
we can call realloc.
 If there is room beyond the end of the existing region for the requested
space, then realloc doesn’t have to move anything; it simply allocates the
additional area at the end and returns the same pointer that we passed it.
 But if there isn’t room at the end of the existing region, realloc allocates
another area that is large enough, copies the existing 512-element array
to the new area, frees the old area, and returns the pointer to the new area.
PROTOTYPES
Dept of CSE, Vemana I.T Page 35 of 41
UNIX System Programming Module-3

#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
All three return: non-null pointer if OK, NULL on error
The pointer returned by the three allocation functions is guaranteed to be suitably aligned so
that it can be used for any data object.
The allocation routines are usually implemented with the sbrk system call. This system call
expands (or contracts) the heap of the process.

void free(void *ptr);

The function free causes the space pointed to by ptr to be deallocated. This freed space is usually
put into a pool of available memory and can be allocated in a later call to one of the three
alloc functions.

d) alloca Function: The function alloca has the same calling sequence as malloc; however,
instead of allocating memory from the heap, the memory is allocated from the stack frame
of the current function. The advantage is that we don't have to free the space; it goes
away automatically when the function returns. The alloca function increases the size of
the stack frame. The disadvantage is that some systems can't support alloca, if it's
impossible to increase the size of the stack frame after the function has been called.

DISADVANTAGES

 It is important to realize that most implementations allocate a little more space


than is requested and use the additional space for record keeping—the size of the
allocated block, a pointer to the next allocated block etc. If user tries to store more
data than allowed in the allocated area, there is a chance of all the records getting
overwritten. These types of errors are often catastrophic, but difficult to find,
because the error may not show up until much later.
 Other possible errors that can be fatal are freeing a block that was already freed
and calling free with a pointer that was not obtained from one of the three alloc
functions.

Dept of CSE, Vemana I.T Page 36 of 41


UNIX System Programming Module-3

 If a process calls malloc, but forgets to call free, its memory usage continually
increases; this is called leakage. By not calling free to return unused space, the
size of a process's address space slowly increases until no free space is left. During
this time, performance can degrade from excess paging overhead.

7) With an example explain the use of setjmp and longjmp functions.


ANS:
 In C, we can't goto a label that's in another function. Instead, we must use the setjmp and
longjmp functions to perform this type of branching.
 these two functions are useful for handling error conditions that occur in a deeply nested
function call.
Prototypes:
#include <setjmp.h>
int setjmp(jmp_buf env);
Returns: 0 if called directly, nonzero if returning from a call to longjmp
void longjmp(jmp_buf env, int val);

 We call setjmp from the location that we want to return to, which in this example is in the
main function. In this case, setjmp returns 0 because we called it directly.
 In the call to setjmp, the argument env is of the special type jmp_buf. This data type is
some form of array that is capable of holding all the information required to restore the status
of the stack to the state when we call longjmp.
 Normally, the env variable is a global variable, since we'll need to reference it from another
function.
 When we encounter an error say, in the add function, we call longjmp with two arguments.
The first is the same env that we used in a call to setjmp, and the second, val, is a nonzero
value that becomes the return value from setjmp. The reason for the second argument is to
allow us to have more than one longjmp for each setjmp.

Example of setjmp and longjmp

Program 1:

#include "apue.h"
#include <setjmp.h>

Dept of CSE, Vemana I.T Page 37 of 41


UNIX System Programming Module-3

jmp_buf env;

int main(void)
{
int i;
if ((i=setjmp(env)) != 0)
printf("error");
add(a,b);
exit(0);
}

Void add(int a,int b)


{
int sum;

sum=a+b;
if(sum<0)
longjmp(env,1)
}

When main is executed, we call setjmp, which records whatever information it needs to in the
variable env and returns 0. We then call add and assume that an error of some form is detected.
longjmp causes the stack to be "unwound" back to the main function, throwing away the stack
frames add .Calling longjmp causes the setjmp in main to return, but this time it returns with a
value of 1 (the second argument for longjmp).

PROGRAMM 2:

#include<stdio.h>
#include<setjmp.h>

jmp_buf env;
void func();

Dept of CSE, Vemana I.T Page 38 of 41


UNIX System Programming Module-3

int main(void)
{
int i;
printf("THIS IS 1 MAIN \n");

if ((i=setjmp(env)) == 0)
{
printf(“ The value of i=%d\n”,i);
fun();
printf("THIS IS 2 MAIN \n");
}
printf("THIS IS 3 MAIN \n");
printf(“ The value of i=%d\n”,i);
return(0);
}

Void fun()
{
printf("THIS IS FUNC \n");
longjmp(env,2)
}

OUTPUT:
$cc 1.c
$./a.out

THIS IS 1 MAIN
The value of i=0
THIS IS FUNC
THIS IS 3 MAIN
The value of i=2

8) Explain getrlimit and setrlimit functions with prototype. Mention the 3 rules to change
the resource limits. Give four resource values.
ANS:
 Every process has a set of resource limits, some of which can be queried
and changed by the getrlimit and setrlimit functions.

 The prototypes of these functions are:


#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const struct rlimit *rlptr);
Both return: 0 if OK, nonzero on error
 The resource limits for a process are normally established by process 0 when the
system is initialized and then inherited by each successive process.
 Each implementation has its own way of tuning the various limits.
 Each call to these two functions specifies a single resource and a pointer to the
following structure:
Dept of CSE, Vemana I.T Page 39 of 41
UNIX System Programming Module-3

struct rlimit {
rlim_t rlim_cur; /* soft limit: current limit */
rlim_t rlim_max; }; /* hard limit: maximum value for rlim_cur */

 Three rules to change the resource limits are


a) A process can change its soft limit to a value less than or equal to its hard limit.
b) A process can lower its hard limit to a value greater than or equal to its soft limit.
This lowering of the hard limit is irreversible for normal users.
c) Only a superuser process can raise a hard limit.

 An infinite limit is specified by the constant RLIM_INFINITY.


 Resource values are
a) RLIMIT_CPU The maximum amount of CPU time in seconds. When
the soft limit is exceeded, the SIGXCPU signal is sent to the
process.
b) RLIMIT_DATA The maximum size in bytes of the data segment: the
sum of the initialized data, uninitialized data, and heap.
c) RLIMIT_LOCKS The maximum number of file locks a process can
hold.
d) RLIMIT_STACK The maximum size in bytes of the stack.
e) RLIMIT_FSIZE The maximum size in bytes of a file that may be
created. When the soft limit is exceeded, the process is sent the
SIGXFSZ signal
Example
/* The program below prints out the current soft limit and hard limit CPU time resource
limit supported on the system.*/

#include <stdio.h>
#include <sys/resource.h>
#include <sys/time.h>

int main(void)
{

struct rlimit limit;

Dept of CSE, Vemana I.T Page 40 of 41


UNIX System Programming Module-3

if (getrlimit(RLIMIT_CPU, &limit) < 0)


printf("getrlimit error for %s", name);
printf("%-14s ", RLIMIT_CPU);

if (limit.rlim_cur == RLIM_INFINITY)
printf("(infinite) ");
else
printf(“%10ld”, limit.rlim_cur);

if (limit.rlim_max == RLIM_INFINITY)
printf("(infinite)");
else
printf((“%10ld”, limit.rlim_max);
return 0;
}

Output:
$./a.out
RLIMIT_CPU (infinite) (infinite)

Dept of CSE, Vemana I.T Page 41 of 41

You might also like