LP Unit-3 Imp
LP Unit-3 Imp
c
Copy code
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
printf("This is the child process.\n");
} else if (pid > 0) {
printf("This is the parent process.\n");
} else {
printf("Fork failed.\n");
}
return 0;
}
c
Copy code
#include <stdlib.h>
#include <stdio.h>
int main() {
printf("Process is terminating.\n");
exit(0); // Terminates the process
}
c
Copy code
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
signal(SIGINT, handle_signal); // Handle Ctrl+C (SIGINT)
while (1) {
printf("Running...\n");
sleep(1);
}
return 0;
}
c
Copy code
#include <signal.h>
#include <stdio.h>
int main() {
struct sigaction sa;
sa.sa_handler = handle_signal;
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL); // Reliable signal handling
while (1);
return 0;
}
c
Copy code
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid > 0) {
printf("Parent process is terminating.\n");
sleep(2); // Allow child to become orphan
} else if (pid == 0) {
sleep(5); // Child process continues execution
printf("Orphan child process is now adopted by init.\n");
}
return 0;
}
0: Normal termination.
Non-zero: Indicates an error or specific condition.
Example:
c
Copy code
#include <stdio.h>
#include <stdlib.h>
int main() {
if (fork() == 0) {
exit(1); // Child process exits with status 1
} else {
int status;
wait(&status); // Parent waits for child
if (WIFEXITED(status)) {
printf("Child exited with status: %d\n", WEXITSTATUS(status));
}
}
return 0;
}
3) (a) What are the signals that are not ignored or blocked? Explain the reason with an example.
Certain signals like SIGKILL and SIGSTOP cannot be ignored or blocked because they are critical for system
and process management.
c
Copy code
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
signal(SIGINT, handle_signal); // Handle SIGINT (Ctrl+C)
printf("Process running. Try sending SIGINT (Ctrl+C).\n");
while (1) {
sleep(1);
}
return 0;
}
To send SIGKILL:
bash
Copy code
kill -9 <process_id>
4) (a) Differentiate between fork() and vfork().
(b) Write the syntax of six versions of exec functions and explain how these differ from each other.
The exec family of functions replaces the current process image with a new one. The six versions are:
1. execl(): Accepts the path to the program and arguments as a variable-length list.
c
Copy code
execl("/bin/ls", "ls", "-l", NULL);
2. execlp(): Searches for the program in PATH and takes arguments as a list.
c
Copy code
execlp("ls", "ls", "-l", NULL);
c
Copy code
execle("/bin/ls", "ls", "-l", NULL, envp);
c
Copy code
char *args[] = {"ls", "-l", NULL};
execv("/bin/ls", args);
c
Copy code
execvp("ls", args);
c
Copy code
execve("/bin/ls", args, envp);
5) (a) What are process identifiers? Mention the commands for getting different IDs of a calling
process.
A process identifier (PID) is a unique number assigned to a process.
Commands to retrieve process IDs:
getpid(): Retrieves the process ID of the calling process.
getppid(): Retrieves the process ID of the parent process.
getuid(): Retrieves the user ID of the calling process.
getgid(): Retrieves the group ID of the calling process.
c
Copy code
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Program is about to terminate.\n");
exit(0); // Exit with status 0
}
Real ID: The actual user or group ID of the user who owns the process.
Effective ID: The ID used by the process for permission checking, which may differ from the real ID
(e.g., for setuid programs).
(b) What is the need for exec() system call? Write syntax.
The exec() system call replaces the current process image with a new one. This is needed when a process
wants to run a different program without creating a new process.
Syntax:
c
Copy code
int execv(const char *path, char *const argv[]);
c
Copy code
#include <unistd.h>
#include <stdio.h>
int main() {
char *args[] = {"ls", "-l", NULL};
execvp("ls", args); // Replace current process with "ls -l"
printf("This line won't be executed.\n"); // Not executed
return 0;
}
7) (a) What is a zombie process? Write a sample program to explain about a zombie process.
A zombie process is a terminated process whose entry still exists in the process table because its parent has
not yet read its exit status.
Example:
c
Copy code
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
printf("Child process.\n");
exit(0);
} else {
printf("Parent sleeping, child becomes zombie.\n");
sleep(10); // Child becomes zombie
}
return 0;
}
c
Copy code
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd = open("output.txt", O_CREAT | O_WRONLY, 0644);
dup2(fd, STDOUT_FILENO); // Redirect stdout to file
close(fd);
printf("This will be written to the file.\n");
return 0;
}
9) Write a C program that accepts two small numbers as arguments and then sums the two numbers
in a child process. The sum should be returned by the child to the parent as its exit status and the
parent should print the sum.
c
Copy code
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
10) (a) Explain the Data Structures that are affected when a process gets created or deleted.
When a process is created or deleted, the following data structures are affected:
1. Process Table: A table maintained by the OS to store information about each active process, such as
PID, state, and resources used.
2. File Descriptor Table: Contains entries for open files, sockets, and devices used by the process.
3. Memory Table: Tracks the memory allocated to the process, including heap, stack, and code
segments.
4. CPU Scheduling Queue: Processes are added to or removed from queues (e.g., ready, waiting)
during creation or termination.
(b) What is a Zombie Process? What is its significance? Describe with an example.
A zombie process occurs when a child process terminates but its parent process has not yet read its exit
status using wait() or waitpid().
Significance:
o It occupies a slot in the process table, potentially causing a shortage if many zombie
processes accumulate.
o Cleaning up zombies ensures system resources are used efficiently.
Example:
c
Copy code
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
printf("Child process terminating.\n");
exit(0);
} else {
printf("Parent sleeping, creating a zombie process.\n");
sleep(10); // During this time, the child is a zombie
wait(NULL); // Reap the child
printf("Zombie process reaped.\n");
}
return 0;
}
11) (a) Define Signals. What do you mean by Unreliable Signals? Explain.
Signals: Signals are software interrupts delivered to a process to notify it of events like termination,
division by zero, or timer expiry.
Unreliable Signals: Earlier UNIX systems did not queue signals. If multiple signals of the same type
arrived before the process handled the first one, subsequent signals were lost. This is considered
unreliable behavior.
c
Copy code
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main() {
signal(SIGINT, handle_signal); // Register handler for SIGINT
while (1) {
printf("Running...\n");
sleep(1);
}
return 0;
}
In this program, pressing Ctrl+C triggers the handle_signal function instead of terminating the process.
12) Explain the following system calls with clear syntax and examples:
(a) fork()
Creates a new process (child) by duplicating the parent process.
Syntax:
c
Copy code
pid_t fork(void);
Example:
c
Copy code
pid_t pid = fork();
if (pid == 0)
printf("Child process.\n");
else
printf("Parent process.\n");
(b) wait()
Waits for a child process to terminate and retrieves its exit status.
Syntax:
c
Copy code
pid_t wait(int *status);
Example:
c
Copy code
pid_t pid = fork();
if (pid == 0)
exit(0); // Child exits
else {
wait(NULL); // Parent waits for child
printf("Child terminated.\n");
}
(c) exec()
Replaces the current process with a new program.
Syntax:
c
Copy code
int execv(const char *path, char *const argv[]);
Example:
c
Copy code
char *args[] = {"ls", "-l", NULL};
execvp("ls", args);
Syntax:
c
Copy code
void (*signal(int signum, void (*handler)(int)))(int);
Example:
c
Copy code
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main() {
signal(SIGTERM, handle_signal); // Handle termination signal
while (1) {
printf("Running...\n");
sleep(1);
}
return 0;
}
Part-2:
1. What is message queue? Explain with example.
Answer:
A message queue is an IPC mechanism that allows processes to communicate by sending and receiving
messages asynchronously. It provides a way to exchange data safely between processes.
Example:
Answer:
FIFO (First In First Out), or named pipe, is a type of IPC that provides a bidirectional communication
channel between processes.
Example:
Create FIFO:
bash
Copy code
mkfifo myfifo
In one terminal:
bash
Copy code
echo "Hello" > myfifo
In another terminal:
bash
Copy code
cat < myfifo
3(a). Write a program to simulate sleep and wakeup behaviors among two processes using
any IPC mechanisms.
Answer:
Using pipes:
c
Copy code
#include <stdio.h>
#include <unistd.h>
int main() {
int fd[2];
pipe(fd);
if (fork() == 0) {
close(fd[0]); // Close reading end
sleep(2); // Simulate sleep
write(fd[1], "Wake up!", 8);
close(fd[1]);
} else {
char buffer[10];
close(fd[1]); // Close writing end
read(fd[0], buffer, sizeof(buffer));
printf("Message: %s\n", buffer);
close(fd[0]);
}
return 0;
}
Answer:
The mkfifo() system call creates a named pipe.
Example:
c
Copy code
#include <stdio.h>
#include <sys/stat.h>
int main() {
mkfifo("myfifo", 0666);
printf("FIFO created.\n");
return 0;
}
Answer:
Pipes provide a unidirectional data flow between two processes, where one process writes data to the pipe,
and the other reads it.
bash
Copy code
command1 | command2 | command3
5. What are pipes? Explain their limitations. Explain how pipes are created and used in
IPC with examples.
Answer:
c
Copy code
#include <stdio.h>
#include <unistd.h>
int main() {
int fd[2];
pipe(fd);
if (fork() == 0) {
close(fd[0]);
write(fd[1], "Hello", 6);
close(fd[1]);
} else {
char buffer[6];
close(fd[1]);
read(fd[0], buffer, 6);
printf("Message: %s\n", buffer);
close(fd[0]);
}
return 0;
}
Answer:
c
Copy code
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msg_buffer {
long msg_type;
char msg_text[100];
} message;
int main() {
key_t key = ftok("progfile", 65);
int msgid = msgget(key, 0666 | IPC_CREAT);
message.msg_type = 1;
sprintf(message.msg_text, "Hello");
msgsnd(msgid, &message, sizeof(message), 0);
6(b). What is meant by namespace? Give the namespaces of various IPC mechanisms in
Unix.
Answer:
Namespace is a way to isolate resources for processes in Unix.
Answer:
Pipes:
o Unidirectional.
o Temporary and limited to related processes.
Message Queues:
o Bidirectional.
o Persistent across processes.
o Allows asynchronous communication.
8. Write a program and explain how to transfer a large amount of data between two
processes using:
(a) Pipes:
Use a loop to write/read large data in chunks.
(b) Message Queues:
Use a loop to send/receive messages in parts using msgsnd and msgrcv.
9(a). What are the security problems associated with System V IPC mechanisms?
Answer:
c
Copy code
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
char *fifo = "myfifo";
mkfifo(fifo, 0666);
if (fork() == 0) {
// Client
int fd = open(fifo, O_WRONLY);
write(fd, "Hello Server", 13);
close(fd);
} else {
// Server
char buffer[20];
int fd = open(fifo, O_RDONLY);
read(fd, buffer, 20);
printf("Received: %s\n", buffer);
close(fd);
}
return 0;
}
Answer:
A coprocess is a subprocess that communicates with its parent process using IPC.
Example:
Using popen to execute a shell command:
c
Copy code
#include <stdio.h>
int main() {
FILE *fp = popen("ls", "r");
char buffer[100];
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}
pclose(fp);
return 0;
}
Answer:
The O-NDELAY flag ensures non-blocking I/O, so read or write operations do not block the process if no
data is available.
Answer:
Processes communicate to share data, synchronize, and coordinate tasks.
Answer:
Answer: