Fortunately, as a good Unix system, Solaris supports easy daemon creation by encapsulating all the necessary steps into a single system function called daemon(3C). Thus the whole process of becoming a daemon is greatly simplified when compared to the traditional / legacy approach:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cerrno>
#include <cstdlib>
#include <cstdarg>
#include "toolbox.hxx"
void error( toolbox::log & log, const char * message )
{
int code = errno;
log.write( "ERROR: %s (%d)\n", message, code );
::exit( EXIT_FAILURE );
}
int main( )
{
toolbox::log log( "trace.log" );
if ( ! log.open() )
return EXIT_FAILURE;
log.write( "Starting up...\n" );
if ( ::daemon( 0, 0 ) < 0 )
error( log, "Couldn't become a daemon." );
log.write( "Successfully became a daemon!\n" );
::umask( 0 );
const int seconds = 30;
log.write( "Resting for %d seconds...\n", seconds );
::sleep( seconds );
log.write( "Bye cruel world!\n\n" );
log.close();
return EXIT_SUCCESS;
}
A typical log output could be similar to:
$ cat trace.log
[2017-05-12 16:29:11] Starting up...
[2017-05-12 16:29:11] Successfully became a daemon!
[2017-05-12 16:29:11] Resting for 30 seconds...
[2017-05-12 16:29:41] Bye cruel world!
It may be interesting to take a look under the hood at the system calls encapsulated by daemon(3C) in order to compare it with the traditional / legacy approach:
$ truss -f ./daemon-01
...
... getcwd("/...", 1024) = 0
... open("/.../trace.log", O_WRONLY|O_APPEND|O_CREAT, 0640) = 3
...
3155: write(3, " [ 2 0 1 7 - 0 5 - 1 2 ".., 22) = 22
3155: write(3, " S t a r t i n g u p .".., 15) = 15
...
3155: forkx(0) = 3156
3155: _exit(0)
...
3156: forkx() (returning as child ...) = 3155
3156: getpid() = 3156 [3155]
...
3156: setsid() = 3156
...
3156: forkx(0) = 3158
3156: _exit(0)
...
3158: forkx() (returning as child ...) = 3156
3158: getpid() = 3158 [1]
...
3158: chdir("/") = 0
...
3158: open("/dev/null", O_RDWR) = 4
3158: fcntl(4, F_DUP2FD, 0x00000000) = 0
3158: fcntl(4, F_DUP2FD, 0x00000001) = 1
3158: fcntl(4, F_DUP2FD, 0x00000002) = 2
3158: close(4) = 0
...
3158: write(3, " [ 2 0 1 7 - 0 5 - 1 2 ".., 22) = 22
3158: write(3, " S u c c e s s f u l l y".., 30) = 30
...
3158: umask(0) = 022
...
3158: write(3, " [ 2 0 1 7 - 0 5 - 1 2 ".., 22) = 22
3158: write(3, " R e s t i n g f o r ".., 26) = 26
3158: nanosleep(...) (sleeping...)
3158: nanosleep(...) = 0
...
3158: write(3, " [ 2 0 1 7 - 0 5 - 1 2 ".., 22) = 22
3158: write(3, " B y e c r u e l w o".., 18) = 18
3158: close(3) = 0
...
3158: _exit(0)
Personal notes and recipes, views and opinions.
If it must run, it runs on Solaris!
Showing posts with label IPC. Show all posts
Showing posts with label IPC. Show all posts
Thursday, May 11, 2017
Daemons - 1st steps
In the very start of the endeavor to the daemons' underground world I thought it would be inevitable to be acquainted with a few, perhaps new, essential concepts about processes in terms of how they are collected within the system. So I set out to knowing more about sessions and process groups. It was very instructive as a ground to better undrestanding the necessary steps to turn an ordinary process into a daemon in the traditional way. So, without further words, in essence, the main() function of a Solaris C++ program (or application) that is (or becomes) a daemon in the traditional way is:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <csignal>
#include <cstdlib>
#include <cstdio>
#include <cstdarg>
#include <string>
#include <iostream>
#include "toolbox.hxx"
int main()
{
// Some other log file or even syslog could be better.
// This is just for illustrational purposes.
// The full implementation is elsewhere.
toolbox::log log( "trace.log" );
if ( log.open() )
std::cout
<< "Log file: "
<< log.filename
<< std::endl;
else
{
std::cout
<< "FAILURE"
<< std::endl;
::exit( EXIT_FAILURE );
}
// This function does all the "magic"!
daemon( log );
log.write( "Finally, success! I'm a daemon!\n" );
const int seconds = 30;
log.write( "Resting for %d seconds...\n", seconds );
::sleep( seconds );
log.write( "Bye cruel world!\n\n" );
log.close();
return EXIT_SUCCESS;
}
Now let me show the magical :-) daemon() function:
// Little helper...
void error( const toolbox::log & log, const char * msg, ... )
{
int code = errno;
va_list ap;
va_start( ap, msg );
// MT-safe if setlocale(3C) not called
// Hence, possbily a serious limitation!
// More advanced C++ to the rescue!
char * buffer = 0;
::vasprintf( &buffer, msg, ap );
log.write( "ERROR: %s (%s)\n", buffer, ::strerror(code) );
::free( buffer );
va_end( ap );
::exit( EXIT_FAILURE );
}
void daemon( toolbox::log & log )
{
if ( ! log.write( "\n\nTrying to \"become\" daemon ...\n\n" ) )
::exit( EXIT_FAILURE );
pid_t pid;
// Creates a new process in the same process group.
// Sure is the new process is NOT a process group leader.
// The new process will be entitled to create a new session.
if ( ( pid = ::fork() ) < 0 )
error( log, "1st call to fork()" );
else if ( pid > 0 )
{
log.write( "Bye 1st generation descendant!\n" );
log.write( "PID %d to become a daemon!\n\n", pid );
::exit( EXIT_SUCCESS );
}
// Creates a new session, effectively
// disassociating from the controlling terminal.
if ( ::setsid() < 0 )
error( log, "setsid()" );
// The SIGHUP does not apply to me anymmore.
// There's no controlling terminal after all!
if ( ::sigignore( SIGHUP ) )
error( log, "sigignore()" );
// Creates another new process in the new process group.
// Sure is the new process is NOT a process group leader.
// The new process won't EVER get a controlling terminal.
if ( ( pid = ::fork() ) < 0 )
error( log, "2nd call to fork()" );
else if ( pid > 0 )
{
log.write( "Bye 2nd generation descendant!\n" );
log.write( "PID %d to become a daemon!\n\n", pid );
::exit( EXIT_SUCCESS );
}
//
// Finally! Almost there...
//
// Initially assures full access to daemon's own files.
// Later, should be diligently and temporarily set to 007,
// specially before library calls that involve files.
::umask( 0 );
// Changes to the selected working directory
// or at least to / so any unmounts should succeed.
// After this call don't forget to specify full paths!
if ( ::chdir( "/" ) < 0 )
error( log, "chdir()" );
{
// Makes sure there's no left over open files.
log.close();
::fcloseall();
// Mute all the standard files.
const int std_stream[] =
{
::open( "/dev/null", O_RDWR ), // stdin
::dup2( 0, 1 ), // stdout
::dup2( 0, 2 ) // stderr
};
if ( ! log.open() )
exit( EXIT_FAILURE );
// Double-check muted descriptors are 0, 1 and 2.
for ( auto i=0; i<3; i++ )
if ( std_stream[ i ] != i )
error( log, "Muting standard files." );
}
}
A log file produced by running this daemon could be:
$ cat trace.log
[2017-05-11 16:29:29]
Trying to "become" daemon ...
[2017-05-11 16:29:29] Bye 1st generation descendant!
[2017-05-11 16:29:29] PID 2508 to become a daemon!
[2017-05-11 16:29:29] Bye 2nd generation descendant!
[2017-05-11 16:29:29] PID 2509 to become a daemon!
[2017-05-11 16:29:29] Finally, success! I'm a daemon!
[2017-05-11 16:29:29] Resting for 30 seconds...
[2017-05-11 16:29:59] Bye cruel world!
The above approach, although traditional is not the recommended one. Nevertheless it's still possible to catch once in a while some daemons logs in SMF logs which reveal they could only have been programmed the old way...
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <csignal>
#include <cstdlib>
#include <cstdio>
#include <cstdarg>
#include <string>
#include <iostream>
#include "toolbox.hxx"
int main()
{
// Some other log file or even syslog could be better.
// This is just for illustrational purposes.
// The full implementation is elsewhere.
toolbox::log log( "trace.log" );
if ( log.open() )
std::cout
<< "Log file: "
<< log.filename
<< std::endl;
else
{
std::cout
<< "FAILURE"
<< std::endl;
::exit( EXIT_FAILURE );
}
// This function does all the "magic"!
daemon( log );
log.write( "Finally, success! I'm a daemon!\n" );
const int seconds = 30;
log.write( "Resting for %d seconds...\n", seconds );
::sleep( seconds );
log.write( "Bye cruel world!\n\n" );
log.close();
return EXIT_SUCCESS;
}
Now let me show the magical :-) daemon() function:
// Little helper...
void error( const toolbox::log & log, const char * msg, ... )
{
int code = errno;
va_list ap;
va_start( ap, msg );
// MT-safe if setlocale(3C) not called
// Hence, possbily a serious limitation!
// More advanced C++ to the rescue!
char * buffer = 0;
::vasprintf( &buffer, msg, ap );
log.write( "ERROR: %s (%s)\n", buffer, ::strerror(code) );
::free( buffer );
va_end( ap );
::exit( EXIT_FAILURE );
}
void daemon( toolbox::log & log )
{
if ( ! log.write( "\n\nTrying to \"become\" daemon ...\n\n" ) )
::exit( EXIT_FAILURE );
pid_t pid;
// Creates a new process in the same process group.
// Sure is the new process is NOT a process group leader.
// The new process will be entitled to create a new session.
if ( ( pid = ::fork() ) < 0 )
error( log, "1st call to fork()" );
else if ( pid > 0 )
{
log.write( "Bye 1st generation descendant!\n" );
log.write( "PID %d to become a daemon!\n\n", pid );
::exit( EXIT_SUCCESS );
}
// Creates a new session, effectively
// disassociating from the controlling terminal.
if ( ::setsid() < 0 )
error( log, "setsid()" );
// The SIGHUP does not apply to me anymmore.
// There's no controlling terminal after all!
if ( ::sigignore( SIGHUP ) )
error( log, "sigignore()" );
// Creates another new process in the new process group.
// Sure is the new process is NOT a process group leader.
// The new process won't EVER get a controlling terminal.
if ( ( pid = ::fork() ) < 0 )
error( log, "2nd call to fork()" );
else if ( pid > 0 )
{
log.write( "Bye 2nd generation descendant!\n" );
log.write( "PID %d to become a daemon!\n\n", pid );
::exit( EXIT_SUCCESS );
}
//
// Finally! Almost there...
//
// Initially assures full access to daemon's own files.
// Later, should be diligently and temporarily set to 007,
// specially before library calls that involve files.
::umask( 0 );
// Changes to the selected working directory
// or at least to / so any unmounts should succeed.
// After this call don't forget to specify full paths!
if ( ::chdir( "/" ) < 0 )
error( log, "chdir()" );
{
// Makes sure there's no left over open files.
log.close();
::fcloseall();
// Mute all the standard files.
const int std_stream[] =
{
::open( "/dev/null", O_RDWR ), // stdin
::dup2( 0, 1 ), // stdout
::dup2( 0, 2 ) // stderr
};
if ( ! log.open() )
exit( EXIT_FAILURE );
// Double-check muted descriptors are 0, 1 and 2.
for ( auto i=0; i<3; i++ )
if ( std_stream[ i ] != i )
error( log, "Muting standard files." );
}
}
A log file produced by running this daemon could be:
$ cat trace.log
[2017-05-11 16:29:29]
Trying to "become" daemon ...
[2017-05-11 16:29:29] Bye 1st generation descendant!
[2017-05-11 16:29:29] PID 2508 to become a daemon!
[2017-05-11 16:29:29] Bye 2nd generation descendant!
[2017-05-11 16:29:29] PID 2509 to become a daemon!
[2017-05-11 16:29:29] Finally, success! I'm a daemon!
[2017-05-11 16:29:29] Resting for 30 seconds...
[2017-05-11 16:29:59] Bye cruel world!
The above approach, although traditional is not the recommended one. Nevertheless it's still possible to catch once in a while some daemons logs in SMF logs which reveal they could only have been programmed the old way...
Saturday, April 22, 2017
Sessions & Process Groups
In the very start of the endeavor to the daemons' underground world it's inevitable to be acquainted with a few, perhaps new, essential concepts about processes in terms of how they are collected within the system.
Without further digressions, processes are collected into process groups. But there's an elaboration on top of this leading to another concept called sessions, which is associated to the historical concept of job control from a time lacking the pletora of GUI terminals if not, perhaps, just the rare and crude xterm which some ancient seems to inconditionally love.
Although not really a big mistery, the descriptions about these concepts (process groups, sessions and their related) seems unecessarily convoluted in Intro(2) and termio(7I), which can partially obfuscate understanding its central apparatus. My intention is, thus, to address these obstacules by attempting to streamline some ideas and clarify some of these concepts definitions and descriptions:
PROCESS GROUP
As for a real world example of a few of these concepts in action applied to a daemon creation you may be interested in browsing the output from truss applied to a sample daemon creation code around the fork() and setsid() system calls and associated PIDs and PPIDs numbers.
Without further digressions, processes are collected into process groups. But there's an elaboration on top of this leading to another concept called sessions, which is associated to the historical concept of job control from a time lacking the pletora of GUI terminals if not, perhaps, just the rare and crude xterm which some ancient seems to inconditionally love.
Although not really a big mistery, the descriptions about these concepts (process groups, sessions and their related) seems unecessarily convoluted in Intro(2) and termio(7I), which can partially obfuscate understanding its central apparatus. My intention is, thus, to address these obstacules by attempting to streamline some ideas and clarify some of these concepts definitions and descriptions:
PROCESS GROUP
A collection of processes that begins when created by a given process which is thereof defined as its process group leader. The process group ends when the last process in the process group ends of leaves the process group.SESSION
During its lifetime it's uniquely identified by a positive integer called the process group ID (PGID), which exactly matches the process ID (PID) of its process group leader and furnishes a way of signaling all its member processes as a whole.
Any process that is not a process group leader may create a new process group or a new session (becoming itself the process group leader and, eventually, the session leader of the newly created entity) or yet may join another process group in the same session.
Each process in the system is a member of a single process group and every newly created process joins the process group and session of its parent (process).
A collection of process groups that begins when created by a given process which is thereof defined as its session leader. The session ends when the last process in the session ends of leaves the session.
During its lifetime it's uniquely identified by a positive integer called the session ID (SID), which exactly matches the process ID (PID) of its original session leader. The original session leader is also the process group leader for the session's originally first process group, hence its process ID (PID) matches its session ID (SID) and its process group ID (PGID) and, as such, the session ID (SID) also matches its originally first process group ID (PGID).
A session is capable of being biunivocally (one-to-one) associated to a terminal (the controlling terminal, /dev/tty according to tty(7D)) by the session leader (the controlling process) which establishes the connection. As sessions are inherited by new processes created within it, so are the controlling terminals, although this association can be broken if these new processes establish a new session (setsid(2)). The controlling terminal can send/handle certain (typically quit and interrupt) signals to the process groups in the (controlling process') session that, in general, will cause them to stop, unless they have made arrangements to mask this out or are orphaned process groups.
Orphaned process groups are those that share the controlling terminal but whose processes' parents do not belong to any other process group in the same session.
Among the process groups in the session, the controlling terminal will distinguish one of them as the foreground process group, thereby exclusively granting it certain terminal access prerrogatives, and treat all the other process groups in that (controlling process') session as background process groups. By default, the controlling process' (session leader's) process group is assigned as the foreground process group.
As for a real world example of a few of these concepts in action applied to a daemon creation you may be interested in browsing the output from truss applied to a sample daemon creation code around the fork() and setsid() system calls and associated PIDs and PPIDs numbers.
Friday, April 21, 2017
Daemons listing
Without entering into any further detail about what a daemon is, I'll just show how to list them under a privileged (root) Solaris terminal by means of the standard shell command ps(1):
# ps -o user,uid,pid,ppid,pgid,sid,tty,args -t '?' \
|(IFS=''; read H; echo "$H"; sort -k5 -k3 \
|grep filtering_options account )
USER UID PID PPID PGID SID TT COMMAND
root 0 1 0 0 0 ? /usr/sbin/init
root 0 3 0 0 0 ? fsflush
root 0 7 0 0 0 ? intrd
root 0 6 0 0 0 ? kmem_task
root 0 2 0 0 0 ? pageout
root 0 9 0 0 0 ? postwaittq
root 0 0 0 0 0 ? sched
root 0 8 0 0 0 ? vmtasks
root 0 770 0 0 0 ? zpool-depot
root 0 788 0 0 0 ? zpool-export
root 0 5 0 0 0 ? zpool-rpool
root 0 96 1 13 13 ? /lib/svc/bin/...
root 0 13 1 13 13 ? /lib/svc/bin/svc.startd
root 0 751 1 13 13 ? /lib/svc/method/iscsid
root 0 1862 1353 13 13 ? /usr/lib/...
root 0 1353 1341 13 13 ? /usr/lib/...
root 0 106 1 13 13 ? /usr/lib/pfexecd
root 0 155 1 13 13 ? /usr/lib/rad/rad -sp
root 0 164 1 13 13 ? /usr/lib/rad/rad -sp
root 0 1341 1 13 13 ? /usr/sbin/gdm-binary
root 0 15 1 15 15 ? /lib/svc/bin/...
netcfg 17 42 1 42 42 ? /lib/inet/netcfgd
netadm 16 45 1 45 45 ? /usr/sbin/ibmgmtd
dladm 15 53 1 53 53 ? /usr/sbin/dlmgmtd
netadm 16 66 1 66 66 ? /lib/inet/ipmgmtd
daemon 1 74 1 74 74 ? /lib/crypto/kcfd
root 0 84 1 83 83 ? /lib/inet/in.mpathd
daemon 1 149 1 149 149 ? /usr/lib/utmpd
root 0 178 1 178 178 ? /usr/sbin/vbiosd
root 0 185 1 185 185 ? /usr/lib/zones/...
root 0 200 1 200 200 ? /usr/lib/sysevent/...
root 0 332 1 332 332 ? /usr/lib/dbus-daemon ...
root 0 430 1 430 430 ? /usr/lib/devfsadm/...
netadm 16 648 1 648 648 ? /lib/inet/nwamd
root 0 688 1 688 688 ? /usr/lib/picl/picld
root 0 757 1 757 757 ? /usr/lib/inet/ntpd ...
root 0 786 1 786 786 ? /usr/sbin/nscd
daemon 1 800 1 800 800 ? /usr/sbin/rpcbind
root 0 813 1 813 813 ? /usr/lib/inet/in.ndpd
root 0 842 1 840 840 ? /opt/VirtualBox/...
root 0 843 1 843 843 ? /usr/lib/inet/...
root 0 856 1 856 856 ? /usr/lib/hotplugd
root 0 860 1 860 860 ? /usr/lib/autofs/...
root 0 862 860 860 860 ? /usr/lib/autofs/...
root 0 866 1 865 865 ? /usr/sbin/...
root 0 870 1 870 870 ? /usr/sbin/cron
root 0 876 1 876 876 ? /usr/lib/hal/...
root 0 899 878 876 876 ? /usr/lib/hal/...
root 0 895 878 876 876 ? /usr/lib/hal/...
root 0 977 878 876 876 ? /usr/lib/hal/...
root 0 1160 878 876 876 ? /usr/lib/hal/...
root 0 1184 878 876 876 ? /usr/lib/hal/...
root 0 1206 878 876 876 ? /usr/lib/hal/...
root 0 1219 878 876 876 ? /usr/lib/hal/...
root 0 1236 878 876 876 ? /usr/lib/hal/...
root 0 878 876 876 876 ? hald-runner
root 0 942 1 941 941 ? /usr/lib/ssh/sshd
root 0 983 1 983 983 ? /usr/sbin/syslogd
root 0 1019 1 987 987 ? /usr/sbin/auditd
smmsp 25 1005 1 1005 1005 ? /usr/lib/inet/...
root 0 1006 1 1006 1006 ? /usr/lib/inet/...
root 0 1024 1 1024 1024 ? /usr/lib/fm/fmd/fmd
root 0 1126 1 1125 1125 ? /usr/bin/python2.7 ...
root 0 1140 1 1140 1140 ? /usr/sbin/cupsd -C ...
noaccess 60002 1228 1 1228 1228 ? /usr/lib/fm/notify/...
root 0 1232 1 1232 1232 ? /usr/lib/devchassis/...
noaccess 60002 1234 1 1234 1234 ? /usr/lib/fm/notify/...
root 0 1349 1 1348 1348 ? /usr/lib/rmvolmgr -s
ocm 62 1639 1 1639 1639 ? /usr/lib/ocm/ccr/...
gdm 50 1652 1 1649 1649 ? /usr/bin/dbus-launch ...
A basic description of each chosen column is on the aforementioned manpage, but it was driven by an interest towards daemon programming. One will note that the main filtering criteria is the absence ('?') of a controlling terminal (TT) and that the output was sorted first by process groups (PGID) and then by process ids (PID). Perhaps one will also note (with the help of Intro(2) manpage) that in this listing each process is a member of the first process group in/of each session because its PGID and SID are equal.
# ps -o user,uid,pid,ppid,pgid,sid,tty,args -t '?' \
|(IFS=''; read H; echo "$H"; sort -k5 -k3 \
|grep filtering_options account )
USER UID PID PPID PGID SID TT COMMAND
root 0 1 0 0 0 ? /usr/sbin/init
root 0 3 0 0 0 ? fsflush
root 0 7 0 0 0 ? intrd
root 0 6 0 0 0 ? kmem_task
root 0 2 0 0 0 ? pageout
root 0 9 0 0 0 ? postwaittq
root 0 0 0 0 0 ? sched
root 0 8 0 0 0 ? vmtasks
root 0 770 0 0 0 ? zpool-depot
root 0 788 0 0 0 ? zpool-export
root 0 5 0 0 0 ? zpool-rpool
root 0 96 1 13 13 ? /lib/svc/bin/...
root 0 13 1 13 13 ? /lib/svc/bin/svc.startd
root 0 751 1 13 13 ? /lib/svc/method/iscsid
root 0 1862 1353 13 13 ? /usr/lib/...
root 0 1353 1341 13 13 ? /usr/lib/...
root 0 106 1 13 13 ? /usr/lib/pfexecd
root 0 155 1 13 13 ? /usr/lib/rad/rad -sp
root 0 164 1 13 13 ? /usr/lib/rad/rad -sp
root 0 1341 1 13 13 ? /usr/sbin/gdm-binary
root 0 15 1 15 15 ? /lib/svc/bin/...
netcfg 17 42 1 42 42 ? /lib/inet/netcfgd
netadm 16 45 1 45 45 ? /usr/sbin/ibmgmtd
dladm 15 53 1 53 53 ? /usr/sbin/dlmgmtd
netadm 16 66 1 66 66 ? /lib/inet/ipmgmtd
daemon 1 74 1 74 74 ? /lib/crypto/kcfd
root 0 84 1 83 83 ? /lib/inet/in.mpathd
daemon 1 149 1 149 149 ? /usr/lib/utmpd
root 0 178 1 178 178 ? /usr/sbin/vbiosd
root 0 185 1 185 185 ? /usr/lib/zones/...
root 0 200 1 200 200 ? /usr/lib/sysevent/...
root 0 332 1 332 332 ? /usr/lib/dbus-daemon ...
root 0 430 1 430 430 ? /usr/lib/devfsadm/...
netadm 16 648 1 648 648 ? /lib/inet/nwamd
root 0 688 1 688 688 ? /usr/lib/picl/picld
root 0 757 1 757 757 ? /usr/lib/inet/ntpd ...
root 0 786 1 786 786 ? /usr/sbin/nscd
daemon 1 800 1 800 800 ? /usr/sbin/rpcbind
root 0 813 1 813 813 ? /usr/lib/inet/in.ndpd
root 0 842 1 840 840 ? /opt/VirtualBox/...
root 0 843 1 843 843 ? /usr/lib/inet/...
root 0 856 1 856 856 ? /usr/lib/hotplugd
root 0 860 1 860 860 ? /usr/lib/autofs/...
root 0 862 860 860 860 ? /usr/lib/autofs/...
root 0 866 1 865 865 ? /usr/sbin/...
root 0 870 1 870 870 ? /usr/sbin/cron
root 0 876 1 876 876 ? /usr/lib/hal/...
root 0 899 878 876 876 ? /usr/lib/hal/...
root 0 895 878 876 876 ? /usr/lib/hal/...
root 0 977 878 876 876 ? /usr/lib/hal/...
root 0 1160 878 876 876 ? /usr/lib/hal/...
root 0 1184 878 876 876 ? /usr/lib/hal/...
root 0 1206 878 876 876 ? /usr/lib/hal/...
root 0 1219 878 876 876 ? /usr/lib/hal/...
root 0 1236 878 876 876 ? /usr/lib/hal/...
root 0 878 876 876 876 ? hald-runner
root 0 942 1 941 941 ? /usr/lib/ssh/sshd
root 0 983 1 983 983 ? /usr/sbin/syslogd
root 0 1019 1 987 987 ? /usr/sbin/auditd
smmsp 25 1005 1 1005 1005 ? /usr/lib/inet/...
root 0 1006 1 1006 1006 ? /usr/lib/inet/...
root 0 1024 1 1024 1024 ? /usr/lib/fm/fmd/fmd
root 0 1126 1 1125 1125 ? /usr/bin/python2.7 ...
root 0 1140 1 1140 1140 ? /usr/sbin/cupsd -C ...
noaccess 60002 1228 1 1228 1228 ? /usr/lib/fm/notify/...
root 0 1232 1 1232 1232 ? /usr/lib/devchassis/...
noaccess 60002 1234 1 1234 1234 ? /usr/lib/fm/notify/...
root 0 1349 1 1348 1348 ? /usr/lib/rmvolmgr -s
ocm 62 1639 1 1639 1639 ? /usr/lib/ocm/ccr/...
gdm 50 1652 1 1649 1649 ? /usr/bin/dbus-launch ...
A basic description of each chosen column is on the aforementioned manpage, but it was driven by an interest towards daemon programming. One will note that the main filtering criteria is the absence ('?') of a controlling terminal (TT) and that the output was sorted first by process groups (PGID) and then by process ids (PID). Perhaps one will also note (with the help of Intro(2) manpage) that in this listing each process is a member of the first process group in/of each session because its PGID and SID are equal.
Tuesday, June 18, 2013
DISM run sample 3.0
This is a sample run for DISM of the shared memory code sample 3.0:
In an attempt to better demonstrate the presumable advantage of DISM, please, consider the following changes in the original sample source code 3.0:
037: std::size_t const size =
12UL * 1024UL * 1024UL * 1024UL;
051: void * p = ::shmat( id, 0, SHM_PAGEABLE );
063: if ( ::mlock( p, size / 4 ) == 0 )
069: ::memset( p, '*', size / 2 );
075: switch ( ::munlock( p, size / 4 ) )
$ getent user_attr
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 500M allocated + 178M reserved = 676M used, 18G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.32 1.37% 8355M 34.0% 10.0G 35.9% 396K 0.01%
[system] 0.32 1.36% 8274M 33.6% 9.9G 35.5% - -
... 0.00 0.00% 81.0M 0.33% 116M 0.40% 228 0.00%
Getting shared memory.
Press <ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 500M allocated + 12G reserved = 13G used, 5.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 0 12884901888 3832 ... 0 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.26 1.11% 8378M 34.1% 22.0G 78.8% 711K 0.02%
[system] 0.26 1.10% 8296M 33.7% 9.9G 35.5% - -
... 0.00 0.00% 82.5M 0.33% 12.1G 43.2% 228 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 5140K 2176K ...
...
Attaching to shared memory.
Press <ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 492M allocated + 12G reserved = 13G used, 5.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 1 12884901888 3832 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.26 1.10% 8391M 34.1% 22.0G 78.8% 534 0.00%
[system] 0.26 1.09% 8308M 33.8% 9.9G 35.5% - -
... 0.00 0.00% 82.6M 0.33% 12.1G 43.3% 432 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 12G 2176K ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FC80000000 12582912 - ... - rwxs- [ dism ... ]
...
Locking shared memory.
Press <ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 3.5G allocated + 9.2G reserved = 13G used, 2.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 1 12884901888 3832 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.29 1.23% 11.1G 46.6% 25.0G 89.5% 704K 0.00%
[system] 0.29 1.22% 8308M 33.8% 12.9G 46.2% - -
... 0.00 0.00% 3154M 12.8% 12.1G 43.3% 1347 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 12G 3074M ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FC80000000 12582912 3145728 ... 3145728 rwxs- [ dism ... ]
...
Using shared memory.
Press <ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 6.5G allocated + 6.2G reserved = 13G used, 2.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 1 12884901888 3832 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.27 1.13% 14.1G 59.1% 25.0G 89.5% 228 0.00%
[system] 0.27 1.12% 8309M 33.8% 12.9G 46.2% - -
... 0.00 0.00% 6225M 25.3% 12.1G 43.3% 228 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 12G 6146M ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FC80000000 12582912 6291456 ... 3145728 rwxs- [ dism ... ]
...
Unlocking shared memory.
Press<ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 6.5G allocated + 6.2G reserved = 13G used, 5.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 1 12884901888 3832 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.30 1.27% 14.1G 59.1% 22.0G 78.8% 181K 0.00%
[system] 0.30 1.27% 8309M 33.8% 9.9G 35.5% - -
... 0.00 0.00% 6225M 25.3% 12.1G 43.2% 432 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 12G 6146M ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FC80000000 12582912 6291456 ... - rwxs- [ dism ... ]
...
Detaching shared memory.
Press<ENTER> to continue...
Success!
vlab-3 $ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 6.5G allocated + 6.2G reserved = 13G used, 5.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 0 12884901888 3832 ... 0 group.staff
vlab-3 $ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.29 1.22% 14.1G 59.1% 22.0G 78.8% 228 0.00%
[system] 0.29 1.22% 14.1G 58.8% 9.9G 35.5% - -
... 0.00 0.00% 81.5M 0.33% 12.1G 43.2% 228 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 5140K 2180K ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FFB8F00000 1620 1024 ... - r-x-- libCstd.so.1
...
Removing shared memory.
Press <ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 500M allocated + 171M reserved = 672M used, 18G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.26 1.11% 8385M 34.1% 10.0G 35.9% 228 0.00%
[system] 0.26 1.11% 8303M 33.8% 9.9G 35.5% - -
... 0.00 0.00% 81.5M 0.33% 123M 0.43% 228 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 5140K 2180K ...
...
Exiting program.
Press<ENTER> to continue...
When Oracle Database fellows argues that "DISM can be dynamically resized depending on the application demand" they induce sysadmins to confusion or error.
As seen above throughout ipcs -mA on all the "output groups" the shared segment size never changes. What may change is the amount of memory the application chooses to lock, contrasting to ISM where the kernel always keep the whole segment locked.
Furthermore, they also believe that "Solaris does not allocate or reserve memory of size SGA_MAX_SIZE at instance startup". Again, for me, this is a misconception of them. I'm convinced that Oracle Database do reserve one or more large DISM segments, but that may not be apparent for a DBA, but the above output shows that Solaris does.
The behavior of ::shmget() is the same for ISM and DISM. The differences start, depending on how the segment is attached to the process. But before that no system resources are actually used, just accounted in the kernel (as a "promise" to the process which called ::shmget()).
Attaching DISM to a process, also just accounts pageable (as seen by pmap -x Mode flag) virtual memory to the process, but not yet any actual resources.
Locking a portion of (or the whole) DISM segment causes adjustments to virtual memory figures (allocated x reserved) because actual resources are allocated. Memory overhead is credited into kernel figures and the process resident size (RSS) also grows.
On the 5th "output group" we see that touching more memory than is locked (as in this sample code), causes even more pages to be allocated. In the example, we touch twice more than is currently locked, just to be more eye catching.
Unlocking DISM, reliefs the accounting of virtual memory but not necessarily frees physical memory (no pageouts) as there may not be memory pressure (as in this example).
And as with ISM, detaching shared memory, just unmaps it from the process, but not from the kernel. To free kernel resources the ::shmctl() must be issued.
In an attempt to better demonstrate the presumable advantage of DISM, please, consider the following changes in the original sample source code 3.0:
037: std::size_t const size =
12UL * 1024UL * 1024UL * 1024UL;
051: void * p = ::shmat( id, 0, SHM_PAGEABLE );
063: if ( ::mlock( p, size / 4 ) == 0 )
069: ::memset( p, '*', size / 2 );
075: switch ( ::munlock( p, size / 4 ) )
$ getent user_attr
...::::defaultpriv=basic,proc_lock_memory;...
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 500M allocated + 178M reserved = 676M used, 18G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.32 1.37% 8355M 34.0% 10.0G 35.9% 396K 0.01%
[system] 0.32 1.36% 8274M 33.6% 9.9G 35.5% - -
... 0.00 0.00% 81.0M 0.33% 116M 0.40% 228 0.00%
Getting shared memory.
Press <ENTER>
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 500M allocated + 12G reserved = 13G used, 5.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 0 12884901888 3832 ... 0 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.26 1.11% 8378M 34.1% 22.0G 78.8% 711K 0.02%
[system] 0.26 1.10% 8296M 33.7% 9.9G 35.5% - -
... 0.00 0.00% 82.5M 0.33% 12.1G 43.2% 228 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 5140K 2176K ...
...
Attaching to shared memory.
Press
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 492M allocated + 12G reserved = 13G used, 5.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 1 12884901888 3832 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.26 1.10% 8391M 34.1% 22.0G 78.8% 534 0.00%
[system] 0.26 1.09% 8308M 33.8% 9.9G 35.5% - -
... 0.00 0.00% 82.6M 0.33% 12.1G 43.3% 432 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 12G 2176K ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FC80000000 12582912 - ... - rwxs- [ dism ... ]
...
Locking shared memory.
Press <ENTER>
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 3.5G allocated + 9.2G reserved = 13G used, 2.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 1 12884901888 3832 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.29 1.23% 11.1G 46.6% 25.0G 89.5% 704K 0.00%
[system] 0.29 1.22% 8308M 33.8% 12.9G 46.2% - -
... 0.00 0.00% 3154M 12.8% 12.1G 43.3% 1347 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 12G 3074M ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FC80000000 12582912 3145728 ... 3145728 rwxs- [ dism ... ]
...
Using shared memory.
Press <ENTER>
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 6.5G allocated + 6.2G reserved = 13G used, 2.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 1 12884901888 3832 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.27 1.13% 14.1G 59.1% 25.0G 89.5% 228 0.00%
[system] 0.27 1.12% 8309M 33.8% 12.9G 46.2% - -
... 0.00 0.00% 6225M 25.3% 12.1G 43.3% 228 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 12G 6146M ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FC80000000 12582912 6291456 ... 3145728 rwxs- [ dism ... ]
...
Unlocking shared memory.
Press
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 6.5G allocated + 6.2G reserved = 13G used, 5.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 1 12884901888 3832 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.30 1.27% 14.1G 59.1% 22.0G 78.8% 181K 0.00%
[system] 0.30 1.27% 8309M 33.8% 9.9G 35.5% - -
... 0.00 0.00% 6225M 25.3% 12.1G 43.2% 432 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 12G 6146M ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FC80000000 12582912 6291456 ... - rwxs- [ dism ... ]
...
Detaching shared memory.
Press
Success!
vlab-3 $ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 6.5G allocated + 6.2G reserved = 13G used, 5.9G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 0 12884901888 3832 ... 0 group.staff
vlab-3 $ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.29 1.22% 14.1G 59.1% 22.0G 78.8% 228 0.00%
[system] 0.29 1.22% 14.1G 58.8% 9.9G 35.5% - -
... 0.00 0.00% 81.5M 0.33% 12.1G 43.2% 228 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 5140K 2180K ...
...
$ pmap -x 3832 | head
3832: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
0000000000400000 8 8 ... - r-x-- shm_v04
0000000000411000 8 8 ... - rw--- shm_v04
0000000000413000 160 68 ... - rw--- [ heap ]
FFFF80FFB8F00000 1620 1024 ... - r-x-- libCstd.so.1
...
Removing shared memory.
Press <ENTER>
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 500M allocated + 171M reserved = 672M used, 18G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.26 1.11% 8385M 34.1% 10.0G 35.9% 228 0.00%
[system] 0.26 1.11% 8303M 33.8% 9.9G 35.5% - -
... 0.00 0.00% 81.5M 0.33% 123M 0.43% 228 0.00%
$ prstat -c -p 3832 1 1
Please wait...
PID USERNAME SIZE RSS ...
3832 ... 5140K 2180K ...
...
Exiting program.
Press
When Oracle Database fellows argues that "DISM can be dynamically resized depending on the application demand" they induce sysadmins to confusion or error.
As seen above throughout ipcs -mA on all the "output groups" the shared segment size never changes. What may change is the amount of memory the application chooses to lock, contrasting to ISM where the kernel always keep the whole segment locked.
Furthermore, they also believe that "Solaris does not allocate or reserve memory of size SGA_MAX_SIZE at instance startup". Again, for me, this is a misconception of them. I'm convinced that Oracle Database do reserve one or more large DISM segments, but that may not be apparent for a DBA, but the above output shows that Solaris does.
The behavior of ::shmget() is the same for ISM and DISM. The differences start, depending on how the segment is attached to the process. But before that no system resources are actually used, just accounted in the kernel (as a "promise" to the process which called ::shmget()).
Attaching DISM to a process, also just accounts pageable (as seen by pmap -x Mode flag) virtual memory to the process, but not yet any actual resources.
Locking a portion of (or the whole) DISM segment causes adjustments to virtual memory figures (allocated x reserved) because actual resources are allocated. Memory overhead is credited into kernel figures and the process resident size (RSS) also grows.
On the 5th "output group" we see that touching more memory than is locked (as in this sample code), causes even more pages to be allocated. In the example, we touch twice more than is currently locked, just to be more eye catching.
Unlocking DISM, reliefs the accounting of virtual memory but not necessarily frees physical memory (no pageouts) as there may not be memory pressure (as in this example).
And as with ISM, detaching shared memory, just unmaps it from the process, but not from the kernel. To free kernel resources the ::shmctl() must be issued.
ISM run sample 3.0
This is a sample run for ISM of the shared memory code sample 3.0:
$ getent user_attr prime ...::::defaultpriv=basic,proc_lock_memory;...
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 496M allocated + 170M reserved = 668M used, 18G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.26 1.09% 7719M 31.4% 10.0G 35.8% 540K 0.00%
[system] 0.26 1.09% 7632M 31.0% 9.9G 35.4% - -
... 0.00 0.00% 86.9M 0.35% 117M 0.40% 1280 0.00%
Getting shared memory.
Press <ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 496M allocated + 1.2G reserved = 1.7G used, 17G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 0 1073741824 3253 ... 0 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.25 1.05% 7720M 31.4% 11.0G 39.4% 317 0.00%
[system] 0.25 1.05% 7633M 31.0% 9.9G 35.4% - -
... 0.00 0.00% 86.9M 0.35% 1144M 3.99% 317 0.00%
$ prstat -c -p 3253 1 1
Please wait...
PID USERNAME SIZE RSS ...
3253 ... 3832K 1720K
...
Attaching to shared memory.
Press<ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 1.5G allocated + 182M reserved = 1.7G used, 17G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 1 1073741824 3253 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.25 1.07% 8741M 35.5% 11.0G 39.4% 1347 0.00%
[system] 0.25 1.06% 7631M 31.0% 9.9G 35.4% - -
... 0.00 0.00% 1109M 4.51% 1148M 4.00% 1347 0.00%
$ prstat -c -p 3253 1 1
Please wait...
PID USERNAME SIZE RSS ...
3253 ... 1028M 1026M ...
...
$ pmap -x 3253 | head
3253: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
08050000 8 8 ... - r-x-- shm_v04
08061000 4 4 ... - rwx-- shm_v04
08062000 128 44 ... - rwx-- [ heap ]
80000000 1048576 1048576 ... 1048576 rwxsR [ ism shmid=... ]
...
Locking shared memory.
Press<ENTER> to continue...
Success!
not relevant for ISM
Using shared memory.
Press<ENTER> to continue...
Success!
not relevant for ISM
Unlocking shared memory.
Press <ENTER> to continue...
Success!
not relevant for ISM
Detaching shared memory.
Press <ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 1.5G allocated + 182M reserved = 1.7G used, 17G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 0 1073741824 3253 ... 0 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.24 1.03% 8742M 35.5% 11.0G 39.4% 228 0.00%
[system] 0.24 1.03% 8656M 35.2% 9.9G 35.4% - -
... 0.00 0.00% 85.9M 0.34% 1143M 3.99% 228 0.00%
$ prstat -c -p 3253 1 1
Please wait...
PID USERNAME SIZE RSS ...
3253 ... 3832K 1720K ...
...
$ pmap -x 3253 | head
3253: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
08050000 8 8 ... - r-x-- shm_v04
08061000 4 4 ... - rwx-- shm_v04
08062000 128 44 ... - rwx-- [ heap ]
FE380000 24 12 ... - rwx-- [ anon ]
...
Removing shared memory.
Press<ENTER> to continue...
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 496M allocated + 174M reserved = 668M used, 18G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.30 1.25% 7718M 31.4% 10.0G 35.8% 9852 0.00%
[system] 0.30 1.25% 7632M 31.0% 9.9G 35.4% - -
... 0.00 0.00% 85.9M 0.34% 120M 0.41% 228 0.00%
$ prstat -c -p 3253 1 1
Please wait...
PID USERNAME SIZE RSS ...
3253 ... 3832K 1720K ...
...
Exiting program.
Press<ENTER> to continue...
When Oracle Database fellows argues that "::shmget() requires swap reservation" they induce sysadmins to confusion or error.
As seen above (on the 2nd "output group") what happens is simply virtual memory reservation within the kernel. Note there's no other swap maneuver or switch between disk and physical memory and so on. The process that does the call doesn't even exhibit different figures.
With ISM, physical memory actually gets allocated only when the reserved shared segment is mapped in the calling process via ::shmat(). This is clearly seen in the 3rd "output group" above.
We also see that ::shmdt() doesn't really release any allocated memory as seen in the 4th "output group". The shared memory segment is unmapped from the process but continues to exist within the kernel.
It's only when ::shmctl() is called that memory is actually freed (fifth "output group").
$ getent user_attr prime ...::::defaultpriv=basic,proc_lock_memory;...
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 496M allocated + 170M reserved = 668M used, 18G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.26 1.09% 7719M 31.4% 10.0G 35.8% 540K 0.00%
[system] 0.26 1.09% 7632M 31.0% 9.9G 35.4% - -
... 0.00 0.00% 86.9M 0.35% 117M 0.40% 1280 0.00%
Getting shared memory.
Press <ENTER>
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 496M allocated + 1.2G reserved = 1.7G used, 17G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 0 1073741824 3253 ... 0 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.25 1.05% 7720M 31.4% 11.0G 39.4% 317 0.00%
[system] 0.25 1.05% 7633M 31.0% 9.9G 35.4% - -
... 0.00 0.00% 86.9M 0.35% 1144M 3.99% 317 0.00%
$ prstat -c -p 3253 1 1
Please wait...
PID USERNAME SIZE RSS ...
3253 ... 3832K 1720K
...
Attaching to shared memory.
Press
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 1.5G allocated + 182M reserved = 1.7G used, 17G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 1 1073741824 3253 ... 1 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.25 1.07% 8741M 35.5% 11.0G 39.4% 1347 0.00%
[system] 0.25 1.06% 7631M 31.0% 9.9G 35.4% - -
... 0.00 0.00% 1109M 4.51% 1148M 4.00% 1347 0.00%
$ prstat -c -p 3253 1 1
Please wait...
PID USERNAME SIZE RSS ...
3253 ... 1028M 1026M ...
...
$ pmap -x 3253 | head
3253: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
08050000 8 8 ... - r-x-- shm_v04
08061000 4 4 ... - rwx-- shm_v04
08062000 128 44 ... - rwx-- [ heap ]
80000000 1048576 1048576 ... 1048576 rwxsR [ ism shmid=... ]
...
Locking shared memory.
Press
Success!
not relevant for ISM
Using shared memory.
Press
Success!
not relevant for ISM
Unlocking shared memory.
Press <ENTER>
Success!
not relevant for ISM
Detaching shared memory.
Press <ENTER>
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 1.5G allocated + 182M reserved = 1.7G used, 17G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
m ... 0x1 ... 0 1073741824 3253 ... 0 group.staff
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.24 1.03% 8742M 35.5% 11.0G 39.4% 228 0.00%
[system] 0.24 1.03% 8656M 35.2% 9.9G 35.4% - -
... 0.00 0.00% 85.9M 0.34% 1143M 3.99% 228 0.00%
$ prstat -c -p 3253 1 1
Please wait...
PID USERNAME SIZE RSS ...
3253 ... 3832K 1720K ...
...
$ pmap -x 3253 | head
3253: ./shm_v04
Address Kbytes RSS ... Locked Mode Mapped File
08050000 8 8 ... - r-x-- shm_v04
08061000 4 4 ... - rwx-- shm_v04
08062000 128 44 ... - rwx-- [ heap ]
FE380000 24 12 ... - rwx-- [ anon ]
...
Removing shared memory.
Press
Success!
$ swap -lh; swap -sh
swapfile dev swaplo blocks free
/dev/swap - 4K 4.0G 3.9G
total: 496M allocated + 174M reserved = 668M used, 18G available
$ ipcs -mA
IPC status ...
T ... KEY ... NATTCH SEGSZ CPID ... ISMATTCH PROJECT
Shared Memory:
$ zonestat 1 1
Collecting data for first interval...
Interval: 1, Duration: 0:00:01
SUMMARY Cpus/Online: 24/24 PhysMem: 23.9G VirtMem: 27.9G
---CPU---- --PhysMem-- --VirtMem-- --PhysNet--
ZONE USED %PART USED %USED USED %USED PBYTE %PUSE
[total] 0.30 1.25% 7718M 31.4% 10.0G 35.8% 9852 0.00%
[system] 0.30 1.25% 7632M 31.0% 9.9G 35.4% - -
... 0.00 0.00% 85.9M 0.34% 120M 0.41% 228 0.00%
$ prstat -c -p 3253 1 1
Please wait...
PID USERNAME SIZE RSS ...
3253 ... 3832K 1720K ...
...
Exiting program.
Press
When Oracle Database fellows argues that "::shmget() requires swap reservation" they induce sysadmins to confusion or error.
As seen above (on the 2nd "output group") what happens is simply virtual memory reservation within the kernel. Note there's no other swap maneuver or switch between disk and physical memory and so on. The process that does the call doesn't even exhibit different figures.
With ISM, physical memory actually gets allocated only when the reserved shared segment is mapped in the calling process via ::shmat(). This is clearly seen in the 3rd "output group" above.
We also see that ::shmdt() doesn't really release any allocated memory as seen in the 4th "output group". The shared memory segment is unmapped from the process but continues to exist within the kernel.
It's only when ::shmctl() is called that memory is actually freed (fifth "output group").
Subscribe to:
Posts (Atom)