Oslab Inhouse Manual

Download as pdf or txt
Download as pdf or txt
You are on page 1of 37

Reference books : 1) Advance programming in the UNIX environment

:: W. Richard Stevans :: Pearson education

2) Unix system programming :: Kay A. Robbins &


Steven Robbins :: pearson education

3) Unix Odyssy :: mita Gandhi :: BPB publication

PROCESS TERMINATION

At process termination OS need to do many activities like canceling pending timers and
signals, releasing virtual memory resources, releasing other process held system
resources such as locks, and closing files that are open. The OS records the process status
and resource usage, notifying the parent in response to a wait function.

Process can terminate normally or abnormally


Abnormal termination : By calling abort or by processing a signal that causes
termination ( like pressing ctrl c or some internal error like attempt to access an illegal
memory location. An abnormal termination may produce a core dump and user installed
exit handlers are not called.

A Normal termination occur under the following conditions.


● Return from the main (exit is called implicitly)
● Implicit return from main (the main function falls off the end) (exit is called
implicitly)
● Call to exit, _Exit or _exit
exit :: 1 :calls user defined exit handler
2 : after 1 the exit flushes any open streams that have unwritten buffered
data and then closes all open stream. Finally exit removes only temporary files that
user created.

_exit/_Exit :: will not call the user defined exit handler (ie 1 but will do the 2 )

#include <stdlib.h>
void exit(int status); // status = 0 means normal termination
void _Exit(int status);

#include <unistd.h>
void _exit(int status);

The status (exit status) can be collected by wait or waitpid functions.


How to know the meaning of exit codes. 🡪 exit codes can be interpreted with the
help of appropriate macros as given below

#include <sys/wait.h>

WIFEXITED (int status) 🡪evaluates to a nonzero value when the child terminated
normally (ie status = = 0)
WEXITSTATUS (int status) 🡪 if WIFEXITED evaluates to a nonzero value, then
WEXITSTATUS evaluates to the low order 8 bits returned by the child through _exit(),
exit() or return from main
WIFSIGNALED (int status) 🡪evaluates to a nonzero value if child terminated because of
an uncaught signal
WTERMSIG (int status) 🡪 if WIFSIGNALED evaluates to non zero value, then
WTERMSIG evaluates to the no. of signal
WIFSTOPPED (int status) 🡪 evaluates to a nonzero value if a child is currently stopped.
WSTOPSIG (int status) 🡪 if WIFSTOPPED evaluates to a nonzero value, then
WSTOPSIG evaluates to the number of the signal that caused the child process to
stop.

#include <stdlib.h>
int atexit(void (*func)(void));

if successful, at exit returns 0, if unsuccessful, at exit returns a nonzero value.

The sysconf function takes a single argument, which is the name of a configurable
system wide limit such as the no. of clock ticks per second (_SC_CLK_TCK) or
maximum no. of processes allowed per user (_SC_CHILD_MAX) and returns the
required system values

#include <unistd.h>
long sysconf(int name); //{_SC_CLK_TCK 🡪 defined in limits.h

#include <sys/times.h>
clock_t times(struct tms *buffer)
returns wall clock time in clock ticks (from some arbitrary time in the past
and returns -1 on error. So to calculate the elapsed time b/w two points in the program
call times twice at the required points/places in the program and calculate the
difference b/e the returned values (and divided by SC_CLK_TCK to get the time in
seconds)
members of struct tms
clock_t tms_utime; /* user cpu time of processes */
clock_t tms_stime; /* system cpu time on behalf of process */
clock_t tms_cutime /* user CPU time of process and terminated childrens */
clock_t tms_cstime; /* system CPU time of process and terminated children */

--------------------Program- 2.10-----------showtimes---------------------------------------
// a program with an exit handler that outputs CPU usage
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/times.h>

static void showtimes(void) {


double ticks;
struct tms tinfo;

if ((ticks = (double) sysconf(_SC_CLK_TCK)) == -1)


perror("Failed to determine clock ticks per second");
else if (times(&tinfo) == -1)
perror("Failed to get times information");
else {
fprintf(stderr, "User time: %8.3f seconds\n",
tinfo.tms_utime/ticks);
fprintf(stderr, "System time: %8.3f seconds\n",
tinfo.tms_stime/ticks);
fprintf(stderr, "Children's user time: %8.3f seconds\n",
tinfo.tms_cutime/ticks);
fprintf(stderr, "Children's system time: %8.3f seconds\n",
tinfo.tms_cstime/ticks);
}
}

int main(void) {
if (atexit(showtimes)) {
fprintf(stderr, "Failed to install showtimes exit handler\n");
return 1;
}
/* rest of main program goes here */
return 0;
}

#include <unistd.h>
pid_t getpid(void)
pid_t getppid(void)

The getpid and getppid function returns the process ID and the parent process ID
respectively. The pid_t is an unsigned integer type that represents a process ID.

🡪 neither the getpid nor the getppid function can return an error.

🡪 other processes commands 🡪 gid_t getegid(void) (get effective group ID of the


process), uid_t geteuid(void), gid_t getgid (void), uid_t getuid(void)
# chmod u+s xyz //real owner may be naveen.
# ls –l
-rws- -x- -x
now when xyz runs/executed and during execution if this process access a file owned by
other user (say super user) then during execution xyz will enjoy all the privilege of owner
(i.e. in our case super user) in other words it’s effective user id became same as the owner
of the file.passwd command is able to update /etc/passwd file using this mechanism.

-----------------EX 3.1---------------outputPID----------------------------------------------

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

int main (void) {


printf("I am process %ld\n", (long)getpid());
printf("My parent is %ld\n", (long)getppid());
return 0;
}

------------------EX 3.2-----------outputIDS--------------------------------------------------

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

int main(void) {
printf("My real user ID is %5ld\n", (long)getuid());
printf("My effective user ID is %5ld\n", (long)geteuid());
printf("My real group ID is %5ld\n", (long)getgid());
printf("My effective group ID is %5ld\n", (long)getegid());
return 0;
}

fork()

#include <unistd.h>
pid_t fork(void)
A process can create a new process by calling fork. The calling process becomes the
parent and the created process is called the child. The fork function copies the parent’s
memory image so that the new process receives a copy of the address space of the parent.
Both processes continue at the instruction after the fork statement (executing in their
respective memory image).
The fork() function returns 0 to the child and returns the child’s process ID to the parent.
When fork fails, it returns -1 and sets the errorno. If the system does not have the
necessary resources to create the child or if limits on the no. of processes would be
exceeded – fork sets errorno. to EAGAIN. In case of failure the fork does not create a
child.
------------------EX 3.6------------------------twoprocs.c-----------------------------------------
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void) {
pid_t childpid;

childpid = fork();
if (childpid == -1) {
perror("Failed to fork");
return 1;
}
if (childpid == 0) /* child code */
printf("I am child %ld\n", (long)getpid());
else /* parent code */
printf("I am parent %ld\n", (long)getpid());
return 0;
}

------------------------program 3.1---------------simplechain--------------------------------
// a program that creates a chain of n processes, where n is a command line arguments
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

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


pid_t childpid = 0;
int i, n;

if (argc != 2){ /* check for valid number of command-line arguments */


fprintf(stderr, "Usage: %s processes\n", argv[0]);
return 1;
}
n = atoi(argv[1]);
for (i = 1; i < n; i++)
if (childpid = fork())
break;

fprintf(stderr, "i:%d process ID:%ld parent ID:%ld child ID:%ld\n",


i, (long)getpid(), (long)getppid(), (long)childpid);
return 0;
}
#include <sys/wait.h>
pid_t wait(int *state_loc);
pid_t waitpid(pid_t pid, int *state_loc, int options);

🡪 The parent can execute wait or waitpid (wait for a particular child) to block itself until
the child finishes.

🡪 The wait function causes the caller to suspend execution until a child’s status become
available (ie child terminates) or until the caller receives a signal.

🡪 if wait or waitpid returns because the status of a child is reported, these function return
the process ID of that child. If an error occurs, these function return -1 and set error no.. if
called with WNOHANG option , waitpid returns 0 to report that the specified child is not
available immediately and so parent will not wait/block.

🡪 some errors are like 🡪 EINTER (function was interrupted by a signal), EINVAL (
option parameter of waitpid was invalid)
--------EX 3.15-----------------------fanwait--------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "restart.h"

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


pid_t childpid;
int i, n;
if (argc != 2) {
fprintf(stderr, "Usage: %s n\n", argv[0]);
return 1;
}
n = atoi(argv[1]);
for (i = 1; i < n; i++)
if ((childpid = fork()) <= 0)
break;

while((wait(NULL) = = -1 ) && (errorno = = EINTER)) ;


/* wait for all of your children ,
EINTER 🡪 FUNCTION WAS INTERRUPTED BY A SIGNAL
ECHILD 🡪 CALLER HAS NO UNWAITED FOR CHILDREN */

fprintf(stderr, "i:%d process ID:%ld parent ID:%ld child ID:%ld\n",


i, (long)getpid(), (long)getppid(), (long)childpid);
return 0;
}

exec

The exec family of function provides a facility for overlaying the process image of the
calling process with a new image.

#include <unistd.h>
extern char ** environ;
int execl (const char *path, const char * arg 0, /* ………char * (0) */);
int execle (const char *path, const char *arg 0, /* …………char * (0) , char *const
envp{} */ );
int execlp (const char *file, const char *arg 0, /*………. Char * (0) */);
int execv (const char *path, char *const argv[]);
int execve (const char *path, char *const argv[], char *const envp[]);
int execvp (const char *file, char *const argv[]);

All exec function returns -1 and set errorno. if unsuccessful. In fact if any of these
function return at all, the call was unsuccessful and some errorno. will be set (like
E2BIG, EACCES, EINVAL etc)

🡪 setsid() 🡪 if setsid is set for a process than it does not get any signal because of ctrl c
from the controlling terminal.

-----------------Program 3.4--------------execls.c--------------------------------------------------
// aprogram that creates a child process to run ls -l
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void) {
pid_t childpid;
childpid = fork();
if (childpid == -1) {
perror("Failed to fork");
return 1;
}
if (childpid == 0) { /* child code */
if(execl("/bin/ls", "ls", "-l", NULL) == -1)
perror("Child failed to exec ls");
return 1;
}
if (childpid != wait(NULL)) { /* parent code */
perror("Parent failed to wait due to signal or error");
return 1;
}
return 0;
}

------------Program 3.7---------------runback.c------------------------------------------------------
// the runback program creates a child process to execute a command string in the
background
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "restart.h"

int makeargv(const char *s, const char *delimiters, char ***argvp);

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


pid_t childpid;
char delim[] = " \t";
char **myargv;

if (argc != 2) {
fprintf(stderr, "Usage: %s string\n", argv[0]);
return 1;
}
childpid = fork();
if (childpid == -1) {
perror("Failed to fork");
return 1;
}
if (childpid == 0) { /* child becomes a background process */
if (setsid() == -1)
perror("Child failed to become a session leader");
else if (makeargv(argv[1], delim, &myargv) == -1)
fprintf(stderr, "Child failed to construct argument array\n");
else {
execvp(myargv[0], &myargv[0]);
perror("Child failed to exec command");
}
return 1; /* child should never return */
}
return 0; /* parent exits */
}

…………………………………………………………………………………….
#include <errno.h>
#include <stdlib.h>
#include <string.h>

int makeargv(const char *s, const char *delimiters, char ***argvp) {


int error;
int i;
int numtokens;
const char *snew;
char *t;

if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {


errno = EINVAL;
return -1;
}
*argvp = NULL;
snew = s + strspn(s, delimiters); /* snew is real start of string */
if ((t = malloc(strlen(snew) + 1)) == NULL)
return -1;
strcpy(t, snew);
numtokens = 0;
if (strtok(t, delimiters) != NULL) /* count the number of tokens in s */
for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;

/* create argument array for ptrs to the tokens */


if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
error = errno;
free(t);
errno = error;
return -1;
}
/* insert pointers to tokens into the argument array */
if (numtokens == 0)
free(t);
else {
strcpy(t, snew);
**argvp = strtok(t, delimiters);
for (i = 1; i < numtokens; i++)
*((*argvp) + i) = strtok(NULL, delimiters);
}
*((*argvp) + numtokens) = NULL; /* put in final NULL pointer */
return numtokens;
}
SYSREMS CALLS - INTRODUCTION
# include <stdio.h>
void perror (const char *msg)
Output -> msg : error message corresponding to the value of error.

getuid() -> Returns the user id of the running process.


getgid() -> Returns the group id of the running process.
/etc/passwd -> Contain the information about user id and group id.
/etc/group -> contains all the group available and related information.

IEEE POSIX -> Portable operating system interface


This standard defines the services that must be provided by the operating system it is to
be “POSIX compliant”.
The POSIX standard specifies an interface and not an implementation.
->Basically defining the set of function prototype for library function/systems calls.

Unbuffered I/O -> Unbuffered refers to the fact that each read or write invokes a system
call in the kernel.
# include <unistd.h>

0->Standard input – STDIN_FILE NO


1->Standard output – STDOUT_FILE NO
3->Standard error – STDERR_FILE NO

Maximum no. of open files at a time =64(but differs with various unix versions )

int open (const char pathname,int oflag,…/*,mode_t mode*/ );


returns : file description if ok, -1 or error
pathname – path of the file to open/create
oflag – O_RDONLY-(open of reading)
O_WRONLY(open for write only)
O_RDWR(open for reading and writing)

{ In most implementation - O_RDONLY - > 0


O_WRONLY- >1
O_RDWR - >2 }
O_APPEND - Append to the end of file on each write
O_CREAT – Create a file if it is doesn’t exist with the permission
specified in mode.
O_EXCL – Generates an error if O_CREAT is also specified and the file
already exists.
O_TRUNC – If the file exist, and if the file is successfully opened for
either write only on read-write, truncate its length to 0.
O_NOCTTY –
O_NONBLOCK –
O_SYNC – this causes each write to wait for the data to be written to disk
before returning.

NOTE 1) oflag can be used by Oring (O_RDONLY or O_WRONLY or


O_RDWR) with other oflags like O_APPEND etc.
2) The file description returned by open is guaranteed to be lowest
numbered unused description.
Example - > open(pathname, O_WRONLY|O_CREAT|O_TRUNC,mode);

Mode – later
The argument mode specifies the permissions to use in case a new file is created. It is
modified by the process’s umask in the usual way: the permissions of the created file are
(mode & ~umask). Note that this mode only applies to future accesses of the newly
created file; the open() call that creates a read-only file may well return a read/write file
descriptor.
The following symbolic constants are provided for mode:
S_IRWXU
  00700 user (file owner) has read, write and execute permission
S_IRUSR
  00400 user has read permission
S_IWUSR
  00200 user has write permission
S_IXUSR
  00100 user has execute permission
S_IRWXG
  00070 group has read, write and execute permission
S_IRGRP
  00040 group has read permission
S_IWGRP
  00020 group has write permission
S_IXGRP
  00010 group has execute permission
S_IRWXO
  00007 others have read, write and execute permission
S_IROTH
  00004 others have read permission
S_IWOTH
  00002 others have write permission
S_IXOTH
  00001 others have execute permission
mode must be specified when O_CREAT is in the flags, and is ignored otherwise.
creat() is equivalent to open() with flags equal to
O_CREAT|O_WRONLY|O_TRUNC.

Create

int creat (const char * pathname, mode_t mode);

Returns file descriptor opened for write only if ok, -1 on error

->equivalent to -> Open (pathname, O_WRONLY|O_CREAT|O_TRUNC, mode)

Note :- if you want to create a file & then read it then


->do creat,close,open for reading
or
open(pathname , O_RDWR|O_CREAT|O_TRUNC,mode);

Close
int close(int filedes); //filedes: file description
Returns: 0 if ok, -1 on error
Note: when a process terminate, the kernel automatically closes all open files.

lseek
off_t lseek (int filedes, off_t offset, int whence);
returns : new file offset if ok,-1 on error

whence – SEEK_SET-> offset calculate from the beginning of the file.


SEEK_CUR->offset calculated from the current position of the file
pointers (file offset).
SEEK_END->offset calculated from the end of file, offset can be positive
or negative.
offset-> long integer.

Note 1: lseek only records the current file offset with in the kernel. It does not cause any
I/O to take place. This offset is then used by the next read or writes option.

Note 2 : The file’s offset can be greater then the file’s current size , in which case the next
write to the file will extend the file. This is referred to as creating a hole in a file and is
allowed. Any bytes in a file that have not been written are read back as 0.

read
ssize_t read (int fledes , void *buff , size_t nbytes)
returns : number of byte read , 0 if end of file, -1 on error.

Note : 1: there can be cases in which the no of bytes actually read is less than the amount
requested.
Note : 2: The read operation starts at the file’s current offset. Before a successful return,
the offset is incremented by the no of bytes actually read.

Write
ssize write (int filedes, const void *buff, size_t nbytes);
returns:no of bytes written if ok, -1 on error.
FILE Sharing
Unix supports the sharing of open files between different processes.

Note :->If we open a file with O_APPEND flag, then before each write the kernel
position the file offset to current end of file.

dup and dup2 :


An existing file description is duplicated by either of the following
function.
#include<unistd.h>
int dup (int filedes)
int dup2 (int filedes, int filedes2);
//filedes2=file description
Both returns: new file description if ok, -1 on error

The new file description returned by dup is guaranteed to be the lowest numbered
available file description. With dup2,we specify the value of new description with the
filedes 2 arguments. If filedes2 is already open, it is first closed. If filedes equals filedes2
then dup2 returns without closing it.
#include <unistd.h>
int dup2 (int fildes, int fildes2)

The dup2 function takes two parameters fildes and fildes2. It closes entry fildes2 of the
file descriptor table, if it was open and then copies the pointer of entry fildes into entry
fildes2

fcntl function
The fcntl function can change the properties of a file that is already open.
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
int fcntl (int filedes, int cmd,………../*int arg*/);

cmd :
F_DUPFD
Duplicate the file description fields. The new file description is
returned as the value of the function (similar to the dup).

F_GETFT
Return the file status flags for filedes as the value of the function.
O_APPEND Append on each file
O_APPEND Append on each write
O_NONBLOCK No blocking mode
O_SYNC Wait for writes to complete
O_ASYNC Asynchronous I/O

1) They are not separate bits that can be tested, they are rather 0,1 & 2. Moreover
O_RDONLY,O_WRONLY and O_RDWR are mutually exclusive – that is for a
file only one of the three can be enabled so use O_ACCMODE mask.

Accmode = Val & O_ACCMODE; {Val is the value returned by the fcntl}
If (Accmode==O_RDONLY)->printf(“read only”);
If (val &O_APPEND)->printf(“append”);

F_SETFL
Set the file status flags to the value of third argument .the only flags that
can be changed are O_APPEND,O_NONBLOCK,O_SYNC and O_ASYNC.

F_GETOWN
Get the process id or process group id.

F_SETOWN
Set the process id or process group id.
F_GETFD
F_SETFD

/dev/fd -> some system provides a directory named /dev/fd where entries are files
names 0,1,2 and so on. Opening the file /dev/fd/n is equivalent to duplicating
description n.

----------------program 4.9------------------------copyfilemain.c---------------------------------
//a program to copy a file
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include "restart.h"

#define READ_FLAGS O_RDONLY


#define WRITE_FLAGS (O_WRONLY | O_CREAT | O_EXCL)
#define WRITE_PERMS (S_IRUSR | S_IWUSR)

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


int bytes;
int fromfd, tofd;
if (argc != 3) {
fprintf(stderr, "Usage: %s from_file to_file\n", argv[0]);
return 1;
}

if ((fromfd = open(argv[1], READ_FLAGS)) == -1) {


perror("Failed to open input file");
return 1;
}

if ((tofd = open(argv[2], WRITE_FLAGS, WRITE_PERMS)) == -1) {


perror("Failed to create output file");
return 1;
}

bytes = copyfile(fromfd, tofd);


printf("%d bytes copied from %s to %s\n", bytes, argv[1], argv[2]);
return 0; /* the return closes the files */
}

#include <unistd.h>
int dup2 (int fildes, int fildes2)

The dup2 function takes two parameters fildes and fildes2. It closes entry fildes2 of the
file descriptor table, if it was open and then copies the pointer of entry fildes into entry
fildes2
---------------program 4.18--------------------redirect.c---------------------------------------------
//a program that redirects standard output to the file my.file
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include "restart.h"
#define CREATE_FLAGS (O_WRONLY | O_CREAT | O_APPEND)
#define CREATE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int main(void) {
int fd;

fd = open("my.file", CREATE_FLAGS, CREATE_MODE);


if (fd == -1) {
perror("Failed to open my.file");
return 1;
}
if (dup2(fd, STDOUT_FILENO) == -1) {
perror("Failed to redirect standard output");
return 1;
}
if (r_close(fd) == -1) {
perror("Failed to close the file");
return 1;
}
if (write(STDOUT_FILENO, "OK", 2) == -1) {
perror("Failed in writing to file");
return 1;
}
return 0;
}

#include <unistd.h>
int chdir (const char *path)

🡪 The chdir function causes the directory specified by path to become the current
working dir for the calling process.
🡪 If successful , chdir returns 0, if unsuccessful chdir returns -1 and sets errno.

#include <unistd.h>
char *getcwd (char *buf, size_t size)

The getcwd function returns the pathname of the current working directory. The buf
parameter of getcwd represents a user supplied buffer for holding the pathname of
the current working directory. The size parameter specifies the maximum length
pathname that buf can accommodate, including the trailing string terminator.

If successful, getcwd returns a pointer to buf. If unsuccessful, getcwd returns NULL and
sets errorno.
🡪 errorno.
EINVAL 🡪 size is 0
ERANGE 🡪 size is greater than 0, but smaller than the pathname + 1

----------Program 5.1-------------------------getcwdpathmax.c------------------------------------
// a complete program to output the current working directory
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#ifndef PATH_MAX
#define PATH_MAX 255
#endif

int main(void) {
char mycwd[PATH_MAX];

if (getcwd(mycwd, PATH_MAX) == NULL) {


perror("Failed to get current working directory");
return 1;
}
printf("Current working directory: %s\n", mycwd);
return 0;
}
# include <sys/stat.h>
struct stat
{
mode_t st_mode; / * file type and mode(permission)* /
ino_t st_ino; / * i_node number(serial no.) */
dev_t st_dev; / * device number(file system) * /
dev_t st_rdev; / * device number for special file */
nlink_t st_nlink; / * number of links */
uid_t st_uid; / * user id of owner */
gid_t st_gid / * group id of owner */
off_t st_size; / * size in bytes for regular files , in case of
symbolic link, file size is the actual no. of bytes in
the filename * /
time_t st_atime; / * time of last access */
time_t st_mtime; / * time of last modification */
time_t st_ctime; / * time of last file status change*/
long st_blksize; / * best I/O block size */
long st_blocks; / * no of 512 – byte blocks allocated */
};

# include<sys/types.h>
# include <sys/stat.h>
int stat (const char *pathname, struct stat *buf);
int fstat (int filedes, struct stat *buf);
int lstat (const char *pathname, struct stat *buf);
All three return : 0 if ok, -1 on error
🡺 buf –will contain the file related information when those function returns.

🡺 fstat – obtain information about the file that is already open on the description
filedes.
🡺 lstat – function is similar to stat, but when the named file is a symbolic link, lstat
returns information about the symbolic link, and not the file referenced by the
symbolic link.

FILE TYPE MACRO

🡺 Regular file S_ISREM (buf.st_mode)-> whether the file is regular if yes


return 1.
🡺 Directory file S_ISDIR( )->whether a directory

🡺 Character special file S_ISCHR( )->A type of file used for certain type of
device an a system.(like keyboard)
🡺 Block special file S_ISBLK ()-> A type of file typically used for disk devices
devices.
All devices on a system are either character special file or
block special file.
🡺 FIFO S_ISFIFO ()->A type of file is used for inter
process communication between process. It is sometime
called named pipe.

🡺 Socket S_ISSOCK ()->A type of file used for network


communication.
🡺 Symbolic link S_ISLNK()-> A types of file that points to another
file.

set user id and set group id

# chmod u+s xyz //real owner may be naveen.


# ls –l
-rws- -x- -x
now when xyz runs/executed and during execution if this process access a file owned by
other user (say super user) then during execution xyz will enjoy all the privilege of owner
(i.e. in our case super user) in other words it’s effective user id became same as the owner
of the file.passwd command is able to update /etc/passwd file using this mechanism.

🡺 st_uid and st_gid both have a bit called set-user-ID & set-group-ID.

🡺 These two bits can be tested against the constants S_ISUID and S_ISGID.
To set -> st_uid & S_ISUID
To see effective user ID of a process xyz use geteuid()
File access Permission

St_mode mask Meaning


S_IRWXU Read ,write & execute by user(owner)
S_IRUSR User -read (owner- read)
S_IWUSR User-write
S_IXUSR User-execute
S_IRWXG Read ,write ,execute by group
S_IRGRP Group read
S_IWGRP Group write
S_IXGRP Group execute
S_IRWXO Read ,write execute by the other
S_IROTH Other read
S_IWOTH Other write
S_IXOTH Other execute
S_ISUID Set user ID on execution
S_ISGID Set group id on execution
S_ISVTX Sticky bit

Read on dir -> no read then you can’t do ls on the dir but still you can display a file
in directory using cat.
Execute on dir ->user can change to that dir i.e. cd allowed.
->Also find or search on that dir is allowed.
->Open (“XYZ/ABC/EFG/ravi.c”,………..)// We need to have execute
permission on XYZ,ABC,EFG
write on dir ->allows the user to remove/create files in that dir. For removing you
need to be owner of the file removed.

The process\program creating a file say XYZ using creat or open(). System call will
have the user id &group id as the effective user id and effective group id of the
process.

int chmod (const char *pathname, mode_t mode);


int fchmod (int filedes, mode_t mode);
Both are returns :0 if on, -1 on error
The chmod function operates on the specified file while the fchmod function operates on
a file that has already been opened.

chmod(“XYZ”,S_TRUSR|S_IWUSR|S_IRGRP|S_IROTH)

🡺 Only super user can set the sticky bit. When a process with a sticky bit terminates,
a copy of its text is kept in the swap space.

# chmod +t/bin/XYZ
# ls –l /bin/XYZ
-rwx- -x- -t

Umask function
Chown,Fchown,lchown functions.

file truncation :
# include <sys/types.h>
# include <unistd.h>
# truncate (const char* pathname , off _t length);
# ftruncate (int filedes , off _t length);
both returns o if on ,-1 on error
🡺 These two function truncate an existing file to length bytes

🡺 If the previous size of the file was greater than length ,the data beyond length is
no longer accessible. if the previous size was less than length, the effect is system
dependent, if the implementation does extend a file , data b/w the old end of file
and the new end of file will read as 0 (i.e. a hole is probably created in the file).

File System
Partition Partition Partition

File System
Boot block super block i - list Directory blocks & data
blocks

i-node i-node ........... i-node


Super block consist of :
1. The size of the file system
2. The no. of free blocks in the file system.
3. A list of free blocks available on the file system.
4. The index of next free blocks in the free block list.
5. The size of i-node list
6. The no of free i node in the file system.
7. A list of free inodes in the file system.
8. The index of the next free inode in the free inode list.
9. Lock fields for the free block & free inode lists.
10. A flag indicating that the super block has been modified.

i-list Data Data Directory Data Directory


block block block block block

i-node file
no. name(xyz)

i-node i-node i-node i-node

i –node file name (xyz)


⮚ ls –l ABC

⮚ xyz .........

⮚ ls –l CSE

⮚ xyz.........
so reference count/link count
for file xyz will be 2
i-node

Permission
Owner
Group

Last Modified time stamp

Size in block

Reference counts (no. of lists)


Direct blocks
.
.
.
.

Single indirect

Double indirect

Triple indirect

🡺 A file can be actually deleted only when its link-count becomes 0.

🡺 The above discussed is called hard link.


🡺 hard links cannot be created across the file system.

🡺 Renaming a file -> Add new name in the directory & make it point to the file’s i-
node.
->Remove old file name from the directory entry.

🡺 Unix command for hard link – ln original_filename added_new_filename


ln today weather
▪ Now today & whether both basically refers to
the same file.
🡺 Soft link /symbolic link : Symbolic link only contain the path of the linked file.(ie
they are like shortcut)
🡺 can span across the file system

🡺 lrwxrwxrwx 1 root ..... .............. lib -> usr/lib

🡺 Unix command :
ln –s lunch /home/CSE/final_year
⮚ ls –l

⮚ lrwxrwxrwx --------------- lunch ->/home/CSE/final_year

# include <unistd.h>

int link (const char* existing path , const char *new path);
returns : 0 if ok , -1 if error
🡺 The system call will create a new directory entry & will increment the link count in
the file’s i-node.
🡺 only a super user process can create a new link that points to a directory as such
directory links can form loops in the file systems.

# include <unistd.h>
int unlink(const char * pathname)

🡺 To remove an existing directory entry we call the unlink function.


Returns : 0 if ok ,-1 if error
🡺 The functions remove the directory entry and decrement the link count of the file
referenced by path name. If there are other links to the file, the data in the file is still
accessible through the other link.
🡺 to unlink we must have write & execute permission on the directory in which the
entry is required to be removed.
🡺 Only when the link count reaches 0 can the contents of the file be deleted. One other
condition prevents the contents of a file from being deleted – as long as some process
has the file open, its contents will not be deleted. when a file is closed the kernel first
checks the count of the no. of process that have the file open. if this count has reached
0 then the kernel checks the link count, and if it is 0, the files contents are deleted.
🡺 If the pathname is a symbolic link ,unlink reference the symbolic link and not the file
referenced by the link.
🡺 The super user can call unlink with pathname specifying a directory, but the function
remdir should be used instead to unlink a directory.

# include<stdio.h>
int remove(const char *pathname);
return: 0 if ok, -1 on error

🡺 For file remove is identical to unlink & for a directory remove is identical to rmdir.

A file on directory is renamed with the rename function.

# include<stdio.h>
int rename(const char *old name, const char *new name);
return: 0 if ok, -1 on error

In case of regular directory (i.e. old name is name of file)


🡺 The new name cannot be the name of the existing directory.

🡺 Otherwise new name is removed and old name is renamed to new name.

🡺 we should have write permission on the directory containing new name and old name.

In case of directory
🡺 If new name is the name of existing directory then the new name directory should be
empty.
🡺 Remove the new name (empty dir) & renamed the old name to new name.

🡺 when we’re renaming a directory new name can not contain a path prefix that names
oldname. For example we can’t rename /user/foo to user/foo/feskir. Since the old
name is a path prefix of the new name & can not be removed.

Function that does not follow the symbolic link & (thus act on the name of the
symbolic link itself).
🡺 chown, lchown , lstat, readlink, remove, rename, unlink.
Function that follow the symbolic link.
🡺 access, chdir, chmod, creat, exec, link, mkdir, opendir, pathconf, mkfifo, mknod,
stat, truncate.

$ mkdir foo
$ touch foo/a -> Create a 0-length file.
// soft link
$ ln –s ../foo foo/test dir

$ unlink (“foo/test dir”) // Easy to remove, as unlink will not follow the symbolic
links.

🡺 you can create a symbolic link to a file that does not exist.

$ ln –s /no/such/file myfile

$ ls myfile
myfile
$ cat myfile
no such file // as the cat follow the symbolic link & the linked file /no/such/file
doesn’t exist.
$ ls –l myfile
lrwxrwxrwx-------------------------------------my file -> no/such/file

# include<unistd.h>
int symlink (const char * actualpath, const char *path);
return : 0 if ok , -1 on error
🡺 A new directory entry, sympath is created that point to actual path. It is not required
that the actual path exists. when the symbolic link is created. Also actual path and
sympath need not reside in the same file system.

# include <unistd.h>

int readlink (const char *pathname, char *buf, int bufsize);


Return: no of bytes read if ok, -1 on error

🡺 Since the open function follows a symbolic link, we need a way to open the link
itself & read the name in the link. If the function is successful it return the no of
bytes placed into buffer. The contents of the symbolic link that are returned in
buf are not null terminated.
File times
Three time fields are maintained for each file.
Field
st_atime -> last access time of file data -> ex –>read {ls -u}
st_mtime ->last modification of file data -> ex -> write {ls –l (default)}
st_ctime -> last change time of i-node status -> ex -> chmod, chown {ls
–c}.

NOTE:- The system does not maintain the last access time for an i-node. This is why the
function access and stat, for example, don’t change any of the three times.

EFFECTS OF VARIOUS FUNCTIONS ON THE ACCESS< MODIFICATION


AND CHANGE ACCESS TIME.

Function Referenced file parent directory of Note


(or directory) referenced file
(or directory)
a M c a m c
chmod, fchmod .
chown. fchown .
creat . . . . . O_CREAT new file
creat . . O_TRUNC existing file
exec .
lchown .
link . . .
mkdir . . . . .
mkfifo . . . . .
open . . . . . O_CREAT new file
open . . O_TRUNS existing file
pipe . . .
read .
remove . . . remove file=unlink
remove . . remove directory=rmdir
rename . . . for both arguments
rmdir . .
truncate, . .
ftruncate
unlink . . .
utime . . .
write . .

utime function
The access time & the modification time of a file can be changed with the utime
function.
#include<sys/types.h>
#include<utime.h>
int utime(const char *pathname, const struct utimebuf *times);
returns : 0 if ok, -1 on error
the structure used by this function is
struct utimebuf {
time_t actime; /* Access time */
time_t modtime; /* Modification time */
}

if times=null - file access & modification time are set to the current time of the system.
if times != null – the access & modification time are set to the value in the structure
pointed to by times.

mkdir & rmdir

#include<sys/types.h>
#include<sys/stat.h>
int mkdir(const char *pathname, mode_t mode);
returns : 0 if ok, -1 on error

🡺 This function creates a new, empty directory. the entries for dot and dot_dot are
automatically created. the specified file access permission, mode are modified by the
file mode creation mask of the process.
🡺 An empty directory is deleted with the rmdir function.
#include<unistd.h>
int rmdir(const char *pathname);
returns : 0 if ok, -1 on error

if the link count of the directory becomes 0 with this call, and no other process has the
directory open, then the space occupied by the directory is used. if one or more
processes have the directory open when the link count reaches 0, the last link is
removed & the dot_dot entries are removed before this function returns. Additionally,
no new files can be created in the directory. the directory is not free, however, until
the last process closes it.

reading directories

directories can be read by anyone who has access permission to read the directory.
but only the kernel can write to a directory (to preserve file system security). recall
from section 4.5 that the write permission bits and execute permission bits for a
directory determine if we can create new files in the directory and remove files from
the directory they don’t specify if we can write to the directory itself.
#include<sys/types.h>
#include<dirent.h>
DIR *opendir (const char *pathname);
return pointer if ok, NULL on error
struct dirent * readdir (DIR *dp);
return pointer if ok, NULL at end of directory on error

void rewindir(DIR *dp);


int closedir(DIR *dp);
returns 0 if ok, -1 on error
🡺 direct structure is defined in <dirent.h >

🡺 struct dirent {
ino_t d_ino; /* i_node number */
char d_name [NAME_MAX *1] /* null terminated filename*/
}

🡺 the DIR structure is an internal structure used by these four functions to


maintain information about the directory being read. it serves a purpose similar
to the FILE structure that is maintained by the standard I/O library.

🡺 the pointer to DIR structure that is returned by opendir is the used with other
three functions. opendir initializes things so that the first readdir reads the first
entry in the directory. the ordering of entries within the directory is
implementation dependent. it is usually not alphabetical.

chdir, fchdir and getcwd

🡺 every process has a current working directory.


🡺 this directory is where the search for all relative pathnames starts (all pathnames
that don’t begin with a slash.)
🡺 when a user log into a unix system, the current working directory normally
starts at the directory specified by the sixth field in the /etc/passwd file users
home directory.
🡺 the current working directory is an attribute of a process; the home directory is
an attribute of login name.
🡺 we can change the current working directory of the calling process by calling the
chdir of fchdir function.

#include<unistd.h>
int chdir(const char *pathname);
int fchdir(int filedes);

both returns 0 if ok, -1 on error

we can specify the new current working directory as either a pathname and through
an open file description.

$ pwd
/ usr/lib
$ mycd /* a program which changes current directory to /tmp */
chdir to /tmp suceeded
$ pwd
/usr/lib

why - b/s -->


🡺 note:- for this reason, the chdir function has to be called directly from the shell
(internal command), so the cd command is built into the shells.
🡺 since the kernel must maintain knowledge of the current working directory, which
should be able to fetch it’s current value. unfortunately all that kernel maintains for
each process is the i_node number and device identification for the current working
directory. the kernel doesn’t maintain the full pathname of the directory.
🡺 so we have a function which gets the pathname of the current working directory from
the current working directory i_node (which is available in kernel)
#include<unistd.h>
char *getcwd(char * buf, size_t size);
returns buf if ok, NULL on error

the buf must be large enough to accommodate the absolute pathname plus a
terminating null bytes.

SPECIAL DEVICE FILES

🡺 Every file system is known by it’s major and minor device number. the device
number is encoded in the primitive system datatype dev_t. recall that a disk drive
often contains several file system.
🡺 We can usually access the major and minor device number through two macro
defined by most implementation : major and minor (include <sys/types.h>). this
means we don’t care how the two number are stored in a dev_t object.
🡺 the st_dev value for every file name on a system is the device number of the file
system containing that file name and it’s corresponding i_node.
🡺 Only character special file and block special file have an st_rdev value. this value
contain the device number for the actual device.

sync and fsync Function

#include<unistd.h>
void sync (void );
int fsync (int filedes);
return 0 if ok, -1 on error

Unix implementation have a buffer cache in the kernel through which most disk I/O
passes. when we write data to a file that data is normally copied by the kernel into one of
it’s buffer and queued for I/O at some later time. this is called delayed write.
sync just a queues all the modified block buffer for writing and return; it doesn’t wait for
actual I/O to take place.

🡺 The function sync is normally called every 30 seconds from a system daemon (often
called update). this is guarantees regular flushing of the kernel block buffer.
🡺 The function fsync refers to a single file and wait for the I/O to complete before
returning.

System data files and Information

passwd is defined <pwd.h>


/etc/passwd

Description struct passwd member POSIX.1


user name char *pw_name .
encrypted password char *pw_password
numerical user ID uid_t pw_uid .
numerical group ID gid_t pw_gid .
comment field char *pw_gecos
initial working char *pw_dir .
directory
initial shell (user char *pw_shell .
program)

Fields in /etc/passwd file

root : g1tt3yy8u67kj4 : 0: 1: The superuser :/: /bin/sh


Stevens: d3g4hju76hfkd : 224 :20: Richard stevens : /home/stevens: /bin/ksh

encrypted userid groupid commentfield initial working initial


username password
directory shell

#include<sys/types.h>
#include<pwd.h>
struct passwd *getpwuid (uid_t uid);
struct passwd *getpwnam (const char *name);

both returns pointer if ok, NULL on error

#include<sys/types.h>
#include<pwd.h>
struct passwd *getpwent (void); /* read the next record, open file if not
already
open */
return pointer if ok, NULL on error or end of file.
void setpwent (void); /* open the file and goto the start (first record) of the
file */
void endpwent(void); /* close the file */
Shadow passwd

🡺 /etc/shadow, keeps the password separate in /etc/shadow with say username/id.

🡺 for login, passwd command the set_user_id root is set, so this command can read the
/etc/shadow as the they have root access when they are executing now /etc/passwd
can be left readable to the world.
Group file

/etc/group
<grp.h>
Description single group member
group name char *gr_name
encrypted password char *gr_passwd
numerical group ID int gr_gid
array of pointer to char **gr_mem
individual user name

The field gr_mem is an array of pointer to the usernames that belongs to this group.
the array is terminated by a NULL pointer.

#include<sys/types.h>
#include<grp.h>
struct group *getgrgid(gid_t gid);
struct group *getgrnam (const char *name);
both returns pointers if ok , NULL on error

#include<sys/types.h>
#include<grp.h>
struct group *getgrent (void); /* read the next record, open file if not already
open*/
void setgrent (void); /* open the file and goes to the start (first record) of the
file */
void endgrent (void); /* close the file */

Supplementary Group Ids

Other data file - Similar commands are also available for other data files like
/etc/hosts, /etc/network, /etc/services (service provided by various network server).
/etc/protocols .etc

Description Data file Header Structure Additonal keyed lookup


functions
Passwords /etc/passwd <pwd.h> passwd getpwnam, getpwuid
Groups /etc/group <grp.h> group getgrnam, getgrgid
Hosts /etc/hosts <netdb.h> hostent gethostbyname, gethostbyaddr
Networks /etc/networks <netdb.h> netent getnetbyname, getnetbyaddr
Protocols /etc/protocols <netdb.h> protoent getprotobyname,
getprotobynumber
Services /etc/services <netdb.h> servent getservbyname, getservbyport
Similar routine for accessing system data files

-------------------------Program 5.3--------------shownames.c--------------------------------------
// a program to list files in a directory
#include <dirent.h>
#include <errno.h>
#include <stdio.h>

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


struct dirent *direntp;
DIR *dirp;

if (argc != 2) {
fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
return 1;
}

if ((dirp = opendir(argv[1])) == NULL) {


perror ("Failed to open directory");
return 1;
}

while ((direntp = readdir(dirp)) != NULL)


printf("%s\n", direntp->d_name);
while ((closedir(dirp) == -1) && (errno == EINTR)) ;
return 0;
}

----------------Ex 5.10----------------------------isdirectory.c--------------------------------------
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>

int isdirectory(char *path) {


struct stat statbuf;

if (stat(path, &statbuf) == -1)


return 0;
else
return S_ISDIR(statbuf.st_mode);
}

#include <unistd.h>
int link(const char *path1, const char *path2);
🡪The link function creates a new directory entry for the existing file specified by path1
in the directory specified by path2.
🡪 If successful the link function returns 0. if unsuccessful link returns -1 and sets errno.
#include <unistd.h>
int symlink(const char *path1, const char *path2);
🡪 The path1 parameter of symlink contains the string that will be the contents of the link
and path2 gives the pathname of the link. That is path2 is the newly created link
and path1 is what the new link points to.
🡪 If successful, symlink returns 0. if unsuccessful, synlink returns -1 and sets errorno.
pipes

The capacity to communicate is essential for process that cooperates to solve a problem.
The simplest UNIX inter-process communication mechanism is the pipe, which is
represented by a special file. The pipe function creates a communication buffer
that the caller can access through the file descriptor fildes[0] and fildes[1]. The
data written to fildes[1] can be read from fildes[0] on a first-in-first-out basis.

#include <unistd.h>
int pipe (int fildes[2]);
🡪 if successful pipe returns 0. if unsuccessful pipe returns -1 and sets errorno. (EMFILE,
ENFILE)
🡪 A pipe has no external or permanent name, so a program can access it only through its
two descriptor. For this reason, a pipe can be used only by the process that created
it and by descendents that inherit the descriptors on fork. The pipe function
described here creates a traditional unidirectional communication buffer.
🡪When a process calls read on a pipe, the read returns immediately, if the pipe is not
empty. The read blocks until something is written to the pipe as long as some
process has the pipe open for writing. On the other hand if no process has the pipe
open for writing, a read from an empty pipe returns o, indicating an end-of-file
condition.
🡪A single process with a pipe is not very useful. Usually a parent process uses pipe to
communicate with its children.

--------------Program 6.3------------------simpleredirect.c-------------------------------------
// a program to execute the equivalent of ls –l | sort –n +4
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void) {
pid_t childpid;
int fd[2];

if ((pipe(fd) == -1) || ((childpid = fork()) == -1)) {


perror("Failed to setup pipeline");
return 1;
}

if (childpid == 0) { /* ls is the child */


if (dup2(fd[1], STDOUT_FILENO) == -1)
perror("Failed to redirect stdout of ls");
else if ((close(fd[0]) == -1) || (close(fd[1]) == -1))
perror("Failed to close extra pipe descriptors on ls");
else {
execl("/bin/ls", "ls", "-l", NULL);
perror("Failed to exec ls");
}
return 1;
}
if (dup2(fd[0], STDIN_FILENO) == -1) /* sort is the parent */
perror("Failed to redirect stdin of sort");
else if ((close(fd[0]) == -1) || (close(fd[1]) == -1))
perror("Failed to close extra pipe file descriptors on sort");
else {
execl("/bin/sort", "sort", "-n", "+4", NULL);
perror("Failed to exec sort");
}
return 1;
}

FIFO (named pipes)

Pipes are temporary in the sense that they disappear when no process has them open.
POSIX represents FIFOs or named pipes by special files that persist even after all
processes have closed them. A FIFO has a name and permission just like an
ordinary file and appears in the directory listing given by ls. Any process with
appropriate permissions can access a FIFO. We can create a FIFO by executing
the mkfifo command from a shell or by calling mkfifo function from program.
🡪 The mkfifo function creates a new FIFO special file corresponding to the pathname
specified by path. The mode argument specifies the permission for the newly
created FIFO.

#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);

🡪 if successful, mkfifo returns 0. if unsuccessful, mkfifo returns -1 and sets errorno. A


return value of -1 means that the FIFO was not created.
🡪 Important property of pipes and FIFO 🡪 writes (of no more than PIPE_BUF bytes ) are
guaranteed to be atomic
🡪 When an attempt is made to open a pipe for reading, open blocks until another process
opens the pipe for writing
🡪 If the process opens the pipe for reading and writing both then open does not block
🡪If the process has the pipe open for writing as well as reading then this process will not
detect the end-of-file (while reading from the FIFO)

-----------------------Program 6.7-----------------pipeserver.c--------------------------------------
//the program reads what is written to a named pipe and writes it to standard output
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "restart.h"
#define FIFOARG 1
#define FIFO_PERMS (S_IRWXU | S_IWGRP| S_IWOTH)

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


int requestfd;

if (argc != 2) { /* name of server fifo is passed on the command line */


fprintf(stderr, "Usage: %s fifoname > logfile\n", argv[0]);
return 1;
}
/* create a named pipe to handle incoming requests */
if ((mkfifo(argv[FIFOARG], FIFO_PERMS) == -1) && (errno != EEXIST)) {
perror("Server failed to create a FIFO");
return 1;
}
/* open a read/write communication endpoint to the pipe */
if ((requestfd = open(argv[FIFOARG], O_RDWR)) == -1) {
perror("Server failed to open its FIFO");
return 1;
}
copyfile(requestfd, STDOUT_FILENO);
return 1;
}

--------------Program 6.8-----------------pipeclient.c------------------------------------------------
//the client writes an informative message to a named pipe
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include "restart.h"
#define FIFOARG 1

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


time_t curtime;
int len;
char requestbuf[PIPE_BUF];
int requestfd;

if (argc != 2) { /* name of server fifo is passed on the command line */


fprintf(stderr, "Usage: %s fifoname\n", argv[0]);
return 1;
}

if ((requestfd = open(argv[FIFOARG], O_WRONLY)) == -1) {


perror("Client failed to open log fifo for writing");
return 1;
}

curtime = time(NULL);
snprintf(requestbuf, PIPE_BUF, "%d: %s", (int)getpid(), ctime(&curtime));
len = strlen(requestbuf);
if (r_write(requestfd, requestbuf, len) != len) {
perror("Client failed to write");
return 1;
}
r_close(requestfd);
return 0;
}

-----------------------------------------------------------------------------------------------------------

OSLAB- Printout-1 (process command brief)

#include <unistd.h>
pid_t getpid(void)
pid_t getppid(void)

The getpid and getppid function returns the process ID and the parent process ID
respectively. The pid_t is an unsigned integer type that represents a process ID.
🡪 neither the getpid nor the getppid function can return an error.

🡪 other processes commands 🡪 gid_t getegid(void) (get effective group ID of the


process), uid_t geteuid(void), gid_t getgid (void), uid_t getuid(void)
# chmod u+s xyz //real owner may be naveen.
# ls –l
-rws- -x- -x
now when xyz runs/executed and during execution if this process access a file owned by
other user (say super user) then during execution xyz will enjoy all the privilege of owner
(i.e. in our case super user) in other words it’s effective user id became same as the owner
of the file.passwd command is able to update /etc/passwd file using this mechanism.

fork()

#include <unistd.h>
pid_t fork(void)
A process can create a new process by calling fork. The calling process becomes the
parent and the created process is called the child. The fork function copies the parent’s
memory image so that the new process receives a copy of the address space of the parent.
Both processes continue at the instruction after the fork statement (executing in their
respective memory image).
The fork() function returns 0 to the child and returns the child’s process ID to the parent.
When fork fails, it returns -1 and sets the errorno. If the system does not have the
necessary resources to create the child or if limits on the no. of processes would be
exceeded – fork sets errorno. to EAGAIN. In case of failure the fork does not create a
child.

#include <sys/wait.h>
pid_t wait(int *state_loc);
pid_t waitpid(pid_t pid, int *state_loc, int options);

🡪 The parent can execute wait or waitpid (wait for a particular child) to block itself until
the child finishes.

🡪 The wait function causes the caller to suspend execution until a child’s status become
available (ie child terminates) or until the caller receives a signal.

🡪 if wait or waitpid returns because the status of a child is reported, these function return
the process ID of that child. If an error occurs, these function return -1 and set error no.. if
called with WNOHANG option , waitpid returns 0 to report that the specified child is not
available immediately and so parent will not wait/block.

🡪 some errors are like 🡪 EINTER (function was interrupted by a signal), EINVAL (
option parameter of waitpid was invalid)

exec
The exec family of function provides a facility for overlaying the process image of the
calling process with a new image.

#include <unistd.h>
extern char ** environ;
int execl (const char *path, const char * arg 0, /* ………char * (0) */);
int execle (const char *path, const char *arg 0, /* …………char * (0) , char *const
envp{} */ );
int execlp (const char *file, const char *arg 0, /*………. Char * (0) */);
int execv (const char *path, char *const argv[]);
int execve (const char *path, char *const argv[], char *const envp[]);
int execvp (const char *file, char *const argv[]);

All exec function returns -1 and set errorno. if unsuccessful. In fact if any of these
function return at all, the call was unsuccessful and some errorno. will be set (like
E2BIG, EACCES, EINVAL etc)

🡪 setsid() 🡪 if setsid is set for a process than it does not get any signal because of ctrl c
from the controlling terminal.

You might also like