I am trying to understand the shared memory output value of pmap -d <pid>
. Towards this I have done an exercise wherein first I have created 2 shared memory segments.
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
using namespace std;
int main(int argc,char *argv[])
{
if ( argc < 2 ) {
cout<<endl<<"Usage : "<<argv[0]<<" Key(numeric)"<<endl<<endl;
exit(EXIT_FAILURE);
}
// ftok to generate unique key
key_t key = key_t(atoi(argv[1]));
// shmget returns an identifier in shmid
int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
exit(EXIT_FAILURE);
}
cout<<endl<<"Shared memory created with id : "<<shmid<<endl<<endl;
return 0;
}
./CreShm.exe 1000
./CreShm.exe 2000
0x000003e8 32816 soumajit 666 1024 1
0x000007d0 32817 soumajit 666 1024 1
Next I have written a program to attach to the 2 shared memory segments.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
using namespace std;
int main(int argc,char *argv[])
{
if ( argc < 3 ) {
cout<<endl<<"Usage : "<<argv[0]<<" Key1(numeric)"<< " Key2(numeric)"<<endl<<endl;
exit(EXIT_FAILURE);
}
key_t key ;
int shmid ;
struct shmseg *shmp;
key = key_t(atoi(argv[1]));
// shmget returns an identifier in shmid
shmid = shmget(key, 1024, 0644 | IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
exit(EXIT_FAILURE);
}
char* str1;
// shmat to attach to shared memory
str1 = (char*)shmat(shmid, (void*)0, 0);
if (str1 == (void *) -1) {
perror("Shared memory not attached!!");
exit(EXIT_FAILURE);
}
cout<<endl<<"Attached to 1st shared memory segment!!"<<endl;
key = key_t(atoi(argv[2]));
// shmget returns an identifier in shmid
shmid = shmget(key, 1024, 0644 | IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
exit(EXIT_FAILURE);
}
char* str2;
// shmat to attach to shared memory
str2 = (char*)shmat(shmid, (void*)0, 0);
if (str2 == (void *) -1) {
perror("Shared memory not attached!!");
exit(EXIT_FAILURE);
}
cout<<endl<<"Attached to 2nd shared memory segment!!"<<endl;
while(1) {
sleep(1);
}
return 0;
}
Then I have generated output of pmap command.
14652: ./ShmDirectConnector.exe 1000 2000
Address Kbytes Mode Offset Device Mapping
000055c88ba97000 4 r-x-- 0000000000000000 008:00002 ShmDirectConnector.exe
000055c88bc98000 4 r---- 0000000000001000 008:00002 ShmDirectConnector.exe
000055c88bc99000 4 rw--- 0000000000002000 008:00002 ShmDirectConnector.exe
000055c88c64d000 132 rw--- 0000000000000000 000:00000 [ anon ]
00007f20b949c000 92 r-x-- 0000000000000000 008:00002 libgcc_s.so.1
00007f20b94b3000 2044 ----- 0000000000017000 008:00002 libgcc_s.so.1
00007f20b96b2000 4 r---- 0000000000016000 008:00002 libgcc_s.so.1
00007f20b96b3000 4 rw--- 0000000000017000 008:00002 libgcc_s.so.1
00007f20b96b4000 1652 r-x-- 0000000000000000 008:00002 libm-2.27.so
00007f20b9851000 2044 ----- 000000000019d000 008:00002 libm-2.27.so
00007f20b9a50000 4 r---- 000000000019c000 008:00002 libm-2.27.so
00007f20b9a51000 4 rw--- 000000000019d000 008:00002 libm-2.27.so
00007f20b9a52000 1948 r-x-- 0000000000000000 008:00002 libc-2.27.so
00007f20b9c39000 2048 ----- 00000000001e7000 008:00002 libc-2.27.so
00007f20b9e39000 16 r---- 00000000001e7000 008:00002 libc-2.27.so
00007f20b9e3d000 8 rw--- 00000000001eb000 008:00002 libc-2.27.so
00007f20b9e3f000 16 rw--- 0000000000000000 000:00000 [ anon ]
00007f20b9e43000 1508 r-x-- 0000000000000000 008:00002 libstdc++.so.6.0.25
00007f20b9fbc000 2048 ----- 0000000000179000 008:00002 libstdc++.so.6.0.25
00007f20ba1bc000 40 r---- 0000000000179000 008:00002 libstdc++.so.6.0.25
00007f20ba1c6000 8 rw--- 0000000000183000 008:00002 libstdc++.so.6.0.25
00007f20ba1c8000 16 rw--- 0000000000000000 000:00000 [ anon ]
00007f20ba1cc000 156 r-x-- 0000000000000000 008:00002 ld-2.27.so
00007f20ba3cd000 24 rw--- 0000000000000000 000:00000 [ anon ]
00007f20ba3f1000 4 rw-s- 0000000000000000 000:00001 [ shmid=0x8031 ]
00007f20ba3f2000 4 rw-s- 0000000000000000 000:00001 [ shmid=0x8030 ]
00007f20ba3f3000 4 r---- 0000000000027000 008:00002 ld-2.27.so
00007f20ba3f4000 4 rw--- 0000000000028000 008:00002 ld-2.27.so
00007f20ba3f5000 4 rw--- 0000000000000000 000:00000 [ anon ]
00007ffdb0f9f000 132 rw--- 0000000000000000 000:00000 [ stack ]
00007ffdb0fe1000 12 r---- 0000000000000000 000:00000 [ anon ]
00007ffdb0fe4000 4 r-x-- 0000000000000000 000:00000 [ anon ]
ffffffffff600000 4 --x-- 0000000000000000 000:00000 [ anon ]
mapped: 14000K writeable/private: 356K shared: 8K
My question is even though the size of 2 shared memory segments add to 2048 bytes, why does the pmap output show 8K ? Is it because of paging ? If it is attributed to paging, wouldn't 1 page have been sufficient to accommodate both the shared memory segments ? Kindly guide me about the underlying reason.
getconf PAGESIZE
output in my system shows 4096 ?
Your intuition about the page size is correct. The shmget man page says:
A new shared memory segment, with size equal to the value of size rounded up to a multiple of PAGE_SIZE, is created if ...
(So technically this means you did not allocate a 1kb shared memory segment, the actual segment size was rounded up at creation time to 4kb.)
I suspect the motivation is to avoid false sharing (and false corruption). If I have two 1kb shared memory segments, and only gave one of them to a process, I would be very surprised if that process could corrupt or influence the contents of the other shared memory segment.
To keep the segments separate, and separately mappable, each segment must be within its own page-granularity sized region, so the OS can leverage the page-granularity access controls.