UNIT3 Complete

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 24

UNIT-III

File management system calls : Regular file management system calls – open( ),
read( ), write( ), lseek( ), Close(),unlink( ),stat( ), getdents( ). Miscellaneous file
management system calls – chown( ) and fchown( ), chmod( ) and fchmod( ),
dup( ) and dup2( ), fcntl( ), ioctl( ), link( ), mknod( ), sync( ), truncate( ) and
ftruncate( ).

Process Management: Creating a new process – fork( ),orphan processes,


terminating a process – exit( ), zombie processes, waiting for child – wait( ),
Differentiating a process – exec( ), changing directories – chdir( ), changing
priorities- nice( ), Accessing user and Group ID’s , file locking – deadlocks.
File management system calls:

What is a system call?


 A system call is how a program requests a service from an operating system's kernel.
 This may include hardware related services (e.g. accessing the hard disk), creating and
executing new processes, and communicating with integral kernel services (like
scheduling).
 System calls provide an essential interface between a process and the operating system.

What is a file descriptor?


 Every opened file is referred by a file descriptor in kernel. A file descriptor is a non
negative integer and this value obtained from kernel while opening or creating a file.
 The same descriptor passed as an argument to read write functions to perform reading
or writing of a file .

A single file may be opened several times and may thus have several file descriptors associated
with it.
Each file descriptors has its own private set of properties, such as the following

 A file pointer that records the offset in the file it is reading or writing. When a file
descriptor is created, its file pointer is positioned at offset 0 in the file by default.
 A file that indicates whether the descriptor should automatically be closed if the
process execs.
 A flag indicates whether all of the output to the file should be appended to the end of
the file.
 A flag that indicates whether a process should block on input from the file if the file
doesn’t currently any input.
 A number that indicates a process ID or process group that should be sent a SIGIO signal
if input becomes available on the file.
File-management system calls ::
File-management system calls allow you to manipulate the full collection of regular,
directory, and special files, including:
4 disk-based files
4 terminals
4 printers
4 inter process communication facilities, such as pipes and sockets

File access function ::


open () ::
Open function is used to create a new file or to open an existing file .The open () function
establishes the connection between a file and a file descriptor.
Header files required ::
#include <sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
Syntax::
int open (const char *path ,int oflag,/*mode_t mode*/….);
path
 The name of the file to open. It includes the file path defining where, in which file
system, the file is found (or should be created).
oflag
This argument formed by optional parameters and (from <fcntl.h>) one of:
 O_RDONLY, - open for read only.
 O_WRONLY open for write only.
 O_RDWR and open for read and write.
Option parameters include:
 O_APPEND : data written will be appended to the end of the file. The file operations
will always adjust the position pointer to the end of the file.
 O_CREAT : Create the file if it does not exist; otherwise the open fails
setting errno to ENOENT.
 O_EXCL : Used with O_CREAT if the file already exists, then fail, setting err no to EEXIST.
 O_TRUNC : If the file already exists then discard its previous contents, reducing it to an
empty file. Not applicable for a device or named pipe.

mode
• Optional and relevant only when creating a new file, defines the file permissions. These
include read, write or execute the file by the owner, group or all users.
Identifying errors:
• How can we tell if the call failed?
– the system call returns a negative number
• How can we tell what was the error?
– Using errno – a global variable set by the system call if an error has occurred.
– Defined in errno.h
– Use strerror to get a string describing the problem
– Use perror to print a string describing the problem
#include <errno.h>
int fd;
fd = open( FILE_NAME, O_RDONLY, 0644 );
if( fd < 0 ) {
printf( "Error opening file: %s\n", strerror( errno ) );
return -1;
}
Create () ::
 A new file can also be created by create function.
 Create function opens the file in write mode only, but with open function you can create
or open a file in read and write mode.
Header files ::
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
Syntax::
int creat(const char *pathname, mode_t mode)
Equivalent to:
open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode)
read () ::
Once we got a file descriptor from opened file, we may read data from a file using read ()
system call.
This call takes three parameters::
i. The file descriptor to read from
ii. A buffer to read data into ,and
iii. The number of characters to read data into the buffer.
This buffer must be large enough to contain the data.
Header file required ::
#include<unitsd.h>
Syntax:
ssize_t read(int fd, void *buf, size_t nbyte);
Note :: if nbytes =0 ,the read()function returns 0 other wise no results .
write () ::
 Just like read() system call ,we use write () system call ,to write data to the file .
 The write operation is done in the location of these current file offset of the given file .
 It writes data, in bytes as specified by the caller, from a buffer declared by the user in
the program and then writes it into the file supplied by the calling process.
Header file required ::
#include<unistd.h>
Syntax:
size_t write(int fd, const void *buf, size_t nbytes);

lseek() ::
 The UNIX system file system treats an ordinary file as a sequence of bytes.
 Generally, a file is read or written sequentially -- that is, from beginning to the end of
the file. Sometimes sequential reading and writing is not appropriate.
 Random access I/O is achieved by changing the value of this file pointer using the lseek()
system call.
 It is used for positioning a file descriptor and move the read /write file offset.
 It allows the file offset to be set beyond the end of the existing data in the file
Header files ::
#include<unistd.h>
#include<sys/types.h>
Syntax::
lseek(int fildes, off_t offset, int whence)

Available Values for whence


lseek: Examples
• Move to byte #16
– newpos = lseek( fd, 16, SEEK_SET );
• Move forward 4 bytes
– newpos = lseek( fd, 4, SEEK_CUR );
• Move to 8 bytes from the end
– newpos = lseek( fd, -8, SEEK_END );
• Move backward 3 bytes
– lseek(fd, -3, SEEK_CUR)

lseek – errno
• lseek() will fail and the file pointer will remain unchanged if:
– EBADF - fd is not an open file descriptor.
– ESPIPE - fd is associated with a pipe, socket, or FIFO.
– EINVAL - Whence is not a proper value, or calculated offset is negative.
fcntl ()::
 The fcntl function can change the properties of a file that is already open.
 The fcntl() function performs the requested operation on the file descriptor fd.
 The operation is defined by oprand is operating system dependent .
 fcntl() performs the operation encoded by cmd on the file associated with the file
descriptor fd ,arg is an optional argument for cmd.
Function name ::
fcntl-file control
Header file required ::
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
Syntax::
int fcntl(int fd, int cmd, int arg)

The most common values of cmd :


fcntl() returns -1 if unsuccessful.
A whole collection of things you can do with files(uses of fCNTL)
 Make I/O synchronous or asynchronous
 File locking
 Receive signal when file is available for read/write
 Receive signal when file is modified by another process
 Keep file open across exec
 Anything else a particular device driver needs to do.

ioctl ()::
 The ioctl system call is an all purpose interface for controlling hardware devices.
 ioctl (an abbreviation of input/output control) is a system call for device-specific
input/output operations and other operations which cannot be expressed by regular
system calls.
 It takes a parameter specifying a request code; the effect of a call depends completely
on the request code.
Header files :
#include<unistd.h>
#include<sys/ioctl.h>
Syntax:
Int ioctl(int filedes,int request,…);
A Unix ioctl call takes as parameters:
1. an open file descriptor
2. a request code number
3. either an integer value, possibly unsigned (going to the driver) or a pointer to data
(either going to the driver, coming back from the driver, or both).
The kernel generally dispatches an ioctl call straight to the device driver, which can interpret
the request number and data in whatever way required.

Stat()
We have seen how to create files and manipulate files data. we often need more than that ;
i. what are the exact set of permission flags of the file?
ii. When it was last changed?
iii. Which user and group owns the file?
iv. How large is the file?
All these are answered by the stat() system call.
There are three variants: i. stat() ii. fstat() iii. lstat()
Function name ::
stat,lstat,fstat -- get file status
Header file required::
#include <sys/types.h>
#include <sys/stat.h>
Syntax::
int stat(const char *path, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *path, struct stat *buf);
 It obtains information about the file pointed to by path.
 No permissions are required on the file itself, but — in the case of stat() and lstat() —
execute (search) permission is required on all of the directories in path that lead to the
file.
 stat() stats the file pointed to by path and fills in buf.
 lstat() is identical to stat(), except that if path is a symbolic link, then the link itself is
stat-ed, not the file that it refers to.
 fstat() is identical to stat(), except that the file to be stat-ed is specified by the file
descriptor filedes.
Structure stat::
Struct stat {
mode_t st_mode; /* file type and mode (type & permissions) */
ino_t st_ino; /* inode’s number */
dev_t st_dev; /* device number (file system) */
nlink_t st_nlink; /* number of links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID */
off_t st_size; /* size in bytes */
time_t st_atime; /* last access */
time_t st_mtime; /* last modified */
time_t st_ctime; /* last file status change */
long st_blksize; /* I/O block size */
long st_blocks; /* number of blocks allocated */
}

link() ::
 The UNIX system file structure allows more than one named reference to a given file, a
feature called "aliasing".
 Making an alias to a file means that the file has more than one name, but all names of
the file refer to the same data.
 Any file can have multiple directory entries pointing to its i-node.
 To create a link to an existing file ,you use link function .
Header file ::
#include<unistd.h>
Syntax:
Int link (const char *existing path, const char *newpath);
 The function creates a new directory entry ,new path that reference the existing
file ,existing path.If new path already exists an error is returned .
 The creation of the new directory entry and the increment of the link count must be an
atomic operation.
 Only super user process can create a new link that points to a directory.

unlink () ::
 To remove an existing directory entry ,we use the unlink function.
Header file ::
#include<unistd.h>
Syntax:
Int unlink( const char *filename);
 This function removes the directory entry and decrements the link count of the file
referenced by pathname.

chown()and fchown() ::
 “chown()” and “fchown()” change the owner and/or group of a file .
 “chown()” causes the owner and group IDs of fileName to be changed to ownerId and
groupId, respectively.
 A value of -1 in a particular field means that its associated value should remain
unchanged.
 fchown():takes an open descriptor as an argument instead of a filename.
Syntax:
int chown( const char* fileName, uid_t ownerId, gid_t groupId )
int fchown( int fd, uid_t ownerId, gid_t groupId )

Example, ::
changed the group of the file “test.txt” from “music” to “cs”. which has a group ID
number of 62.
Program::
main()
{
int flag;
flag = chown(“test.txt”, -1, 62 ); /* Leave user ID uchanged */
if ( flag == -1 )
perror(“mychown.c”);
}

chmod() and fchmod() ::


 “chmod()” and “fchmod()” change a file’s permission flags.
 “chmod()” changes the mode of fileName to mode, where mode is usually supplied as
an octal number .
 To change a file’s mode, you must either own it or be a super-user.
 “fchmod()” works just like “chmod()” except that it takes an open file descriptor as an
argument instead of a filename.
 They both return a value of -1 if unsuccessful, and a value of 0 otherwise.

Syntax:
int chmod( const char* fileName, int mode )
int fchmod( int fd, mode_t mode );
Example ::
changed the permission flags of the file “test.txt” to 600 octal,which corresponds to read and
write permission for the owner only:
program::
main()
{
int flag;
flag = chmod(“test.txt”, 0600); /* Use an octal encoding */
if ( flag==-1 )
perror(“mychmod.c”);
}
dup() and dup2()::
 “dup()”, “dup2()” used to duplicate file descriptors .
 “dup()” finds the smallest free file-descriptor entry and points it to the same file to
which oldFd points.
 “dup2()” closes newFd if it’s currently active and then points it to the same file to
which oldFd points.
 The original and copied file descriptors share the same file pointer and access mode.
 It return the index of the new file descriptor if successful and a value of -1 otherwise.
Syntax::
int dup( int oldFd )
int dup2( int oldFd, int newFd )
example :
created a file called “test.txt” and wrote to it via four different file descriptors:
4The first file descriptor was the original descriptor.
4The second descriptor was a copy of the first, allocated in slot 4.
4The third descriptor was a copy of the first, allocated in slot 0 ( the standard input
channel ), which was freed by the “close(0)” statement.
4The fourth descriptor was a copy of the third descriptor,copied over the existing
descriptor in slot 2 ( the standard error channel ).
#include <stdio.h>
#include <fcntl.h>
main()
{
int fd1, fd2, fd3;
fd1 = open( “test.txt”, O_RDWR | O_TRUNC );
printf(“fd1 = %d”\n”, fd1 );
write( fd1, “what’s “, 6 );
fd2 = dup(fd1); /* Make a copy of fd1 */
printf( “fd2=%d\n”, fd2);
write( fd2, “up”, 3 );
close(0); /* Close standard input */
fd3 = dup(fd1); /* Make another copy of fd1 */
printf(“fd3 = %d\n”, fd3);
write(0, “ doc“, 4);
dup2(3,2); /* Duplicate channel 3 to channel 2 */
write(2, “?\n”, 2 );
}

Reading Directory Information: getdents()


 “processDirectory()” opens a directory file for reading and then

Header files : #include<unistd.h>


#include<sys/types.h>
Syntax:
int getdents( int fd, struct dirent* buf, int structSize )
 It reads the directory file with descriptor fd from its current position and fills the
strcuture pointed to be by buf with the next entry.
 The structure “dirent” is defined in “/usr/include/sys/dirent.h” and contains the
following fields:
NAME MEANING
1. d_ino the inode number
2. d_off the offset of the next directory entry
3. d_reclen the length of the directory entry structure
4. d_nam the length of the filename

Creating Special Files: mknod()


 “mknod()” allows you to create a special file,
Header files: #include<unistd.h>
#include<sys/types.h>
Syntax: int mknod( const char* fileName, mode_t type, dev_t device )
 “mknod()” creates a new regular, directory, or special file called fileName whose type
can be one of the following:
VALUE MEANING
1. S_IFDIR directory
2. S_IFCHR character-oriented file
3. S_IFBLK block-oriented file
4. S_IFREG regular file
5. S_IFIFO named pipe
If the file is a character-or block-oriented file,
I. the low-order byte of device should specify the minor device number,
II. the high-order byte should specify the major device number.
In other cases, the value of device is ignored.
I. Only a super-user can use “mknod()” to create directories,character-oriented files, or
block-oriented special files.
II. It is typical now to use the “mkdir()” system call to create directories.
III. “mknod()” returns a value of -1 if unsuccessful
and a value of 0 otherwise.

Flushing the File-System Buffer: sync()


 - “sync()” flushes the file-system buffers
Header files:
#include<unistd.h>
#include<sys/types.h>
Syntax::
void sync()
 “sync()” schedules all of the file system buffers to be written to disk.
“sync()” should be performed by any programs that bypass the file
 system buffers and examine the raw file system.
 “sync()” always succeeds.

Truncating a File: truncate() and ftruncate() ::


 “truncate()” and “ftruncate()” set the length of a file.
Header files :
#include<unistd.h>
#include<sys/types.h>
Syntax:
int truncate( const char* fileName, off_t length )
int ftruncate( int fd, off_t length )
 “truncate()” sets the length of the file fileName to be length bytes,
I. If the file is longer than length, it is truncated.
II. If it is shorter than length, it is padded with ASCII NULLS.
 “ftruncate()” works just like “truncate()” does, except that it takes an open file
descriptor as an argument instead of a filename.
 They both return a value of -1 if unsuccessful
and a value of 0 otherwise.

Process Management

 A unix process is a unique instance of a running or runnable program.


 When you execute a program on your UNIX system, the system creates a special
environment for that program. This environment contains everything needed for the
system to run the program as if no other program were running on the system .
 A process, in simple terms, is an instance of a running program.
 Every process in a UNIX system has the following attributes:
4 some code( a.k.a. text )
4 some data
4 a stack
4 a unique process ID number(PID)
 When UNIX is first started, there’s only one visible process in the system.
 This process is called “init”, and it has a process ID of 1.
 The only way to create a new process in UNIXis to duplicate an existing process, so
“init” is the ancestor of all subsequent processes.
The process hierarchy

 When a child process terminates, its death is communicated to its parent so that the
parent may take some appropriate action.
 When a shell executes a utility in the foreground, it duplicates into two shell processes;
 the child-shell process replaces its code with that of the utility, whereas the parent shell
waits for the child process to terminate.
 When the child process terminates, the original parent process awakens and presents
the user with the next shell prompt.
Creating a new process:: fork()
 The fork() function creates a new process. The new process (the child process) is an
exact copy of the calling process (the parent process).
Header file :: #include <unistd.h>
Syntax: pid_t fork(void);
The child process inherits the following attributes from the parent process:
• Real and effective user and group IDs
• Environment settings
• Signal handling settings
• Attached shared memory segments
• Memory mapped segments
• Process group ID
• Current working directory
• File mode creation mask
• Controlling terminal
• nice value
The child process differs from the parent process in the following ways:
• The child process has a unique process ID, which also does not match any active process
group ID.
• The child process has a different parent process ID (that is, the process ID of the process
that called fork()).
• The child process has its own copy of the parent's file descriptors Each of the child's file
descriptors refers to the same open file structures as the file descriptor of the parent.
• The child process has its own copy of the parent's open directory streams.
• The child process' process execution times (as returned by times()) are set to zero.
• Pending alarms are cleared for the child.
• All semaphore adjustment values are cleared.
• File locks set by the parent process are not inherited by the child process.
• The set of signals pending for the child process is cleared.
• Interval timers are reset.
Example 1:: write a c program to explain simple fork()
#include<stdio.h>
main()
{
int pid;
pid=fork();
if(pid==0)
{
printf("iam the child and my processid is%d\n",getpid());
printf("the child's parent process id is %d\n",getppid());
}
else
{
printf("iam the parent ,my process id is %d\n",getpid());
printf("the parents parent process id is %d\n",getppid());
}
}
Output::
iam the child and my processid is 17407
the child's parent process id is 17406
iam the parent ,my process id is 17406
the parents parent process id is 17086

Orphan process::
• unix supports the concept of orphans. In Unix after execution of the fork()function, if the
parent terminates first ,the child is helpless. This creates situation of orphan

Illustrating orphan process


Example:
Write a c program to illustrate orphan process
#include<stdio.h>
#include<unistd.h>
main()
{
int pid;
printf("iam the original process with pid%d and ppid %d\n",getpid(),getppid());
pid=fork(); /*creating a child thread, child and parent continue from here*/
if(pid!=0) /*pid is non -zero ,so it must be the parent*/
{
printf("iam the parent process with pid %d and ppid%d\n",getpid(),getppid());
printf("my childs pid is%d \n",pid);
}
else /*pid is zero ,so it must be the child*/
{
sleep(5); /*make sure that the parent teriminates first*/
printf("iam the child process with pid%d and ppid%d \n",getpid(),getppid());
}
printf("pid%d teriminates \n",getpid()); /*both parent and child execute this*/
}

Exit ():
In general a process can terminate in two modes.
1. normal mode and
2. abnormal mode .
 However in any mode a process is terminated the code which is executed by kernel is
same.
 In every mode the every case (or) mode the terminating process should notify its parent
about its termination.
 In the case of exit/_exit function it is done by passing an exit status as the argument to
these functions.
 In the case of abnormal termination ,however ,the kernel generates a termination status
to indicate the reason for abnormal termination.
Syntax:
void exit(int status) -- terminates the process which calls this function and returns
the exit status value

Wait() ::
• You can control the execution of child processes by calling wait() in the parent.
• Wait () forces the parent to suspend execution until the child is finished.
• Wait returns the process id of a child process that finished.
• If the child finishes before the parent gets around to calling wait(),then when wait()is
called by the parent ,it will return immediately with error message.
Syntax:
int wait(status)
int *status;
Where status is a pointer to an integer where the unix system stores the value returned by the
child process .
• Wait returns the process ID of the process that ended .
• Wait () fails if any of the following condition holds:
1. the process has no children to wait for.
2.status points to an invalid address.
Example :
Write a c program to illustrate wait () and exit ()
#include<stdio.h>
#include<unistd.h>
main()
{
int status,childpid,pid;
printf("im the parent process and my pid is%d\n",getpid());
pid=fork(); /*creating child*/
if(pid!=0) /*pid is non zero ,so it must be the parent*/
{
printf("iam the parent process with pid %d and ppid %d \n",getpid(),getppid());
childpid=wait(&status);
printf("a child with pid %d teriminated with exit code %d\n",childpid,status>>8);
}
else
{
printf("iam the child process with pid%d and ppid%d\n" ,getpid(),getppid());
exit(42);
}
printf("pid%d teriminates \n",getpid());
return 0;
}
Exec ()::
• The UNIX system provides several system calls to create and end program, to send and
receive software interrupts, to allocate memory, and to do other useful jobs for a
process.
• Four system calls are provided for creating a process, ending a process, and waiting for a
process to complete.
• These system calls are fork(), the "exec" family, wait(), and exit().
• The exec is a collection of functions of Unix-like operating systems cause the running
process to be completely replaced by the program passed as an argument to the
function.
• When a process calls one of the exec functions, that process is completely replaces by
the new program, and the new program starts executing at its main function.
• A new program is run using the exec(l, lp, le,v ,vp) family of system calls.
Exec family of functions ::
• int execl ( const char *path, const char *arg, ...);
• int execlp ( const char *file, const char *arg, ...);
• int execle ( const char *path, const char *arg , ..., char * const envp[]);
• int execv ( const char *path, char *const argv[]);
• int execvp ( const char *file, char *const argv[]);
Letters added to the end of exec indicate the type of arguments:
• l argn is specified as a list of arguments.
• v argv is specified as a vector (array of character pointers).
• e environment is specified as an array of character pointers.
• p user's PATH is searched for command, and command can be a shell program.
path
• The argument specifies the path name of the file to execute as the new process .
Arguments beginning at arg0 are pointers to arguments to be passed to the new
process image. The argv value is an array of pointers to arguments.
arg0
• The first argument arg0 should be the name of the executable file. Usually it is the
same value as the path argument. Some programs may incorrectly rely on this
argument providing the location of the executable, but there is no guarantee of this nor
is it standardized across platforms.
envp
• Argument envp is an array of pointers to environment settings. The exec calls named
ending with an e alter the environment for the new process image by passing a list of
environment settings through the envp argument.
Exec family of functions ::
1. execl Takes the path name of an executable program (binary file) as its first
argument. The rest of the arguments are a list of command line arguments to the new
program (argv[]).
The list is terminated with a null pointer:
execl("/bin/cat", "cat", "f1", "f2", (char *) 0);
execl("a.out", "a.out", (char *) 0);
2. execle Same as execl(), except that the end of the argument list is followed by a pointer
to a null-terminated list of character pointers that is passed a the environment of the
new program (i.e., the place that getenv() searches for exported shell variables):
static char *env[] = { "TERM=vt100",
"PATH=/bin:/usr/bin",
(char *) 0 };
execle("/bin/cat", "cat", "f1", "f2", (char *) 0, env);

3. execv i. Takes the path name of an executable program (binary file) as it first
argument.
ii. The second argument is a pointer to a list of character pointers (like argv[])
that is passed as command line arguments to the new program:
static char *args[] = { "cat",
"f1",
"f2", (char *) 0 };
execv("/bin/cat", args);

4. execve Same as execv(), except that a third argument is given as a pointer to a


list of character pointers (like argv[]) that is passed as the environment
of the new program:
static char *env[] = { "TERM=vt100",
"PATH=/bin:/usr/bin",
(char *) 0 };
static char *args[] = { "cat",
"f1",
"f2",
(char *) 0 };
execve("/bin/cat", args, env);

5. execlp () Same as execl(), except that the program name doesn't have to be a full
path name, and it can be a shell program instead of an executable module:
execlp("ls",
"ls",
"-l",
"/usr",
(char *) 0);
6. execvp() searches the PATH environment variable to find the specified
program. execvp Same as execv(), except that the program name
doesn't have to be a full path name, and it can be a shell program
instead of an executable module:
static char *args[] = { "cat",
"f1",
"f2",
(char *) 0 }; execvp("cat", args);
Example:
• In this example, the program displays a small message and then replaces its code with
that of the “ls”.
#include <stdio.h>
main()
{
printf(“I’m process %d and I’m about to exec an ls -l \n”, getpid() );
execl( “/bin/ls”, “ls”, “-l”, NULL ); /* Execute ls */
printf(“This line should never be executed \n”);
}
Output:
$ myexec ---> run the program.
I’m process 13623 and I’m about to exec an ls -l
total 125
-rw-r--r-- 1 glass 277 Feb 15 00:47 myexec.c
-rwxr-xr-x 1 glass 24576 Feb 15 00:48 myexec
$_

Changing Directories: chdir()


• Every process has a current working directory that is used when processing a
relative pathname.
• A child process inherits its current working directory from its parent.
• For example,
when a utility is executed from a shell, its process inherits the shell’s
current working directory.
• To change a process’ current working directory, use “chdir()”, which works as follows:
Syntax: int chdir( const char* pathname )
• “chdir()” sets a process’ current working directory to the directory pathname.
• The process must have execute permission from the directory to succeed.
Example:
the process prints its current working directory before and after executing “chdir()” by
executing pwd using the “system()” library routine:
#include <stdio.h>
main()
{
system(“pwd”); /* Display current working directory */
chdir(“/”); /* Change working directory to root directory */
system(“pwd”); /* Display new working directory */
chdir(“/home/glass”); /* Change again */
system(“pwd”); /* Display again */
}
---> execute the program. /home/glass
/
/home/glass
Changing Priorities: nice()
• A child process inherits its priority value from its parent and may change it by using
“nice()”:
• Every process has a priority value between -20 and +19 that affects the amount of CPU
time that it’s allocated.
• In general, the smaller the priority value, the faster the process will run.
• Only super-user and kernel processes can have a negative priority value, and login
shells start with a priority value of zero.
syntax: int nice(int delta)
• “nice()” adds delta to a process’ current priority value. Only a superuser may specify a
delta that leads to a negative priority value.
Example:
#include <stdio.h>
main()
{
printf(“original priority \n”);
system(“ps”); /* Execute a ps */
nice(0); /* Add 0 to my priority */
printf(“running at priority 0 \n”);
system(“ps”); /* Execute another ps */
nice(10); /* Add 10 to my priority */
printf(“running at priority 10 \n”);
system(“ps”); /* Execute the last ps */
}

Zombie process:
• A process that terminates cannot leave the system until its parent accepts its return
code.
• If its parent process is already dead. It’ll already have been adopted by the “init”
process, which always accepts its children ‘s return codes.
• However, if a process parent is alive, but never executes a wait() , the child process
return code will never be accepted and the process will remain a zombie.
• A zombie process doesn’t have any code, data or stack , so it doesn’t use up many
system resources , but it does continue to habit the system ‘s fixed-size process table.
Example, program created a zombie process, which was indicated in the output from the ps
utility. When I killed the parent process, the child was adopted by “init” and allowed to rest in
peace .

#include<stdio.h>
Main()
{
Int pid;
Pid=fork(); /*create a child*/
If(pid!=0)
{
while(1) /* never terminate, and never execute a wait()*/
sleep(1000);
}
else
{
exit(42);
}
}
Output:
$ zombie & …………….execute the program in the background.
[1] 13545
$ ps …………..obtain process status.
PID TT STAT TIME COMMAND
13535 p2 S 0:00 -ksh (ksh) ……….the shell
13545 p2 S 0:00 zombie ……..the parent process.
13546 p2 Z 0:00 <defunct> ……the zombie child.
13547 p2 R 0:00 ps
$ kill 13545 ………kill the parent process.
[1] Terminated zombie
$ ps ………….notice the zombie is gone now
PID TT STAT TIME COMMAND
13535 p2 S 0:00 -ksh(ksh)
13548 p2 R 0:00 ps

Accessing User and Group IDs


The system calls that allow you to read a process’ real and effective IDs
Syntax:
uid_t getuid()
uid_t geteuid()
gid_t getgid()
gid_t getegid()
• getuid()” and “geteuid()” return the calling process’ real and effective user IDs,
respectively.
• “getgid()” and “getegid()” return the calling process’ real and effective group IDs,
respectively.
• The ID numbers correspond to the user and group IDs listed in “/etc/passwd” and
“/etc/group” files.
• These calls always succeed.
The system calls that allow you to set a process’ real and effective IDs:
Syntax: int setuid(uid_t id)
int seteuid(uid_t id)
int setgid(gid_t id)
int setegid(gid_t id)
• setuid()” and “setgid()” set the calling process’ effective user ID and group ID,
respectively.
• “setuid()” and “setgid()” set the calling process’ effective and real user IDs and group
IDs, respectively, to the specified value.
• These calls succeed only if executed by a super-user, or if id is the real or effective user
or group ID of the calling process.
• They return a value of 0 if successful;
otherwise, they return a value of -1.

You might also like