LP Unit 3
LP Unit 3
System Calls
UNIT - 3
• Introduction to system calls and file management, Regular file
management system calls – open( ), read(), write(), lseek(),
Close(),unlink( ),stat( ), getdents( ). file management system
calls – chown() and fchown(), chmod() and fchmod( ), dup( )
and dup2( ), fcntl(), ioctl(), link(), mknod(), sync(), truncate( )
and ftruncate( ).
pathname: The path to the file that you want to open. Return Value:
•On success: It returns a file
flags: Specifies the mode in which the file should be opened.
descriptor (a non-negative
O_RDONLY: Open for reading only. integer).
•On failure: It returns -1 and sets
O_WRONLY: Open for writing only.
errno to indicate the error.
O_RDWR: Open for both reading and writing.
O_CREAT: Create the file if it does not exist (requires a third argument mode).
O_TRUNC: Truncate the file to zero length if it already exists.
O_APPEND: Append to the file if it already exists .
mode (optional): permissions for the newly created file (e.g., 0644 for read/write permissions).
Program for open() system call:
#include <stdio.h>
#include <fcntl.h> // For open()
#include <unistd.h> // For close()
int main() {
// Step 1: Open or create the file using open() system call
int fd = open("example.txt", O_RDWR | O_CREAT, 0644);
if (bytes_written == -1) {
perror("Error writing to file");
close(fd);
return 1;
}
printf("Successfully wrote %ld bytes to the file.\n", bytes_written);
unlink() system call
• The unlink() system call is used to delete a file from the file system.
• It removes the directory entry, and if no other process is using the file, the
system will free up the file’s resources.
#include <stdio.h>
#include <unistd.h> // For unlink()
int main()
{
// Step 1: Delete the file "example.txt"
if (unlink("example.txt") == -1)
{
perror("Error deleting file");
return 1; // Return error code
}
int main()
{
// Change owner and group of "example.txt" to UID 1000 and GID 1000
if (chown("example.txt", 1000, 1000) == -1)
{
perror("Error changing ownership");
return 1;
}
In this example, the program prints a message and then terminates with an exit
code of 0. After the exit() call, the process is removed from the active
processes, but before it is fully cleaned up by the system, it may briefly become
a zombie process.
Zombie Process
• A zombie process is a process whose execution is
completed but it still has an entry in the process table.
• Zombie processes usually occur for child processes, as
the parent process still needs to read its child’s exit
status.
• Once this is done using the wait system call, the zombie
process is eliminated from the process table. This is
known as reaping the zombie process.
Zombie Process
Zombie Process
• Behavior of wait
– If the parent process has multiple children, the wait() call will cause the parent to
wait until any child process terminates.
– If a child process terminates, wait() returns the PID of the terminated child.
– If multiple child processes terminate, wait() will reap any one of them arbitrarily and
return its PID.
– If no children exist, wait() immediately returns -1.
waiting for a child – wait( )
•path: The file path to the program that will replace the current
process.
•argv[]: An array of strings (arguments) passed to the new program,
where the last element must be NULL.
•If execv() or any other exec() function is successful, it does not
return. If there is an error, it returns -1.
exec() Family of Functions
Current niceness: 0
New niceness: 5
Accessing User and Group IDs
• Every user in Unix like operating system is identified by a different integer
number, this unique number is called as UserID.
• These IDs determine the permissions and access rights of the process.
• The getuid(), getgid(), geteuid(), and getegid() system calls are used to access
these IDs.
• There are three types of UID defined for a process, which can be dynamically
changed as per the privilege of task.
• The three different types of UIDs defined are :
• 1. Real UserID
• 2. Effective UserID
• 3. Saved UserID
Accessing User and Group IDs
• 1. Real UserID : For a process, Real UserId is simply the UserID of the user
that has started it. It defines which files that this process has access to.
• 2. Effective UserID : It is normally the same as Real UserID, but sometimes it
is changed to enable a non-privileged user to access files that can only be
accessed by a privileged user like root.
• 3. Saved UserID : It is used when a process is running with elevated privileges
(generally root) needs to do some under-privileged work, this can be achieved
by temporarily switching to a non-privileged account.
• While performing under-privileged work, the effective UID is changed to some
lower privilege value, and the euid is saved to saved userID(suid), so that it can
be used for switching back to a privileged account when the task is completed.
Accessing User and Group IDs
Accessing User and Group IDs
• User and Group IDs:
• User ID (UID): A unique identifier for a user. Each user on
the system has a distinct UID.
• Group ID (GID): A unique identifier for a group. Users can
belong to one or more groups, and each group has a distinct
GID.
• Effective User ID (EUID): The UID used by the kernel to
determine the permissions for a process. It can be different
from the real UID when a program is executed with elevated
permissions (e.g., setuid programs).
• Effective Group ID (EGID): The GID used by the kernel to
determine group permissions for a process.
Accessing User and Group IDs
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
uid_t uid, euid;
gid_t gid, egid;
uid = getuid(); Output:
euid = geteuid();
Real UID: 1000
Effective UID: 1000
gid = getgid();
Real GID: 1000
egid = getegid();
Effective GID: 1000
printf("Real UID: %d\n", uid);
printf("Effective UID: %d\n", euid);
printf("Real GID: %d\n", gid);
printf("Effective GID: %d\n", egid);
return 0;
}
Setting User and Group IDs