This program (rc-03) uses the Solaris interface to resource control.
It lists all the controls that are active to its running process.
Following the listing there's a sample output.
#include <rctl.h>
#include <alloca.h>
#include <cstdlib>
#include <cerrno>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <iostream>
#include <iomanip>
//
// Convenience "special" vector.
//
template< typename T >
struct vector : public std::vector< T >
{
};
//
// Convenience operator for just the "special" vector.
// For simplicity, not dealing with formatting or state issues.
//
template< typename T >
std::istream & operator >> ( std::istream & is, vector<T> & v )
{
typename vector<T>::value_type element;
if ( is >> element )
v.push_back( element );
return is;
}
//
// The main data structure for organization.
// Key: resource containment.
// Data: list of controls.
//
std::map< const std::string, vector< std::string > > resource;
//
// The resource walking routine.
//
int active( const char * name, void * )
{
std::istringstream iss( name );
std::string containment;
if ( std::getline( iss, containment, '.' ) )
iss >> resource[ containment ];
return 0;
}
const size_t size = ::rctlblk_size( );
typedef ::rctlblk_t * p_blk;
// May suffer from stream formatting issues...
void print_limit( const p_blk rl )
{
//
// Type
//
std::cout
<< "\t\t"
<< std::setw( 11 ) << std::left;
switch ( ::rctlblk_get_privilege( rl ) )
{
case RCPRIV_BASIC:
std::cout << "basic";
break;
case RCPRIV_PRIVILEGED:
std::cout << "privileged";
break;
case RCPRIV_SYSTEM:
std::cout << "system";
break;
}
//
// Value
//
std::cout
<< ":"
<< std::setw( 21 ) << std::right
<< ::rctlblk_get_value( rl );
std::cout
<< std::endl;
std::cout
<< std::setw( 0 ) << std::left;
}
// May suffer from stream formatting issues...
void print_control( std::string containment,
vector< std::string > & control_list )
{
p_blk rl = static_cast < p_blk >
(
// Never leaks memory
::alloca( size )
);
containment += ".";
std::sort( control_list.begin( ), control_list.end( ) );
for ( auto & control : control_list )
{
std::cout
<< "\t";
std::cout
<< std::setw( 32 ) << std::left
<< control;
const std::string name = containment + control;
p_blk p = 0; // Tracking pointer
int rv = ::getrctl( name.c_str(), p, rl, RCTL_FIRST );
const int gflags = ::rctlblk_get_global_flags( rl );
std::cout
<< std::setw( 9 ) << std::right
<<
(
gflags & RCTL_GLOBAL_BYTES ? "(bytes)" :
gflags & RCTL_GLOBAL_SECONDS ? "(seconds)" :
gflags & RCTL_GLOBAL_COUNT ? "(count)" :
"(?)"
)
<< std::endl;
std::cout
<< std::setw( 0 ) << std::left;
while ( rv == 0 )
{
print_limit( rl );
p = rl; // Smart(?) move...
rv = ::getrctl( name.c_str(), p, rl, RCTL_NEXT );
}
if ( errno != ENOENT )
std::cout
<< "\t\tError getting limits!"
<< std::endl;
std::cout
<< std::endl;
}
}
// May suffer from stream formatting issues...
void print( )
{
std::cout
<< std::endl
<< "Printing active resource controls..."
<< std::endl
<< std::endl;
// I want to list containments as ordered below
auto known = { "process", "task", "project", "zone" };
for ( auto & containment : known )
{
std::cout
<< containment
<< std::endl
<< std::endl;
print_control( containment, resource[ containment ] );
}
//
// In case new (currently unknown) containments appear
// in the future, just list them at the bottom.
//
for ( auto & r : resource )
{
auto c = r.first; // A containment
if ( std::none_of( known.begin( ), known.end( ),
[ &c ]( const char * s ) { return s == c; } ) )
{
std::cout
<< c // An unknown containment
<< std::endl
<< std::endl;
print_control( r.first, r.second );
}
}
}
// May suffer from stream formatting issues...
int main( )
{
std::cout
<< std::endl
<< "Gathering active resource controls..."
<< std::endl
<< std::endl;
std::cout
<< "\tRC walk starting..."
<< std::endl;
if ( ::rctl_walk( active, 0 ) == 0 )
std::cout
<< "\tRC walk completed successfuly!"
<< std::endl;
print( );
return EXIT_SUCCESS;
}
A possible output is:
$ ./rc-03
Gathering active resource controls...
RC walk starting...
RC walk completed successfuly!
Printing active resource controls...
process
max-address-space (bytes)
privileged : 18446744073709551615
system : 18446744073709551615
max-core-size (bytes)
privileged : 9223372036854775807
system : 9223372036854775807
max-cpu-time (seconds)
privileged : 18446744073709551615
system : 18446744073709551615
max-data-size (bytes)
privileged : 18446744073709551615
system : 18446744073709551615
max-deferred-posts (count)
basic : 32
privileged : 100
system : 8192
max-file-descriptor (count)
basic : 1024
privileged : 65536
system : 2147483647
max-file-size (bytes)
privileged : 9223372036854775807
system : 9223372036854775807
max-itimers (count)
privileged : 1000
system : 65536
max-msg-messages (count)
privileged : 8192
system : 4294967295
max-msg-qbytes (bytes)
privileged : 65536
system : 18446744073709551615
max-port-events (count)
privileged : 65536
system : 2147483647
max-sem-nsems (count)
privileged : 512
system : 32767
max-sem-ops (count)
privileged : 512
system : 2147483647
max-sigqueue-size (count)
basic : 128
privileged : 512
system : 8192
max-stack-size (bytes)
basic : 8388608
privileged : 1098437885952
system : 1098437885952
task
max-cpu-time (seconds)
system : 18446744073709551615
max-lwps (count)
system : 2147483647
max-processes (count)
system : 2147483647
project
cpu-cap (count)
system : 4294967295
cpu-shares (count)
privileged : 1
system : 65535
max-contracts (count)
privileged : 10000
system : 2147483647
max-crypto-memory (bytes)
privileged : 2143089664
system : 18446744073709551615
max-locked-memory (bytes)
system : 18446744073709551615
max-lwps (count)
system : 2147483647
max-mrp-ids (count)
privileged : 128
system : 16777216
max-msg-ids (count)
privileged : 128
system : 16777216
max-port-ids (count)
privileged : 8192
system : 65536
max-processes (count)
system : 2147483647
max-sem-ids (count)
privileged : 128
system : 16777216
max-shm-ids (count)
privileged : 128
system : 16777216
max-shm-memory (bytes)
privileged : 2143089664
system : 18446744073709551615
max-tasks (count)
system : 2147483647
zone
cpu-cap (count)
system : 4294967295
cpu-shares (count)
privileged : 1
system : 65535
max-locked-memory (bytes)
system : 18446744073709551615
max-lofi (count)
system : 18446744073709551615
max-lwps (count)
system : 2147483647
max-mrp-ids (count)
system : 16777216
max-msg-ids (count)
system : 16777216
max-processes (count)
system : 2147483647
max-sem-ids (count)
system : 16777216
max-shm-ids (count)
system : 16777216
max-shm-memory (bytes)
system : 18446744073709551615
max-swap (bytes)
system : 18446744073709551615
Personal notes and recipes, views and opinions.
If it must run, it runs on Solaris!
Friday, April 28, 2017
Thursday, April 27, 2017
Resource control - rc-02
This program (rc-02) uses the Solaris interface to resource control.
The main() function was listed first just to let the logic more clear.
Note how its approach is more complex than the traditional one:
#include <rctl.h>
#include <strings.h>
#include <alloca.h>
#include <unistd.h>
#include <cerrno>
#include <cstdlib>
#include <iostream>
const ::pid_t ppid = ::getppid( );
const size_t size = ::rctlblk_size();
static const char name[] = "process.max-file-descriptor";
typedef ::rctlblk_t * p_blk;
// May suffer from stream formatting issues...
int main( )
{
std::cout
<< std::endl
<< "Resource limit: " << name
<< std::endl;
p_blk p = 0; // Tracking pointer
p_blk rl = static_cast < p_blk >
(
// Never leaks memory
::alloca( size )
);
int rv = ::getrctl( name, p, rl, RCTL_FIRST );
while ( rv == 0 )
{
print( rl );
p = rl; // Smart(?) move...
rv = ::getrctl( name, p, rl, RCTL_NEXT );
}
if ( errno != ENOENT )
{
...
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
And now the auxiliary printing function:
// May suffer from stream formatting issues...
void print( const p_blk rl )
{
std::cout << std::endl;
//
// Type
//
std::cout << "\tType: ";
switch ( ::rctlblk_get_privilege( rl ) )
{
case RCPRIV_BASIC:
std::cout << "Basic";
break;
case RCPRIV_PRIVILEGED:
std::cout << "Privileged";
break;
case RCPRIV_SYSTEM:
std::cout << "System";
break;
}
//
// PID & PPID
//
const ::id_t pid = ::rctlblk_get_recipient_pid( rl );
std::cout << " (PID " << pid;
if ( pid > -1 )
std::cout << "; PPID " << ppid;
std::cout << ")" << std::endl;
//
// Flags
//
const int gflags = ::rctlblk_get_global_flags( rl );
std::cout << "\tGlobal action: "
<<
(
gflags == RCTL_GLOBAL_NOACTION ? "no action" :
gflags & RCTL_GLOBAL_DENY_ALWAYS ? "deny" :
gflags & RCTL_GLOBAL_DENY_NEVER ? "allow" :
"other"
)
<< "; ";
std::cout << "Syslog: "
<<
(
gflags & RCTL_GLOBAL_SYSLOG ? "yes" : "no"
)
<< std::endl;
std::cout << "\tLowerable: "
<<
(
gflags & RCTL_GLOBAL_LOWERABLE ? "yes" : "no"
)
<< "; ";
std::cout << "Infinite: "
<<
(
gflags & RCTL_GLOBAL_INFINITE ? "yes" : "no"
)
<< std::endl;
const int lflags = ::rctlblk_get_local_flags( rl );
std::cout << "\tLocally maximal: "
<<
(
lflags & RCTL_LOCAL_MAXIMAL ? "yes" : "no"
)
<< "; ";
std::cout << "Local project: "
<<
(
lflags & RCTL_LOCAL_PROJDB ? "yes" : "no"
)
<< std::endl;
std::cout << "\tLimit type: "
<<
(
gflags & RCTL_GLOBAL_BYTES ? "bytes" :
gflags & RCTL_GLOBAL_SECONDS ? "seconds" :
gflags & RCTL_GLOBAL_COUNT ? "count" :
"?"
)
<< std::endl;
//
// Values
//
std::cout << "\tCurrent: "
<< ::rctlblk_get_value( rl )
<< std::endl;
std::cout << "\tEnforced: "
<< ::rctlblk_get_enforced_value( rl )
<< std::endl;
}
This program works in Solaris 11.3.
I used the GCC 4.8.2 and NetBeans 8.1 with no issues at all.
The main() function was listed first just to let the logic more clear.
Note how its approach is more complex than the traditional one:
#include <rctl.h>
#include <strings.h>
#include <alloca.h>
#include <unistd.h>
#include <cerrno>
#include <cstdlib>
#include <iostream>
const ::pid_t ppid = ::getppid( );
const size_t size = ::rctlblk_size();
static const char name[] = "process.max-file-descriptor";
typedef ::rctlblk_t * p_blk;
// May suffer from stream formatting issues...
int main( )
{
std::cout
<< std::endl
<< "Resource limit: " << name
<< std::endl;
p_blk p = 0; // Tracking pointer
p_blk rl = static_cast < p_blk >
(
// Never leaks memory
::alloca( size )
);
int rv = ::getrctl( name, p, rl, RCTL_FIRST );
while ( rv == 0 )
{
print( rl );
p = rl; // Smart(?) move...
rv = ::getrctl( name, p, rl, RCTL_NEXT );
}
if ( errno != ENOENT )
{
...
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
And now the auxiliary printing function:
// May suffer from stream formatting issues...
void print( const p_blk rl )
{
std::cout << std::endl;
//
// Type
//
std::cout << "\tType: ";
switch ( ::rctlblk_get_privilege( rl ) )
{
case RCPRIV_BASIC:
std::cout << "Basic";
break;
case RCPRIV_PRIVILEGED:
std::cout << "Privileged";
break;
case RCPRIV_SYSTEM:
std::cout << "System";
break;
}
//
// PID & PPID
//
const ::id_t pid = ::rctlblk_get_recipient_pid( rl );
std::cout << " (PID " << pid;
if ( pid > -1 )
std::cout << "; PPID " << ppid;
std::cout << ")" << std::endl;
//
// Flags
//
const int gflags = ::rctlblk_get_global_flags( rl );
std::cout << "\tGlobal action: "
<<
(
gflags == RCTL_GLOBAL_NOACTION ? "no action" :
gflags & RCTL_GLOBAL_DENY_ALWAYS ? "deny" :
gflags & RCTL_GLOBAL_DENY_NEVER ? "allow" :
"other"
)
<< "; ";
std::cout << "Syslog: "
<<
(
gflags & RCTL_GLOBAL_SYSLOG ? "yes" : "no"
)
<< std::endl;
std::cout << "\tLowerable: "
<<
(
gflags & RCTL_GLOBAL_LOWERABLE ? "yes" : "no"
)
<< "; ";
std::cout << "Infinite: "
<<
(
gflags & RCTL_GLOBAL_INFINITE ? "yes" : "no"
)
<< std::endl;
const int lflags = ::rctlblk_get_local_flags( rl );
std::cout << "\tLocally maximal: "
<<
(
lflags & RCTL_LOCAL_MAXIMAL ? "yes" : "no"
)
<< "; ";
std::cout << "Local project: "
<<
(
lflags & RCTL_LOCAL_PROJDB ? "yes" : "no"
)
<< std::endl;
std::cout << "\tLimit type: "
<<
(
gflags & RCTL_GLOBAL_BYTES ? "bytes" :
gflags & RCTL_GLOBAL_SECONDS ? "seconds" :
gflags & RCTL_GLOBAL_COUNT ? "count" :
"?"
)
<< std::endl;
//
// Values
//
std::cout << "\tCurrent: "
<< ::rctlblk_get_value( rl )
<< std::endl;
std::cout << "\tEnforced: "
<< ::rctlblk_get_enforced_value( rl )
<< std::endl;
}
This program works in Solaris 11.3.
I used the GCC 4.8.2 and NetBeans 8.1 with no issues at all.
Resource control - rc-01
This program (rc-01) uses the UNIX portable interface to resource control.
This is the traditional (legacy) standard as well.
Note how simple it is!
But the recommended Solaris approach is far more complex...
#include <sys/resource.h>
#include <cstdlib>
#include <iostream>
// May suffer from stream formatting issues...
int main( )
{
::rlimit rl;
if ( ::getrlimit( RLIMIT_NOFILE, &rl ) != 0 )
{
...
return EXIT_FAILURE;
}
std::cout << "Process' inherited FD limits:" << std::endl;
std::cout << "Current: " << rl.rlim_cur << "." << std::endl;
std::cout << "Maximum: " << rl.rlim_max << "." << std::endl;
return EXIT_SUCCESS;
}
This program works in Solaris 11.3.
I used the GCC 4.8.2 and NetBeans 8.1 with no issues at all.
This is the traditional (legacy) standard as well.
Note how simple it is!
But the recommended Solaris approach is far more complex...
#include <sys/resource.h>
#include <cstdlib>
#include <iostream>
// May suffer from stream formatting issues...
int main( )
{
::rlimit rl;
if ( ::getrlimit( RLIMIT_NOFILE, &rl ) != 0 )
{
...
return EXIT_FAILURE;
}
std::cout << "Process' inherited FD limits:" << std::endl;
std::cout << "Current: " << rl.rlim_cur << "." << std::endl;
std::cout << "Maximum: " << rl.rlim_max << "." << std::endl;
return EXIT_SUCCESS;
}
This program works in Solaris 11.3.
I used the GCC 4.8.2 and NetBeans 8.1 with no issues at all.
Monday, April 24, 2017
Resource control - Intro
Resource control historically appeared for limiting the system's
resources that processes and their children could consume, but nowadays
in Solaris this concept has been elaborated to other collections of
processes: tasks, projects and zones as well.
The best practice is to carefully assess (as using extended accounting) the resource consumption of the workloads on the system before applying any fine-grained resource control to prevent over-consumptions. And, of course, above all, the system must meet or exceed the combined resource requirements of all the workloads it's supposed to host.
This topic is vast because there are many resources (resource-controls(5)) ranging from the most "elementary" to the most complex ones, there 3 control levels (basic, privileged and system), there are 4 containment levels (process, task, project and zone), 2 types of actions and flags (local and global) as well more than one available interface managing part (ulimit(1) and getrlimit(2)) or all of this stuff (rctladm(1M), prctl(1), setrctl(2), the projects database and zone configuration).
All the manpages provide extensive information I won't discuss, at least for now. In addition there are some other lenghty references such as the chapter 5 of Resource Management and Oracle® Solaris Zones Developer's Guide which is a kind of revamp of the original chapter 5 of the (partially) archived Solaris Containers: Resource Management and Solaris Zones Developer's Guide.
The best practice is to carefully assess (as using extended accounting) the resource consumption of the workloads on the system before applying any fine-grained resource control to prevent over-consumptions. And, of course, above all, the system must meet or exceed the combined resource requirements of all the workloads it's supposed to host.
This topic is vast because there are many resources (resource-controls(5)) ranging from the most "elementary" to the most complex ones, there 3 control levels (basic, privileged and system), there are 4 containment levels (process, task, project and zone), 2 types of actions and flags (local and global) as well more than one available interface managing part (ulimit(1) and getrlimit(2)) or all of this stuff (rctladm(1M), prctl(1), setrctl(2), the projects database and zone configuration).
All the manpages provide extensive information I won't discuss, at least for now. In addition there are some other lenghty references such as the chapter 5 of Resource Management and Oracle® Solaris Zones Developer's Guide which is a kind of revamp of the original chapter 5 of the (partially) archived Solaris Containers: Resource Management and Solaris Zones Developer's Guide.
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.
Subscribe to:
Posts (Atom)