A Simple way to increase shared memory in Solaris10
By gjl on Jul 05, 2005
Short VersionTo increase the shared memory available to a given user on Solaris 10.
- Find out which project the user is in
- Use prctl to raise the limit e.g. to 200mb, using the project ID returned by id -p.
arches $ id -p uid=90712(garyli) gid=10(staff) projid=10(group.staff) arches $ su Password: # prctl -n project.max-shm-memory -r - v 200mb -i project 10
Long VersionBy default the maximum amount of shared memory that a process can use is around 25% of physical memory. If you try to create a shared memory sgement larger than the allowable limit, you will see an error in the messages file, and the shmget system call will fail with EINVAL.
Jul 4 17:51:53 arches genunix: [ID 883052 kern.notice] privileged rctl project.max-shm-memory (value 195078144) exceeded by project 10For instance, on arches we have only 512Mb
SunOS arches 5.10 s10_43 sun4u sparc SUNW,Ultra-5_10 arches $ prtdiag | head System Configuration: Sun Microsystems sun4u Sun Ultra 5/10 UPA/PCI (UltraSPAR C-IIi 300MHz) System clock frequency: 100 MHz Memory size: 512 MegabytesAnd we can see what the default maximum shared memory segment will be, by using prctl
arches $ prctl -n project.max-shm-memory -i project 10 25758: prctl -n project.max-shm-memory -i project 10 project.max-shm-memory [ no-basic deny ] 128100352 privileged deny 18446744073709551615 system deny [ max ] arches $ bc 128100352/(1024\*1024) 122In the above case we have a maximum of 128100352 (122 mb) which we can allocate using shmat()/shmget()
We can now demonstrate that it is the case, by trying to allocate first 122mb, then 123mb of shared memory. The program shm_var takes a single value as its input, which is the size in Mb of a shared memory segment that we want to create
arches $ ./shm_var 122 Attempting attach of 122 Mb shm base address = F7000000 shmid = 5 shmat time = 1 sec arches $ ./shm_var 123 Attempting attach of 123 Mb shm base address = FFFFFFFF shmid = FFFFFFFF shmat time = 0 secIn the above example, shmat() fails because shmget() returned -1 as the address after it failed to get the shared segment which we asked for. Using truss, we see shmget fail...
shmget(25851, 128974971, 0777|IPC_CREAT) Err#22 EINVALSo, how to change all this is actually quite simple, and can be done on the fly. IMHO the prtctl command doesn't do us any favours with what looks to me like an overy complex syntax. However, here's a cook-book approach.
Firstly, because the shared memory resource is controlled on a project basis, need to know the project to adjust. In the simple case, the project to change will be the project that the user belongs to. So, in the case of an oracle install - su to oracle and issue id -p. Unless you have changed things manually, the project will be '3' 'default'. However, in the example below, my project ID is based on my groupid - so my projectid is 10. Your project id can simply be found by issuing id -p
arches $ id -p uid=90712(garyli) gid=10(staff) projid=10(group.staff)Then we issue the magic prctl command to raise the value
# prctl -n project.max-shm-memory -r -v 200mb -i project 10We can now allocate 200mb, but NOT 201mb
roxy $ ./shm_var 200 Attempting attach of 200 Mb shm base address = F2800000 shmid = 2 shmat time = 1 sec roxy $ ./shm_var 201 Attempting attach of 201 Mb shm base address = FFFFFFFF shmid = FFFFFFFF shmat time = 0 secInterestingly the shmmax limit is cumulative - and so does away with the confusing shmmax, shmseg etc.
roxy $ ./shm_var 100 Attempting attach of 100 Mb shm base address = F8C00000 shmid = 3 shmat time = 0 sec \^Croxy $ ./shm_var 100 Attempting attach of 100 Mb shm base address = F8C00000 shmid = 4 shmat time = 1 sec \^Croxy $ ./shm_var 1 Attempting attach of 1 Mb shm base address = FFFFFFFF shmid = FFFFFFFF shmat time = 0 secNote, that in the above test we did not do a shmdt() between each run of shm_var, and so in ipcs -a we see 200Mb of shared memory across two segments
IPC status fromNotice also that Oracle has 46Mb that is not affected by our allocation (or vice versa)
as of Mon Jul 4 17:59:50 BST 2005 T ID KEY MODE OWNER GROUP CREATOR CGROUP CBYTES QNUM QBYTES LSPID LRPID STIME RTIME CTIME Message Queues: T ID KEY MODE OWNER GROUP CREATOR CGROUP NATTCH SEGSZ CPID LPID ATIME DTIME CTIME Shared Memory: m 4 0x2f8b --rw-rw-rw- garyli staff garyli staff 0 104857600 12171 12171 17:58:16 17:58:18 17:58:15 m 3 0x2f86 --rw-rw-rw- garyli staff garyli staff 0 104857600 12166 12166 17:58:07 17:58:12 17:58:07 m 1 0x43cb9a88 --rw-r----- oracle dba oracle dba 6 46235648 791 809 13:25:22 13:25:53 13:25:14 T ID KEY MODE OWNER GROUP CREATOR CGROUP NSEMS OTIME CTIME Semaphores: s 5 0xe49024ec --ra-r----- oracle dba oracle dba 39 17:56:57 13:25:14 s 1 0x71000b51 --ra-ra-ra- root root root root 1 13:18:56 13:18:34 s 0 0x187cf --ra-ra-ra- root sys root sys 1 13:17:55 13:17:54 roxy $
# su - oracle Sun Microsystems Inc. SunOS 5.10 Generic January 2005 -bash-3.00$ id -p uid=101(oracle) gid=1001(dba) projid=11(user.oracle) -bash-3.00$ prctl -n project.max-shm-memory -i project user.oracle project: 11: user.oracle NAME PRIVILEGE VALUE FLAG ACTION RECIPIENT project.max-shm-memory privileged 186MB - deny - system 16.0EB max denyNotice also I used user.oracle, rather than the project ID, although -i project 11 would have achieved the same thing.