Please answer the following questions: Consider the given code: 1. Rename the sh
ID: 3736145 • Letter: P
Question
Please answer the following questions:
Consider the given code:
1. Rename the shared memory partition “/brs_memory” to your “username_memory”.
2. Figure out how to compile this code.
3. Execute this code and explain what is it doing.
4. What are the command line parameters doing in this code?
Code:
int *mem;
int main ( int argc, char **argv )
{
int i, pid, kids, shmfd;
kids = argc > 1 ? atoi(argv[1]) : 5;
shmfd = shm_open ( "/brs_memory", O_RDWR | O_CREAT, 0666 );
if ( shmfd < 0 ) {
fprintf(stderr,"Could not create brs_memory ");
exit(1);
}
ftruncate ( shmfd, kids*sizeof(int) );
mem = (int *)mmap ( NULL, kids*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0 );
if ( mem == NULL ) {
fprintf(stderr,"Could not map brs_memory ");
exit(1);
}
close ( shmfd );
shm_unlink ( "/brs_memory" );
for ( i = 0; i < kids; i++ ) mem[i] = i+1;
for ( i = 0; i < kids; i++ ) {
pid = fork();
if ( pid < 0 ) {
fprintf(stderr,"fork failed at %d ",i);
exit(1);
} else if ( pid > 0 ) {
printf("parent: new child is %d ",pid);
} else {
usleep ( 1000 );
printf("child %d, parent is %d ",i, getppid());
mem[i] = mem[i] * mem[i];
exit(0);
}
}
for ( i = 0; i < kids; i++ ) wait(NULL);
for ( i = 0; i < kids; i++ ) printf("mem[%d] = %d ",i,mem[i]);
return 0;
}
Explanation / Answer
/*****************************************PART 1*******************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
//given below headers used shared memory IPC
#include <sys/ipc.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>// for ftruncate;
/*
*
*/
int *mem;
int main ( int argc, char **argv )
{
int i, pid, kids, shmfd;
printf("argc : %d ",argc);
kids = argc > 1 ? atoi(argv[1]) : 5;
shmfd = shm_open ( "/username_memory", O_RDWR | O_CREAT, 0666 );
/*int shm_open(const char *name, int oflag, mode_t mode);
* shm_open() creates and opens a new, or opens an existing, POSIX
shared memory object.A POSIX shared memory object is in effect a
handle which can be used by unrelated processes to mmap(2) the same
region of shared memory. The shm_unlink() function performs the
converse operation, removing an object previously created by
shm_open().
*
* const char *name
specifies the shared memory object to be created or opened.
*
* int oflag
* is a bit mask created by ORing together exactly one of O_RDONLY
or O_RDWR and any of the other flags listed here:
*
* O_RDWR Open the object for read-write access.
O_CREAT Create the shared memory object if it does not exist. The
user and group ownership of the object are taken from the
corresponding effective IDs of the calling process, and
the object's permission bits are set according to the low-
order 9 bits of mode, except that those bits set in the
process file mode creation mask (see umask(2)) are cleared
for the new object. A set of macro constants which can be
used to define mode is listed in open(2). (Symbolic
definitions of these constants can be obtained by
including <sys/stat.h>.)
*/
if ( shmfd < 0 ) {
fprintf(stderr,"Could not create brs_memory ");
exit(1);
}
ftruncate ( shmfd, kids*sizeof(int) );
/*
The truncate() and ftruncate() functions cause the regular file named by path or referenced by fd to be truncated to a size of precisely length bytes.
If the file previously was larger than this size, the extra data is lost. If the file previously was shorter, it is extended, and the extended part reads as null bytes ('').
The file offset is not changed.
*/
mem = (int *)mmap ( NULL, kids*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0 );
/*
* mmap() creates a new mapping in the virtual address space of the
calling process. The starting address for the new mapping is
specified in addr. The length argument specifies the length of the
mapping (which must be greater than 0).
If addr is NULL, then the kernel chooses the address at which to
create the mapping; this is the most portable method of creating a
new mapping. If addr is not NULL, then the kernel takes it as a hint
about where to place the mapping; on Linux, the mapping will be
created at a nearby page boundary. The address of the new mapping is
returned as the result of the call.
*/
if ( mem == NULL ) {
fprintf(stderr,"Could not map brs_memory ");
exit(1);
}
close ( shmfd );
shm_unlink ( "/brs_memory" );
/*
The shm_unlink() function shall remove the name of the shared memory object named by the string pointed to by name.
If one or more references to the shared memory object exist when the object is unlinked, the name shall be removed before shm_unlink() returns, but the removal of the memory object contents shall be postponed until all open and map references to the shared memory object have been removed.
Even if the object continues to exist after the last shm_unlink(), reuse of the name shall subsequently cause shm_open() to behave as if no shared memory object of this name exists (that is, shm_open() will fail if O_CREAT is not set, or will create a new shared memory object if O_CREAT is set).
*/
for ( i = 0; i < kids; i++ ) mem[i] = i+1;
for ( i = 0; i < kids; i++ ) {
pid = fork();
if ( pid < 0 ) {
fprintf(stderr,"fork failed at %d ",i);
exit(1);
} else if ( pid > 0 ) {
printf("parent: new child is %d ",pid);
} else {
usleep ( 1000 );
printf("child %d, parent is %d ",i, getppid());
mem[i] = mem[i] * mem[i];
//changing share memory variable
exit(0);
}
}
for ( i = 0; i < kids; i++ ) wait(NULL);
for ( i = 0; i < kids; i++ ) printf("mem[%d] = %d ",i,mem[i]);
return 0;
}
/*****************************************PART 2*******************************/
gcc -o a.out main.c -lrt -lpthread
/*****************************************PART 3*******************************/
In the given code illustrates an example of shared memory concept which comes under IPC(Inter process communication).
The API used in the code has been explained in the comment section.
In given code we are creating shared by using shm_open() api, after creating shared memory by using ftruncate we were defining the fixed size to shared memory.
by using mmap creates a new mapping in the virtual address space of the calling process.
After creating and giving space to shared memory we closed the file discriptor of shared memory;
The shm_unlink() function shall remove the name of the shared memory object named by the string pointed to by name.
If one or more references to the shared memory object exist when the object is unlinked, the name shall be removed before shm_unlink() returns, but the removal of the memory object contents shall be postponed until all open and map references to the shared memory object have been removed.
Even if the object continues to exist after the last shm_unlink(), reuse of the name shall subsequently cause shm_open() to behave as if no shared memory object of this name exists (that is, shm_open() will fail if O_CREAT is not set, or will create a new shared memory object if O_CREAT is set).
Now,
by using for loop we assgin the values to share memory;
Fork() , system call fork() is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller. After a new child process is created, both processes will execute the next instruction following the fork() system call. Therefore, we have to distinguish the parent from the child. This can be done by testing the returned value of fork():
If fork() returns a negative value, the creation of a child process was unsuccessful.
fork() returns a zero to the newly created child process.
fork() returns a positive value, the process ID of the child process, to the parent. The returned process ID is of type pid_t defined in sys/types.h. Normally, the process ID is an integer. Moreover, a process can use function getpid() to retrieve the process ID assigned to this process.
If the call to fork() is executed successfully, Unix will
make two identical copies of address spaces, one for the parent and the other for the child.
Both processes will start their execution at the next statement following the fork() call. In this case, both processes will start their execution at the assignment statement.
for more detail follow this link : http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html
Now we got about fork(),
if we change the value of simple variable in the child process which is defined in the parent process then changed varible value in the child process will not affect the variable value in the parent process. because both the processess has identical but seprate address space.
but if we do changes in shared memory by child process that will reflect in parent process because by using shared memory we can communicate among two process.
therefore the output of shared memory variable(i.e, mem) is changed in parent process while printng it.
/*****************************************PART 4*******************************/
argv and argc are how command line arguments are passed to main() in C and C++.
argc will be the number of strings pointed to by argv. This will (in practice) be 1 plus the number of arguments, as virtually all implementations will prepend the name of the program to the array.
The variables are named argc (argument count) and argv (argument vector) by convention, but they can be given any valid identifier: int main(int num_args, char** arg_strings) is equally valid.
They can also be omitted entirely, yielding int main(), if you do not intend to process command line arguments.
Try the following program:
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Have " << argc << " arguments:" << std::endl;
for (int i = 0; i < argc; ++i) {
std::cout << argv[i] << std::endl;
}
}
Running it with ./test a1 b2 c3 will output
Have 4 arguments:
./test
a1
b2
c3