Operating System Lab Report
Operating System Lab Report
Inter-Process Communication
Objective:
processes to manage shared data. The objective of this lab is to help you
Including:
Shared memory
Pipes
Equipment:
1 Inter-Process communication
address space, which comprises the memory locations that the process is
by other executing processes. Though one can think that those processes,
there are many situations when co-operative nature can be utilized for
mechanism that will allow them to exchange data and information. There
can then exchange information by reading and writing data to the shared
region. In the message-passing model, communication takes place by
2 Experiments
communication
address space.
object successfully.
• Map the shared memory object into the current address space with
establishes a shared memory object and writes to shared memory, and the
You need to write codes that implements a parent and child process
shared memory
The producer process calls shm_open to create and open the shared
shm_fd. After adjusting the size of the shared memory object shm_fd to
the specified size, call mmap to map it to the shared memory area pointed
to by ptr, and the mapping flag Consistent with the flag when the object is
objects.
string name and message0 together into the common memory object. The
consumer program can directly access the shared memory object and
output the content written by the producer after calling shm_open and
mmap.
./shm-posix-producer
./shm-posix-consumer
From the program structure, the producer first writes data to the shared
memory area, and then the consumer utputs the data in the shared
memory area. If the producer keeps inputting data into the shared
Questions:
Solution:
may list them with ls -l /dev/shm. You may also remove a shared
producer– consumer fashion: the producer writes to one end of the pipe
(the write-end) and the consumer reads from the other end (the read-end).
one process writes the message Greetings to the pipe, while the other
process reads this message from the pipe. An ordinary pipe cannot be
accessed from outside the process that created it. Typically, a parent
pipe(int fd[ ])
This function creates a pipe that is accessed through the int fd[] file
descriptors: fd[0] is the read-end of the pipe, and fd[1] is the write-end.
For instance, imagine you are sending a struct type: you have to turn the
struct into a sequence of bytes in order to send them over the pipe.
distinguish where one datum ends and the next one begins. What you use
up to you to define.
Copy the pipes-test.c program from the text book (Page 143) to
another file named pipes.c. Now, modify your new program so that the
parent process read to the pipe content from child process when child
process executed commands.
The program first creates a pipe, and then creates a child process of
the current process through fork(). Then each process closes the file
descriptors that are not needed for the read and write pipes. The child
process executes the "ls -a" command under the current path, and writes
the command execution output to the pipe by copying the pipe write
descriptor fd[1] to standard output; the parent process reads the pipe data
the script runs, abstracted as a file to again make writing scripts &
program easier
default, file descriptor 0 (zero) refers to the standard input & often
You can use dup(2) function to duplicate a file descriptor with the
pipe write descriptor fd[1] by using function dup2 in order to relocate the
standard output.
pipes.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#define BUFFER_SIZE 25
#define READ_END 0
#define WRITE_END 1
int main(void) {
char write_msg[BUFFER_SIZE] = "Greetings";
char read_msg[BUFFER_SIZE];
int fd[2];
pid_t pid;
char EoF = '\0';
if (pipe(fd) == -1) {
fprintf(stderr, "Pipe failed");
return 1;
}
pid = fork();
//Pipe(fd);
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
if (pid > 0) {
//parent process
close(fd[READ_END]);
//printf("%s", write_msg);
for (int i = 0; i < strlen(write_msg); i++) {
write(fd[WRITE_END], &write_msg[i], 1);
}
write(fd[WRITE_END], &EoF, 1);
close(fd[WRITE_END]);
}
else {
//child process
close(fd[WRITE_END]);
printf("read \n");
for (int j = 0; j < strlen(write_msg); j++) {
if (read(fd[READ_END], &read_msg[j], BUFFER_SIZE) >= 0){
read(fd[READ_END], &read_msg[j], BUFFER_SIZE);
printf("%c", read_msg[j]);
}
}
close(fd[READ_END]);
}
return 0;
}
Modify your program so that it defines two pipes: one for communication
from parent to child and another for communication from child to parent.
Make sure to close the correct ends of each pipe. Ultimately, your goal is
to have two pipes, one in each direction, so that you have bi-directional
communication between the two processes. It helps a lot to use names for
the pipes file descriptors that indicate their direction. For instance: p-to-c
and c-to-p tell us the processes that the pipes interconnect and the
second pipe. As the parent reads the characters received from the
child, it prints them to standard out.
Make sure to reason carefully about when the write ends of the two
pipes should be closed, so that your processes can terminate their loops
gracefully and reach their termination state when appropriate. Also, make
sure to use the wrappers defined previously (Fork, Pipe, Read, and
Write).
upper.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <ctype.h>
#define BUFFER_SIZE 25
#define READ_END 0
#define WRITE_END 1
int main(void) {
char write_msg[BUFFER_SIZE] = "Greetings";
char read_msg[BUFFER_SIZE];
int p2c[2];
int c2p[2];
pid_t pid;
char EoF = '\0';
int status;
if (pipe(p2c) == -1) {
fprintf(stderr, "Pipe failed");
return 1;
}
if (pipe(c2p) == -1) {
fprintf(stderr, "Pipe failed");
return 1;
}
pid = fork();
//Pipe(fd);
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
if (pid > 0) {
//parent process
close(p2c[READ_END]);
close(c2p[WRITE_END]);
//printf("%s", write_msg);
for (int i = 0; i < strlen(write_msg); i++) {
write(p2c[WRITE_END], &write_msg[i], BUFFER_SIZE);
}
write(p2c[WRITE_END], &EoF, BUFFER_SIZE);
close(p2c[WRITE_END]);
wait(&status);
//printf("we made it here\n");
for (int c = 0; c < strlen(write_msg); c++) {
//printf("c");
read(c2p[READ_END], &read_msg[c], BUFFER_SIZE);
printf("%c", read_msg[c]);
}
printf("\n");
close(c2p[READ_END]);
}
else {
//child process
close(p2c[WRITE_END]);
close(c2p[READ_END]);
const char *filler;
printf("read\n");
for (int j = 0; j < strlen(write_msg); j++) {
//printf("a");
Questions:
Solution:
communication.
(the read-end).
required.
Solution:
each pipe sending data in a different direction. Pipes are half duplex
transmission is permitted.
Solution:
yes
We used one pipe for one-way communication and two pipes for bi-
and the client, plus the client and the server at the same time) as Named
A named pipe, however, can last as long as the system is up, beyond
named pipe appears as a file and generally processes attach to it for inter-
in C. Once we have created a FIFO special file in this way, any process
can open it for reading or writing, in the same way as an ordinary file.
The following steps outline how to use a named pipe from Linux
programs:
Create a named pipe using the mkfifo() function. Only one of the
processes that use the named pipe needs to do this.
Access the named pipe using the appropriate I/O method such as
open().
Communicate through the pipe with another process using file I/O
functions:
Creating a FIFO file: In order to create a FIFO file, a function calls i.e.
mkfifo is used.
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char
*pathname, mode_t mode);
Requriments:
Owner.
If the message received from the client is not “end”, prints the
back to the client. If the message is “end”, closes the fifo and
“end”, this closes the FIFO and also ends the process.
(reversed string) from the client and prints the reversed string.
// fifo_Server_2way.c
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main() {
int fd;
char readbuf[80];
char end[10];
int to_end;
int read_bytes;
mkfifo(FIFO_FILE, S_IFIFO|0640);
strcpy(end, "end");
fd = open(FIFO_FILE, O_RDWR);
while(1) {
readbuf[read_bytes] = '\0';
readbuf, (int)strlen(readbuf));
if (to_end == 0) {
close(fd);
break;
reverse_string(readbuf);
/*
sleep - This is to make sure other process reads this, otherwise this
*/
sleep(2);
}
return 0;
char temp;
last = strlen(str) - 1;
limit = last/2;
first = 0;
temp = str[first];
str[first] = str[last];
str[last] = temp;
first++;
last--;
return;
is 10
FIFOSERVER: Sending Reversed String: "sCPI XUNIL" and
length is 10
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define FIFO_FILE "/tmp/fifo_twoway"
int main() {
int fd;
int end_process;
int stringlen;
int read_bytes;
char readbuf[80];
char end_str[5];
printf("FIFO_CLIENT: Send messages, infinitely, to end enter \"end\"\n");
fd = open(FIFO_FILE, O_CREAT|O_RDWR);
strcpy(end_str, "end");
while (1) {
printf("Enter string: ");
fgets(readbuf, sizeof(readbuf), stdin);
stringlen = strlen(readbuf);
readbuf[stringlen - 1] = '\0';
end_process = strcmp(readbuf, end_str);
//printf("end_process is %d\n", end_process);
if (end_process != 0) {
write(fd, readbuf, strlen(readbuf));
printf("FIFOCLIENT: Sent string: \"%s\" and string length is %d\n",
readbuf, (int)strlen(readbuf));
read_bytes = read(fd, readbuf, sizeof(readbuf));
readbuf[read_bytes] = '\0';
printf("FIFOCLIENT: Received string: \"%s\" and length is %d\n", readbuf,
(int)strlen(readbuf));
} else {
write(fd, readbuf, strlen(readbuf));
printf("FIFOCLIENT: Sent string: \"%s\" and string length is %d\n",
readbuf, (int)strlen(readbuf));
close(fd);
break;
}
}
return 0;
}
"end"
length is 10
is 10
Questions:
Solution:
send requests through the same named pipe and each request is
response to an ordinary file, closing the file, and then informing the
recipient that the results are available. The receiving process can
Then share a folder between the two, put your FIFO onto the
a port.
named pipe, and for some reason the requestor is not ready to read
the results, the message handler cannot move on to read the next
request.